OLD | NEW |
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 <windows.h> | 9 #include <windows.h> |
10 | 10 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 } | 169 } |
170 | 170 |
171 void ClearRlzProductState() { | 171 void ClearRlzProductState() { |
172 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, | 172 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, |
173 rlz_lib::CHROME_HOME_PAGE, | 173 rlz_lib::CHROME_HOME_PAGE, |
174 rlz_lib::NO_ACCESS_POINT}; | 174 rlz_lib::NO_ACCESS_POINT}; |
175 | 175 |
176 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 176 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
177 | 177 |
178 // If chrome has been reactivated, clear all events for this brand as well. | 178 // If chrome has been reactivated, clear all events for this brand as well. |
179 string16 reactivation_brand_wide; | 179 base::string16 reactivation_brand_wide; |
180 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { | 180 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { |
181 std::string reactivation_brand(WideToASCII(reactivation_brand_wide)); | 181 std::string reactivation_brand(WideToASCII(reactivation_brand_wide)); |
182 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); | 182 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); |
183 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 183 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 // Decides whether setup.exe and the installer archive should be removed based | 187 // Decides whether setup.exe and the installer archive should be removed based |
188 // on the original and installer states: | 188 // on the original and installer states: |
189 // * non-multi product being uninstalled: remove both | 189 // * non-multi product being uninstalled: remove both |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 | 666 |
667 return should_delete; | 667 return should_delete; |
668 } | 668 } |
669 | 669 |
670 // Removes XP-era filetype registration making Chrome the default browser. | 670 // Removes XP-era filetype registration making Chrome the default browser. |
671 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) | 671 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) |
672 // tells us not to do this, but certain applications break following | 672 // tells us not to do this, but certain applications break following |
673 // uninstallation if we don't. | 673 // uninstallation if we don't. |
674 void RemoveFiletypeRegistration(const InstallerState& installer_state, | 674 void RemoveFiletypeRegistration(const InstallerState& installer_state, |
675 HKEY root, | 675 HKEY root, |
676 const string16& browser_entry_suffix) { | 676 const base::string16& browser_entry_suffix) { |
677 string16 classes_path(ShellUtil::kRegClasses); | 677 base::string16 classes_path(ShellUtil::kRegClasses); |
678 classes_path.push_back(base::FilePath::kSeparators[0]); | 678 classes_path.push_back(base::FilePath::kSeparators[0]); |
679 | 679 |
680 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); | 680 BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
681 const string16 prog_id( | 681 const base::string16 prog_id( |
682 distribution->GetBrowserProgIdPrefix() + browser_entry_suffix); | 682 distribution->GetBrowserProgIdPrefix() + browser_entry_suffix); |
683 | 683 |
684 // Delete each filetype association if it references this Chrome. Take care | 684 // Delete each filetype association if it references this Chrome. Take care |
685 // not to delete the association if it references a system-level install of | 685 // not to delete the association if it references a system-level install of |
686 // Chrome (only a risk if the suffix is empty). Don't delete the whole key | 686 // Chrome (only a risk if the suffix is empty). Don't delete the whole key |
687 // since other apps may have stored data there. | 687 // since other apps may have stored data there. |
688 std::vector<const wchar_t*> cleared_assocs; | 688 std::vector<const wchar_t*> cleared_assocs; |
689 if (installer_state.system_install() || | 689 if (installer_state.system_install() || |
690 !browser_entry_suffix.empty() || | 690 !browser_entry_suffix.empty() || |
691 !base::win::RegKey(HKEY_LOCAL_MACHINE, (classes_path + prog_id).c_str(), | 691 !base::win::RegKey(HKEY_LOCAL_MACHINE, (classes_path + prog_id).c_str(), |
692 KEY_QUERY_VALUE).Valid()) { | 692 KEY_QUERY_VALUE).Valid()) { |
693 InstallUtil::ValueEquals prog_id_pred(prog_id); | 693 InstallUtil::ValueEquals prog_id_pred(prog_id); |
694 for (const wchar_t* const* filetype = | 694 for (const wchar_t* const* filetype = |
695 &ShellUtil::kPotentialFileAssociations[0]; *filetype != NULL; | 695 &ShellUtil::kPotentialFileAssociations[0]; *filetype != NULL; |
696 ++filetype) { | 696 ++filetype) { |
697 if (InstallUtil::DeleteRegistryValueIf( | 697 if (InstallUtil::DeleteRegistryValueIf( |
698 root, (classes_path + *filetype).c_str(), NULL, | 698 root, (classes_path + *filetype).c_str(), NULL, |
699 prog_id_pred) == InstallUtil::DELETED) { | 699 prog_id_pred) == InstallUtil::DELETED) { |
700 cleared_assocs.push_back(*filetype); | 700 cleared_assocs.push_back(*filetype); |
701 } | 701 } |
702 } | 702 } |
703 } | 703 } |
704 | 704 |
705 // For all filetype associations in HKLM that have just been removed, attempt | 705 // For all filetype associations in HKLM that have just been removed, attempt |
706 // to restore some reasonable value. We have no definitive way of knowing | 706 // to restore some reasonable value. We have no definitive way of knowing |
707 // what handlers are the most appropriate, so we use a fixed mapping based on | 707 // what handlers are the most appropriate, so we use a fixed mapping based on |
708 // the default values for a fresh install of Windows. | 708 // the default values for a fresh install of Windows. |
709 if (root == HKEY_LOCAL_MACHINE) { | 709 if (root == HKEY_LOCAL_MACHINE) { |
710 string16 assoc; | 710 base::string16 assoc; |
711 base::win::RegKey key; | 711 base::win::RegKey key; |
712 | 712 |
713 for (size_t i = 0; i < cleared_assocs.size(); ++i) { | 713 for (size_t i = 0; i < cleared_assocs.size(); ++i) { |
714 const wchar_t* replacement_prog_id = NULL; | 714 const wchar_t* replacement_prog_id = NULL; |
715 assoc.assign(cleared_assocs[i]); | 715 assoc.assign(cleared_assocs[i]); |
716 | 716 |
717 // Inelegant, but simpler than a pure data-driven approach. | 717 // Inelegant, but simpler than a pure data-driven approach. |
718 if (assoc == L".htm" || assoc == L".html") | 718 if (assoc == L".htm" || assoc == L".html") |
719 replacement_prog_id = L"htmlfile"; | 719 replacement_prog_id = L"htmlfile"; |
720 else if (assoc == L".xht" || assoc == L".xhtml") | 720 else if (assoc == L".xht" || assoc == L".xhtml") |
(...skipping 13 matching lines...) Expand all Loading... |
734 LOG(ERROR) << "Failed to restore system-level filetype association " | 734 LOG(ERROR) << "Failed to restore system-level filetype association " |
735 << assoc << " = " << replacement_prog_id; | 735 << assoc << " = " << replacement_prog_id; |
736 } | 736 } |
737 } | 737 } |
738 } | 738 } |
739 } | 739 } |
740 | 740 |
741 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, | 741 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, |
742 BrowserDistribution* dist, | 742 BrowserDistribution* dist, |
743 HKEY root, | 743 HKEY root, |
744 const string16& browser_entry_suffix, | 744 const base::string16& browser_entry_suffix, |
745 InstallStatus* exit_code) { | 745 InstallStatus* exit_code) { |
746 DCHECK(exit_code); | 746 DCHECK(exit_code); |
747 if (dist->GetDefaultBrowserControlPolicy() == | 747 if (dist->GetDefaultBrowserControlPolicy() == |
748 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { | 748 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { |
749 // We should have never set those keys. | 749 // We should have never set those keys. |
750 return true; | 750 return true; |
751 } | 751 } |
752 | 752 |
753 base::FilePath chrome_exe(installer_state.target_path().Append(kChromeExe)); | 753 base::FilePath chrome_exe(installer_state.target_path().Append(kChromeExe)); |
754 | 754 |
755 // Delete Software\Classes\ChromeHTML. | 755 // Delete Software\Classes\ChromeHTML. |
756 const string16 prog_id( | 756 const base::string16 prog_id( |
757 dist->GetBrowserProgIdPrefix() + browser_entry_suffix); | 757 dist->GetBrowserProgIdPrefix() + browser_entry_suffix); |
758 string16 reg_prog_id(ShellUtil::kRegClasses); | 758 base::string16 reg_prog_id(ShellUtil::kRegClasses); |
759 reg_prog_id.push_back(base::FilePath::kSeparators[0]); | 759 reg_prog_id.push_back(base::FilePath::kSeparators[0]); |
760 reg_prog_id.append(prog_id); | 760 reg_prog_id.append(prog_id); |
761 InstallUtil::DeleteRegistryKey(root, reg_prog_id); | 761 InstallUtil::DeleteRegistryKey(root, reg_prog_id); |
762 | 762 |
763 // Delete Software\Classes\Chrome. | 763 // Delete Software\Classes\Chrome. |
764 string16 reg_app_id(ShellUtil::kRegClasses); | 764 base::string16 reg_app_id(ShellUtil::kRegClasses); |
765 reg_app_id.push_back(base::FilePath::kSeparators[0]); | 765 reg_app_id.push_back(base::FilePath::kSeparators[0]); |
766 // Append the requested suffix manually here (as ShellUtil::GetBrowserModelId | 766 // Append the requested suffix manually here (as ShellUtil::GetBrowserModelId |
767 // would otherwise try to figure out the currently installed suffix). | 767 // would otherwise try to figure out the currently installed suffix). |
768 reg_app_id.append(dist->GetBaseAppId() + browser_entry_suffix); | 768 reg_app_id.append(dist->GetBaseAppId() + browser_entry_suffix); |
769 InstallUtil::DeleteRegistryKey(root, reg_app_id); | 769 InstallUtil::DeleteRegistryKey(root, reg_app_id); |
770 | 770 |
771 // Delete all Start Menu Internet registrations that refer to this Chrome. | 771 // Delete all Start Menu Internet registrations that refer to this Chrome. |
772 { | 772 { |
773 using base::win::RegistryKeyIterator; | 773 using base::win::RegistryKeyIterator; |
774 InstallUtil::ProgramCompare open_command_pred(chrome_exe); | 774 InstallUtil::ProgramCompare open_command_pred(chrome_exe); |
775 string16 client_name; | 775 base::string16 client_name; |
776 string16 client_key; | 776 base::string16 client_key; |
777 string16 open_key; | 777 base::string16 open_key; |
778 for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet); | 778 for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet); |
779 iter.Valid(); ++iter) { | 779 iter.Valid(); ++iter) { |
780 client_name.assign(iter.Name()); | 780 client_name.assign(iter.Name()); |
781 client_key.assign(ShellUtil::kRegStartMenuInternet) | 781 client_key.assign(ShellUtil::kRegStartMenuInternet) |
782 .append(1, L'\\') | 782 .append(1, L'\\') |
783 .append(client_name); | 783 .append(client_name); |
784 open_key.assign(client_key).append(ShellUtil::kRegShellOpen); | 784 open_key.assign(client_key).append(ShellUtil::kRegShellOpen); |
785 if (InstallUtil::DeleteRegistryKeyIf(root, client_key, open_key, NULL, | 785 if (InstallUtil::DeleteRegistryKeyIf(root, client_key, open_key, NULL, |
786 open_command_pred) != InstallUtil::NOT_FOUND) { | 786 open_command_pred) != InstallUtil::NOT_FOUND) { |
787 // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it | 787 // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it |
788 // references this Chrome (i.e., if it was made the default browser). | 788 // references this Chrome (i.e., if it was made the default browser). |
789 InstallUtil::DeleteRegistryValueIf( | 789 InstallUtil::DeleteRegistryValueIf( |
790 root, ShellUtil::kRegStartMenuInternet, NULL, | 790 root, ShellUtil::kRegStartMenuInternet, NULL, |
791 InstallUtil::ValueEquals(client_name)); | 791 InstallUtil::ValueEquals(client_name)); |
792 // Also delete the value for the default user if we're operating in | 792 // Also delete the value for the default user if we're operating in |
793 // HKLM. | 793 // HKLM. |
794 if (root == HKEY_LOCAL_MACHINE) { | 794 if (root == HKEY_LOCAL_MACHINE) { |
795 InstallUtil::DeleteRegistryValueIf( | 795 InstallUtil::DeleteRegistryValueIf( |
796 HKEY_USERS, | 796 HKEY_USERS, |
797 string16(L".DEFAULT\\").append( | 797 base::string16(L".DEFAULT\\").append( |
798 ShellUtil::kRegStartMenuInternet).c_str(), | 798 ShellUtil::kRegStartMenuInternet).c_str(), |
799 NULL, InstallUtil::ValueEquals(client_name)); | 799 NULL, InstallUtil::ValueEquals(client_name)); |
800 } | 800 } |
801 } | 801 } |
802 } | 802 } |
803 } | 803 } |
804 | 804 |
805 // Delete Software\RegisteredApplications\Chromium | 805 // Delete Software\RegisteredApplications\Chromium |
806 InstallUtil::DeleteRegistryValue( | 806 InstallUtil::DeleteRegistryValue( |
807 root, ShellUtil::kRegRegisteredApplications, | 807 root, ShellUtil::kRegRegisteredApplications, |
808 dist->GetBaseAppName() + browser_entry_suffix); | 808 dist->GetBaseAppName() + browser_entry_suffix); |
809 | 809 |
810 // Delete the App Paths and Applications keys that let Explorer find Chrome: | 810 // Delete the App Paths and Applications keys that let Explorer find Chrome: |
811 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 | 811 // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121 |
812 string16 app_key(ShellUtil::kRegClasses); | 812 base::string16 app_key(ShellUtil::kRegClasses); |
813 app_key.push_back(base::FilePath::kSeparators[0]); | 813 app_key.push_back(base::FilePath::kSeparators[0]); |
814 app_key.append(L"Applications"); | 814 app_key.append(L"Applications"); |
815 app_key.push_back(base::FilePath::kSeparators[0]); | 815 app_key.push_back(base::FilePath::kSeparators[0]); |
816 app_key.append(installer::kChromeExe); | 816 app_key.append(installer::kChromeExe); |
817 InstallUtil::DeleteRegistryKey(root, app_key); | 817 InstallUtil::DeleteRegistryKey(root, app_key); |
818 | 818 |
819 string16 app_path_key(ShellUtil::kAppPathsRegistryKey); | 819 base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey); |
820 app_path_key.push_back(base::FilePath::kSeparators[0]); | 820 app_path_key.push_back(base::FilePath::kSeparators[0]); |
821 app_path_key.append(installer::kChromeExe); | 821 app_path_key.append(installer::kChromeExe); |
822 InstallUtil::DeleteRegistryKey(root, app_path_key); | 822 InstallUtil::DeleteRegistryKey(root, app_path_key); |
823 | 823 |
824 // Cleanup OpenWithList and OpenWithProgids: | 824 // Cleanup OpenWithList and OpenWithProgids: |
825 // http://msdn.microsoft.com/en-us/library/bb166549 | 825 // http://msdn.microsoft.com/en-us/library/bb166549 |
826 string16 file_assoc_key; | 826 base::string16 file_assoc_key; |
827 string16 open_with_list_key; | 827 base::string16 open_with_list_key; |
828 string16 open_with_progids_key; | 828 base::string16 open_with_progids_key; |
829 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; ++i) { | 829 for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; ++i) { |
830 file_assoc_key.assign(ShellUtil::kRegClasses); | 830 file_assoc_key.assign(ShellUtil::kRegClasses); |
831 file_assoc_key.push_back(base::FilePath::kSeparators[0]); | 831 file_assoc_key.push_back(base::FilePath::kSeparators[0]); |
832 file_assoc_key.append(ShellUtil::kPotentialFileAssociations[i]); | 832 file_assoc_key.append(ShellUtil::kPotentialFileAssociations[i]); |
833 file_assoc_key.push_back(base::FilePath::kSeparators[0]); | 833 file_assoc_key.push_back(base::FilePath::kSeparators[0]); |
834 | 834 |
835 open_with_list_key.assign(file_assoc_key); | 835 open_with_list_key.assign(file_assoc_key); |
836 open_with_list_key.append(L"OpenWithList"); | 836 open_with_list_key.append(L"OpenWithList"); |
837 open_with_list_key.push_back(base::FilePath::kSeparators[0]); | 837 open_with_list_key.push_back(base::FilePath::kSeparators[0]); |
838 open_with_list_key.append(installer::kChromeExe); | 838 open_with_list_key.append(installer::kChromeExe); |
839 InstallUtil::DeleteRegistryKey(root, open_with_list_key); | 839 InstallUtil::DeleteRegistryKey(root, open_with_list_key); |
840 | 840 |
841 open_with_progids_key.assign(file_assoc_key); | 841 open_with_progids_key.assign(file_assoc_key); |
842 open_with_progids_key.append(ShellUtil::kRegOpenWithProgids); | 842 open_with_progids_key.append(ShellUtil::kRegOpenWithProgids); |
843 InstallUtil::DeleteRegistryValue(root, open_with_progids_key, prog_id); | 843 InstallUtil::DeleteRegistryValue(root, open_with_progids_key, prog_id); |
844 } | 844 } |
845 | 845 |
846 // Cleanup in case Chrome had been made the default browser. | 846 // Cleanup in case Chrome had been made the default browser. |
847 | 847 |
848 // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it | 848 // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it |
849 // references this Chrome. Do this explicitly here for the case where HKCU is | 849 // references this Chrome. Do this explicitly here for the case where HKCU is |
850 // being processed; the iteration above will have no hits since registration | 850 // being processed; the iteration above will have no hits since registration |
851 // lives in HKLM. | 851 // lives in HKLM. |
852 InstallUtil::DeleteRegistryValueIf( | 852 InstallUtil::DeleteRegistryValueIf( |
853 root, ShellUtil::kRegStartMenuInternet, NULL, | 853 root, ShellUtil::kRegStartMenuInternet, NULL, |
854 InstallUtil::ValueEquals(dist->GetBaseAppName() + browser_entry_suffix)); | 854 InstallUtil::ValueEquals(dist->GetBaseAppName() + browser_entry_suffix)); |
855 | 855 |
856 // Delete each protocol association if it references this Chrome. | 856 // Delete each protocol association if it references this Chrome. |
857 InstallUtil::ProgramCompare open_command_pred(chrome_exe); | 857 InstallUtil::ProgramCompare open_command_pred(chrome_exe); |
858 string16 parent_key(ShellUtil::kRegClasses); | 858 base::string16 parent_key(ShellUtil::kRegClasses); |
859 parent_key.push_back(base::FilePath::kSeparators[0]); | 859 parent_key.push_back(base::FilePath::kSeparators[0]); |
860 const string16::size_type base_length = parent_key.size(); | 860 const base::string16::size_type base_length = parent_key.size(); |
861 string16 child_key; | 861 base::string16 child_key; |
862 for (const wchar_t* const* proto = | 862 for (const wchar_t* const* proto = |
863 &ShellUtil::kPotentialProtocolAssociations[0]; | 863 &ShellUtil::kPotentialProtocolAssociations[0]; |
864 *proto != NULL; | 864 *proto != NULL; |
865 ++proto) { | 865 ++proto) { |
866 parent_key.resize(base_length); | 866 parent_key.resize(base_length); |
867 parent_key.append(*proto); | 867 parent_key.append(*proto); |
868 child_key.assign(parent_key).append(ShellUtil::kRegShellOpen); | 868 child_key.assign(parent_key).append(ShellUtil::kRegShellOpen); |
869 InstallUtil::DeleteRegistryKeyIf(root, parent_key, child_key, NULL, | 869 InstallUtil::DeleteRegistryKeyIf(root, parent_key, child_key, NULL, |
870 open_command_pred); | 870 open_command_pred); |
871 } | 871 } |
872 | 872 |
873 RemoveFiletypeRegistration(installer_state, root, browser_entry_suffix); | 873 RemoveFiletypeRegistration(installer_state, root, browser_entry_suffix); |
874 | 874 |
875 *exit_code = installer::UNINSTALL_SUCCESSFUL; | 875 *exit_code = installer::UNINSTALL_SUCCESSFUL; |
876 return true; | 876 return true; |
877 } | 877 } |
878 | 878 |
879 void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist, | 879 void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist, |
880 const string16& chrome_exe) { | 880 const base::string16& chrome_exe) { |
881 // We used to register Chrome to handle crx files, but this turned out | 881 // We used to register Chrome to handle crx files, but this turned out |
882 // to be not worth the hassle. Remove these old registry entries if | 882 // to be not worth the hassle. Remove these old registry entries if |
883 // they exist. See: http://codereview.chromium.org/210007 | 883 // they exist. See: http://codereview.chromium.org/210007 |
884 | 884 |
885 #if defined(GOOGLE_CHROME_BUILD) | 885 #if defined(GOOGLE_CHROME_BUILD) |
886 const wchar_t kChromeExtProgId[] = L"ChromeExt"; | 886 const wchar_t kChromeExtProgId[] = L"ChromeExt"; |
887 #else | 887 #else |
888 const wchar_t kChromeExtProgId[] = L"ChromiumExt"; | 888 const wchar_t kChromeExtProgId[] = L"ChromiumExt"; |
889 #endif | 889 #endif |
890 | 890 |
891 HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER }; | 891 HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER }; |
892 for (size_t i = 0; i < arraysize(roots); ++i) { | 892 for (size_t i = 0; i < arraysize(roots); ++i) { |
893 string16 suffix; | 893 base::string16 suffix; |
894 if (roots[i] == HKEY_LOCAL_MACHINE) | 894 if (roots[i] == HKEY_LOCAL_MACHINE) |
895 suffix = ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe); | 895 suffix = ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe); |
896 | 896 |
897 // Delete Software\Classes\ChromeExt, | 897 // Delete Software\Classes\ChromeExt, |
898 string16 ext_prog_id(ShellUtil::kRegClasses); | 898 base::string16 ext_prog_id(ShellUtil::kRegClasses); |
899 ext_prog_id.push_back(base::FilePath::kSeparators[0]); | 899 ext_prog_id.push_back(base::FilePath::kSeparators[0]); |
900 ext_prog_id.append(kChromeExtProgId); | 900 ext_prog_id.append(kChromeExtProgId); |
901 ext_prog_id.append(suffix); | 901 ext_prog_id.append(suffix); |
902 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); | 902 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); |
903 | 903 |
904 // Delete Software\Classes\.crx, | 904 // Delete Software\Classes\.crx, |
905 string16 ext_association(ShellUtil::kRegClasses); | 905 base::string16 ext_association(ShellUtil::kRegClasses); |
906 ext_association.append(L"\\"); | 906 ext_association.append(L"\\"); |
907 ext_association.append(extensions::kExtensionFileExtension); | 907 ext_association.append(extensions::kExtensionFileExtension); |
908 InstallUtil::DeleteRegistryKey(roots[i], ext_association); | 908 InstallUtil::DeleteRegistryKey(roots[i], ext_association); |
909 } | 909 } |
910 } | 910 } |
911 | 911 |
912 // Builds and executes a work item list to remove DelegateExecute verb handler | 912 // Builds and executes a work item list to remove DelegateExecute verb handler |
913 // work items for |product|. This will be a noop for products whose | 913 // work items for |product|. This will be a noop for products whose |
914 // corresponding BrowserDistribution implementations do not publish a CLSID via | 914 // corresponding BrowserDistribution implementations do not publish a CLSID via |
915 // GetCommandExecuteImplClsid. | 915 // GetCommandExecuteImplClsid. |
(...skipping 16 matching lines...) Expand all Loading... |
932 BrowserDistribution* distribution = product.distribution(); | 932 BrowserDistribution* distribution = product.distribution(); |
933 | 933 |
934 if (!product.is_chrome() || !installer_state.system_install()) { | 934 if (!product.is_chrome() || !installer_state.system_install()) { |
935 const char* install_level = | 935 const char* install_level = |
936 installer_state.system_install() ? "system" : "user"; | 936 installer_state.system_install() ? "system" : "user"; |
937 VLOG(1) << "No Active Setup processing to do for " << install_level | 937 VLOG(1) << "No Active Setup processing to do for " << install_level |
938 << "-level " << distribution->GetDisplayName(); | 938 << "-level " << distribution->GetDisplayName(); |
939 return; | 939 return; |
940 } | 940 } |
941 | 941 |
942 const string16 active_setup_path( | 942 const base::string16 active_setup_path( |
943 InstallUtil::GetActiveSetupPath(distribution)); | 943 InstallUtil::GetActiveSetupPath(distribution)); |
944 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); | 944 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); |
945 | 945 |
946 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ | 946 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ |
947 // Active Setup\\Installed Components\\{guid} | 947 // Active Setup\\Installed Components\\{guid} |
948 // for every user that logged in since system-level Chrome was installed. | 948 // for every user that logged in since system-level Chrome was installed. |
949 // This is a problem because Windows compares the value of the Version subkey | 949 // This is a problem because Windows compares the value of the Version subkey |
950 // in there with the value of the Version subkey in the matching HKLM entries | 950 // in there with the value of the Version subkey in the matching HKLM entries |
951 // before running Chrome's Active Setup so if Chrome was to be reinstalled | 951 // before running Chrome's Active Setup so if Chrome was to be reinstalled |
952 // with a lesser version (e.g. switching back to a more stable channel), the | 952 // with a lesser version (e.g. switching back to a more stable channel), the |
953 // affected users would not have Chrome's Active Setup called until Chrome | 953 // affected users would not have Chrome's Active Setup called until Chrome |
954 // eventually updated passed that user's registered Version. | 954 // eventually updated passed that user's registered Version. |
955 // | 955 // |
956 // It is however very hard to delete those values as the registry hives for | 956 // It is however very hard to delete those values as the registry hives for |
957 // other users are not loaded by default under HKEY_USERS (unless a user is | 957 // other users are not loaded by default under HKEY_USERS (unless a user is |
958 // logged on or has a process impersonating him). | 958 // logged on or has a process impersonating him). |
959 // | 959 // |
960 // Following our best effort uninstall practices, try to delete the value in | 960 // Following our best effort uninstall practices, try to delete the value in |
961 // all users hives. If a given user's hive is not loaded, try to load it to | 961 // all users hives. If a given user's hive is not loaded, try to load it to |
962 // proceed with the deletion (failure to do so is ignored). | 962 // proceed with the deletion (failure to do so is ignored). |
963 | 963 |
964 static const wchar_t kProfileList[] = | 964 static const wchar_t kProfileList[] = |
965 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; | 965 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; |
966 | 966 |
967 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, | 967 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, |
968 // but doesn't seem to do so when manually deleting the user-level keys it | 968 // but doesn't seem to do so when manually deleting the user-level keys it |
969 // created. | 969 // created. |
970 string16 alternate_active_setup_path(active_setup_path); | 970 base::string16 alternate_active_setup_path(active_setup_path); |
971 alternate_active_setup_path.insert(arraysize("Software\\") - 1, | 971 alternate_active_setup_path.insert(arraysize("Software\\") - 1, |
972 L"Wow6432Node\\"); | 972 L"Wow6432Node\\"); |
973 | 973 |
974 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. | 974 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. |
975 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); | 975 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); |
976 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); | 976 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); |
977 if (!se_restore_name_privilege.is_enabled() || | 977 if (!se_restore_name_privilege.is_enabled() || |
978 !se_backup_name_privilege.is_enabled()) { | 978 !se_backup_name_privilege.is_enabled()) { |
979 // This is not a critical failure as those privileges aren't required to | 979 // This is not a critical failure as those privileges aren't required to |
980 // clean hives that are already loaded, but attempts to LoadRegKey() below | 980 // clean hives that are already loaded, but attempts to LoadRegKey() below |
981 // will fail. | 981 // will fail. |
982 LOG(WARNING) << "Failed to enable privileges required to load registry " | 982 LOG(WARNING) << "Failed to enable privileges required to load registry " |
983 "hives."; | 983 "hives."; |
984 } | 984 } |
985 | 985 |
986 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); | 986 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); |
987 it.Valid(); ++it) { | 987 it.Valid(); ++it) { |
988 const wchar_t* profile_sid = it.Name(); | 988 const wchar_t* profile_sid = it.Name(); |
989 | 989 |
990 // First check if this user's registry hive needs to be loaded in | 990 // First check if this user's registry hive needs to be loaded in |
991 // HKEY_USERS. | 991 // HKEY_USERS. |
992 base::win::RegKey user_reg_root_probe( | 992 base::win::RegKey user_reg_root_probe( |
993 HKEY_USERS, profile_sid, KEY_READ); | 993 HKEY_USERS, profile_sid, KEY_READ); |
994 bool loaded_hive = false; | 994 bool loaded_hive = false; |
995 if (!user_reg_root_probe.Valid()) { | 995 if (!user_reg_root_probe.Valid()) { |
996 VLOG(1) << "Attempting to load registry hive for " << profile_sid; | 996 VLOG(1) << "Attempting to load registry hive for " << profile_sid; |
997 | 997 |
998 string16 reg_profile_info_path(kProfileList); | 998 base::string16 reg_profile_info_path(kProfileList); |
999 reg_profile_info_path.append(profile_sid); | 999 reg_profile_info_path.append(profile_sid); |
1000 base::win::RegKey reg_profile_info_key( | 1000 base::win::RegKey reg_profile_info_key( |
1001 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); | 1001 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); |
1002 | 1002 |
1003 string16 profile_path; | 1003 base::string16 profile_path; |
1004 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", | 1004 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", |
1005 &profile_path); | 1005 &profile_path); |
1006 if (result != ERROR_SUCCESS) { | 1006 if (result != ERROR_SUCCESS) { |
1007 LOG(ERROR) << "Error reading ProfileImagePath: " << result; | 1007 LOG(ERROR) << "Error reading ProfileImagePath: " << result; |
1008 continue; | 1008 continue; |
1009 } | 1009 } |
1010 base::FilePath registry_hive_file(profile_path); | 1010 base::FilePath registry_hive_file(profile_path); |
1011 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); | 1011 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); |
1012 | 1012 |
1013 result = RegLoadKey(HKEY_USERS, profile_sid, | 1013 result = RegLoadKey(HKEY_USERS, profile_sid, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 | 1046 |
1047 InstallStatus UninstallProduct(const InstallationState& original_state, | 1047 InstallStatus UninstallProduct(const InstallationState& original_state, |
1048 const InstallerState& installer_state, | 1048 const InstallerState& installer_state, |
1049 const base::FilePath& setup_path, | 1049 const base::FilePath& setup_path, |
1050 const Product& product, | 1050 const Product& product, |
1051 bool remove_all, | 1051 bool remove_all, |
1052 bool force_uninstall, | 1052 bool force_uninstall, |
1053 const CommandLine& cmd_line) { | 1053 const CommandLine& cmd_line) { |
1054 InstallStatus status = installer::UNINSTALL_CONFIRMED; | 1054 InstallStatus status = installer::UNINSTALL_CONFIRMED; |
1055 BrowserDistribution* browser_dist = product.distribution(); | 1055 BrowserDistribution* browser_dist = product.distribution(); |
1056 const string16 chrome_exe( | 1056 const base::string16 chrome_exe( |
1057 installer_state.target_path().Append(installer::kChromeExe).value()); | 1057 installer_state.target_path().Append(installer::kChromeExe).value()); |
1058 | 1058 |
1059 bool is_chrome = product.is_chrome(); | 1059 bool is_chrome = product.is_chrome(); |
1060 | 1060 |
1061 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); | 1061 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); |
1062 | 1062 |
1063 if (force_uninstall) { | 1063 if (force_uninstall) { |
1064 // Since --force-uninstall command line option is used, we are going to | 1064 // Since --force-uninstall command line option is used, we are going to |
1065 // do silent uninstall. Try to close all running Chrome instances. | 1065 // do silent uninstall. Try to close all running Chrome instances. |
1066 // NOTE: We don't do this for Chrome Frame. | 1066 // NOTE: We don't do this for Chrome Frame. |
1067 if (is_chrome) | 1067 if (is_chrome) |
1068 CloseAllChromeProcesses(); | 1068 CloseAllChromeProcesses(); |
1069 } else if (is_chrome) { | 1069 } else if (is_chrome) { |
1070 // no --force-uninstall so lets show some UI dialog boxes. | 1070 // no --force-uninstall so lets show some UI dialog boxes. |
1071 status = IsChromeActiveOrUserCancelled(installer_state, product); | 1071 status = IsChromeActiveOrUserCancelled(installer_state, product); |
1072 if (status != installer::UNINSTALL_CONFIRMED && | 1072 if (status != installer::UNINSTALL_CONFIRMED && |
1073 status != installer::UNINSTALL_DELETE_PROFILE) | 1073 status != installer::UNINSTALL_DELETE_PROFILE) |
1074 return status; | 1074 return status; |
1075 | 1075 |
1076 const string16 suffix(ShellUtil::GetCurrentInstallationSuffix(browser_dist, | 1076 const base::string16 suffix( |
1077 chrome_exe)); | 1077 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); |
1078 | 1078 |
1079 // Check if we need admin rights to cleanup HKLM (the conditions for | 1079 // Check if we need admin rights to cleanup HKLM (the conditions for |
1080 // requiring a cleanup are the same as the conditions to do the actual | 1080 // requiring a cleanup are the same as the conditions to do the actual |
1081 // cleanup where DeleteChromeRegistrationKeys() is invoked for | 1081 // cleanup where DeleteChromeRegistrationKeys() is invoked for |
1082 // HKEY_LOCAL_MACHINE below). If we do, try to launch another uninstaller | 1082 // HKEY_LOCAL_MACHINE below). If we do, try to launch another uninstaller |
1083 // (silent) in elevated mode to do HKLM cleanup. | 1083 // (silent) in elevated mode to do HKLM cleanup. |
1084 // And continue uninstalling in the current process also to do HKCU cleanup. | 1084 // And continue uninstalling in the current process also to do HKCU cleanup. |
1085 if (remove_all && | 1085 if (remove_all && |
1086 ShellUtil::QuickIsChromeRegisteredInHKLM( | 1086 ShellUtil::QuickIsChromeRegisteredInHKLM( |
1087 browser_dist, chrome_exe, suffix) && | 1087 browser_dist, chrome_exe, suffix) && |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 } | 1137 } |
1138 | 1138 |
1139 DeleteShortcuts(installer_state, product, base::FilePath(chrome_exe)); | 1139 DeleteShortcuts(installer_state, product, base::FilePath(chrome_exe)); |
1140 } | 1140 } |
1141 | 1141 |
1142 // Delete the registry keys (Uninstall key and Version key). | 1142 // Delete the registry keys (Uninstall key and Version key). |
1143 HKEY reg_root = installer_state.root_key(); | 1143 HKEY reg_root = installer_state.root_key(); |
1144 | 1144 |
1145 // Note that we must retrieve the distribution-specific data before deleting | 1145 // Note that we must retrieve the distribution-specific data before deleting |
1146 // product.GetVersionKey(). | 1146 // product.GetVersionKey(). |
1147 string16 distribution_data(browser_dist->GetDistributionData(reg_root)); | 1147 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); |
1148 | 1148 |
1149 // Remove Control Panel uninstall link. | 1149 // Remove Control Panel uninstall link. |
1150 if (product.ShouldCreateUninstallEntry()) { | 1150 if (product.ShouldCreateUninstallEntry()) { |
1151 InstallUtil::DeleteRegistryKey(reg_root, | 1151 InstallUtil::DeleteRegistryKey(reg_root, |
1152 browser_dist->GetUninstallRegPath()); | 1152 browser_dist->GetUninstallRegPath()); |
1153 } | 1153 } |
1154 | 1154 |
1155 // Remove Omaha product key. | 1155 // Remove Omaha product key. |
1156 InstallUtil::DeleteRegistryKey(reg_root, browser_dist->GetVersionKey()); | 1156 InstallUtil::DeleteRegistryKey(reg_root, browser_dist->GetVersionKey()); |
1157 | 1157 |
1158 // Also try to delete the MSI value in the ClientState key (it might not be | 1158 // Also try to delete the MSI value in the ClientState key (it might not be |
1159 // there). This is due to a Google Update behaviour where an uninstall and a | 1159 // there). This is due to a Google Update behaviour where an uninstall and a |
1160 // rapid reinstall might result in stale values from the old ClientState key | 1160 // rapid reinstall might result in stale values from the old ClientState key |
1161 // being picked up on reinstall. | 1161 // being picked up on reinstall. |
1162 product.SetMsiMarker(installer_state.system_install(), false); | 1162 product.SetMsiMarker(installer_state.system_install(), false); |
1163 | 1163 |
1164 InstallStatus ret = installer::UNKNOWN_STATUS; | 1164 InstallStatus ret = installer::UNKNOWN_STATUS; |
1165 | 1165 |
1166 if (is_chrome) { | 1166 if (is_chrome) { |
1167 const string16 suffix(ShellUtil::GetCurrentInstallationSuffix(browser_dist, | 1167 const base::string16 suffix( |
1168 chrome_exe)); | 1168 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); |
1169 | 1169 |
1170 // Remove all Chrome registration keys. | 1170 // Remove all Chrome registration keys. |
1171 // Registration data is put in HKCU for both system level and user level | 1171 // Registration data is put in HKCU for both system level and user level |
1172 // installs. | 1172 // installs. |
1173 DeleteChromeRegistrationKeys(installer_state, browser_dist, | 1173 DeleteChromeRegistrationKeys(installer_state, browser_dist, |
1174 HKEY_CURRENT_USER, suffix, &ret); | 1174 HKEY_CURRENT_USER, suffix, &ret); |
1175 | 1175 |
1176 // If the user's Chrome is registered with a suffix: it is possible that old | 1176 // If the user's Chrome is registered with a suffix: it is possible that old |
1177 // unsuffixed registrations were left in HKCU (e.g. if this install was | 1177 // unsuffixed registrations were left in HKCU (e.g. if this install was |
1178 // previously installed with no suffix in HKCU (old suffix rules if the user | 1178 // previously installed with no suffix in HKCU (old suffix rules if the user |
1179 // is not an admin (or declined UAC at first run)) and later had to be | 1179 // is not an admin (or declined UAC at first run)) and later had to be |
1180 // suffixed when fully registered in HKLM (e.g. when later making Chrome | 1180 // suffixed when fully registered in HKLM (e.g. when later making Chrome |
1181 // default through the UI)). | 1181 // default through the UI)). |
1182 // Remove remaining HKCU entries with no suffix if any. | 1182 // Remove remaining HKCU entries with no suffix if any. |
1183 if (!suffix.empty()) { | 1183 if (!suffix.empty()) { |
1184 DeleteChromeRegistrationKeys(installer_state, browser_dist, | 1184 DeleteChromeRegistrationKeys(installer_state, browser_dist, |
1185 HKEY_CURRENT_USER, string16(), &ret); | 1185 HKEY_CURRENT_USER, base::string16(), &ret); |
1186 | 1186 |
1187 // For similar reasons it is possible in very few installs (from | 1187 // For similar reasons it is possible in very few installs (from |
1188 // 21.0.1180.0 and fixed shortly after) to be installed with the new-style | 1188 // 21.0.1180.0 and fixed shortly after) to be installed with the new-style |
1189 // suffix, but have some old-style suffix registrations left behind. | 1189 // suffix, but have some old-style suffix registrations left behind. |
1190 string16 old_style_suffix; | 1190 base::string16 old_style_suffix; |
1191 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) && | 1191 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) && |
1192 suffix != old_style_suffix) { | 1192 suffix != old_style_suffix) { |
1193 DeleteChromeRegistrationKeys(installer_state, browser_dist, | 1193 DeleteChromeRegistrationKeys(installer_state, browser_dist, |
1194 HKEY_CURRENT_USER, old_style_suffix, &ret); | 1194 HKEY_CURRENT_USER, old_style_suffix, &ret); |
1195 } | 1195 } |
1196 } | 1196 } |
1197 | 1197 |
1198 // Chrome is registered in HKLM for all system-level installs and for | 1198 // Chrome is registered in HKLM for all system-level installs and for |
1199 // user-level installs for which Chrome has been made the default browser. | 1199 // user-level installs for which Chrome has been made the default browser. |
1200 // Always remove the HKLM registration for system-level installs. For | 1200 // Always remove the HKLM registration for system-level installs. For |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 original_state.GetProductState(installer_state.system_install(), | 1257 original_state.GetProductState(installer_state.system_install(), |
1258 browser_dist->GetType()); | 1258 browser_dist->GetType()); |
1259 | 1259 |
1260 // Delete shared registry keys as well (these require admin rights) if | 1260 // Delete shared registry keys as well (these require admin rights) if |
1261 // remove_all option is specified. | 1261 // remove_all option is specified. |
1262 if (remove_all) { | 1262 if (remove_all) { |
1263 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { | 1263 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { |
1264 // Delete media player registry key that exists only in HKLM. | 1264 // Delete media player registry key that exists only in HKLM. |
1265 // We don't delete this key in SxS uninstall or Chrome Frame uninstall | 1265 // We don't delete this key in SxS uninstall or Chrome Frame uninstall |
1266 // as we never set the key for those products. | 1266 // as we never set the key for those products. |
1267 string16 reg_path(installer::kMediaPlayerRegPath); | 1267 base::string16 reg_path(installer::kMediaPlayerRegPath); |
1268 reg_path.push_back(base::FilePath::kSeparators[0]); | 1268 reg_path.push_back(base::FilePath::kSeparators[0]); |
1269 reg_path.append(installer::kChromeExe); | 1269 reg_path.append(installer::kChromeExe); |
1270 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path); | 1270 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path); |
1271 } | 1271 } |
1272 | 1272 |
1273 // Unregister any dll servers that we may have registered for this | 1273 // Unregister any dll servers that we may have registered for this |
1274 // product. | 1274 // product. |
1275 if (product_state != NULL) { | 1275 if (product_state != NULL) { |
1276 std::vector<base::FilePath> com_dll_list; | 1276 std::vector<base::FilePath> com_dll_list; |
1277 product.AddComDllList(&com_dll_list); | 1277 product.AddComDllList(&com_dll_list); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1416 // If we need a reboot to continue, schedule the parent directories for | 1416 // If we need a reboot to continue, schedule the parent directories for |
1417 // deletion unconditionally. If they are not empty, the session manager | 1417 // deletion unconditionally. If they are not empty, the session manager |
1418 // will not delete them on reboot. | 1418 // will not delete them on reboot. |
1419 ScheduleParentAndGrandparentForDeletion(target_path); | 1419 ScheduleParentAndGrandparentForDeletion(target_path); |
1420 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1420 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
1421 *uninstall_status = UNINSTALL_FAILED; | 1421 *uninstall_status = UNINSTALL_FAILED; |
1422 } | 1422 } |
1423 } | 1423 } |
1424 | 1424 |
1425 } // namespace installer | 1425 } // namespace installer |
OLD | NEW |