Index: chrome/installer/setup/uninstall.cc |
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc |
index 8a56753df03ec07fe1b2f9ee2b29da593cfa85bb..33cc7007ef0115545bec048158b6e1858b3ee8bc 100644 |
--- a/chrome/installer/setup/uninstall.cc |
+++ b/chrome/installer/setup/uninstall.cc |
@@ -220,33 +220,6 @@ void CloseChromeFrameHelperProcess() { |
} |
} |
-// This method tries to figure out if current user has registered Chrome. |
-// It returns true iff there is a registered browser that will launch the |
-// same chrome.exe as the current installation. |
-bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state) { |
- using base::win::RegistryKeyIterator; |
- const HKEY root = HKEY_LOCAL_MACHINE; |
- InstallUtil::ProgramCompare open_command_pred( |
- installer_state.target_path().Append(kChromeExe)); |
- string16 client_open_path; |
- RegKey client_open_key; |
- string16 reg_exe; |
- for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet); |
- iter.Valid(); ++iter) { |
- client_open_path.assign(ShellUtil::kRegStartMenuInternet) |
- .append(1, L'\\') |
- .append(iter.Name()) |
- .append(ShellUtil::kRegShellOpen); |
- if (client_open_key.Open(root, client_open_path.c_str(), |
- KEY_QUERY_VALUE) == ERROR_SUCCESS && |
- client_open_key.ReadValue(L"", ®_exe) == ERROR_SUCCESS && |
- open_command_pred.Evaluate(reg_exe)) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
// This method deletes Chrome shortcut folder from Windows Start menu. It |
// checks system_uninstall to see if the shortcut is in all users start menu |
// or current user start menu. |
@@ -664,7 +637,8 @@ bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root, |
return true; |
} |
-void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist) { |
+void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist, |
+ const string16& chrome_exe) { |
// We used to register Chrome to handle crx files, but this turned out |
// to be not worth the hassle. Remove these old registry entries if |
// they exist. See: http://codereview.chromium.org/210007 |
@@ -678,9 +652,8 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt"; |
HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER }; |
for (size_t i = 0; i < arraysize(roots); ++i) { |
string16 suffix; |
- if (roots[i] == HKEY_LOCAL_MACHINE && |
- !ShellUtil::GetUserSpecificDefaultBrowserSuffix(dist, &suffix)) |
- suffix = L""; |
+ if (roots[i] == HKEY_LOCAL_MACHINE) |
+ suffix = ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe); |
// Delete Software\Classes\ChromeExt, |
string16 ext_prog_id(ShellUtil::kRegClasses); |
@@ -730,12 +703,13 @@ InstallStatus UninstallProduct(const InstallationState& original_state, |
bool force_uninstall, |
const CommandLine& cmd_line) { |
InstallStatus status = installer::UNINSTALL_CONFIRMED; |
- string16 suffix; |
- if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(product.distribution(), |
- &suffix)) |
- suffix = L""; |
- |
BrowserDistribution* browser_dist = product.distribution(); |
+ const string16 chrome_exe( |
+ installer_state.target_path().Append(installer::kChromeExe).value()); |
+ |
+ const string16 suffix(ShellUtil::GetCurrentInstallationSuffix(browser_dist, |
+ chrome_exe)); |
+ |
bool is_chrome = product.is_chrome(); |
VLOG(1) << "UninstallProduct: " << browser_dist->GetApplicationName(); |
@@ -753,11 +727,15 @@ InstallStatus UninstallProduct(const InstallationState& original_state, |
status != installer::UNINSTALL_DELETE_PROFILE) |
return status; |
- // Check if we need admin rights to cleanup HKLM. If we do, try to launch |
- // another uninstaller (silent) in elevated mode to do HKLM cleanup. |
+ // Check if we need admin rights to cleanup HKLM (the conditions for |
+ // requiring a cleanup are the same as the conditions to do the actual |
+ // cleanup where DeleteChromeRegistrationKeys() is invoked for |
+ // HKEY_LOCAL_MACHINE below). If we do, try to launch another uninstaller |
+ // (silent) in elevated mode to do HKLM cleanup. |
// And continue uninstalling in the current process also to do HKCU cleanup. |
if (remove_all && |
- (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state)) && |
+ ShellUtil::QuickIsChromeRegisteredInHKLM( |
+ browser_dist, chrome_exe, suffix) && |
!::IsUserAnAdmin() && |
base::win::GetVersion() >= base::win::VERSION_VISTA && |
!cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) { |
@@ -811,21 +789,40 @@ InstallStatus UninstallProduct(const InstallationState& original_state, |
// Registration data is put in HKCU for both system level and user level |
// installs. |
InstallStatus ret = installer::UNKNOWN_STATUS; |
- DeleteChromeRegistrationKeys(product.distribution(), HKEY_CURRENT_USER, |
- suffix, installer_state.target_path(), &ret); |
+ DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, suffix, |
+ installer_state.target_path(), &ret); |
+ |
+ // If the user's Chrome is registered with a suffix: it is possible that old |
+ // unsuffixed registrations were left in HKCU (e.g. if this install was |
+ // previously installed with no suffix in HKCU (old suffix rules if the user |
+ // is not an admin (or declined UAC at first run)) and later had to be |
+ // suffixed when fully registered in HKLM (e.g. when later making Chrome |
+ // default through the UI)). |
+ // Remove remaining HKCU entries with no suffix if any. |
+ if (!suffix.empty()) { |
+ DeleteChromeRegistrationKeys(browser_dist, HKEY_CURRENT_USER, string16(), |
+ installer_state.target_path(), &ret); |
+ } |
// Chrome is registered in HKLM for all system-level installs and for |
// user-level installs for which Chrome has been made the default browser. |
// Always remove the HKLM registration for system-level installs. For |
- // user-level installs, only remove it if both: 1) this uninstall isn't a |
- // self-destruct following the installation of system-level Chrome (because |
- // the system-level Chrome owns the HKLM registration now), and 2) this user |
- // had made Chrome their default browser. |
+ // user-level installs, only remove it if both: 1) this uninstall isn't a self |
+ // destruct following the installation of a system-level Chrome (because the |
+ // system-level Chrome owns the HKLM registration now), and 2) this user has |
+ // made Chrome their default browser (i.e. has system entries registered with |
+ // |suffix| (note: |suffix| will be the empty string if required as it is |
+ // obtained by GetCurrentInstallationSuffix() above)). |
+ // TODO(gab): This can still leave parts of a suffixed install behind. To be |
+ // able to remove them we would need to be able to remove only suffixed |
+ // entries (as it is now some of the system entries are unsuffixed; thus |
+ // removing suffixed installs is prohibited in HKLM if !|remove_all| for now). |
if (installer_state.system_install() || |
(remove_all && |
- (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state)))) { |
- DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE, |
- suffix, installer_state.target_path(), &ret); |
+ ShellUtil::QuickIsChromeRegisteredInHKLM( |
+ browser_dist, chrome_exe, suffix))) { |
+ DeleteChromeRegistrationKeys(browser_dist, HKEY_LOCAL_MACHINE, suffix, |
+ installer_state.target_path(), &ret); |
} |
ProcessDelegateExecuteWorkItems(installer_state, product); |