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

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

Issue 96193003: Uninstall multi-install Chrome Frame when updated. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Unittest and Robert comments Created 7 years 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 | « PRESUBMIT.py ('k') | chrome/installer/util/install_util.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/setup/setup_main.cc
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 9ffc986279f0534a5ddc63e3bc7b722a7ee72ca3..2d67de2f2ba09fec43f16e4658fdc99d13a03735 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -701,63 +701,6 @@ bool CreateTemporaryAndUnpackDirectories(
return true;
}
-installer::InstallStatus InstallProducts(
- const InstallationState& original_state,
- const CommandLine& cmd_line,
- const MasterPreferences& prefs,
- InstallerState* installer_state,
- base::FilePath* installer_directory) {
- DCHECK(installer_state);
- const bool system_install = installer_state->system_install();
- installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
- installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
- bool delegated_to_existing = false;
- installer_state->UpdateStage(installer::PRECONDITIONS);
- // The stage provides more fine-grained information than -multifail, so remove
- // the -multifail suffix from the Google Update "ap" value.
- BrowserDistribution::GetSpecificDistribution(installer_state->state_type())->
- UpdateInstallStatus(system_install, archive_type, install_status);
- if (CheckPreInstallConditions(original_state, installer_state,
- &install_status)) {
- VLOG(1) << "Installing to " << installer_state->target_path().value();
- install_status = InstallProductsHelper(
- original_state, cmd_line, prefs, *installer_state,
- installer_directory, &archive_type, &delegated_to_existing);
- } else {
- // CheckPreInstallConditions must set the status on failure.
- DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
- }
-
- // Delete the master preferences file if present. Note that we do not care
- // about rollback here and we schedule for deletion on reboot if the delete
- // fails. As such, we do not use DeleteTreeWorkItem.
- if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
- base::FilePath prefs_path(cmd_line.GetSwitchValuePath(
- installer::switches::kInstallerData));
- if (!base::DeleteFile(prefs_path, false)) {
- LOG(ERROR) << "Failed deleting master preferences file "
- << prefs_path.value()
- << ", scheduling for deletion after reboot.";
- ScheduleFileSystemEntityForDeletion(prefs_path);
- }
- }
-
- // Early exit if this setup.exe delegated to another, since that one would
- // have taken care of UpdateInstallStatus and UpdateStage.
- if (delegated_to_existing)
- return install_status;
-
- const Products& products = installer_state->products();
- for (Products::const_iterator it = products.begin(); it < products.end();
- ++it) {
- (*it)->distribution()->UpdateInstallStatus(
- system_install, archive_type, install_status);
- }
-
- installer_state->UpdateStage(installer::NO_STAGE);
- return install_status;
-}
-
installer::InstallStatus UninstallProduct(
const InstallationState& original_state,
const InstallerState& installer_state,
@@ -868,6 +811,100 @@ installer::InstallStatus UninstallProducts(
return install_status;
}
+// Uninstall the binaries if they are the only product present and they're not
+// in-use.
+void UninstallBinariesIfUnused(
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
+ installer::InstallStatus* install_status) {
+ // Early exit if the binaries are still in use.
+ if (*install_status != installer::UNUSED_BINARIES ||
+ installer_state.AreBinariesInUse(original_state)) {
+ return;
+ }
+
+ LOG(INFO) << "Uninstalling unused binaries";
robertshield 2013/12/03 02:20:05 VLOG(1) instead?
grt (UTC plus 2) 2013/12/03 13:37:51 I thought this would be useful to have in the inst
+ installer_state.UpdateStage(installer::UNINSTALLING_BINARIES);
+
+ // Simulate the uninstall as coming from the installed version.
+ const ProductState* binaries_state =
+ original_state.GetProductState(installer_state.system_install(),
+ BrowserDistribution::CHROME_BINARIES);
+ const CommandLine& uninstall_cmd(binaries_state->uninstall_command());
+ MasterPreferences uninstall_prefs(uninstall_cmd);
+ InstallerState uninstall_state;
+ uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, original_state);
+
+ *install_status =
+ UninstallProducts(original_state, uninstall_state, uninstall_cmd);
+
+ // Report that the binaries were uninstalled if they were. This translates
+ // into a successful install return code.
+ if (IsUninstallSuccess(*install_status)) {
+ *install_status = installer::UNUSED_BINARIES_UNINSTALLED;
+ installer_state.WriteInstallerResult(*install_status, 0, NULL);
+ }
+}
+
+installer::InstallStatus InstallProducts(
+ const InstallationState& original_state,
+ const CommandLine& cmd_line,
+ const MasterPreferences& prefs,
+ InstallerState* installer_state,
+ base::FilePath* installer_directory) {
+ DCHECK(installer_state);
+ const bool system_install = installer_state->system_install();
+ installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
+ installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
+ bool delegated_to_existing = false;
+ installer_state->UpdateStage(installer::PRECONDITIONS);
+ // The stage provides more fine-grained information than -multifail, so remove
+ // the -multifail suffix from the Google Update "ap" value.
+ BrowserDistribution::GetSpecificDistribution(installer_state->state_type())->
+ UpdateInstallStatus(system_install, archive_type, install_status);
+ if (CheckPreInstallConditions(original_state, installer_state,
+ &install_status)) {
+ VLOG(1) << "Installing to " << installer_state->target_path().value();
+ install_status = InstallProductsHelper(
+ original_state, cmd_line, prefs, *installer_state,
+ installer_directory, &archive_type, &delegated_to_existing);
+ } else {
+ // CheckPreInstallConditions must set the status on failure.
+ DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
+ }
+
+ // Delete the master preferences file if present. Note that we do not care
+ // about rollback here and we schedule for deletion on reboot if the delete
+ // fails. As such, we do not use DeleteTreeWorkItem.
+ if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
+ base::FilePath prefs_path(cmd_line.GetSwitchValuePath(
+ installer::switches::kInstallerData));
+ if (!base::DeleteFile(prefs_path, false)) {
+ LOG(ERROR) << "Failed deleting master preferences file "
+ << prefs_path.value()
+ << ", scheduling for deletion after reboot.";
+ ScheduleFileSystemEntityForDeletion(prefs_path);
+ }
+ }
+
+ // Early exit if this setup.exe delegated to another, since that one would
+ // have taken care of UpdateInstallStatus and UpdateStage.
+ if (delegated_to_existing)
+ return install_status;
+
+ const Products& products = installer_state->products();
+ for (Products::const_iterator it = products.begin(); it < products.end();
+ ++it) {
+ (*it)->distribution()->UpdateInstallStatus(
+ system_install, archive_type, install_status);
+ }
+
+ UninstallBinariesIfUnused(original_state, *installer_state, &install_status);
+
+ installer_state->UpdateStage(installer::NO_STAGE);
+ return install_status;
+}
+
installer::InstallStatus ShowEULADialog(const string16& inner_frame) {
VLOG(1) << "About to show EULA";
string16 eula_path = installer::GetLocalizedEulaResource();
@@ -1367,6 +1404,63 @@ google_breakpad::ExceptionHandler* InitializeCrashReporting(
return breakpad;
}
+// Uninstalls multi-install Chrome Frame if the current operation is a
+// multi-install install or update. The operation is performed directly rather
+// than delegated to the existing install since there is no facility in older
+// versions of setup.exe to uninstall GCF without touching the binaries. The
+// binaries will be uninstalled during later processing if they are not in-use
+// (see UninstallBinariesIfUnused). |original_state| and |installer_state| are
+// updated to reflect the state of the world following the operation.
+void UninstallMultiChromeFrameIfPresent(const CommandLine& cmd_line,
+ const MasterPreferences& prefs,
+ InstallationState* original_state,
+ InstallerState* installer_state) {
+ // Early exit if not installing or updating multi-install product(s).
+ if (installer_state->operation() != InstallerState::MULTI_INSTALL &&
+ installer_state->operation() != InstallerState::MULTI_UPDATE) {
+ return;
+ }
+
+ // Early exit if Chrome Frame is not present as multi-install.
+ const ProductState* chrome_frame_state =
+ original_state->GetProductState(installer_state->system_install(),
+ BrowserDistribution::CHROME_FRAME);
+ if (!chrome_frame_state || !chrome_frame_state->is_multi_install())
+ return;
+
+ LOG(INFO) << "Uninstalling multi-install Chrome Frame.";
+ installer_state->UpdateStage(installer::UNINSTALLING_CHROME_FRAME);
+
+ // Uninstall Chrome Frame without touching the multi-install binaries.
+ // Simulate the uninstall as coming from the installed version.
+ const CommandLine& uninstall_cmd(chrome_frame_state->uninstall_command());
+ MasterPreferences uninstall_prefs(uninstall_cmd);
+ InstallerState uninstall_state;
+ uninstall_state.Initialize(uninstall_cmd, uninstall_prefs, *original_state);
+ const Product* chrome_frame_product = uninstall_state.FindProduct(
+ BrowserDistribution::CHROME_FRAME);
+ if (chrome_frame_product) {
+ // No shared state should be left behind.
+ const bool remove_all = true;
+ // Don't accept no for an answer.
+ const bool force_uninstall = true;
+ installer::InstallStatus uninstall_status =
+ installer::UninstallProduct(*original_state, uninstall_state,
+ uninstall_cmd.GetProgram(),
+ *chrome_frame_product, remove_all,
+ force_uninstall, cmd_line);
+
+ VLOG(1) << "Uninstallation of Chrome Frame returned status "
+ << uninstall_status;
+ } else {
+ LOG(ERROR) << "Chrome Frame not found for uninstall.";
+ }
+
+ // Refresh state for the continuation of the original install/update.
+ original_state->Initialize();
+ installer_state->Initialize(cmd_line, prefs, *original_state);
+}
+
} // namespace
namespace installer {
@@ -1775,27 +1869,21 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
}
}
+ UninstallMultiChromeFrameIfPresent(cmd_line, prefs,
+ &original_state, &installer_state);
+
base::FilePath installer_directory;
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
- // If --uninstall option is not specified, we assume it is install case.
- if (!is_uninstall) {
+ // If --uninstall option is given, uninstall the identified product(s)
+ if (is_uninstall) {
+ install_status =
+ UninstallProducts(original_state, installer_state, cmd_line);
+ } else {
+ // If --uninstall option is not specified, we assume it is install case.
install_status =
InstallProducts(original_state, cmd_line, prefs, &installer_state,
&installer_directory);
}
- // If --uninstall option is given or only the binaries are present and they're
- // not in-use, uninstall the identified product(s).
- if (is_uninstall || (install_status == installer::UNUSED_BINARIES &&
- !installer_state.AreBinariesInUse(original_state))) {
- install_status =
- UninstallProducts(original_state, installer_state, cmd_line);
- // Report that the binaries were uninstalled if they were. This translates
- // into a successful install return code.
- if (!is_uninstall && IsUninstallSuccess(install_status)) {
- install_status = installer::UNUSED_BINARIES_UNINSTALLED;
- installer_state.WriteInstallerResult(install_status, 0, NULL);
- }
- }
// Validate that the machine is now in a good state following the operation.
// TODO(grt): change this to log at DFATAL once we're convinced that the
« no previous file with comments | « PRESUBMIT.py ('k') | chrome/installer/util/install_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698