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

Unified Diff: chrome/installer/setup/uninstall.cc

Issue 6288009: More installer refactoring in the interest of fixing some bugs and cleaning t... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/installer/setup/setup_util.cc ('k') | chrome/installer/util/browser_distribution.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/setup/uninstall.cc
===================================================================
--- chrome/installer/setup/uninstall.cc (revision 72487)
+++ chrome/installer/setup/uninstall.cc (working copy)
@@ -29,7 +29,6 @@
#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/installer_state.h"
#include "chrome/installer/util/logging_installer.h"
-#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
@@ -38,6 +37,7 @@
using base::win::RegKey;
using installer::InstallStatus;
+using installer::MasterPreferences;
namespace {
@@ -47,10 +47,12 @@
// installed products and for the multi-installer package.
void ProcessGoogleUpdateItems(
const installer::InstallationState& original_state,
+ const installer::InstallerState& installer_state,
const installer::Product& product) {
- const bool system_level = product.system_level();
+ DCHECK(installer_state.is_multi_install());
+ const bool system_level = installer_state.system_install();
BrowserDistribution* distribution = product.distribution();
- const HKEY reg_root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ const HKEY reg_root = installer_state.root_key();
const installer::ProductState* product_state =
original_state.GetProductState(system_level, distribution->GetType());
DCHECK(product_state != NULL);
@@ -58,41 +60,42 @@
// Remove product's flags from the channel value.
channel_info.set_value(product_state->channel().value());
- const bool modified = distribution->SetChannelFlags(false, &channel_info);
+ const bool modified = product.SetChannelFlags(false, &channel_info);
// Apply the new channel value to all other products and to the multi package.
if (modified) {
- BrowserDistribution::Type other_dist_type =
+ BrowserDistribution::Type other_dist_types[] = {
(distribution->GetType() == BrowserDistribution::CHROME_BROWSER) ?
- BrowserDistribution::CHROME_FRAME :
- BrowserDistribution::CHROME_BROWSER;
- BrowserDistribution* other_dist =
- BrowserDistribution::GetSpecificDistribution(other_dist_type,
- installer::MasterPreferences::ForCurrentProcess());
+ BrowserDistribution::CHROME_FRAME :
+ BrowserDistribution::CHROME_BROWSER,
+ BrowserDistribution::CHROME_BINARIES
+ };
scoped_ptr<WorkItemList>
update_list(WorkItem::CreateNoRollbackWorkItemList());
- product_state = original_state.GetProductState(system_level,
- other_dist_type);
- if (installer::IsInstalledAsMulti(system_level, other_dist) &&
- !product_state->channel().Equals(channel_info)) {
- update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
- google_update::kRegApField, channel_info.value(), true);
- } else {
- VLOG(1) << other_dist->GetApplicationName()
- << "'s ap value is unexpectedly up to date.";
+ for (int i = 0; i < arraysize(other_dist_types); ++i) {
+ BrowserDistribution::Type other_dist_type = other_dist_types[i];
+ product_state =
+ original_state.GetProductState(system_level, other_dist_type);
+ // Only modify other products if they're installed and multi.
+ if (product_state != NULL &&
+ product_state->is_multi_install() &&
+ !product_state->channel().Equals(channel_info)) {
+ BrowserDistribution* other_dist =
+ BrowserDistribution::GetSpecificDistribution(other_dist_type);
+ update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
+ google_update::kRegApField, channel_info.value(), true);
+ } else {
+ LOG_IF(DFATAL,
+ product_state != NULL && product_state->is_multi_install())
+ << "Channel value for "
+ << BrowserDistribution::GetSpecificDistribution(
+ other_dist_type)->GetAppShortCutName()
+ << " is somehow already set to the desired new value of "
+ << channel_info.value();
+ }
}
- product_state = original_state.GetMultiPackageState(system_level);
- DCHECK(product_state != NULL);
- if (!product_state->channel().Equals(channel_info)) {
- update_list->AddSetRegValueWorkItem(reg_root,
- product.package().properties()->GetStateKey(),
- google_update::kRegApField, channel_info.value(), true);
- } else {
- VLOG(1) << "Multi-install package's ap value is unexpectedly up to date.";
- }
-
bool success = update_list->Do();
LOG_IF(ERROR, !success) << "Failed updating channel values.";
}
@@ -175,14 +178,16 @@
// It returns true iff:
// - Software\Clients\StartMenuInternet\Chromium\"" key has a valid value.
// - The value is same as chrome.exe path for the current installation.
-bool CurrentUserHasDefaultBrowser(const Product& product) {
+bool CurrentUserHasDefaultBrowser(const InstallerState& installer_state,
+ const Product& product) {
std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
- reg_key.append(L"\\" + product.distribution()->GetApplicationName() +
- ShellUtil::kRegShellOpen);
+ reg_key.append(1, L'\\')
+ .append(product.distribution()->GetApplicationName())
+ .append(ShellUtil::kRegShellOpen);
RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str(), KEY_READ);
std::wstring reg_exe;
if (key.ReadValue(L"", &reg_exe) == ERROR_SUCCESS && reg_exe.length() > 2) {
- FilePath chrome_exe(product.package().path()
+ FilePath chrome_exe(installer_state.target_path()
.Append(installer::kChromeExe));
// The path in the registry will always have quotes.
reg_exe = reg_exe.substr(1, reg_exe.length() - 2);
@@ -199,14 +204,15 @@
// 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 DeleteChromeShortcuts(const Product& product) {
+void DeleteChromeShortcuts(const InstallerState& installer_state,
+ const Product& product) {
if (!product.is_chrome()) {
VLOG(1) << __FUNCTION__ " called for non-CHROME distribution";
return;
}
FilePath shortcut_path;
- if (product.system_level()) {
+ if (installer_state.system_install()) {
PathService::Get(base::DIR_COMMON_START_MENU, &shortcut_path);
if (!ShellUtil::RemoveChromeDesktopShortcut(product.distribution(),
ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, false)) {
@@ -332,11 +338,11 @@
return result;
}
-bool MoveSetupOutOfInstallFolder(const Package& package,
+bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
const FilePath& setup_path,
const Version& installed_version) {
bool ret = false;
- FilePath setup_exe(package.GetInstallerDirectory(installed_version)
+ FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version)
.Append(setup_path.BaseName()));
FilePath temp_file;
if (!file_util::CreateTemporaryFile(&temp_file)) {
@@ -349,33 +355,33 @@
return ret;
}
-DeleteResult DeleteFilesAndFolders(const Package& package,
+DeleteResult DeleteFilesAndFolders(const InstallerState& installer_state,
const Version& installed_version) {
- VLOG(1) << "DeleteFilesAndFolders: " << package.path().value();
- if (package.path().empty()) {
+ VLOG(1) << "DeleteFilesAndFolders: " << installer_state.target_path().value();
+ if (installer_state.target_path().empty()) {
LOG(ERROR) << "Could not get installation destination path.";
return DELETE_FAILED; // Nothing else we can do to uninstall, so we return.
}
DeleteResult result = DELETE_SUCCEEDED;
- VLOG(1) << "Deleting install path " << package.path().value();
- if (!file_util::Delete(package.path(), true)) {
+ VLOG(1) << "Deleting install path " << installer_state.target_path().value();
+ if (!file_util::Delete(installer_state.target_path(), true)) {
LOG(ERROR) << "Failed to delete folder (1st try): "
- << package.path().value();
- if (FindProduct(package.products(),
- BrowserDistribution::CHROME_FRAME)) {
+ << installer_state.target_path().value();
+ if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
// We don't try killing Chrome processes for Chrome Frame builds since
// that is unlikely to help. Instead, schedule files for deletion and
// return a value that will trigger a reboot prompt.
- ScheduleDirectoryForDeletion(package.path().value().c_str());
+ ScheduleDirectoryForDeletion(
+ installer_state.target_path().value().c_str());
result = DELETE_REQUIRES_REBOOT;
} else {
// Try closing any running chrome processes and deleting files once again.
CloseAllChromeProcesses();
- if (!file_util::Delete(package.path(), true)) {
+ if (!file_util::Delete(installer_state.target_path(), true)) {
LOG(ERROR) << "Failed to delete folder (2nd try): "
- << package.path().value();
+ << installer_state.target_path().value();
result = DELETE_FAILED;
}
}
@@ -385,11 +391,11 @@
// If we need a reboot to continue, schedule the parent directories for
// deletion unconditionally. If they are not empty, the session manager
// will not delete them on reboot.
- ScheduleParentAndGrandparentForDeletion(package.path());
+ ScheduleParentAndGrandparentForDeletion(installer_state.target_path());
} else {
// Now check and delete if the parent directories are empty
// For example Google\Chrome or Chromium
- DeleteEmptyParentDir(package.path());
+ DeleteEmptyParentDir(installer_state.target_path());
}
return result;
}
@@ -397,7 +403,9 @@
// This method checks if Chrome is currently running or if the user has
// cancelled the uninstall operation by clicking Cancel on the confirmation
// box that Chrome pops up.
-InstallStatus IsChromeActiveOrUserCancelled(const Product& product) {
+InstallStatus IsChromeActiveOrUserCancelled(
+ const InstallerState& installer_state,
+ const Product& product) {
int32 exit_code = ResultCodes::NORMAL_EXIT;
CommandLine options(CommandLine::NO_PROGRAM);
options.AppendSwitch(installer::switches::kUninstall);
@@ -411,7 +419,8 @@
// give this method some brains and not kill chrome.exe launched
// by us, we will not uninstall if we get this return code).
VLOG(1) << "Launching Chrome to do uninstall tasks.";
- if (product.LaunchChromeAndWait(options, &exit_code)) {
+ if (product.LaunchChromeAndWait(installer_state.target_path(), options,
+ &exit_code)) {
VLOG(1) << "chrome.exe launched for uninstall confirmation returned: "
<< exit_code;
if ((exit_code == ResultCodes::UNINSTALL_CHROME_ALIVE) ||
@@ -428,7 +437,8 @@
return installer::UNINSTALL_CONFIRMED;
}
-bool ShouldDeleteProfile(const CommandLine& cmd_line, InstallStatus status,
+bool ShouldDeleteProfile(const InstallerState& installer_state,
+ const CommandLine& cmd_line, InstallStatus status,
const Product& product) {
bool should_delete = false;
@@ -436,7 +446,7 @@
// UI to prompt otherwise and the profile stores no useful data anyway)
// unless they are managed by MSI. MSI uninstalls will explicitly include
// the --delete-profile flag to distinguish them from MSI upgrades.
- if (!product.is_chrome() && !product.IsMsi()) {
+ if (!product.is_chrome() && !installer_state.is_msi()) {
should_delete = true;
} else {
should_delete =
@@ -542,16 +552,16 @@
}
}
-bool ProcessChromeFrameWorkItems(const FilePath& setup_path,
- const Product& product,
- const ProductState* product_state) {
+bool ProcessChromeFrameWorkItems(const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const FilePath& setup_path,
+ const Product& product) {
if (!product.is_chrome_frame())
return false;
- DCHECK(product_state != NULL);
scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
- AddChromeFrameWorkItems(false, setup_path, product_state->version(), product,
- item_list.get());
+ AddChromeFrameWorkItems(original_state, installer_state, setup_path,
+ Version(), product, item_list.get());
return item_list->Do();
}
@@ -581,7 +591,7 @@
CloseAllChromeProcesses();
} else if (is_chrome) {
// no --force-uninstall so lets show some UI dialog boxes.
- status = IsChromeActiveOrUserCancelled(product);
+ status = IsChromeActiveOrUserCancelled(installer_state, product);
if (status != installer::UNINSTALL_CONFIRMED &&
status != installer::UNINSTALL_DELETE_PROFILE)
return status;
@@ -590,7 +600,8 @@
// 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(product)) &&
+ (!suffix.empty() ||
+ CurrentUserHasDefaultBrowser(installer_state, product)) &&
!::IsUserAnAdmin() &&
base::win::GetVersion() >= base::win::VERSION_VISTA &&
!cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) {
@@ -615,11 +626,10 @@
// in case of errors.
// First delete shortcuts from Start->Programs, Desktop & Quick Launch.
- DeleteChromeShortcuts(product);
+ DeleteChromeShortcuts(installer_state, product);
// Delete the registry keys (Uninstall key and Version key).
- HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
+ HKEY reg_root = installer_state.root_key();
RegKey key(reg_root, L"", KEY_ALL_ACCESS);
// Note that we must retrieve the distribution-specific data before deleting
@@ -634,31 +644,34 @@
// there). This is due to a Google Update behaviour where an uninstall and a
// rapid reinstall might result in stale values from the old ClientState key
// being picked up on reinstall.
- product.SetMsiMarker(false);
+ product.SetMsiMarker(installer_state.system_install(), false);
// Remove all Chrome registration keys.
InstallStatus ret = installer::UNKNOWN_STATUS;
DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret);
- // Get the state of the installed product (if any)
- const ProductState* product_state =
- original_state.GetProductState(installer_state.system_install(),
- browser_dist->GetType());
+ if (!is_chrome) {
+ ProcessChromeFrameWorkItems(original_state, installer_state, setup_path,
+ product);
+ }
- if (!is_chrome)
- ProcessChromeFrameWorkItems(setup_path, product, product_state);
+ if (installer_state.is_multi_install())
+ ProcessGoogleUpdateItems(original_state, installer_state, product);
- if (product.package().multi_install())
- ProcessGoogleUpdateItems(original_state, product);
-
// 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 && !product.system_level() &&
- (!suffix.empty() || CurrentUserHasDefaultBrowser(product))) {
+ if (remove_all && !installer_state.system_install() &&
+ (!suffix.empty() || CurrentUserHasDefaultBrowser(installer_state,
+ product))) {
DeleteChromeRegistrationKeys(product.distribution(), HKEY_LOCAL_MACHINE,
suffix, ret);
}
+ // Get the state of the installed product (if any)
+ const ProductState* product_state =
+ original_state.GetProductState(installer_state.system_install(),
+ browser_dist->GetType());
+
// Delete shared registry keys as well (these require admin rights) if
// remove_all option is specified.
if (remove_all) {
@@ -675,8 +688,9 @@
// Unregister any dll servers that we may have registered for this
// product.
if (product_state != NULL) {
- std::vector<FilePath> com_dll_list(browser_dist->GetComDllList());
- FilePath dll_folder = product.package().path().Append(
+ std::vector<FilePath> com_dll_list;
+ product.AddComDllList(&com_dll_list);
+ FilePath dll_folder = installer_state.target_path().Append(
UTF8ToWide(product_state->version().GetString()));
scoped_ptr<WorkItemList> unreg_work_item_list(
@@ -685,7 +699,7 @@
AddRegisterComDllWorkItems(dll_folder,
com_dll_list,
- product.system_level(),
+ installer_state.system_install(),
false, // Unregister
true, // May fail
unreg_work_item_list.get());
@@ -704,25 +718,35 @@
// Finally delete all the files from Chrome folder after moving setup.exe
// and the user's Local State to a temp location.
- bool delete_profile = ShouldDeleteProfile(cmd_line, status, product);
+ bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status,
+ product);
ret = installer::UNINSTALL_SUCCESSFUL;
// When deleting files, we must make sure that we're either a "single"
// (aka non-multi) installation or, in the case of multi, that no other
// "multi" products share the binaries we are about to delete.
- bool can_delete_files;
- if (product.package().multi_install()) {
- can_delete_files =
- (product.package().GetMultiInstallDependencyCount() == 0);
+ bool can_delete_files = true;
+ if (installer_state.is_multi_install()) {
+ BrowserDistribution::Type types[] = {
+ BrowserDistribution::CHROME_BROWSER,
+ BrowserDistribution::CHROME_FRAME
+ };
+ ProductState prod_state;
+ for (int i = 0; i < arraysize(types); ++i) {
+ if (prod_state.Initialize(installer_state.system_install(), types[i]) &&
+ prod_state.is_multi_install()) {
+ can_delete_files = false;
+ break;
+ }
+ }
LOG(INFO) << (can_delete_files ? "Shared binaries will be deleted." :
"Shared binaries still in use.");
- PackageProperties* props = product.package().properties();
- if (can_delete_files && props->ReceivesUpdates()) {
- InstallUtil::DeleteRegistryKey(key, props->GetVersionKey());
+ if (can_delete_files) {
+ BrowserDistribution* multi_dist =
+ installer_state.multi_package_binaries_distribution();
+ InstallUtil::DeleteRegistryKey(key, multi_dist->GetVersionKey());
}
- } else {
- can_delete_files = true;
}
FilePath backup_state_file(BackupLocalStateFile(
@@ -733,9 +757,9 @@
// In order to be able to remove the folder in which we're running, we
// need to move setup.exe out of the install folder.
// TODO(tommi): What if the temp folder is on a different volume?
- MoveSetupOutOfInstallFolder(product.package(), setup_path,
+ MoveSetupOutOfInstallFolder(installer_state, setup_path,
product_state->version());
- delete_result = DeleteFilesAndFolders(product.package(),
+ delete_result = DeleteFilesAndFolders(installer_state,
product_state->version());
}
@@ -763,4 +787,3 @@
}
} // namespace installer
-
« no previous file with comments | « chrome/installer/setup/setup_util.cc ('k') | chrome/installer/util/browser_distribution.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698