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

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

Issue 10451074: Always suffix ChromeHTML entries on Windows for user-level installs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments + introduce ShellUtil::QuickIsChromeRegistered() Created 8 years, 6 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 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 } 213 }
214 } 214 }
215 215
216 if (kill) { 216 if (kill) {
217 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing."; 217 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing.";
218 base::CleanupProcesses(installer::kChromeFrameHelperExe, 0, 218 base::CleanupProcesses(installer::kChromeFrameHelperExe, 0,
219 content::RESULT_CODE_HUNG, NULL); 219 content::RESULT_CODE_HUNG, NULL);
220 } 220 }
221 } 221 }
222 222
223 // This method tries to figure out if current user has registered Chrome.
224 // It returns true iff there is a registered browser that will launch the
225 // same chrome.exe as the current installation.
226 bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state) {
227 using base::win::RegistryKeyIterator;
228 const HKEY root = HKEY_LOCAL_MACHINE;
229 InstallUtil::ProgramCompare open_command_pred(
230 installer_state.target_path().Append(kChromeExe));
231 string16 client_open_path;
232 RegKey client_open_key;
233 string16 reg_exe;
234 for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet);
235 iter.Valid(); ++iter) {
236 client_open_path.assign(ShellUtil::kRegStartMenuInternet)
237 .append(1, L'\\')
238 .append(iter.Name())
239 .append(ShellUtil::kRegShellOpen);
240 if (client_open_key.Open(root, client_open_path.c_str(),
241 KEY_QUERY_VALUE) == ERROR_SUCCESS &&
242 client_open_key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS &&
243 open_command_pred.Evaluate(reg_exe)) {
244 return true;
245 }
246 }
247 return false;
248 }
249
250 // This method deletes Chrome shortcut folder from Windows Start menu. It 223 // This method deletes Chrome shortcut folder from Windows Start menu. It
251 // checks system_uninstall to see if the shortcut is in all users start menu 224 // checks system_uninstall to see if the shortcut is in all users start menu
252 // or current user start menu. 225 // or current user start menu.
253 // We try to remove the standard desktop shortcut but if that fails we try 226 // We try to remove the standard desktop shortcut but if that fails we try
254 // to remove the alternate desktop shortcut. Only one of them should be 227 // to remove the alternate desktop shortcut. Only one of them should be
255 // present in a given install but at this point we don't know which one. 228 // present in a given install but at this point we don't know which one.
256 void DeleteChromeShortcuts(const InstallerState& installer_state, 229 void DeleteChromeShortcuts(const InstallerState& installer_state,
257 const Product& product) { 230 const Product& product) {
258 if (!product.is_chrome()) { 231 if (!product.is_chrome()) {
259 VLOG(1) << __FUNCTION__ " called for non-CHROME distribution"; 232 VLOG(1) << __FUNCTION__ " called for non-CHROME distribution";
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 } 630 }
658 631
659 // Note that we do not attempt to delete filetype associations since MSDN 632 // Note that we do not attempt to delete filetype associations since MSDN
660 // says "Windows respects the Default value only if the ProgID found there is 633 // says "Windows respects the Default value only if the ProgID found there is
661 // a registered ProgID. If the ProgID is unregistered, it is ignored." 634 // a registered ProgID. If the ProgID is unregistered, it is ignored."
662 635
663 *exit_code = installer::UNINSTALL_SUCCESSFUL; 636 *exit_code = installer::UNINSTALL_SUCCESSFUL;
664 return true; 637 return true;
665 } 638 }
666 639
667 void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist) { 640 void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist,
641 const string16& chrome_exe) {
668 // We used to register Chrome to handle crx files, but this turned out 642 // We used to register Chrome to handle crx files, but this turned out
669 // to be not worth the hassle. Remove these old registry entries if 643 // to be not worth the hassle. Remove these old registry entries if
670 // they exist. See: http://codereview.chromium.org/210007 644 // they exist. See: http://codereview.chromium.org/210007
671 645
672 #if defined(GOOGLE_CHROME_BUILD) 646 #if defined(GOOGLE_CHROME_BUILD)
673 const wchar_t kChromeExtProgId[] = L"ChromeExt"; 647 const wchar_t kChromeExtProgId[] = L"ChromeExt";
674 #else 648 #else
675 const wchar_t kChromeExtProgId[] = L"ChromiumExt"; 649 const wchar_t kChromeExtProgId[] = L"ChromiumExt";
676 #endif 650 #endif
677 651
678 HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER }; 652 HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER };
679 for (size_t i = 0; i < arraysize(roots); ++i) { 653 for (size_t i = 0; i < arraysize(roots); ++i) {
680 string16 suffix; 654 string16 suffix;
681 if (roots[i] == HKEY_LOCAL_MACHINE && 655 if (roots[i] == HKEY_LOCAL_MACHINE)
682 !ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) 656 suffix = ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe);
683 suffix = L"";
684 657
685 // Delete Software\Classes\ChromeExt, 658 // Delete Software\Classes\ChromeExt,
686 string16 ext_prog_id(ShellUtil::kRegClasses); 659 string16 ext_prog_id(ShellUtil::kRegClasses);
687 ext_prog_id.push_back(FilePath::kSeparators[0]); 660 ext_prog_id.push_back(FilePath::kSeparators[0]);
688 ext_prog_id.append(kChromeExtProgId); 661 ext_prog_id.append(kChromeExtProgId);
689 ext_prog_id.append(suffix); 662 ext_prog_id.append(suffix);
690 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); 663 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id);
691 664
692 // Delete Software\Classes\.crx, 665 // Delete Software\Classes\.crx,
693 string16 ext_association(ShellUtil::kRegClasses); 666 string16 ext_association(ShellUtil::kRegClasses);
(...skipping 29 matching lines...) Expand all
723 } 696 }
724 697
725 InstallStatus UninstallProduct(const InstallationState& original_state, 698 InstallStatus UninstallProduct(const InstallationState& original_state,
726 const InstallerState& installer_state, 699 const InstallerState& installer_state,
727 const FilePath& setup_path, 700 const FilePath& setup_path,
728 const Product& product, 701 const Product& product,
729 bool remove_all, 702 bool remove_all,
730 bool force_uninstall, 703 bool force_uninstall,
731 const CommandLine& cmd_line) { 704 const CommandLine& cmd_line) {
732 InstallStatus status = installer::UNINSTALL_CONFIRMED; 705 InstallStatus status = installer::UNINSTALL_CONFIRMED;
733 string16 suffix; 706 BrowserDistribution* browser_dist = product.distribution();
734 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(), 707 const string16 chrome_exe(
735 &suffix)) 708 installer_state.target_path().Append(installer::kChromeExe).value());
736 suffix = L"";
737 709
738 BrowserDistribution* browser_dist = product.distribution(); 710 const string16 suffix(ShellUtil::GetCurrentInstallationSuffix(browser_dist,
711 chrome_exe));
712
739 bool is_chrome = product.is_chrome(); 713 bool is_chrome = product.is_chrome();
740 714
741 VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName(); 715 VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName();
742 716
743 if (force_uninstall) { 717 if (force_uninstall) {
744 // Since --force-uninstall command line option is used, we are going to 718 // Since --force-uninstall command line option is used, we are going to
745 // do silent uninstall. Try to close all running Chrome instances. 719 // do silent uninstall. Try to close all running Chrome instances.
746 // NOTE: We don't do this for Chrome Frame. 720 // NOTE: We don't do this for Chrome Frame.
747 if (is_chrome) 721 if (is_chrome)
748 CloseAllChromeProcesses(); 722 CloseAllChromeProcesses();
749 } else if (is_chrome) { 723 } else if (is_chrome) {
750 // no --force-uninstall so lets show some UI dialog boxes. 724 // no --force-uninstall so lets show some UI dialog boxes.
751 status = IsChromeActiveOrUserCancelled(installer_state, product); 725 status = IsChromeActiveOrUserCancelled(installer_state, product);
752 if (status != installer::UNINSTALL_CONFIRMED && 726 if (status != installer::UNINSTALL_CONFIRMED &&
753 status != installer::UNINSTALL_DELETE_PROFILE) 727 status != installer::UNINSTALL_DELETE_PROFILE)
754 return status; 728 return status;
755 729
756 // Check if we need admin rights to cleanup HKLM. If we do, try to launch 730 // Check if we need admin rights to cleanup HKLM (the conditions for
757 // another uninstaller (silent) in elevated mode to do HKLM cleanup. 731 // requiring a cleanup are the same as the conditions to do the actual
732 // cleanup where DeleteChromeRegistrationKeys() is invoked for
733 // HKEY_LOCAL_MACHINE below). If we do, try to launch another uninstaller
734 // (silent) in elevated mode to do HKLM cleanup.
758 // And continue uninstalling in the current process also to do HKCU cleanup. 735 // And continue uninstalling in the current process also to do HKCU cleanup.
759 if (remove_all && 736 if (remove_all &&
760 (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state)) && 737 ShellUtil::QuickIsChromeRegistered(
738 browser_dist, chrome_exe, suffix,
739 ShellUtil::CONFIRM_SYSTEM_REGISTRATION) &&
761 !::IsUserAnAdmin() && 740 !::IsUserAnAdmin() &&
762 base::win::GetVersion() >= base::win::VERSION_VISTA && 741 base::win::GetVersion() >= base::win::VERSION_VISTA &&
763 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { 742 !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) {
764 CommandLine new_cmd(CommandLine::NO_PROGRAM); 743 CommandLine new_cmd(CommandLine::NO_PROGRAM);
765 new_cmd.AppendArguments(cmd_line, true); 744 new_cmd.AppendArguments(cmd_line, true);
766 // Append --run-as-admin flag to let the new instance of setup.exe know 745 // Append --run-as-admin flag to let the new instance of setup.exe know
767 // that we already tried to launch ourselves as admin. 746 // that we already tried to launch ourselves as admin.
768 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin); 747 new_cmd.AppendSwitch(installer::switches::kRunAsAdmin);
769 // Append --remove-chrome-registration to remove registry keys only. 748 // Append --remove-chrome-registration to remove registry keys only.
770 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); 749 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 // Also try to delete the MSI value in the ClientState key (it might not be 783 // Also try to delete the MSI value in the ClientState key (it might not be
805 // there). This is due to a Google Update behaviour where an uninstall and a 784 // there). This is due to a Google Update behaviour where an uninstall and a
806 // rapid reinstall might result in stale values from the old ClientState key 785 // rapid reinstall might result in stale values from the old ClientState key
807 // being picked up on reinstall. 786 // being picked up on reinstall.
808 product.SetMsiMarker(installer_state.system_install(), false); 787 product.SetMsiMarker(installer_state.system_install(), false);
809 788
810 // Remove all Chrome registration keys. 789 // Remove all Chrome registration keys.
811 // Registration data is put in HKCU for both system level and user level 790 // Registration data is put in HKCU for both system level and user level
812 // installs. 791 // installs.
813 InstallStatus ret = installer::UNKNOWN_STATUS; 792 InstallStatus ret = installer::UNKNOWN_STATUS;
814 DeleteChromeRegistrationKeys(product.distribution(), HKEY_CURRENT_USER, 793 DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, suffix,
815 suffix, installer_state.target_path(), &ret); 794 installer_state.target_path(), &ret);
795
796 // If the user's Chrome is registered with a suffix: it is possible that old
797 // unsuffixed registrations were left in HKCU (e.g. if this install was
798 // previously installed with no suffix in HKCU (old suffix rules if the user
799 // is not an admin (or declined UAC at first run)) and later had to be
800 // suffixed when fully registered in HKLM (e.g. when later making Chrome
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);
806 }
816 807
817 // Chrome is registered in HKLM for all system-level installs and for 808 // Chrome is registered in HKLM for all system-level installs and for
818 // user-level installs for which Chrome has been made the default browser. 809 // user-level installs for which Chrome has been made the default browser.
819 // Always remove the HKLM registration for system-level installs. For 810 // Always remove the HKLM registration for system-level installs. For
820 // user-level installs, only remove it if both: 1) this uninstall isn't a 811 // user-level installs, only remove it if both: 1) this uninstall isn't a self
821 // self-destruct following the installation of system-level Chrome (because 812 // destruct following the installation of a system-level Chrome (because the
822 // the system-level Chrome owns the HKLM registration now), and 2) this user 813 // system-level Chrome owns the HKLM registration now), and 2) this user has
823 // had made Chrome their default browser. 814 // made Chrome their default browser (i.e. has system entries registered with
815 // |suffix| (note: |suffix| will be the empty string if required as it is
816 // obtained by GetCurrentInstallationSuffix() above)).
817 // TODO(gab): This can still leave parts of a suffixed install behind. To be
818 // able to remove them we would need to be able to remove only suffixed
819 // entries (as it is now some of the system entries are unsuffixed; thus
820 // removing suffixed installs is prohibited in HKLM if !|remove_all| for now).
824 if (installer_state.system_install() || 821 if (installer_state.system_install() ||
825 (remove_all && 822 (remove_all &&
826 (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state)))) { 823 ShellUtil::QuickIsChromeRegistered(
827 DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE, 824 browser_dist, chrome_exe, suffix,
828 suffix, installer_state.target_path(), &ret); 825 ShellUtil::CONFIRM_SYSTEM_REGISTRATION))) {
826 DeleteChromeRegistrationKeys(browser_dist, HKEY_LOCAL_MACHINE, suffix,
827 installer_state.target_path(), &ret);
829 } 828 }
830 829
831 ProcessDelegateExecuteWorkItems(installer_state, product); 830 ProcessDelegateExecuteWorkItems(installer_state, product);
832 831
833 if (!is_chrome) { 832 if (!is_chrome) {
834 ProcessChromeFrameWorkItems(original_state, installer_state, setup_path, 833 ProcessChromeFrameWorkItems(original_state, installer_state, setup_path,
835 product); 834 product);
836 } 835 }
837 836
838 if (installer_state.is_multi_install()) 837 if (installer_state.is_multi_install())
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 951
953 // Try and delete the preserved local state once the post-install 952 // Try and delete the preserved local state once the post-install
954 // operations are complete. 953 // operations are complete.
955 if (!backup_state_file.empty()) 954 if (!backup_state_file.empty())
956 file_util::Delete(backup_state_file, false); 955 file_util::Delete(backup_state_file, false);
957 956
958 return ret; 957 return ret;
959 } 958 }
960 959
961 } // namespace installer 960 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698