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

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

Issue 10665002: Implement installation of the Chrome App Host. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unittests. Created 8 years, 5 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <vector> 9 #include <vector>
10 10
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 42
43 // Build-time generated include file. 43 // Build-time generated include file.
44 #include "registered_dlls.h" // NOLINT 44 #include "registered_dlls.h" // NOLINT
45 45
46 using base::win::RegKey; 46 using base::win::RegKey;
47 using installer::InstallStatus; 47 using installer::InstallStatus;
48 using installer::MasterPreferences; 48 using installer::MasterPreferences;
49 49
50 namespace { 50 namespace {
51 51
52 // Avoid leaving behind a Temp dir. If one exists, ask SelfCleaningTempDir to
53 // clean it up for us. This may involve scheduling it for deletion after
54 // reboot. Don't report that a reboot is required in this case, however.
55 // TODO(erikwright): Shouldn't this still lead to
56 // ScheduleParentAndGrandparentForDeletion?
grt (UTC plus 2) 2012/07/23 11:31:12 i don't understand the question; could you elabora
57 void DeleteInstallTempDir(const FilePath& target_path) {
58 FilePath temp_path(target_path.DirName().Append(installer::kInstallTempDir));
59 if (file_util::DirectoryExists(temp_path)) {
60 installer::SelfCleaningTempDir temp_dir;
61 if (!temp_dir.Initialize(target_path.DirName(),
62 installer::kInstallTempDir) ||
63 !temp_dir.Delete()) {
64 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value();
65 }
66 }
67 }
68
52 // Makes appropriate changes to the Google Update "ap" value in the registry. 69 // Makes appropriate changes to the Google Update "ap" value in the registry.
53 // Specifically, removes the flags associated with this product ("-chrome" or 70 // Specifically, removes the flags associated with this product ("-chrome" or
54 // "-chromeframe[-readymode]") from the "ap" values for all other 71 // "-chromeframe[-readymode]") from the "ap" values for all other
55 // installed products and for the multi-installer package. 72 // installed products and for the multi-installer package.
56 void ProcessGoogleUpdateItems( 73 void ProcessGoogleUpdateItems(
57 const installer::InstallationState& original_state, 74 const installer::InstallationState& original_state,
58 const installer::InstallerState& installer_state, 75 const installer::InstallerState& installer_state,
59 const installer::Product& product) { 76 const installer::Product& product) {
60 DCHECK(installer_state.is_multi_install()); 77 DCHECK(installer_state.is_multi_install());
61 const bool system_level = installer_state.system_install(); 78 const bool system_level = installer_state.system_install();
62 BrowserDistribution* distribution = product.distribution(); 79 BrowserDistribution* distribution = product.distribution();
63 const HKEY reg_root = installer_state.root_key(); 80 const HKEY reg_root = installer_state.root_key();
64 const installer::ProductState* product_state = 81 const installer::ProductState* product_state =
65 original_state.GetProductState(system_level, distribution->GetType()); 82 original_state.GetProductState(system_level, distribution->GetType());
66 DCHECK(product_state != NULL); 83 DCHECK(product_state != NULL);
67 installer::ChannelInfo channel_info; 84 installer::ChannelInfo channel_info;
68 85
69 // Remove product's flags from the channel value. 86 // Remove product's flags from the channel value.
70 channel_info.set_value(product_state->channel().value()); 87 channel_info.set_value(product_state->channel().value());
71 const bool modified = product.SetChannelFlags(false, &channel_info); 88 const bool modified = product.SetChannelFlags(false, &channel_info);
72 89
73 // Apply the new channel value to all other products and to the multi package. 90 // Apply the new channel value to all other products and to the multi package.
74 if (modified) { 91 if (modified) {
75 BrowserDistribution::Type other_dist_types[] = {
76 (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) ?
77 BrowserDistribution::CHROME_FRAME :
78 BrowserDistribution::CHROME_BROWSER,
79 BrowserDistribution::CHROME_BINARIES
80 };
81 scoped_ptr<WorkItemList> 92 scoped_ptr<WorkItemList>
82 update_list(WorkItem::CreateNoRollbackWorkItemList()); 93 update_list(WorkItem::CreateNoRollbackWorkItemList());
83 94
84 for (int i = 0; i < arraysize(other_dist_types); ++i) { 95 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
85 BrowserDistribution::Type other_dist_type = other_dist_types[i]; 96 BrowserDistribution::Type other_dist_type =
97 static_cast<BrowserDistribution::Type>(i);
98 if (distribution->GetType() == other_dist_type)
99 continue;
100
86 product_state = 101 product_state =
87 original_state.GetProductState(system_level, other_dist_type); 102 original_state.GetProductState(system_level, other_dist_type);
88 // Only modify other products if they're installed and multi. 103 // Only modify other products if they're installed and multi.
89 if (product_state != NULL && 104 if (product_state != NULL &&
90 product_state->is_multi_install() && 105 product_state->is_multi_install() &&
91 !product_state->channel().Equals(channel_info)) { 106 !product_state->channel().Equals(channel_info)) {
92 BrowserDistribution* other_dist = 107 BrowserDistribution* other_dist =
93 BrowserDistribution::GetSpecificDistribution(other_dist_type); 108 BrowserDistribution::GetSpecificDistribution(other_dist_type);
94 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(), 109 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
95 google_update::kRegApField, channel_info.value(), true); 110 google_update::kRegApField, channel_info.value(), true);
(...skipping 14 matching lines...) Expand all
110 } 125 }
111 126
112 // Adds or removes the quick-enable-cf command to the binaries' version key in 127 // Adds or removes the quick-enable-cf command to the binaries' version key in
113 // the registry as needed. 128 // the registry as needed.
114 void ProcessQuickEnableWorkItems( 129 void ProcessQuickEnableWorkItems(
115 const installer::InstallerState& installer_state, 130 const installer::InstallerState& installer_state,
116 const installer::InstallationState& machine_state) { 131 const installer::InstallationState& machine_state) {
117 scoped_ptr<WorkItemList> work_item_list( 132 scoped_ptr<WorkItemList> work_item_list(
118 WorkItem::CreateNoRollbackWorkItemList()); 133 WorkItem::CreateNoRollbackWorkItemList());
119 134
120 AddQuickEnableWorkItems(installer_state, machine_state, NULL, NULL, 135 AddQuickEnableChromeFrameWorkItems(installer_state, machine_state, NULL, NULL,
121 work_item_list.get()); 136 work_item_list.get());
137
138 AddQuickEnableApplicationHostWorkItems(installer_state, machine_state, NULL,
139 NULL, work_item_list.get());
122 if (!work_item_list->Do()) 140 if (!work_item_list->Do())
123 LOG(ERROR) << "Failed to update quick-enable-cf command."; 141 LOG(ERROR) << "Failed to update quick-enable-cf command.";
124 } 142 }
125 143
126 void ProcessIELowRightsPolicyWorkItems( 144 void ProcessIELowRightsPolicyWorkItems(
127 const installer::InstallerState& installer_state) { 145 const installer::InstallerState& installer_state) {
128 scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList()); 146 scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList());
129 AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); 147 AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get());
130 work_items->Do(); 148 work_items->Do();
131 installer::RefreshElevationPolicy(); 149 installer::RefreshElevationPolicy();
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 // We cannot delete the file right away, but try to delete it some other 407 // We cannot delete the file right away, but try to delete it some other
390 // way. Either with the help of a different process or the system. 408 // way. Either with the help of a different process or the system.
391 if (ret && !file_util::DeleteAfterReboot(temp_file)) { 409 if (ret && !file_util::DeleteAfterReboot(temp_file)) {
392 static const uint32 kDeleteAfterMs = 10 * 1000; 410 static const uint32 kDeleteAfterMs = 10 * 1000;
393 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); 411 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs);
394 } 412 }
395 } 413 }
396 return ret; 414 return ret;
397 } 415 }
398 416
399 DeleteResult DeleteFilesAndFolders(const InstallerState& installer_state, 417 DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state,
400 const Version& installed_version) { 418 const Version& installed_version) {
401 const FilePath& target_path = installer_state.target_path(); 419 const FilePath& target_path = installer_state.target_path();
402 if (target_path.empty()) { 420 if (target_path.empty()) {
403 LOG(ERROR) << "DeleteFilesAndFolders: no installation destination path."; 421 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination "
422 << "path.";
404 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. 423 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return.
405 } 424 }
406 425
426 DeleteInstallTempDir(target_path);
427
407 DeleteResult result = DELETE_SUCCEEDED; 428 DeleteResult result = DELETE_SUCCEEDED;
408 429
409 // Avoid leaving behind a Temp dir. If one exists, ask SelfCleaningTempDir to 430 FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe));
410 // clean it up for us. This may involve scheduling it for deletion after 431 if (!file_util::Delete(app_host_exe, false)) {
411 // reboot. Don't report that a reboot is required in this case, however. 432 result = DELETE_FAILED;
412 FilePath temp_path(target_path.DirName().Append(kInstallTempDir)); 433 LOG(ERROR) << "Failed to delete path: " << app_host_exe.value();
413 if (file_util::DirectoryExists(temp_path)) { 434 } else {
414 installer::SelfCleaningTempDir temp_dir; 435 DeleteEmptyParentDir(target_path);
415 if (!temp_dir.Initialize(target_path.DirName(), kInstallTempDir) ||
416 !temp_dir.Delete()) {
417 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value();
418 }
419 } 436 }
420 437
421 VLOG(1) << "Deleting install path " << target_path.value(); 438 return result;
422 if (!file_util::Delete(target_path, true)) { 439 }
423 LOG(ERROR) << "Failed to delete folder (1st try): " << target_path.value(); 440
424 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { 441 DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state,
425 // We don't try killing Chrome processes for Chrome Frame builds since 442 const Version& installed_version) {
426 // that is unlikely to help. Instead, schedule files for deletion and 443 const FilePath& target_path = installer_state.target_path();
427 // return a value that will trigger a reboot prompt. 444 if (target_path.empty()) {
428 ScheduleDirectoryForDeletion(target_path.value().c_str()); 445 LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination "
429 result = DELETE_REQUIRES_REBOOT; 446 << "path.";
430 } else { 447 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return.
431 // Try closing any running chrome processes and deleting files once again. 448 }
432 CloseAllChromeProcesses(); 449
433 if (!file_util::Delete(target_path, true)) { 450 DeleteInstallTempDir(target_path);
434 LOG(ERROR) << "Failed to delete folder (2nd try): " 451
435 << target_path.value(); 452 DeleteResult result = DELETE_SUCCEEDED;
436 result = DELETE_FAILED; 453
454 using file_util::FileEnumerator;
455 FileEnumerator file_enumerator(
456 target_path,
457 false,
458 static_cast<FileEnumerator::FileType>(FileEnumerator::FILES |
459 FileEnumerator::DIRECTORIES));
460 while (true) {
461 FilePath to_delete(file_enumerator.Next());
462 if (to_delete.empty())
463 break;
464 if (to_delete.BaseName().value() == installer::kChromeAppHostExe)
465 continue;
466
467 VLOG(1) << "Deleting install path " << target_path.value();
468 if (!file_util::Delete(to_delete, true)) {
469 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value();
470 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
471 // We don't try killing Chrome processes for Chrome Frame builds since
472 // that is unlikely to help. Instead, schedule files for deletion and
473 // return a value that will trigger a reboot prompt.
474 FileEnumerator::FindInfo find_info;
475 file_enumerator.GetFindInfo(&find_info);
476 if (FileEnumerator::IsDirectory(find_info))
477 ScheduleDirectoryForDeletion(to_delete.value().c_str());
478 else
479 ScheduleFileSystemEntityForDeletion(to_delete.value().c_str());
480 result = DELETE_REQUIRES_REBOOT;
481 } else {
482 // Try closing any running Chrome processes and deleting files once
483 // again.
484 CloseAllChromeProcesses();
485 if (!file_util::Delete(to_delete, true)) {
486 LOG(ERROR) << "Failed to delete path (2nd try): "
487 << to_delete.value();
488 result = DELETE_FAILED;
489 break;
490 }
437 } 491 }
438 } 492 }
439 } 493 }
440 494
441 if (result == DELETE_REQUIRES_REBOOT) { 495 if (result == DELETE_REQUIRES_REBOOT) {
442 // If we need a reboot to continue, schedule the parent directories for 496 // If we need a reboot to continue, schedule the parent directories for
443 // deletion unconditionally. If they are not empty, the session manager 497 // deletion unconditionally. If they are not empty, the session manager
444 // will not delete them on reboot. 498 // will not delete them on reboot.
445 ScheduleParentAndGrandparentForDeletion(target_path); 499 ScheduleParentAndGrandparentForDeletion(target_path);
446 } else { 500 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 544
491 bool ShouldDeleteProfile(const InstallerState& installer_state, 545 bool ShouldDeleteProfile(const InstallerState& installer_state,
492 const CommandLine& cmd_line, InstallStatus status, 546 const CommandLine& cmd_line, InstallStatus status,
493 const Product& product) { 547 const Product& product) {
494 bool should_delete = false; 548 bool should_delete = false;
495 549
496 // Chrome Frame uninstallations always want to delete the profile (we have no 550 // Chrome Frame uninstallations always want to delete the profile (we have no
497 // UI to prompt otherwise and the profile stores no useful data anyway) 551 // UI to prompt otherwise and the profile stores no useful data anyway)
498 // unless they are managed by MSI. MSI uninstalls will explicitly include 552 // unless they are managed by MSI. MSI uninstalls will explicitly include
499 // the --delete-profile flag to distinguish them from MSI upgrades. 553 // the --delete-profile flag to distinguish them from MSI upgrades.
500 if (!product.is_chrome() && !installer_state.is_msi()) { 554 if (product.is_chrome_frame() && !installer_state.is_msi()) {
501 should_delete = true; 555 should_delete = true;
502 } else { 556 } else {
503 should_delete = 557 should_delete =
504 status == installer::UNINSTALL_DELETE_PROFILE || 558 status == installer::UNINSTALL_DELETE_PROFILE ||
505 cmd_line.HasSwitch(installer::switches::kDeleteProfile); 559 cmd_line.HasSwitch(installer::switches::kDeleteProfile);
506 } 560 }
507 561
508 return should_delete; 562 return should_delete;
509 } 563 }
510 564
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 } 811 }
758 812
759 // Chrome is not in use so lets uninstall Chrome by deleting various files 813 // Chrome is not in use so lets uninstall Chrome by deleting various files
760 // and registry entries. Here we will just make best effort and keep going 814 // and registry entries. Here we will just make best effort and keep going
761 // in case of errors. 815 // in case of errors.
762 if (is_chrome) { 816 if (is_chrome) {
763 ClearRlzProductState(); 817 ClearRlzProductState();
764 818
765 auto_launch_util::DisableAllAutoStartFeatures( 819 auto_launch_util::DisableAllAutoStartFeatures(
766 ASCIIToUTF16(chrome::kInitialProfile)); 820 ASCIIToUTF16(chrome::kInitialProfile));
821
822 // First delete shortcuts from Start->Programs, Desktop & Quick Launch.
823 DeleteChromeShortcuts(installer_state, product);
767 } 824 }
768 825
769 // First delete shortcuts from Start->Programs, Desktop & Quick Launch.
770 DeleteChromeShortcuts(installer_state, product);
771
772 // Delete the registry keys (Uninstall key and Version key). 826 // Delete the registry keys (Uninstall key and Version key).
773 HKEY reg_root = installer_state.root_key(); 827 HKEY reg_root = installer_state.root_key();
774 828
775 // Note that we must retrieve the distribution-specific data before deleting 829 // Note that we must retrieve the distribution-specific data before deleting
776 // product.GetVersionKey(). 830 // product.GetVersionKey().
777 string16 distribution_data(browser_dist->GetDistributionData(reg_root)); 831 string16 distribution_data(browser_dist->GetDistributionData(reg_root));
778 832
779 // Remove Control Panel uninstall link and Omaha product key. 833 // Remove Control Panel uninstall link.
780 InstallUtil::DeleteRegistryKey(reg_root, browser_dist->GetUninstallRegPath()); 834 if (product.ShouldCreateUninstallEntry()) {
835 InstallUtil::DeleteRegistryKey(reg_root,
836 browser_dist->GetUninstallRegPath());
837 }
838
839 // Remove Omaha product key.
781 InstallUtil::DeleteRegistryKey(reg_root, browser_dist->GetVersionKey()); 840 InstallUtil::DeleteRegistryKey(reg_root, browser_dist->GetVersionKey());
782 841
783 // Also try to delete the MSI value in the ClientState key (it might not be 842 // Also try to delete the MSI value in the ClientState key (it might not be
784 // there). This is due to a Google Update behaviour where an uninstall and a 843 // there). This is due to a Google Update behaviour where an uninstall and a
785 // rapid reinstall might result in stale values from the old ClientState key 844 // rapid reinstall might result in stale values from the old ClientState key
786 // being picked up on reinstall. 845 // being picked up on reinstall.
787 product.SetMsiMarker(installer_state.system_install(), false); 846 product.SetMsiMarker(installer_state.system_install(), false);
788 847
789 // Remove all Chrome registration keys.
790 // Registration data is put in HKCU for both system level and user level
791 // installs.
792 InstallStatus ret = installer::UNKNOWN_STATUS; 848 InstallStatus ret = installer::UNKNOWN_STATUS;
793 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, suffix,
794 installer_state.target_path(), &ret);
795 849
796 // If the user's Chrome is registered with a suffix: it is possible that old 850 if (is_chrome) {
797 // unsuffixed registrations were left in HKCU (e.g. if this install was 851 // Remove all Chrome registration keys.
798 // previously installed with no suffix in HKCU (old suffix rules if the user 852 // Registration data is put in HKCU for both system level and user level
799 // is not an admin (or declined UAC at first run)) and later had to be 853 // installs.
800 // suffixed when fully registered in HKLM (e.g. when later making Chrome 854 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, suffix,
801 // default through the UI)).
802 // Remove remaining HKCU entries with no suffix if any.
803 if (!suffix.empty()) {
804 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, string16(),
805 installer_state.target_path(), &ret); 855 installer_state.target_path(), &ret);
806 856
807 // For similar reasons it is possible in very few installs (from 21.0.1180.0 857 // If the user's Chrome is registered with a suffix: it is possible that old
808 // and fixed shortly after) to be installed with the new-style suffix, but 858 // unsuffixed registrations were left in HKCU (e.g. if this install was
809 // have some old-style suffix registrations left behind. 859 // previously installed with no suffix in HKCU (old suffix rules if the user
810 string16 old_style_suffix; 860 // is not an admin (or declined UAC at first run)) and later had to be
811 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) && 861 // suffixed when fully registered in HKLM (e.g. when later making Chrome
812 suffix != old_style_suffix) { 862 // default through the UI)).
813 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, 863 // Remove remaining HKCU entries with no suffix if any.
814 old_style_suffix, 864 if (!suffix.empty()) {
865 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, string16(),
866 installer_state.target_path(), &ret);
867
868 // For similar reasons it is possible in very few installs (from
869 // 21.0.1180.0 and fixed shortly after) to be installed with the new-style
870 // suffix, but have some old-style suffix registrations left behind.
871 string16 old_style_suffix;
872 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) &&
873 suffix != old_style_suffix) {
874 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER,
875 old_style_suffix,
876 installer_state.target_path(), &ret);
877 }
878 }
879
880 // Chrome is registered in HKLM for all system-level installs and for
881 // user-level installs for which Chrome has been made the default browser.
882 // Always remove the HKLM registration for system-level installs. For
883 // user-level installs, only remove it if both: 1) this uninstall isn't a
884 // self destruct following the installation of a system-level Chrome
885 // (because the system-level Chrome owns the HKLM registration now), and 2)
886 // this user has made Chrome their default browser (i.e. has shell
887 // integration entries registered with |suffix| (note: |suffix| will be the
888 // empty string if required as it is obtained by
889 // GetCurrentInstallationSuffix() above)).
890 // TODO(gab): This can still leave parts of a suffixed install behind. To be
891 // able to remove them we would need to be able to remove only suffixed
892 // entries (as it is now some of the shell integration entries are
893 // unsuffixed; thus removing suffixed installs is prohibited in HKLM if
894 // !|remove_all| for now).
895 if (installer_state.system_install() ||
896 (remove_all &&
897 ShellUtil::QuickIsChromeRegisteredInHKLM(
898 browser_dist, chrome_exe, suffix))) {
899 DeleteChromeRegistrationKeys(browser_dist, HKEY_LOCAL_MACHINE, suffix,
815 installer_state.target_path(), &ret); 900 installer_state.target_path(), &ret);
816 } 901 }
902
903 ProcessDelegateExecuteWorkItems(installer_state, product);
817 } 904 }
818 905
819 // Chrome is registered in HKLM for all system-level installs and for 906 if (product.is_chrome_frame()) {
820 // user-level installs for which Chrome has been made the default browser.
821 // Always remove the HKLM registration for system-level installs. For
822 // user-level installs, only remove it if both: 1) this uninstall isn't a self
823 // destruct following the installation of a system-level Chrome (because the
824 // system-level Chrome owns the HKLM registration now), and 2) this user has
825 // made Chrome their default browser (i.e. has shell integration entries
826 // registered with |suffix| (note: |suffix| will be the empty string if
827 // required as it is obtained by GetCurrentInstallationSuffix() above)).
828 // TODO(gab): This can still leave parts of a suffixed install behind. To be
829 // able to remove them we would need to be able to remove only suffixed
830 // entries (as it is now some of the shell integration entries are unsuffixed;
831 // thus removing suffixed installs is prohibited in HKLM if !|remove_all| for
832 // now).
833 if (installer_state.system_install() ||
834 (remove_all &&
835 ShellUtil::QuickIsChromeRegisteredInHKLM(
836 browser_dist, chrome_exe, suffix))) {
837 DeleteChromeRegistrationKeys(browser_dist, HKEY_LOCAL_MACHINE, suffix,
838 installer_state.target_path(), &ret);
839 }
840
841 ProcessDelegateExecuteWorkItems(installer_state, product);
842
843 if (!is_chrome) {
844 ProcessChromeFrameWorkItems(original_state, installer_state, setup_path, 907 ProcessChromeFrameWorkItems(original_state, installer_state, setup_path,
845 product); 908 product);
846 } 909 }
847 910
848 if (installer_state.is_multi_install()) 911 if (installer_state.is_multi_install())
849 ProcessGoogleUpdateItems(original_state, installer_state, product); 912 ProcessGoogleUpdateItems(original_state, installer_state, product);
850 913
851 ProcessQuickEnableWorkItems(installer_state, original_state); 914 ProcessQuickEnableWorkItems(installer_state, original_state);
852 915
853 // Get the state of the installed product (if any) 916 // Get the state of the installed product (if any)
(...skipping 27 matching lines...) Expand all
881 944
882 AddRegisterComDllWorkItems(dll_folder, 945 AddRegisterComDllWorkItems(dll_folder,
883 com_dll_list, 946 com_dll_list,
884 installer_state.system_install(), 947 installer_state.system_install(),
885 false, // Unregister 948 false, // Unregister
886 true, // May fail 949 true, // May fail
887 unreg_work_item_list.get()); 950 unreg_work_item_list.get());
888 unreg_work_item_list->Do(); 951 unreg_work_item_list->Do();
889 } 952 }
890 953
891 if (!is_chrome) 954 if (product.is_chrome_frame())
892 ProcessIELowRightsPolicyWorkItems(installer_state); 955 ProcessIELowRightsPolicyWorkItems(installer_state);
893 } 956 }
894 957
895 // Close any Chrome Frame helper processes that may be running. 958 // Close any Chrome Frame helper processes that may be running.
896 if (product.is_chrome_frame()) { 959 if (product.is_chrome_frame()) {
897 VLOG(1) << "Closing the Chrome Frame helper process"; 960 VLOG(1) << "Closing the Chrome Frame helper process";
898 CloseChromeFrameHelperProcess(); 961 CloseChromeFrameHelperProcess();
899 } 962 }
900 963
901 if (product_state == NULL) 964 if (product_state == NULL)
902 return installer::UNINSTALL_SUCCESSFUL; 965 return installer::UNINSTALL_SUCCESSFUL;
903 966
904 // Finally delete all the files from Chrome folder after moving setup.exe 967 // Finally delete all the files from Chrome folder after moving setup.exe
905 // and the user's Local State to a temp location. 968 // and the user's Local State to a temp location.
906 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, 969 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status,
907 product); 970 product);
908 ret = installer::UNINSTALL_SUCCESSFUL; 971 ret = installer::UNINSTALL_SUCCESSFUL;
909 972
910 // When deleting files, we must make sure that we're either a "single" 973 // When deleting files, we must make sure that we're either a "single"
911 // (aka non-multi) installation or, in the case of multi, that no other 974 // (aka non-multi) installation or we are the Chrome Binaries.
912 // "multi" products share the binaries we are about to delete.
913 975
914 bool can_delete_files = true; 976 FilePath backup_state_file(
915 if (installer_state.is_multi_install()) { 977 BackupLocalStateFile(GetLocalStateFolder(product)));
916 ProductState prod_state;
917 for (size_t i = 0; i < BrowserDistribution::kNumProductTypes; ++i) {
918 if (prod_state.Initialize(installer_state.system_install(),
919 BrowserDistribution::kProductTypes[i]) &&
920 prod_state.is_multi_install()) {
921 can_delete_files = false;
922 break;
923 }
924 }
925 LOG(INFO) << (can_delete_files ? "Shared binaries will be deleted." :
926 "Shared binaries still in use.");
927 if (can_delete_files) {
928 BrowserDistribution* multi_dist =
929 installer_state.multi_package_binaries_distribution();
930 InstallUtil::DeleteRegistryKey(reg_root, multi_dist->GetVersionKey());
931 }
932 }
933
934 FilePath backup_state_file(BackupLocalStateFile(
935 GetLocalStateFolder(product)));
936 978
937 DeleteResult delete_result = DELETE_SUCCEEDED; 979 DeleteResult delete_result = DELETE_SUCCEEDED;
938 if (can_delete_files) { 980
981 if (product.is_chrome_app_host()) {
982 DeleteAppHostFilesAndFolders(installer_state, product_state->version());
983 } else if (!installer_state.is_multi_install() ||
984 product.is_chrome_binaries()) {
985
939 // In order to be able to remove the folder in which we're running, we 986 // In order to be able to remove the folder in which we're running, we
940 // need to move setup.exe out of the install folder. 987 // need to move setup.exe out of the install folder.
941 // TODO(tommi): What if the temp folder is on a different volume? 988 // TODO(tommi): What if the temp folder is on a different volume?
942 MoveSetupOutOfInstallFolder(installer_state, setup_path, 989 MoveSetupOutOfInstallFolder(installer_state, setup_path,
943 product_state->version()); 990 product_state->version());
944 delete_result = DeleteFilesAndFolders(installer_state, 991 delete_result = DeleteChromeFilesAndFolders(installer_state,
945 product_state->version()); 992 product_state->version());
946 } 993 }
947 994
948 if (delete_profile) 995 if (delete_profile)
949 DeleteLocalState(product); 996 DeleteLocalState(product);
950 997
951 if (delete_result == DELETE_FAILED) { 998 if (delete_result == DELETE_FAILED) {
952 ret = installer::UNINSTALL_FAILED; 999 ret = installer::UNINSTALL_FAILED;
953 } else if (delete_result == DELETE_REQUIRES_REBOOT) { 1000 } else if (delete_result == DELETE_REQUIRES_REBOOT) {
954 ret = installer::UNINSTALL_REQUIRES_REBOOT; 1001 ret = installer::UNINSTALL_REQUIRES_REBOOT;
955 } 1002 }
956 1003
957 if (!force_uninstall) { 1004 if (!force_uninstall) {
958 VLOG(1) << "Uninstallation complete. Launching Uninstall survey."; 1005 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
959 browser_dist->DoPostUninstallOperations(product_state->version(), 1006 browser_dist->DoPostUninstallOperations(product_state->version(),
960 backup_state_file, distribution_data); 1007 backup_state_file, distribution_data);
961 } 1008 }
962 1009
963 // Try and delete the preserved local state once the post-install 1010 // Try and delete the preserved local state once the post-install
964 // operations are complete. 1011 // operations are complete.
965 if (!backup_state_file.empty()) 1012 if (!backup_state_file.empty())
966 file_util::Delete(backup_state_file, false); 1013 file_util::Delete(backup_state_file, false);
967 1014
968 return ret; 1015 return ret;
969 } 1016 }
970 1017
971 } // namespace installer 1018 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698