1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/mini_installer_test/installer_test_util.h"
7 #include "base/file_util.h"
8 #include "base/path_service.h"
9 #include "base/process/kill.h"
10 #include "base/process/launch.h"
11 #include "base/process/process.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/platform_thread.h"
14 #include "chrome/common/chrome_result_codes.h"
15 #include "chrome/installer/util/google_update_constants.h"
16 #include "chrome/installer/util/helper.h"
17 #include "chrome/installer/util/install_util.h"
18 #include "chrome/installer/util/util_constants.h"
19 #include "chrome/test/mini_installer_test/mini_installer_test_constants.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using installer::InstallationValidator
;
26 BrowserDistribution::Type
ToBrowserDistributionType(
27 InstallationValidator::InstallationType type
) {
28 const int kChromeMask
=
29 (InstallationValidator::ProductBits::CHROME_SINGLE
|
30 InstallationValidator::ProductBits::CHROME_MULTI
);
31 const int kChromeFrameMask
=
32 (InstallationValidator::ProductBits::CHROME_FRAME_SINGLE
|
33 InstallationValidator::ProductBits::CHROME_FRAME_MULTI
);
34 const int kBinariesMask
=
35 (InstallationValidator::ProductBits::CHROME_MULTI
|
36 InstallationValidator::ProductBits::CHROME_FRAME_MULTI
);
37 // Default return is CHROME_BINARIES.
38 BrowserDistribution::Type ret_value
= BrowserDistribution::CHROME_BINARIES
;
39 if (type
& kChromeMask
)
40 ret_value
= BrowserDistribution::CHROME_BROWSER
;
41 if (type
& kChromeFrameMask
)
42 ret_value
= BrowserDistribution::CHROME_FRAME
;
43 if (type
& kBinariesMask
)
44 ret_value
= BrowserDistribution::CHROME_BINARIES
;
50 namespace installer_test
{
52 bool DeleteInstallDirectory(bool system_level
,
53 InstallationValidator::InstallationType type
) {
54 std::string version
= GetVersion(type
);
58 bool has_install_dir
= GetInstallDirectory(system_level
,
59 ToBrowserDistributionType(type
),
61 if (!has_install_dir
|| !base::PathExists(path
))
63 path
= path
.AppendASCII(version
);
64 return base::DeleteFile(path
, true);
67 bool DeleteRegistryKey(bool system_level
,
68 InstallationValidator::InstallationType type
) {
69 BrowserDistribution
* dist
= BrowserDistribution::GetSpecificDistribution(
70 ToBrowserDistributionType(type
));
71 base::FilePath::StringType
key(google_update::kRegPathClients
);
72 key
.push_back(base::FilePath::kSeparators
[0]);
73 key
.append(dist
->GetAppGuid());
74 HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
75 return InstallUtil::DeleteRegistryKey(root
, key
);
78 bool GetChromeInstallDirectory(bool system_level
, base::FilePath
* path
) {
79 return GetInstallDirectory(system_level
,
80 BrowserDistribution::CHROME_BROWSER
, path
);
83 bool GetInstallDirectory(bool system_level
,
84 BrowserDistribution::Type type
, base::FilePath
* path
) {
85 BrowserDistribution
* dist
=
86 BrowserDistribution::GetSpecificDistribution(type
);
87 *path
= installer::GetChromeInstallPath(system_level
, dist
);
88 base::FilePath parent
;
90 PathService::Get(base::DIR_PROGRAM_FILES
, &parent
);
92 PathService::Get(base::DIR_LOCAL_APP_DATA
, &parent
);
93 return parent
.IsParent(*path
);
96 bool GetInstalledProducts(
97 std::vector
<installer_test::InstalledProduct
>* products
) {
98 // Clear out the products list.
100 // Check user-level and system-level for products.
101 BrowserDistribution
* current_dist
;
102 installer_test::InstalledProduct current_prod
;
103 for (int i
= 0; i
< 2; ++i
) {
104 const bool system_level
= (i
!= 0);
105 InstallationValidator::InstallationType type
=
106 InstallationValidator::NO_PRODUCTS
;
108 InstallationValidator::ValidateInstallationType(system_level
, &type
);
109 if (type
!= InstallationValidator::NO_PRODUCTS
) {
110 current_dist
= BrowserDistribution::GetSpecificDistribution(
111 ToBrowserDistributionType(type
));
113 InstallUtil::GetChromeVersion(current_dist
, system_level
, &version
);
114 if (version
.IsValid()) {
115 current_prod
.type
= type
;
116 current_prod
.version
= version
.GetString();
117 current_prod
.system
= system_level
;
118 products
->push_back(current_prod
);
122 return !products
->empty();
125 bool ValidateInstall(bool system_level
,
126 InstallationValidator::InstallationType expected
,
127 const std::string
& version
) {
128 if (GetVersion(expected
) != version
)
130 InstallationValidator::InstallationType type
;
131 InstallationValidator::ValidateInstallationType(system_level
, &type
);
132 if (type
== InstallationValidator::NO_PRODUCTS
) {
133 LOG(ERROR
) << "No installed Chrome or Chrome Frame versions found.";
136 if ((type
& expected
) == 0) {
137 LOG(ERROR
) << "Expected type: " << expected
<< "\n Actual type: " << type
;
143 std::string
GetVersion(InstallationValidator::InstallationType product
) {
144 std::vector
<installer_test::InstalledProduct
> installed
;
145 if (GetInstalledProducts(&installed
)) {
146 for (size_t i
= 0; i
< installed
.size(); ++i
) {
147 if ((installed
[i
].type
& product
) != 0) {
148 return installed
[i
].version
;
155 bool Install(const base::FilePath
& installer
) {
156 if (!base::PathExists(installer
)) {
157 LOG(ERROR
) << "Installer does not exist: " << installer
.MaybeAsASCII();
160 CommandLine
command(installer
);
161 LOG(INFO
) << "Running installer command: "
162 << command
.GetCommandLineString();
163 return installer_test::RunAndWaitForCommandToFinish(command
);
166 bool Install(const base::FilePath
& installer
, const SwitchBuilder
& switches
) {
167 if (!base::PathExists(installer
)) {
168 LOG(ERROR
) << "Installer does not exist: " << installer
.MaybeAsASCII();
171 CommandLine
command(installer
);
172 command
.AppendArguments(switches
.GetSwitches(), false);
173 LOG(INFO
) << "Running installer command: "
174 << command
.GetCommandLineString();
175 return installer_test::RunAndWaitForCommandToFinish(command
);
178 bool LaunchChrome(bool close_after_launch
, bool system_level
) {
179 base::CleanupProcesses(installer::kChromeExe
, base::TimeDelta(),
180 content::RESULT_CODE_HUNG
, NULL
);
181 base::FilePath install_path
;
182 if (!GetChromeInstallDirectory(
183 system_level
, &install_path
)) {
184 LOG(ERROR
) << "Could not find Chrome install directory";
187 install_path
= install_path
.Append(installer::kChromeExe
);
188 CommandLine
browser(install_path
);
190 base::FilePath exe
= browser
.GetProgram();
191 LOG(INFO
) << "Browser launch command: " << browser
.GetCommandLineString();
192 base::ProcessHandle chrome
;
193 if (!base::LaunchProcess(browser
, base::LaunchOptions(), &chrome
)) {
194 LOG(ERROR
) << "Could not launch process: " << exe
.value();
197 if (close_after_launch
) {
198 if (base::KillProcess(chrome
, 0, true)) {
199 LOG(ERROR
) << "Failed to close chrome.exe after launch.";
206 bool LaunchIE(const std::string
& url
) {
207 base::FilePath browser_path
;
208 PathService::Get(base::DIR_PROGRAM_FILES
, &browser_path
);
209 browser_path
= browser_path
.Append(mini_installer_constants::kIELocation
);
210 browser_path
= browser_path
.Append(mini_installer_constants::kIEProcessName
);
212 CommandLine
cmd_line(browser_path
);
213 cmd_line
.AppendArg(url
);
214 return base::LaunchProcess(cmd_line
, base::LaunchOptions(), NULL
);
217 bool UninstallAll() {
218 base::CleanupProcesses(installer::kChromeExe
, base::TimeDelta(),
219 content::RESULT_CODE_HUNG
, NULL
);
220 base::CleanupProcesses(installer::kChromeFrameHelperExe
, base::TimeDelta(),
221 content::RESULT_CODE_HUNG
, NULL
);
222 std::vector
<installer_test::InstalledProduct
> installed
;
223 if (!GetInstalledProducts(&installed
)) {
224 LOG(WARNING
) << "No installed products to uninstall.";
227 bool ret_val
= false;
228 for (size_t i
= 0; i
< installed
.size(); ++i
) {
229 if (!Uninstall(installed
[i
].system
, installed
[i
].type
))
235 bool Uninstall(bool system_level
,
236 InstallationValidator::InstallationType type
) {
237 std::vector
<BrowserDistribution::Type
> products
;
238 if (ToBrowserDistributionType(type
) !=
239 BrowserDistribution::CHROME_BINARIES
) {
240 products
.push_back(ToBrowserDistributionType(type
));
242 products
.push_back(BrowserDistribution::CHROME_BROWSER
);
243 products
.push_back(BrowserDistribution::CHROME_FRAME
);
245 bool ret_val
= false;
246 for (size_t i
= 0; i
< products
.size(); ++i
) {
247 if (!Uninstall(system_level
, products
[i
]))
253 bool Uninstall(bool system_level
,
254 BrowserDistribution::Type product
) {
255 static const int kMultiMask
=
256 (InstallationValidator::ProductBits::CHROME_MULTI
|
257 InstallationValidator::ProductBits::CHROME_FRAME_MULTI
);
258 CommandLine
uninstall_cmd(InstallUtil::GetChromeUninstallCmd(system_level
,
260 CommandLine::StringType archive
=
261 uninstall_cmd
.GetProgram().DirName().AppendASCII("chrome.7z").value();
262 uninstall_cmd
.AppendSwitch(installer::switches::kUninstall
);
263 uninstall_cmd
.AppendSwitch(installer::switches::kForceUninstall
);
264 uninstall_cmd
.AppendSwitchNative(
265 installer::switches::kInstallArchive
, archive
);
267 uninstall_cmd
.AppendSwitch(installer::switches::kSystemLevel
);
268 if ((product
& kMultiMask
) !=0)
269 uninstall_cmd
.AppendSwitch(installer::switches::kMultiInstall
);
270 LOG(INFO
) << "Uninstall command: " << uninstall_cmd
.GetCommandLineString();
271 bool ret_val
= RunAndWaitForCommandToFinish(uninstall_cmd
);
272 // Close IE notification when uninstalling Chrome Frame.
273 base::CleanupProcesses(mini_installer_constants::kIEProcessName
,
275 content::RESULT_CODE_HUNG
, NULL
);
280 bool RunAndWaitForCommandToFinish(CommandLine command
) {
281 if (!base::PathExists(command
.GetProgram())) {
282 LOG(ERROR
) << "Command executable does not exist: "
283 << command
.GetProgram().MaybeAsASCII();
286 base::ProcessHandle process
;
287 if (!base::LaunchProcess(command
, base::LaunchOptions(), &process
)) {
288 LOG(ERROR
) << "Failed to launch command: "
289 << command
.GetCommandLineString();
292 if (!base::WaitForSingleProcess(process
, base::TimeDelta::FromMinutes(1))) {
293 LOG(ERROR
) << "Launched process did not complete.";