diff options
author | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-06 16:20:18 +0000 |
---|---|---|
committer | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-06 16:20:18 +0000 |
commit | 09a988dd76797e19acd4702b96aa6c283d66a1e5 (patch) | |
tree | a03bee69be2f6be1eddea21545951ec991b5abeb /chrome/installer | |
parent | 91c1719fd596d7381e359d294314b24abd02597c (diff) | |
download | chromium_src-09a988dd76797e19acd4702b96aa6c283d66a1e5.zip chromium_src-09a988dd76797e19acd4702b96aa6c283d66a1e5.tar.gz chromium_src-09a988dd76797e19acd4702b96aa6c283d66a1e5.tar.bz2 |
Re-re-write the logic to elevate uninstaller.
BUG=7178
TEST=Test install/uninstall in various combinations as described below and make sure that files or registry keys are not left behind:
Distribution: {Chromium|Google Chrome}
Install Level: {system|user}
Delete Profile Option: {Selected|Not selected}
Default Browser: {set|not set}
Review URL: http://codereview.chromium.org/109037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15412 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/setup/main.cc | 92 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.cc | 148 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.h | 10 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.cc | 5 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.h | 3 |
5 files changed, 140 insertions, 118 deletions
diff --git a/chrome/installer/setup/main.cc b/chrome/installer/setup/main.cc index 20fb65c..2795edd 100644 --- a/chrome/installer/setup/main.cc +++ b/chrome/installer/setup/main.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -278,22 +278,6 @@ void CopyPreferenceFileForFirstRun(int options, const CommandLine& cmd_line) { } } -// This method is temporary and only called by UpdateChromeOpenCmd() below. -void ReplaceRegistryValue(const std::wstring& reg_key, - const std::wstring& old_val, - const std::wstring& new_val) { - RegKey key; - std::wstring value; - if (key.Open(HKEY_CLASSES_ROOT, reg_key.c_str(), KEY_READ) && - key.ReadValue(NULL, &value) && (old_val == value)) { - std::wstring key_path = L"Software\\Classes\\" + reg_key; - if (key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE)) - key.WriteValue(NULL, new_val.c_str()); - if (key.Open(HKEY_LOCAL_MACHINE, key_path.c_str(), KEY_WRITE)) - key.WriteValue(NULL, new_val.c_str()); - } -} - bool CheckPreInstallConditions(const installer::Version* installed_version, int options, installer_util::InstallStatus& status) { @@ -501,6 +485,49 @@ installer_util::InstallStatus ShowEULADialog(const std::wstring& inner_frame) { return installer_util::EULA_ACCEPTED; } +// This method processes any command line options that make setup.exe do +// various tasks other than installation (renaming chrome.exe, showing eula +// among others). This function returns true if any such command line option +// has been found and processed (so setup.exe should exit at that point). +bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line, + bool system_install, + int& exit_code) { + if (cmd_line.HasSwitch(installer_util::switches::kShowEula)) { + // Check if we need to show the EULA. If it is passed as a command line + // then the dialog is shown and regardless of the outcome setup exits here. + std::wstring inner_frame = + cmd_line.GetSwitchValue(installer_util::switches::kShowEula); + exit_code = ShowEULADialog(inner_frame); + if (installer_util::EULA_REJECTED != exit_code) + GoogleUpdateSettings::SetEULAConsent(true); + return true;; + } else if (cmd_line.HasSwitch( + installer_util::switches::kRegisterChromeBrowser)) { + // If --register-chrome-browser option is specified, register all + // Chrome protocol/file associations as well as register it as a valid + // browser for Start Menu->Internet shortcut. This option should only + // be used when setup.exe is launched with admin rights. We do not + // make any user specific changes in this option. + std::wstring chrome_exe(cmd_line.GetSwitchValue( + installer_util::switches::kRegisterChromeBrowser)); + exit_code = ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true); + return true; + } else if (cmd_line.HasSwitch(installer_util::switches::kRenameChromeExe)) { + // If --rename-chrome-exe is specified, we want to rename the executables + // and exit. + exit_code = RenameChromeExecutables(system_install); + return true; + } else if (cmd_line.HasSwitch( + installer_util::switches::kRemoveChromeRegistration)) { + installer_util::InstallStatus tmp = installer_util::UNKNOWN_STATUS; + installer_setup::DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE, tmp); + exit_code = tmp; + return true; + } + + return false; +} + } // namespace int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, @@ -536,33 +563,10 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, return installer_util::OS_ERROR; } - // Check if we need to show the EULA. If it is passed as a command line - // then the dialog is shown and regardless of the outcome setup exits here. - if (parsed_command_line.HasSwitch(installer_util::switches::kShowEula)) { - std::wstring inner_frame = - parsed_command_line.GetSwitchValue(installer_util::switches::kShowEula); - installer_util::InstallStatus eula = ShowEULADialog(inner_frame); - if (installer_util::EULA_REJECTED != eula) - GoogleUpdateSettings::SetEULAConsent(true); - return eula; - } - - // If --register-chrome-browser option is specified, register all - // Chrome protocol/file associations as well as register it as a valid - // browser for Start Menu->Internet shortcut. This option should only - // be used when setup.exe is launched with admin rights. We do not - // make any user specific changes in this option. - if (parsed_command_line.HasSwitch( - installer_util::switches::kRegisterChromeBrowser)) { - std::wstring chrome_exe(parsed_command_line.GetSwitchValue( - installer_util::switches::kRegisterChromeBrowser)); - return ShellUtil::AddChromeToSetAccessDefaults(chrome_exe, true); - // If --rename-chrome-exe is specified, we want to rename the executables - // and exit. - } else if (parsed_command_line.HasSwitch( - installer_util::switches::kRenameChromeExe)) { - return RenameChromeExecutables(system_install); - } + int exit_code = 0; + if (HandleNonInstallCmdLineOptions(parsed_command_line, system_install, + exit_code)) + return exit_code; if (system_install && !IsUserAnAdmin()) { if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA && diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc index 1203125..ef04da4 100644 --- a/chrome/installer/setup/uninstall.cc +++ b/chrome/installer/setup/uninstall.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -6,8 +6,6 @@ #include "chrome/installer/setup/uninstall.h" -#include <shlobj.h> - #include "base/file_util.h" #include "base/path_service.h" #include "base/registry.h" @@ -66,7 +64,7 @@ void CloseAllChromeProcesses() { // We try to remove the standard desktop shortcut but if that fails we try // to remove the alternate desktop shortcut. Only one of them should be // present in a given install but at this point we don't know which one. -void DeleteChromeShortcut(bool system_uninstall) { +void DeleteChromeShortcuts(bool system_uninstall) { FilePath shortcut_path; if (system_uninstall) { PathService::Get(base::DIR_COMMON_START_MENU, &shortcut_path); @@ -226,6 +224,67 @@ installer_util::InstallStatus IsChromeActiveOrUserCancelled( } // namespace +bool installer_setup::DeleteChromeRegistrationKeys(HKEY root, + installer_util::InstallStatus& exit_code) { + RegKey key(root, L"", KEY_ALL_ACCESS); + + // Delete Software\Classes\ChromeHTML, + std::wstring html_prog_id(ShellUtil::kRegClasses); + file_util::AppendToPath(&html_prog_id, ShellUtil::kChromeHTMLProgId); + DeleteRegistryKey(key, html_prog_id); + + // Delete Software\Classes\ChromeExt, + std::wstring ext_prog_id(ShellUtil::kRegClasses); + file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId); + DeleteRegistryKey(key, ext_prog_id); + + // Delete Software\Classes\.crx, + std::wstring ext_association(ShellUtil::kRegClasses); + ext_association.append(L"\\."); + ext_association.append(chrome::kExtensionFileExtension); + DeleteRegistryKey(key, ext_association); + + // Delete Software\Clients\StartMenuInternet\chrome.exe + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + std::wstring set_access_key(ShellUtil::kRegStartMenuInternet); + file_util::AppendToPath(&set_access_key, dist->GetApplicationName()); + DeleteRegistryKey(key, set_access_key); + // We have renamed the StartMenuInternet\chrome.exe to + // StartMenuInternet\Chromium so for old users we still need to delete + // the old key. + std::wstring old_set_access_key(ShellUtil::kRegStartMenuInternet); + file_util::AppendToPath(&old_set_access_key, installer_util::kChromeExe); + DeleteRegistryKey(key, old_set_access_key); + + // Delete Software\RegisteredApplications\Chrome + DeleteRegistryValue(root, ShellUtil::kRegRegisteredApplications, + dist->GetApplicationName()); + + // Delete Software\Classes\Applications\chrome.exe + std::wstring app_key(ShellUtil::kRegClasses); + file_util::AppendToPath(&app_key, L"Applications"); + file_util::AppendToPath(&app_key, installer_util::kChromeExe); + DeleteRegistryKey(key, app_key); + + // Delete the App Paths key that lets explorer find Chrome. + std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); + file_util::AppendToPath(&app_path_key, installer_util::kChromeExe); + DeleteRegistryKey(key, app_path_key); + + //Cleanup OpenWithList + for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { + std::wstring open_with_key(ShellUtil::kRegClasses); + file_util::AppendToPath(&open_with_key, ShellUtil::kFileAssociations[i]); + file_util::AppendToPath(&open_with_key, L"OpenWithList"); + file_util::AppendToPath(&open_with_key, installer_util::kChromeExe); + DeleteRegistryKey(key, open_with_key); + } + + key.Close(); + exit_code = installer_util::UNINSTALL_SUCCESSFUL; + return true; +} + installer_util::InstallStatus installer_setup::UninstallChrome( const std::wstring& exe_path, bool system_uninstall, bool remove_all, bool force_uninstall, @@ -255,13 +314,9 @@ installer_util::InstallStatus installer_setup::UninstallChrome( // that we already tried to launch ourselves as admin. params.append(L" --"); params.append(installer_util::switches::kRunAsAdmin); - // Append --force-uninstall to keep it silent. + // Append --remove-chrome-registration to remove registry keys only. params.append(L" --"); - params.append(installer_util::switches::kForceUninstall); - if (status == installer_util::UNINSTALL_DELETE_PROFILE) { - params.append(L" --"); - params.append(installer_util::switches::kDeleteProfile); - } + params.append(installer_util::switches::kRemoveChromeRegistration); DWORD exit_code = installer_util::UNKNOWN_STATUS; InstallUtil::ExecuteExeAsAdmin(exe, params, &exit_code); } @@ -274,8 +329,9 @@ installer_util::InstallStatus installer_setup::UninstallChrome( // Chrome is not in use so lets uninstall Chrome by deleting various files // and registry entries. Here we will just make best effort and keep going // in case of errors. + // First delete shortcuts from Start->Programs, Desktop & Quick Launch. - DeleteChromeShortcut(system_uninstall); + DeleteChromeShortcuts(system_uninstall); // Delete the registry keys (Uninstall key and Version key). HKEY reg_root = system_uninstall ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; @@ -286,74 +342,24 @@ installer_util::InstallStatus installer_setup::UninstallChrome( // dist->GetVersionKey(). std::wstring distribution_data(dist->GetDistributionData(&key)); + // Remove Control Panel uninstall link and Omaha product key. DeleteRegistryKey(key, dist->GetUninstallRegPath()); DeleteRegistryKey(key, dist->GetVersionKey()); - // Delete Software\Classes\ChromeHTML, - // Delete Software\Classes\ChromeExt, - // Delete Software\Classes\.crx, - // Software\Clients\StartMenuInternet\chrome.exe and - // Software\RegisteredApplications\Chrome - std::wstring html_prog_id(ShellUtil::kRegClasses); - file_util::AppendToPath(&html_prog_id, ShellUtil::kChromeHTMLProgId); - DeleteRegistryKey(key, html_prog_id); - std::wstring ext_prog_id(ShellUtil::kRegClasses); - file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId); - DeleteRegistryKey(key, ext_prog_id); - std::wstring ext_association(ShellUtil::kRegClasses); - ext_association.append(L"\\."); - ext_association.append(chrome::kExtensionFileExtension); - DeleteRegistryKey(key, ext_association); - - std::wstring set_access_key(ShellUtil::kRegStartMenuInternet); - file_util::AppendToPath(&set_access_key, dist->GetApplicationName()); - DeleteRegistryKey(key, set_access_key); - // We have renamed the StartMenuInternet\chrome.exe to - // StartMenuInternet\Chromium so for old users we still need to delete - // the old key. - std::wstring old_set_access_key(ShellUtil::kRegStartMenuInternet); - file_util::AppendToPath(&old_set_access_key, installer_util::kChromeExe); - DeleteRegistryKey(key, old_set_access_key); - - DeleteRegistryValue(reg_root, ShellUtil::kRegRegisteredApplications, - dist->GetApplicationName()); + // Remove all Chrome registration keys. + installer_util::InstallStatus ret = installer_util::UNKNOWN_STATUS; + DeleteChromeRegistrationKeys(reg_root, ret); - // Cleanup Software\Classes\Applications\chrome.exe and OpenWithList - RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS); - std::wstring app_key(ShellUtil::kRegClasses); - file_util::AppendToPath(&app_key, L"Applications"); - file_util::AppendToPath(&app_key, installer_util::kChromeExe); - DeleteRegistryKey(key, app_key); - if (remove_all) - DeleteRegistryKey(hklm_key, app_key); - for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { - std::wstring open_with_key(ShellUtil::kRegClasses); - file_util::AppendToPath(&open_with_key, ShellUtil::kFileAssociations[i]); - file_util::AppendToPath(&open_with_key, L"OpenWithList"); - file_util::AppendToPath(&open_with_key, installer_util::kChromeExe); - DeleteRegistryKey(key, open_with_key); - if (remove_all) - DeleteRegistryKey(hklm_key, open_with_key); - } - key.Close(); + // For user level install also we end up creating some keys in HKLM if user + // sets Chrome as default browser. So delete those as well (needs admin). + if (remove_all && !system_uninstall) + DeleteChromeRegistrationKeys(HKEY_LOCAL_MACHINE, ret); // Delete shared registry keys as well (these require admin rights) if // remove_all option is specified. if (remove_all) { - DeleteRegistryKey(hklm_key, set_access_key); - DeleteRegistryKey(hklm_key, html_prog_id); - DeleteRegistryKey(hklm_key, ext_prog_id); - DeleteRegistryKey(hklm_key, ext_association); - DeleteRegistryValue(HKEY_LOCAL_MACHINE, - ShellUtil::kRegRegisteredApplications, - dist->GetApplicationName()); - - // Delete the App Paths key that lets explorer find Chrome. - std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); - file_util::AppendToPath(&app_path_key, installer_util::kChromeExe); - DeleteRegistryKey(hklm_key, app_path_key); - // Delete media player registry key that exists only in HKLM. + RegKey hklm_key(HKEY_LOCAL_MACHINE, L"", KEY_ALL_ACCESS); std::wstring reg_path(installer::kMediaPlayerRegPath); file_util::AppendToPath(®_path, installer_util::kChromeExe); DeleteRegistryKey(hklm_key, reg_path); @@ -381,7 +387,7 @@ installer_util::InstallStatus installer_setup::UninstallChrome( bool delete_profile = (status == installer_util::UNINSTALL_DELETE_PROFILE) || (cmd_line.HasSwitch(installer_util::switches::kDeleteProfile)); std::wstring local_state_path; - installer_util::InstallStatus ret = installer_util::UNINSTALL_SUCCESSFUL; + ret = installer_util::UNINSTALL_SUCCESSFUL; if (!DeleteFilesAndFolders(exe_path, system_uninstall, *installed_version, &local_state_path, delete_profile)) ret = installer_util::UNINSTALL_FAILED; diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h index b8478b7..2f44f80 100644 --- a/chrome/installer/setup/uninstall.h +++ b/chrome/installer/setup/uninstall.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,11 +9,19 @@ #include <string> +#include <shlobj.h> + #include "base/command_line.h" #include "chrome/installer/util/util_constants.h" #include "chrome/installer/util/version.h" namespace installer_setup { +// This function removes all Chrome registration related keys. It returns true +// if successful, otherwise false. The error code is set in |exit_code|. +// |root| is the registry root (HKLM|HKCU) +bool DeleteChromeRegistrationKeys(HKEY root, + installer_util::InstallStatus& exit_code); + // This function uninstalls Chrome. // // exe_path: Path to the executable (setup.exe) as it will be copied diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index 223ae2e..1a29688 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -57,6 +57,9 @@ const wchar_t kRegisterChromeBrowser[] = L"register-chrome-browser"; // to support in-use updates. Also deletes opv key. const wchar_t kRenameChromeExe[] = L"rename-chrome-exe"; +// Removes Chrome registration from current machine. Requires admin rights. +const wchar_t kRemoveChromeRegistration[] = L"remove-chrome-registration"; + // When we try to relaunch setup.exe as admin on Vista, we append this command // line flag so that we try the launch only once. const wchar_t kRunAsAdmin[] = L"run-as-admin"; diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index 2c1d674..625b253 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -80,6 +80,7 @@ extern const wchar_t kLogFile[]; extern const wchar_t kMakeChromeDefault[]; extern const wchar_t kRegisterChromeBrowser[]; extern const wchar_t kRenameChromeExe[]; +extern const wchar_t kRemoveChromeRegistration[]; extern const wchar_t kRunAsAdmin[]; extern const wchar_t kSystemLevel[]; extern const wchar_t kUninstall[]; |