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

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

Issue 2333853002: Support --delete-old-versions in setup.exe. (Closed)
Patch Set: CR grt/rkaplow #8-9 Created 4 years, 2 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/install.cc ('k') | chrome/installer/setup/setup_singleton.h » ('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 966ac436cf6d69fa4edda23d967cb45996b202c9..9a9fe4b7399fd5e971a27000dee3dedfdb345d0e 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -26,6 +26,7 @@
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/memory.h"
+#include "base/process/process.h"
#include "base/process/process_metrics.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
@@ -56,6 +57,7 @@
#include "chrome/installer/setup/uninstall.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
+#include "chrome/installer/util/delete_old_versions.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
@@ -386,14 +388,79 @@ void AddExistingMultiInstalls(const InstallationState& original_state,
}
}
+void RecordNumDeleteOldVersionsAttempsBeforeAbort(int num_attempts) {
+ UMA_HISTOGRAM_COUNTS_100(
+ "Setup.Install.NumDeleteOldVersionsAttemptsBeforeAbort", num_attempts);
+}
+
+// Repetitively attempts to delete all files that belong to old versions of
+// Chrome from |install_dir|. Waits 15 seconds before the first attempt and 5
+// minutes after each unsuccessful attempt. Returns when no files that belong to
+// an old version of Chrome remain or when another process tries to acquire the
+// SetupSingleton.
+installer::InstallStatus RepeatDeleteOldVersions(
+ const base::FilePath& install_dir,
+ const installer::SetupSingleton& setup_singleton) {
+ constexpr int kMaxNumAttempts = 12;
+ int num_attempts = 0;
+
+ while (num_attempts < kMaxNumAttempts) {
+ // Wait 15 seconds before the first attempt because trying to delete old
+ // files right away is likely to fail. Indeed, this is called in 2
+ // occasions:
+ // - When the installer fails to delete old files after a not-in-use update:
+ // retrying immediately is likely to fail again.
+ // - When executables are successfully renamed on Chrome startup or
+ // shutdown: old files can't be deleted because Chrome is still in use.
+ // Wait 5 minutes after an unsuccessful attempt because retrying immediately
+ // is likely to fail again.
+ const base::TimeDelta max_wait_time = num_attempts == 0
+ ? base::TimeDelta::FromSeconds(15)
+ : base::TimeDelta::FromMinutes(5);
+ if (setup_singleton.WaitForInterrupt(max_wait_time)) {
+ VLOG(1) << "Exiting --delete-old-versions process because another "
+ "process tries to acquire the SetupSingleton.";
+ RecordNumDeleteOldVersionsAttempsBeforeAbort(num_attempts);
+ return installer::SETUP_SINGLETON_RELEASED;
+ }
+
+ const bool was_backgrounded =
+ base::Process::Current().SetProcessBackgrounded(true);
+ const bool delete_old_versions_success =
+ installer::DeleteOldVersions(install_dir);
+ if (!was_backgrounded)
+ base::Process::Current().SetProcessBackgrounded(false);
+ ++num_attempts;
+
+ if (delete_old_versions_success) {
+ VLOG(1) << "Successfully deleted all old files from "
+ "--delete-old-versions process.";
+ UMA_HISTOGRAM_COUNTS_100(
+ "Setup.Install.NumDeleteOldVersionsAttemptsBeforeSuccess",
+ num_attempts);
+ return installer::DELETE_OLD_VERSIONS_SUCCESS;
+ } else if (num_attempts == 1) {
+ VLOG(1) << "Failed to delete all old files from --delete-old-versions "
+ "process. Will retry every five minutes.";
+ }
+ }
+
+ VLOG(1) << "Exiting --delete-old-versions process after retrying too many "
+ "times to delete all old files.";
+ DCHECK_EQ(num_attempts, kMaxNumAttempts);
+ RecordNumDeleteOldVersionsAttempsBeforeAbort(num_attempts);
+ return installer::DELETE_OLD_VERSIONS_TOO_MANY_ATTEMPTS;
+}
+
// This function is called when --rename-chrome-exe option is specified on
// setup.exe command line. This function assumes an in-use update has happened
// for Chrome so there should be a file called new_chrome.exe on the file
// system and a key called 'opv' in the registry. This function will move
// new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation.
// This function also deletes elevation policies associated with the old version
-// if they exist.
+// if they exist. |setup_exe| is the path to the current executable.
installer::InstallStatus RenameChromeExecutables(
+ const base::FilePath& setup_exe,
const InstallationState& original_state,
InstallerState* installer_state) {
// See what products are already installed in multi mode. When we do the
@@ -454,7 +521,9 @@ installer::InstallStatus RenameChromeExecutables(
->set_best_effort(true);
installer::InstallStatus ret = installer::RENAME_SUCCESSFUL;
- if (!install_list->Do()) {
+ if (install_list->Do()) {
+ installer::LaunchDeleteOldVersionsProcess(setup_exe, *installer_state);
+ } else {
LOG(ERROR) << "Renaming of executables failed. Rolling back any changes.";
install_list->Rollback();
ret = installer::RENAME_FAILED;
@@ -1235,17 +1304,26 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
LOG(DFATAL) << "Can't register browser - Chrome distribution not found";
}
*exit_code = InstallUtil::GetInstallReturnCode(status);
- } else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) {
- // If --rename-chrome-exe is specified, we want to rename the executables
- // and exit.
+ } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions) ||
+ cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) {
std::unique_ptr<installer::SetupSingleton> setup_singleton(
installer::SetupSingleton::Acquire(
cmd_line, MasterPreferences::ForCurrentProcess(), original_state,
installer_state));
- if (!setup_singleton)
+ if (!setup_singleton) {
*exit_code = installer::SETUP_SINGLETON_ACQUISITION_FAILED;
- else
- *exit_code = RenameChromeExecutables(*original_state, installer_state);
+ } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions)) {
+ // In multi-install mode, determine what products are installed to
+ // populate the target_path() used below.
+ AddExistingMultiInstalls(*original_state, installer_state);
+
+ *exit_code = RepeatDeleteOldVersions(installer_state->target_path(),
+ *setup_singleton);
+ } else {
+ DCHECK(cmd_line.HasSwitch(installer::switches::kRenameChromeExe));
+ *exit_code =
+ RenameChromeExecutables(setup_exe, *original_state, installer_state);
+ }
} else if (cmd_line.HasSwitch(
installer::switches::kRemoveChromeRegistration)) {
// This is almost reverse of --register-chrome-browser option above.
« no previous file with comments | « chrome/installer/setup/install.cc ('k') | chrome/installer/setup/setup_singleton.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698