Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: chrome/installer/setup/uninstall.cc

Issue 6288009: More installer refactoring in the interest of fixing some bugs and cleaning t... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/installer/setup/setup_util.cc ('k') | chrome/installer/util/browser_distribution.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file defines the methods useful for uninstalling Chrome. 5 // This file defines the methods useful for uninstalling Chrome.
6 6
7 #include "chrome/installer/setup/uninstall.h" 7 #include "chrome/installer/setup/uninstall.h"
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
(...skipping 11 matching lines...) Expand all
22 #include "chrome/installer/setup/setup_constants.h" 22 #include "chrome/installer/setup/setup_constants.h"
23 #include "chrome/installer/util/browser_distribution.h" 23 #include "chrome/installer/util/browser_distribution.h"
24 #include "chrome/installer/util/channel_info.h" 24 #include "chrome/installer/util/channel_info.h"
25 #include "chrome/installer/util/delete_after_reboot_helper.h" 25 #include "chrome/installer/util/delete_after_reboot_helper.h"
26 #include "chrome/installer/util/google_update_constants.h" 26 #include "chrome/installer/util/google_update_constants.h"
27 #include "chrome/installer/util/helper.h" 27 #include "chrome/installer/util/helper.h"
28 #include "chrome/installer/util/install_util.h" 28 #include "chrome/installer/util/install_util.h"
29 #include "chrome/installer/util/installation_state.h" 29 #include "chrome/installer/util/installation_state.h"
30 #include "chrome/installer/util/installer_state.h" 30 #include "chrome/installer/util/installer_state.h"
31 #include "chrome/installer/util/logging_installer.h" 31 #include "chrome/installer/util/logging_installer.h"
32 #include "chrome/installer/util/package_properties.h"
33 #include "chrome/installer/util/shell_util.h" 32 #include "chrome/installer/util/shell_util.h"
34 #include "chrome/installer/util/util_constants.h" 33 #include "chrome/installer/util/util_constants.h"
35 34
36 // Build-time generated include file. 35 // Build-time generated include file.
37 #include "registered_dlls.h" // NOLINT 36 #include "registered_dlls.h" // NOLINT
38 37
39 using base::win::RegKey; 38 using base::win::RegKey;
40 using installer::InstallStatus; 39 using installer::InstallStatus;
40 using installer::MasterPreferences;
41 41
42 namespace { 42 namespace {
43 43
44 // Makes appropriate changes to the Google Update "ap" value in the registry. 44 // Makes appropriate changes to the Google Update "ap" value in the registry.
45 // Specifically, removes the flags associated with this product ("-chrome" or 45 // Specifically, removes the flags associated with this product ("-chrome" or
46 // "-chromeframe[-CEEE][-readymode]") from the "ap" values for all other 46 // "-chromeframe[-CEEE][-readymode]") from the "ap" values for all other
47 // installed products and for the multi-installer package. 47 // installed products and for the multi-installer package.
48 void ProcessGoogleUpdateItems( 48 void ProcessGoogleUpdateItems(
49 const installer::InstallationState& original_state, 49 const installer::InstallationState& original_state,
50 const installer::InstallerState& installer_state,
50 const installer::Product& product) { 51 const installer::Product& product) {
51 const bool system_level = product.system_level(); 52 DCHECK(installer_state.is_multi_install());
53 const bool system_level = installer_state.system_install();
52 BrowserDistribution* distribution = product.distribution(); 54 BrowserDistribution* distribution = product.distribution();
53 const HKEY reg_root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 55 const HKEY reg_root = installer_state.root_key();
54 const installer::ProductState* product_state = 56 const installer::ProductState* product_state =
55 original_state.GetProductState(system_level, distribution->GetType()); 57 original_state.GetProductState(system_level, distribution->GetType());
56 DCHECK(product_state != NULL); 58 DCHECK(product_state != NULL);
57 installer::ChannelInfo channel_info; 59 installer::ChannelInfo channel_info;
58 60
59 // Remove product's flags from the channel value. 61 // Remove product's flags from the channel value.
60 channel_info.set_value(product_state->channel().value()); 62 channel_info.set_value(product_state->channel().value());
61 const bool modified = distribution->SetChannelFlags(false, &channel_info); 63 const bool modified = product.SetChannelFlags(false, &channel_info);
62 64
63 // Apply the new channel value to all other products and to the multi package. 65 // Apply the new channel value to all other products and to the multi package.
64 if (modified) { 66 if (modified) {
65 BrowserDistribution::Type other_dist_type = 67 BrowserDistribution::Type other_dist_types[] = {
66 (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) ? 68 (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) ?
67 BrowserDistribution::CHROME_FRAME : 69 BrowserDistribution::CHROME_FRAME :
68 BrowserDistribution::CHROME_BROWSER; 70 BrowserDistribution::CHROME_BROWSER,
69 BrowserDistribution* other_dist = 71 BrowserDistribution::CHROME_BINARIES
70 BrowserDistribution::GetSpecificDistribution(other_dist_type, 72 };
71 installer::MasterPreferences::ForCurrentProcess());
72 scoped_ptr<WorkItemList> 73 scoped_ptr<WorkItemList>
73 update_list(WorkItem::CreateNoRollbackWorkItemList()); 74 update_list(WorkItem::CreateNoRollbackWorkItemList());
74 75
75 product_state = original_state.GetProductState(system_level, 76 for (int i = 0; i < arraysize(other_dist_types); ++i) {
76 other_dist_type); 77 BrowserDistribution::Type other_dist_type = other_dist_types[i];
77 if (installer::IsInstalledAsMulti(system_level, other_dist) && 78 product_state =
78 !product_state->channel().Equals(channel_info)) { 79 original_state.GetProductState(system_level, other_dist_type);
79 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(), 80 // Only modify other products if they're installed and multi.
80 google_update::kRegApField, channel_info.value(), true); 81 if (product_state != NULL &&
81 } else { 82 product_state->is_multi_install() &&
82 VLOG(1) << other_dist->GetApplicationName() 83 !product_state->channel().Equals(channel_info)) {
83 << "'s ap value is unexpectedly up to date."; 84 BrowserDistribution* other_dist =
84 } 85 BrowserDistribution::GetSpecificDistribution(other_dist_type);
85 86 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
86 product_state = original_state.GetMultiPackageState(system_level); 87 google_update::kRegApField, channel_info.value(), true);
87 DCHECK(product_state != NULL); 88 } else {
88 if (!product_state->channel().Equals(channel_info)) { 89 LOG_IF(DFATAL,
89 update_list->AddSetRegValueWorkItem(reg_root, 90 product_state != NULL && product_state->is_multi_install())
90 product.package().properties()->GetStateKey(), 91 << "Channel value for "
91 google_update::kRegApField, channel_info.value(), true); 92 << BrowserDistribution::GetSpecificDistribution(
92 } else { 93 other_dist_type)->GetAppShortCutName()
93 VLOG(1) << "Multi-install package's ap value is unexpectedly up to date."; 94 << " is somehow already set to the desired new value of "
95 << channel_info.value();
96 }
94 } 97 }
95 98
96 bool success = update_list->Do(); 99 bool success = update_list->Do();
97 LOG_IF(ERROR, !success) << "Failed updating channel values."; 100 LOG_IF(ERROR, !success) << "Failed updating channel values.";
98 } 101 }
99 } 102 }
100 103
101 } // namespace 104 } // namespace
102 105
103 namespace installer { 106 namespace installer {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing."; 171 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing.";
169 base::CleanupProcesses(installer::kChromeFrameHelperExe, 0, 172 base::CleanupProcesses(installer::kChromeFrameHelperExe, 0,
170 ResultCodes::HUNG, NULL); 173 ResultCodes::HUNG, NULL);
171 } 174 }
172 } 175 }
173 176
174 // This method tries to figure out if current user has registered Chrome. 177 // This method tries to figure out if current user has registered Chrome.
175 // It returns true iff: 178 // It returns true iff:
176 // - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value. 179 // - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value.
177 // - The value is same as chrome.exe path for the current installation. 180 // - The value is same as chrome.exe path for the current installation.
178 bool CurrentUserHasDefaultBrowser(const Product& product) { 181 bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state,
182 const Product& product) {
179 std::wstring reg_key(ShellUtil::kRegStartMenuInternet); 183 std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
180 reg_key.append(L"\\" + product.distribution()->GetApplicationName() + 184 reg_key.append(1, L'\\')
181 ShellUtil::kRegShellOpen); 185 .append(product.distribution()->GetApplicationName())
186 .append(ShellUtil::kRegShellOpen);
182 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ); 187 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
183 std::wstring reg_exe; 188 std::wstring reg_exe;
184 if (key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS && reg_exe.length() > 2) { 189 if (key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS && reg_exe.length() > 2) {
185 FilePath chrome_exe(product.package().path() 190 FilePath chrome_exe(installer_state.target_path()
186 .Append(installer::kChromeExe)); 191 .Append(installer::kChromeExe));
187 // The path in the registry will always have quotes. 192 // The path in the registry will always have quotes.
188 reg_exe = reg_exe.substr(1, reg_exe.length() - 2); 193 reg_exe = reg_exe.substr(1, reg_exe.length() - 2);
189 if (FilePath::CompareEqualIgnoreCase(reg_exe, chrome_exe.value())) 194 if (FilePath::CompareEqualIgnoreCase(reg_exe, chrome_exe.value()))
190 return true; 195 return true;
191 } 196 }
192 197
193 return false; 198 return false;
194 } 199 }
195 200
196 // This method deletes Chrome shortcut folder from Windows Start menu. It 201 // This method deletes Chrome shortcut folder from Windows Start menu. It
197 // checks system_uninstall to see if the shortcut is in all users start menu 202 // checks system_uninstall to see if the shortcut is in all users start menu
198 // or current user start menu. 203 // or current user start menu.
199 // We try to remove the standard desktop shortcut but if that fails we try 204 // We try to remove the standard desktop shortcut but if that fails we try
200 // to remove the alternate desktop shortcut. Only one of them should be 205 // to remove the alternate desktop shortcut. Only one of them should be
201 // present in a given install but at this point we don't know which one. 206 // present in a given install but at this point we don't know which one.
202 void DeleteChromeShortcuts(const Product& product) { 207 void DeleteChromeShortcuts(const InstallerState& installer_state,
208 const Product& product) {
203 if (!product.is_chrome()) { 209 if (!product.is_chrome()) {
204 VLOG(1) << __FUNCTION__ " called for non-CHROME distribution"; 210 VLOG(1) << __FUNCTION__ " called for non-CHROME distribution";
205 return; 211 return;
206 } 212 }
207 213
208 FilePath shortcut_path; 214 FilePath shortcut_path;
209 if (product.system_level()) { 215 if (installer_state.system_install()) {
210 PathService::Get(base::DIR_COMMON_START_MENU, &shortcut_path); 216 PathService::Get(base::DIR_COMMON_START_MENU, &shortcut_path);
211 if (!ShellUtil::RemoveChromeDesktopShortcut(product.distribution(), 217 if (!ShellUtil::RemoveChromeDesktopShortcut(product.distribution(),
212 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, false)) { 218 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, false)) {
213 ShellUtil::RemoveChromeDesktopShortcut(product.distribution(), 219 ShellUtil::RemoveChromeDesktopShortcut(product.distribution(),
214 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, true); 220 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, true);
215 } 221 }
216 222
217 ShellUtil::RemoveChromeQuickLaunchShortcut(product.distribution(), 223 ShellUtil::RemoveChromeQuickLaunchShortcut(product.distribution(),
218 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL); 224 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL);
219 } else { 225 } else {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 331
326 if (result == DELETE_REQUIRES_REBOOT) { 332 if (result == DELETE_REQUIRES_REBOOT) {
327 ScheduleParentAndGrandparentForDeletion(user_local_state); 333 ScheduleParentAndGrandparentForDeletion(user_local_state);
328 } else { 334 } else {
329 DeleteEmptyParentDir(user_local_state); 335 DeleteEmptyParentDir(user_local_state);
330 } 336 }
331 337
332 return result; 338 return result;
333 } 339 }
334 340
335 bool MoveSetupOutOfInstallFolder(const Package& package, 341 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
336 const FilePath& setup_path, 342 const FilePath& setup_path,
337 const Version& installed_version) { 343 const Version& installed_version) {
338 bool ret = false; 344 bool ret = false;
339 FilePath setup_exe(package.GetInstallerDirectory(installed_version) 345 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version)
340 .Append(setup_path.BaseName())); 346 .Append(setup_path.BaseName()));
341 FilePath temp_file; 347 FilePath temp_file;
342 if (!file_util::CreateTemporaryFile(&temp_file)) { 348 if (!file_util::CreateTemporaryFile(&temp_file)) {
343 LOG(ERROR) << "Failed to create temporary file for setup.exe."; 349 LOG(ERROR) << "Failed to create temporary file for setup.exe.";
344 } else { 350 } else {
345 VLOG(1) << "Attempting to move setup to: " << temp_file.value(); 351 VLOG(1) << "Attempting to move setup to: " << temp_file.value();
346 ret = file_util::Move(setup_exe, temp_file); 352 ret = file_util::Move(setup_exe, temp_file);
347 LOG_IF(ERROR, !ret) << "Failed to move setup to " << temp_file.value(); 353 LOG_IF(ERROR, !ret) << "Failed to move setup to " << temp_file.value();
348 } 354 }
349 return ret; 355 return ret;
350 } 356 }
351 357
352 DeleteResult DeleteFilesAndFolders(const Package& package, 358 DeleteResult DeleteFilesAndFolders(const InstallerState& installer_state,
353 const Version& installed_version) { 359 const Version& installed_version) {
354 VLOG(1) << "DeleteFilesAndFolders: " << package.path().value(); 360 VLOG(1) << "DeleteFilesAndFolders: " << installer_state.target_path().value();
355 if (package.path().empty()) { 361 if (installer_state.target_path().empty()) {
356 LOG(ERROR) << "Could not get installation destination path."; 362 LOG(ERROR) << "Could not get installation destination path.";
357 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. 363 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return.
358 } 364 }
359 365
360 DeleteResult result = DELETE_SUCCEEDED; 366 DeleteResult result = DELETE_SUCCEEDED;
361 367
362 VLOG(1) << "Deleting install path " << package.path().value(); 368 VLOG(1) << "Deleting install path " << installer_state.target_path().value();
363 if (!file_util::Delete(package.path(), true)) { 369 if (!file_util::Delete(installer_state.target_path(), true)) {
364 LOG(ERROR) << "Failed to delete folder (1st try): " 370 LOG(ERROR) << "Failed to delete folder (1st try): "
365 << package.path().value(); 371 << installer_state.target_path().value();
366 if (FindProduct(package.products(), 372 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
367 BrowserDistribution::CHROME_FRAME)) {
368 // We don't try killing Chrome processes for Chrome Frame builds since 373 // We don't try killing Chrome processes for Chrome Frame builds since
369 // that is unlikely to help. Instead, schedule files for deletion and 374 // that is unlikely to help. Instead, schedule files for deletion and
370 // return a value that will trigger a reboot prompt. 375 // return a value that will trigger a reboot prompt.
371 ScheduleDirectoryForDeletion(package.path().value().c_str()); 376 ScheduleDirectoryForDeletion(
377 installer_state.target_path().value().c_str());
372 result = DELETE_REQUIRES_REBOOT; 378 result = DELETE_REQUIRES_REBOOT;
373 } else { 379 } else {
374 // Try closing any running chrome processes and deleting files once again. 380 // Try closing any running chrome processes and deleting files once again.
375 CloseAllChromeProcesses(); 381 CloseAllChromeProcesses();
376 if (!file_util::Delete(package.path(), true)) { 382 if (!file_util::Delete(installer_state.target_path(), true)) {
377 LOG(ERROR) << "Failed to delete folder (2nd try): " 383 LOG(ERROR) << "Failed to delete folder (2nd try): "
378 << package.path().value(); 384 << installer_state.target_path().value();
379 result = DELETE_FAILED; 385 result = DELETE_FAILED;
380 } 386 }
381 } 387 }
382 } 388 }
383 389
384 if (result == DELETE_REQUIRES_REBOOT) { 390 if (result == DELETE_REQUIRES_REBOOT) {
385 // If we need a reboot to continue, schedule the parent directories for 391 // If we need a reboot to continue, schedule the parent directories for
386 // deletion unconditionally. If they are not empty, the session manager 392 // deletion unconditionally. If they are not empty, the session manager
387 // will not delete them on reboot. 393 // will not delete them on reboot.
388 ScheduleParentAndGrandparentForDeletion(package.path()); 394 ScheduleParentAndGrandparentForDeletion(installer_state.target_path());
389 } else { 395 } else {
390 // Now check and delete if the parent directories are empty 396 // Now check and delete if the parent directories are empty
391 // For example Google\Chrome or Chromium 397 // For example Google\Chrome or Chromium
392 DeleteEmptyParentDir(package.path()); 398 DeleteEmptyParentDir(installer_state.target_path());
393 } 399 }
394 return result; 400 return result;
395 } 401 }
396 402
397 // This method checks if Chrome is currently running or if the user has 403 // This method checks if Chrome is currently running or if the user has
398 // cancelled the uninstall operation by clicking Cancel on the confirmation 404 // cancelled the uninstall operation by clicking Cancel on the confirmation
399 // box that Chrome pops up. 405 // box that Chrome pops up.
400 InstallStatus IsChromeActiveOrUserCancelled(const Product& product) { 406 InstallStatus IsChromeActiveOrUserCancelled(
407 const InstallerState& installer_state,
408 const Product& product) {
401 int32 exit_code = ResultCodes::NORMAL_EXIT; 409 int32 exit_code = ResultCodes::NORMAL_EXIT;
402 CommandLine options(CommandLine::NO_PROGRAM); 410 CommandLine options(CommandLine::NO_PROGRAM);
403 options.AppendSwitch(installer::switches::kUninstall); 411 options.AppendSwitch(installer::switches::kUninstall);
404 412
405 // Here we want to save user from frustration (in case of Chrome crashes) 413 // Here we want to save user from frustration (in case of Chrome crashes)
406 // and continue with the uninstallation as long as chrome.exe process exit 414 // and continue with the uninstallation as long as chrome.exe process exit
407 // code is NOT one of the following: 415 // code is NOT one of the following:
408 // - UNINSTALL_CHROME_ALIVE - chrome.exe is currently running 416 // - UNINSTALL_CHROME_ALIVE - chrome.exe is currently running
409 // - UNINSTALL_USER_CANCEL - User cancelled uninstallation 417 // - UNINSTALL_USER_CANCEL - User cancelled uninstallation
410 // - HUNG - chrome.exe was killed by HuntForZombieProcesses() (until we can 418 // - HUNG - chrome.exe was killed by HuntForZombieProcesses() (until we can
411 // give this method some brains and not kill chrome.exe launched 419 // give this method some brains and not kill chrome.exe launched
412 // by us, we will not uninstall if we get this return code). 420 // by us, we will not uninstall if we get this return code).
413 VLOG(1) << "Launching Chrome to do uninstall tasks."; 421 VLOG(1) << "Launching Chrome to do uninstall tasks.";
414 if (product.LaunchChromeAndWait(options, &exit_code)) { 422 if (product.LaunchChromeAndWait(installer_state.target_path(), options,
423 &exit_code)) {
415 VLOG(1) << "chrome.exe launched for uninstall confirmation returned: " 424 VLOG(1) << "chrome.exe launched for uninstall confirmation returned: "
416 << exit_code; 425 << exit_code;
417 if ((exit_code == ResultCodes::UNINSTALL_CHROME_ALIVE) || 426 if ((exit_code == ResultCodes::UNINSTALL_CHROME_ALIVE) ||
418 (exit_code == ResultCodes::UNINSTALL_USER_CANCEL) || 427 (exit_code == ResultCodes::UNINSTALL_USER_CANCEL) ||
419 (exit_code == ResultCodes::HUNG)) 428 (exit_code == ResultCodes::HUNG))
420 return installer::UNINSTALL_CANCELLED; 429 return installer::UNINSTALL_CANCELLED;
421 430
422 if (exit_code == ResultCodes::UNINSTALL_DELETE_PROFILE) 431 if (exit_code == ResultCodes::UNINSTALL_DELETE_PROFILE)
423 return installer::UNINSTALL_DELETE_PROFILE; 432 return installer::UNINSTALL_DELETE_PROFILE;
424 } else { 433 } else {
425 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; 434 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation.";
426 } 435 }
427 436
428 return installer::UNINSTALL_CONFIRMED; 437 return installer::UNINSTALL_CONFIRMED;
429 } 438 }
430 439
431 bool ShouldDeleteProfile(const CommandLine& cmd_line, InstallStatus status, 440 bool ShouldDeleteProfile(const InstallerState& installer_state,
441 const CommandLine& cmd_line, InstallStatus status,
432 const Product& product) { 442 const Product& product) {
433 bool should_delete = false; 443 bool should_delete = false;
434 444
435 // Chrome Frame uninstallations always want to delete the profile (we have no 445 // Chrome Frame uninstallations always want to delete the profile (we have no
436 // UI to prompt otherwise and the profile stores no useful data anyway) 446 // UI to prompt otherwise and the profile stores no useful data anyway)
437 // unless they are managed by MSI. MSI uninstalls will explicitly include 447 // unless they are managed by MSI. MSI uninstalls will explicitly include
438 // the --delete-profile flag to distinguish them from MSI upgrades. 448 // the --delete-profile flag to distinguish them from MSI upgrades.
439 if (!product.is_chrome() && !product.IsMsi()) { 449 if (!product.is_chrome() && !installer_state.is_msi()) {
440 should_delete = true; 450 should_delete = true;
441 } else { 451 } else {
442 should_delete = 452 should_delete =
443 status == installer::UNINSTALL_DELETE_PROFILE || 453 status == installer::UNINSTALL_DELETE_PROFILE ||
444 cmd_line.HasSwitch(installer::switches::kDeleteProfile); 454 cmd_line.HasSwitch(installer::switches::kDeleteProfile);
445 } 455 }
446 456
447 return should_delete; 457 return should_delete;
448 } 458 }
449 459
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 InstallUtil::DeleteRegistryKey(key, ext_prog_id); 545 InstallUtil::DeleteRegistryKey(key, ext_prog_id);
536 546
537 // Delete Software\Classes\.crx, 547 // Delete Software\Classes\.crx,
538 std::wstring ext_association(ShellUtil::kRegClasses); 548 std::wstring ext_association(ShellUtil::kRegClasses);
539 ext_association.append(L"\\"); 549 ext_association.append(L"\\");
540 ext_association.append(chrome::kExtensionFileExtension); 550 ext_association.append(chrome::kExtensionFileExtension);
541 InstallUtil::DeleteRegistryKey(key, ext_association); 551 InstallUtil::DeleteRegistryKey(key, ext_association);
542 } 552 }
543 } 553 }
544 554
545 bool ProcessChromeFrameWorkItems(const FilePath& setup_path, 555 bool ProcessChromeFrameWorkItems(const InstallationState& original_state,
546 const Product& product, 556 const InstallerState& installer_state,
547 const ProductState* product_state) { 557 const FilePath& setup_path,
558 const Product& product) {
548 if (!product.is_chrome_frame()) 559 if (!product.is_chrome_frame())
549 return false; 560 return false;
550 561
551 DCHECK(product_state != NULL);
552 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList()); 562 scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
553 AddChromeFrameWorkItems(false, setup_path, product_state->version(), product, 563 AddChromeFrameWorkItems(original_state, installer_state, setup_path,
554 item_list.get()); 564 Version(), product, item_list.get());
555 return item_list->Do(); 565 return item_list->Do();
556 } 566 }
557 567
558 InstallStatus UninstallProduct(const InstallationState& original_state, 568 InstallStatus UninstallProduct(const InstallationState& original_state,
559 const InstallerState& installer_state, 569 const InstallerState& installer_state,
560 const FilePath& setup_path, 570 const FilePath& setup_path,
561 const Product& product, 571 const Product& product,
562 bool remove_all, 572 bool remove_all,
563 bool force_uninstall, 573 bool force_uninstall,
564 const CommandLine& cmd_line) { 574 const CommandLine& cmd_line) {
565 InstallStatus status = installer::UNINSTALL_CONFIRMED; 575 InstallStatus status = installer::UNINSTALL_CONFIRMED;
566 std::wstring suffix; 576 std::wstring suffix;
567 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(), 577 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(),
568 &suffix)) 578 &suffix))
569 suffix = L""; 579 suffix = L"";
570 580
571 BrowserDistribution* browser_dist = product.distribution(); 581 BrowserDistribution* browser_dist = product.distribution();
572 bool is_chrome = product.is_chrome(); 582 bool is_chrome = product.is_chrome();
573 583
574 VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName(); 584 VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName();
575 585
576 if (force_uninstall) { 586 if (force_uninstall) {
577 // Since --force-uninstall command line option is used, we are going to 587 // Since --force-uninstall command line option is used, we are going to
578 // do silent uninstall. Try to close all running Chrome instances. 588 // do silent uninstall. Try to close all running Chrome instances.
579 // NOTE: We don't do this for Chrome Frame or CEEE. 589 // NOTE: We don't do this for Chrome Frame or CEEE.
580 if (is_chrome) 590 if (is_chrome)
581 CloseAllChromeProcesses(); 591 CloseAllChromeProcesses();
582 } else if (is_chrome) { 592 } else if (is_chrome) {
583 // no --force-uninstall so lets show some UI dialog boxes. 593 // no --force-uninstall so lets show some UI dialog boxes.
584 status = IsChromeActiveOrUserCancelled(product); 594 status = IsChromeActiveOrUserCancelled(installer_state, product);
585 if (status != installer::UNINSTALL_CONFIRMED && 595 if (status != installer::UNINSTALL_CONFIRMED &&
586 status != installer::UNINSTALL_DELETE_PROFILE) 596 status != installer::UNINSTALL_DELETE_PROFILE)
587 return status; 597 return status;
588 598
589 // Check if we need admin rights to cleanup HKLM. If we do, try to launch 599 // Check if we need admin rights to cleanup HKLM. If we do, try to launch
590 // another uninstaller (silent) in elevated mode to do HKLM cleanup. 600 // another uninstaller (silent) in elevated mode to do HKLM cleanup.
591 // And continue uninstalling in the current process also to do HKCU cleanup. 601 // And continue uninstalling in the current process also to do HKCU cleanup.
592 if (remove_all && 602 if (remove_all &&
593 (!suffix.empty() || CurrentUserHasDefaultBrowser(product)) && 603 (!suffix.empty() ||
604 CurrentUserHasDefaultBrowser(installer_state, product)) &&
594 !::IsUserAnAdmin() && 605 !::IsUserAnAdmin() &&
595 base::win::GetVersion() >= base::win::VERSION_VISTA && 606 base::win::GetVersion() >= base::win::VERSION_VISTA &&
596 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { 607 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) {
597 CommandLine new_cmd(CommandLine::NO_PROGRAM); 608 CommandLine new_cmd(CommandLine::NO_PROGRAM);
598 new_cmd.AppendArguments(cmd_line, true); 609 new_cmd.AppendArguments(cmd_line, true);
599 // Append --run-as-admin flag to let the new instance of setup.exe know 610 // Append --run-as-admin flag to let the new instance of setup.exe know
600 // that we already tried to launch ourselves as admin. 611 // that we already tried to launch ourselves as admin.
601 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); 612 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin);
602 // Append --remove-chrome-registration to remove registry keys only. 613 // Append --remove-chrome-registration to remove registry keys only.
603 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); 614 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration);
604 if (!suffix.empty()) { 615 if (!suffix.empty()) {
605 new_cmd.AppendSwitchNative( 616 new_cmd.AppendSwitchNative(
606 installer::switches::kRegisterChromeBrowserSuffix, suffix); 617 installer::switches::kRegisterChromeBrowserSuffix, suffix);
607 } 618 }
608 DWORD exit_code = installer::UNKNOWN_STATUS; 619 DWORD exit_code = installer::UNKNOWN_STATUS;
609 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); 620 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code);
610 } 621 }
611 } 622 }
612 623
613 // Chrome is not in use so lets uninstall Chrome by deleting various files 624 // Chrome is not in use so lets uninstall Chrome by deleting various files
614 // and registry entries. Here we will just make best effort and keep going 625 // and registry entries. Here we will just make best effort and keep going
615 // in case of errors. 626 // in case of errors.
616 627
617 // First delete shortcuts from Start->Programs, Desktop & Quick Launch. 628 // First delete shortcuts from Start->Programs, Desktop & Quick Launch.
618 DeleteChromeShortcuts(product); 629 DeleteChromeShortcuts(installer_state, product);
619 630
620 // Delete the registry keys (Uninstall key and Version key). 631 // Delete the registry keys (Uninstall key and Version key).
621 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : 632 HKEY reg_root = installer_state.root_key();
622 HKEY_CURRENT_USER;
623 RegKey key(reg_root, L"", KEY_ALL_ACCESS); 633 RegKey key(reg_root, L"", KEY_ALL_ACCESS);
624 634
625 // Note that we must retrieve the distribution-specific data before deleting 635 // Note that we must retrieve the distribution-specific data before deleting
626 // product.GetVersionKey(). 636 // product.GetVersionKey().
627 std::wstring distribution_data(browser_dist->GetDistributionData(reg_root)); 637 std::wstring distribution_data(browser_dist->GetDistributionData(reg_root));
628 638
629 // Remove Control Panel uninstall link and Omaha product key. 639 // Remove Control Panel uninstall link and Omaha product key.
630 InstallUtil::DeleteRegistryKey(key, browser_dist->GetUninstallRegPath()); 640 InstallUtil::DeleteRegistryKey(key, browser_dist->GetUninstallRegPath());
631 InstallUtil::DeleteRegistryKey(key, browser_dist->GetVersionKey()); 641 InstallUtil::DeleteRegistryKey(key, browser_dist->GetVersionKey());
632 642
633 // Also try to delete the MSI value in the ClientState key (it might not be 643 // Also try to delete the MSI value in the ClientState key (it might not be
634 // there). This is due to a Google Update behaviour where an uninstall and a 644 // there). This is due to a Google Update behaviour where an uninstall and a
635 // rapid reinstall might result in stale values from the old ClientState key 645 // rapid reinstall might result in stale values from the old ClientState key
636 // being picked up on reinstall. 646 // being picked up on reinstall.
637 product.SetMsiMarker(false); 647 product.SetMsiMarker(installer_state.system_install(), false);
638 648
639 // Remove all Chrome registration keys. 649 // Remove all Chrome registration keys.
640 InstallStatus ret = installer::UNKNOWN_STATUS; 650 InstallStatus ret = installer::UNKNOWN_STATUS;
641 DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret); 651 DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret);
642 652
653 if (!is_chrome) {
654 ProcessChromeFrameWorkItems(original_state, installer_state, setup_path,
655 product);
656 }
657
658 if (installer_state.is_multi_install())
659 ProcessGoogleUpdateItems(original_state, installer_state, product);
660
661 // For user level install also we end up creating some keys in HKLM if user
662 // sets Chrome as default browser. So delete those as well (needs admin).
663 if (remove_all && !installer_state.system_install() &&
664 (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state,
665 product))) {
666 DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE,
667 suffix, ret);
668 }
669
643 // Get the state of the installed product (if any) 670 // Get the state of the installed product (if any)
644 const ProductState* product_state = 671 const ProductState* product_state =
645 original_state.GetProductState(installer_state.system_install(), 672 original_state.GetProductState(installer_state.system_install(),
646 browser_dist->GetType()); 673 browser_dist->GetType());
647 674
648 if (!is_chrome)
649 ProcessChromeFrameWorkItems(setup_path, product, product_state);
650
651 if (product.package().multi_install())
652 ProcessGoogleUpdateItems(original_state, product);
653
654 // For user level install also we end up creating some keys in HKLM if user
655 // sets Chrome as default browser. So delete those as well (needs admin).
656 if (remove_all && !product.system_level() &&
657 (!suffix.empty() || CurrentUserHasDefaultBrowser(product))) {
658 DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE,
659 suffix, ret);
660 }
661
662 // Delete shared registry keys as well (these require admin rights) if 675 // Delete shared registry keys as well (these require admin rights) if
663 // remove_all option is specified. 676 // remove_all option is specified.
664 if (remove_all) { 677 if (remove_all) {
665 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { 678 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) {
666 // Delete media player registry key that exists only in HKLM. 679 // Delete media player registry key that exists only in HKLM.
667 // We don't delete this key in SxS uninstall or Chrome Frame uninstall 680 // We don't delete this key in SxS uninstall or Chrome Frame uninstall
668 // as we never set the key for those products. 681 // as we never set the key for those products.
669 RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS); 682 RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS);
670 std::wstring reg_path(installer::kMediaPlayerRegPath); 683 std::wstring reg_path(installer::kMediaPlayerRegPath);
671 file_util::AppendToPath(&reg_path, installer::kChromeExe); 684 file_util::AppendToPath(&reg_path, installer::kChromeExe);
672 InstallUtil::DeleteRegistryKey(hklm_key, reg_path); 685 InstallUtil::DeleteRegistryKey(hklm_key, reg_path);
673 } 686 }
674 687
675 // Unregister any dll servers that we may have registered for this 688 // Unregister any dll servers that we may have registered for this
676 // product. 689 // product.
677 if (product_state != NULL) { 690 if (product_state != NULL) {
678 std::vector<FilePath> com_dll_list(browser_dist->GetComDllList()); 691 std::vector<FilePath> com_dll_list;
679 FilePath dll_folder = product.package().path().Append( 692 product.AddComDllList(&com_dll_list);
693 FilePath dll_folder = installer_state.target_path().Append(
680 UTF8ToWide(product_state->version().GetString())); 694 UTF8ToWide(product_state->version().GetString()));
681 695
682 scoped_ptr<WorkItemList> unreg_work_item_list( 696 scoped_ptr<WorkItemList> unreg_work_item_list(
683 WorkItem::CreateWorkItemList()); 697 WorkItem::CreateWorkItemList());
684 698
685 699
686 AddRegisterComDllWorkItems(dll_folder, 700 AddRegisterComDllWorkItems(dll_folder,
687 com_dll_list, 701 com_dll_list,
688 product.system_level(), 702 installer_state.system_install(),
689 false, // Unregister 703 false, // Unregister
690 true, // May fail 704 true, // May fail
691 unreg_work_item_list.get()); 705 unreg_work_item_list.get());
692 unreg_work_item_list->Do(); 706 unreg_work_item_list->Do();
693 } 707 }
694 } 708 }
695 709
696 // Close any Chrome Frame helper processes that may be running. 710 // Close any Chrome Frame helper processes that may be running.
697 if (product.is_chrome_frame()) { 711 if (product.is_chrome_frame()) {
698 VLOG(1) << "Closing the Chrome Frame helper process"; 712 VLOG(1) << "Closing the Chrome Frame helper process";
699 CloseChromeFrameHelperProcess(); 713 CloseChromeFrameHelperProcess();
700 } 714 }
701 715
702 if (product_state == NULL) 716 if (product_state == NULL)
703 return installer::UNINSTALL_SUCCESSFUL; 717 return installer::UNINSTALL_SUCCESSFUL;
704 718
705 // Finally delete all the files from Chrome folder after moving setup.exe 719 // Finally delete all the files from Chrome folder after moving setup.exe
706 // and the user's Local State to a temp location. 720 // and the user's Local State to a temp location.
707 bool delete_profile = ShouldDeleteProfile(cmd_line, status, product); 721 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status,
722 product);
708 ret = installer::UNINSTALL_SUCCESSFUL; 723 ret = installer::UNINSTALL_SUCCESSFUL;
709 724
710 // When deleting files, we must make sure that we're either a "single" 725 // When deleting files, we must make sure that we're either a "single"
711 // (aka non-multi) installation or, in the case of multi, that no other 726 // (aka non-multi) installation or, in the case of multi, that no other
712 // "multi" products share the binaries we are about to delete. 727 // "multi" products share the binaries we are about to delete.
713 728
714 bool can_delete_files; 729 bool can_delete_files = true;
715 if (product.package().multi_install()) { 730 if (installer_state.is_multi_install()) {
716 can_delete_files = 731 BrowserDistribution::Type types[] = {
717 (product.package().GetMultiInstallDependencyCount() == 0); 732 BrowserDistribution::CHROME_BROWSER,
733 BrowserDistribution::CHROME_FRAME
734 };
735 ProductState prod_state;
736 for (int i = 0; i < arraysize(types); ++i) {
737 if (prod_state.Initialize(installer_state.system_install(), types[i]) &&
738 prod_state.is_multi_install()) {
739 can_delete_files = false;
740 break;
741 }
742 }
718 LOG(INFO) << (can_delete_files ? "Shared binaries will be deleted." : 743 LOG(INFO) << (can_delete_files ? "Shared binaries will be deleted." :
719 "Shared binaries still in use."); 744 "Shared binaries still in use.");
720 PackageProperties* props = product.package().properties(); 745 if (can_delete_files) {
721 if (can_delete_files && props->ReceivesUpdates()) { 746 BrowserDistribution* multi_dist =
722 InstallUtil::DeleteRegistryKey(key, props->GetVersionKey()); 747 installer_state.multi_package_binaries_distribution();
748 InstallUtil::DeleteRegistryKey(key, multi_dist->GetVersionKey());
723 } 749 }
724 } else {
725 can_delete_files = true;
726 } 750 }
727 751
728 FilePath backup_state_file(BackupLocalStateFile( 752 FilePath backup_state_file(BackupLocalStateFile(
729 GetLocalStateFolder(product))); 753 GetLocalStateFolder(product)));
730 754
731 DeleteResult delete_result = DELETE_SUCCEEDED; 755 DeleteResult delete_result = DELETE_SUCCEEDED;
732 if (can_delete_files) { 756 if (can_delete_files) {
733 // In order to be able to remove the folder in which we're running, we 757 // In order to be able to remove the folder in which we're running, we
734 // need to move setup.exe out of the install folder. 758 // need to move setup.exe out of the install folder.
735 // TODO(tommi): What if the temp folder is on a different volume? 759 // TODO(tommi): What if the temp folder is on a different volume?
736 MoveSetupOutOfInstallFolder(product.package(), setup_path, 760 MoveSetupOutOfInstallFolder(installer_state, setup_path,
737 product_state->version()); 761 product_state->version());
738 delete_result = DeleteFilesAndFolders(product.package(), 762 delete_result = DeleteFilesAndFolders(installer_state,
739 product_state->version()); 763 product_state->version());
740 } 764 }
741 765
742 if (delete_profile) 766 if (delete_profile)
743 DeleteLocalState(product); 767 DeleteLocalState(product);
744 768
745 if (delete_result == DELETE_FAILED) { 769 if (delete_result == DELETE_FAILED) {
746 ret = installer::UNINSTALL_FAILED; 770 ret = installer::UNINSTALL_FAILED;
747 } else if (delete_result == DELETE_REQUIRES_REBOOT) { 771 } else if (delete_result == DELETE_REQUIRES_REBOOT) {
748 ret = installer::UNINSTALL_REQUIRES_REBOOT; 772 ret = installer::UNINSTALL_REQUIRES_REBOOT;
749 } 773 }
750 774
751 if (!force_uninstall) { 775 if (!force_uninstall) {
752 VLOG(1) << "Uninstallation complete. Launching Uninstall survey."; 776 VLOG(1) << "Uninstallation complete. Launching Uninstall survey.";
753 browser_dist->DoPostUninstallOperations(product_state->version(), 777 browser_dist->DoPostUninstallOperations(product_state->version(),
754 backup_state_file, distribution_data); 778 backup_state_file, distribution_data);
755 } 779 }
756 780
757 // Try and delete the preserved local state once the post-install 781 // Try and delete the preserved local state once the post-install
758 // operations are complete. 782 // operations are complete.
759 if (!backup_state_file.empty()) 783 if (!backup_state_file.empty())
760 file_util::Delete(backup_state_file, false); 784 file_util::Delete(backup_state_file, false);
761 785
762 return ret; 786 return ret;
763 } 787 }
764 788
765 } // namespace installer 789 } // namespace installer
766
OLDNEW
« no previous file with comments | « chrome/installer/setup/setup_util.cc ('k') | chrome/installer/util/browser_distribution.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698