| Index: chrome/installer/setup/setup_main.cc
|
| diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
|
| index 94f38532e53c1ac647e158c9c8e2e4c005d4f256..8506c0bb032f3e6b180715b6c7f6a5987181d3ad 100644
|
| --- a/chrome/installer/setup/setup_main.cc
|
| +++ b/chrome/installer/setup/setup_main.cc
|
| @@ -85,7 +85,6 @@ using installer::InstallationState;
|
| using installer::MasterPreferences;
|
| using installer::Product;
|
| using installer::ProductState;
|
| -using installer::Products;
|
|
|
| namespace {
|
|
|
| @@ -222,9 +221,9 @@ std::unique_ptr<installer::ArchivePatchHelper> CreateChromeArchiveHelper(
|
| // This format is strange and its provenance is shrouded in mystery but it has
|
| // the data we need, so use it.
|
| base::string16 FindMsiProductId(const InstallerState& installer_state,
|
| - const Product* product) {
|
| + const Product& product) {
|
| HKEY reg_root = installer_state.root_key();
|
| - BrowserDistribution* dist = product->distribution();
|
| + BrowserDistribution* dist = product.distribution();
|
| DCHECK(dist);
|
|
|
| base::win::RegistryValueIterator value_iter(reg_root,
|
| @@ -338,51 +337,6 @@ bool UncompressAndPatchChromeArchive(
|
| return true;
|
| }
|
|
|
| -// In multi-install, adds all products to |installer_state| that are
|
| -// multi-installed and must be updated along with the products already present
|
| -// in |installer_state|.
|
| -void AddExistingMultiInstalls(const InstallationState& original_state,
|
| - InstallerState* installer_state) {
|
| - if (installer_state->is_multi_install()) {
|
| - for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
|
| - BrowserDistribution::Type type =
|
| - static_cast<BrowserDistribution::Type>(i);
|
| -
|
| - if (!installer_state->FindProduct(type)) {
|
| - const ProductState* state =
|
| - original_state.GetProductState(installer_state->system_install(),
|
| - type);
|
| - if (state) {
|
| - if (state->is_multi_install()) {
|
| - installer_state->AddProductFromState(type, *state);
|
| - VLOG(1) << "Product already installed and must be included: "
|
| - << BrowserDistribution::GetSpecificDistribution(type)
|
| - ->GetDisplayName();
|
| - }
|
| - } else if (type == BrowserDistribution::CHROME_BROWSER) {
|
| - // Chrome is not installed from Google Update's point of view (missing
|
| - // "pv" in its Clients key). This is an edge case resulting from
|
| - // either local tampering or from a bug when a multi-install Chrome
|
| - // Frame was uninstalled; see https://crbug.com/579627. Check to see
|
| - // if any user has run Chrome within the last 28 days.
|
| - const bool is_used = IsChromeActivelyUsed(*installer_state);
|
| - UMA_HISTOGRAM_BOOLEAN("Setup.Install.StrandedChromeIsUsed", is_used);
|
| - if (is_used) {
|
| - // Add Chrome to the set of products to update to avoid leaving it
|
| - // behind.
|
| - std::unique_ptr<Product> multi_chrome(new Product(
|
| - BrowserDistribution::GetSpecificDistribution(type)));
|
| - multi_chrome->SetOption(installer::kOptionMultiInstall, true);
|
| - Product* chrome = installer_state->AddProduct(&multi_chrome);
|
| - VLOG(1) << "Broken install of product to be included for repair: "
|
| - << chrome->distribution()->GetDisplayName();
|
| - } // else uninstall the binaries in UninstallBinariesIfUnused.
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| void RecordNumDeleteOldVersionsAttempsBeforeAbort(int num_attempts) {
|
| UMA_HISTOGRAM_COUNTS_100(
|
| "Setup.Install.NumDeleteOldVersionsAttemptsBeforeAbort", num_attempts);
|
| @@ -458,10 +412,6 @@ 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
|
| - // rename for multi installs, we must update all installations since they
|
| - // share the binaries.
|
| - AddExistingMultiInstalls(original_state, installer_state);
|
| const base::FilePath &target_path = installer_state->target_path();
|
| base::FilePath chrome_exe(target_path.Append(installer::kChromeExe));
|
| base::FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe));
|
| @@ -489,28 +439,20 @@ installer::InstallStatus RenameChromeExecutables(
|
| WorkItem::ALWAYS_MOVE);
|
| install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path());
|
|
|
| - // Add work items to delete the "opv", "cpv", and "cmd" values from all
|
| - // products we're operating on (which including the multi-install binaries).
|
| - const Products& products = installer_state->products();
|
| + // Add work items to delete Chrome's "opv", "cpv", and "cmd" values.
|
| + // TODO(grt): Clean this up; https://crbug.com/577816.
|
| HKEY reg_root = installer_state->root_key();
|
| base::string16 version_key;
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - version_key = (*it)->distribution()->GetVersionKey();
|
| - install_list->AddDeleteRegValueWorkItem(reg_root,
|
| - version_key,
|
| - KEY_WOW64_32KEY,
|
| - google_update::kRegOldVersionField);
|
| - install_list->AddDeleteRegValueWorkItem(
|
| - reg_root,
|
| - version_key,
|
| - KEY_WOW64_32KEY,
|
| - google_update::kRegCriticalVersionField);
|
| - install_list->AddDeleteRegValueWorkItem(reg_root,
|
| - version_key,
|
| - KEY_WOW64_32KEY,
|
| - google_update::kRegRenameCmdField);
|
| - }
|
| + version_key = installer_state->product().distribution()->GetVersionKey();
|
| + install_list->AddDeleteRegValueWorkItem(reg_root, version_key,
|
| + KEY_WOW64_32KEY,
|
| + google_update::kRegOldVersionField);
|
| + install_list->AddDeleteRegValueWorkItem(
|
| + reg_root, version_key, KEY_WOW64_32KEY,
|
| + google_update::kRegCriticalVersionField);
|
| + install_list->AddDeleteRegValueWorkItem(reg_root, version_key,
|
| + KEY_WOW64_32KEY,
|
| + google_update::kRegRenameCmdField);
|
| // old_chrome.exe is still in use in most cases, so ignore failures here.
|
| install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path())
|
| ->set_best_effort(true);
|
| @@ -530,60 +472,8 @@ installer::InstallStatus RenameChromeExecutables(
|
| return ret;
|
| }
|
|
|
| -// Fail with UNUSED_BINARIES if only the binaries are being updated.
|
| -bool CheckMultiInstallConditions(const InstallationState& original_state,
|
| - InstallerState* installer_state,
|
| - installer::InstallStatus* status) {
|
| - const Products& products = installer_state->products();
|
| - DCHECK(products.size());
|
| -
|
| - const bool system_level = installer_state->system_install();
|
| -
|
| - if (installer_state->is_multi_install()) {
|
| - const Product* chrome =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| - const Product* binaries =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES);
|
| - const ProductState* chrome_state =
|
| - original_state.GetProductState(system_level,
|
| - BrowserDistribution::CHROME_BROWSER);
|
| -
|
| - if (binaries) {
|
| - if (products.size() == 1) {
|
| - // There are no products aside from the binaries, so there is no update
|
| - // to be applied. This can happen after multi-install Chrome Frame is
|
| - // migrated to single-install. This is treated as an update failure
|
| - // unless the binaries are not in-use, in which case they will be
|
| - // uninstalled and success will be reported (see handling in wWinMain).
|
| - VLOG(1) << "No products to be updated.";
|
| - *status = installer::UNUSED_BINARIES;
|
| - installer_state->WriteInstallerResult(*status, 0, NULL);
|
| - return false;
|
| - }
|
| - } else {
|
| - // This will only be hit if --multi-install is given with no products.
|
| - return true;
|
| - }
|
| -
|
| - if (!chrome && chrome_state) {
|
| - // A product other than Chrome is being installed in multi-install mode,
|
| - // and Chrome is already present. Add Chrome to the set of products
|
| - // (making it multi-install in the process) so that it is updated, too.
|
| - std::unique_ptr<Product> multi_chrome(
|
| - new Product(BrowserDistribution::GetSpecificDistribution(
|
| - BrowserDistribution::CHROME_BROWSER)));
|
| - multi_chrome->SetOption(installer::kOptionMultiInstall, true);
|
| - chrome = installer_state->AddProduct(&multi_chrome);
|
| - VLOG(1) << "Upgrading existing Chrome browser in multi-install mode.";
|
| - }
|
| - } // else migrate multi-install Chrome to single-install.
|
| -
|
| - return true;
|
| -}
|
| -
|
| // Checks for compatibility between the current state of the system and the
|
| -// desired operation. Also applies policy that mutates the desired operation;
|
| -// specifically, the |installer_state| object.
|
| +// desired operation.
|
| // Also blocks simultaneous user-level and system-level installs. In the case
|
| // of trying to install user-level Chrome when system-level exists, the
|
| // existing system-level Chrome is launched.
|
| @@ -591,88 +481,52 @@ bool CheckMultiInstallConditions(const InstallationState& original_state,
|
| // the registry (via WriteInstallerResult), |status| is set appropriately, and
|
| // false is returned.
|
| bool CheckPreInstallConditions(const InstallationState& original_state,
|
| - InstallerState* installer_state,
|
| + const InstallerState& installer_state,
|
| installer::InstallStatus* status) {
|
| - // See what products are already installed in multi mode. When we do multi
|
| - // installs, we must upgrade all installations since they share the binaries.
|
| - AddExistingMultiInstalls(original_state, installer_state);
|
| + if (!installer_state.system_install()) {
|
| + // This is a user-level installation. Make sure that we are not installing
|
| + // on top of an existing system-level installation.
|
| + const Product& product = installer_state.product();
|
| + BrowserDistribution* browser_dist = product.distribution();
|
|
|
| - if (!CheckMultiInstallConditions(original_state, installer_state, status)) {
|
| - DCHECK_NE(*status, installer::UNKNOWN_STATUS);
|
| - return false;
|
| - }
|
| + const ProductState* user_level_product_state =
|
| + original_state.GetProductState(false, browser_dist->GetType());
|
| + const ProductState* system_level_product_state =
|
| + original_state.GetProductState(true, browser_dist->GetType());
|
|
|
| - const Products& products = installer_state->products();
|
| - if (products.empty()) {
|
| - // We haven't been given any products on which to operate.
|
| - LOG(ERROR)
|
| - << "Not given any products to install and no products found to update.";
|
| - *status = installer::CHROME_NOT_INSTALLED;
|
| - installer_state->WriteInstallerResult(*status,
|
| - IDS_INSTALL_NO_PRODUCTS_TO_UPDATE_BASE, nullptr);
|
| - return false;
|
| - }
|
| + // Allow upgrades to proceed so that out-of-date versions are not left
|
| + // around.
|
| + if (user_level_product_state)
|
| + return true;
|
|
|
| - if (!installer_state->system_install()) {
|
| - // This is a user-level installation. Make sure that we are not installing
|
| - // on top of an existing system-level installation.
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - const Product& product = **it;
|
| - BrowserDistribution* browser_dist = product.distribution();
|
| -
|
| - // Skip over the binaries, as it's okay for them to be at both levels
|
| - // for different products.
|
| - if (browser_dist->GetType() == BrowserDistribution::CHROME_BINARIES)
|
| - continue;
|
| -
|
| - const ProductState* user_level_product_state =
|
| - original_state.GetProductState(false, browser_dist->GetType());
|
| - const ProductState* system_level_product_state =
|
| - original_state.GetProductState(true, browser_dist->GetType());
|
| -
|
| - // Allow upgrades to proceed so that out-of-date versions are not left
|
| - // around.
|
| - if (user_level_product_state)
|
| - continue;
|
| -
|
| - // This is a new user-level install...
|
| -
|
| - if (system_level_product_state) {
|
| - // ... and the product already exists at system-level.
|
| - LOG(ERROR) << "Already installed version "
|
| - << system_level_product_state->version().GetString()
|
| - << " at system-level conflicts with this one at user-level.";
|
| - if (product.is_chrome()) {
|
| - // Instruct Google Update to launch the existing system-level Chrome.
|
| - // There should be no error dialog.
|
| - base::FilePath install_path(installer::GetChromeInstallPath(
|
| - true, // system
|
| - browser_dist));
|
| - if (install_path.empty()) {
|
| - // Give up if we failed to construct the install path.
|
| - *status = installer::OS_ERROR;
|
| - installer_state->WriteInstallerResult(*status,
|
| - IDS_INSTALL_OS_ERROR_BASE,
|
| - nullptr);
|
| - } else {
|
| - *status = installer::EXISTING_VERSION_LAUNCHED;
|
| - base::FilePath chrome_exe =
|
| - install_path.Append(installer::kChromeExe);
|
| - base::CommandLine cmd(chrome_exe);
|
| - cmd.AppendSwitch(switches::kForceFirstRun);
|
| - installer_state->WriteInstallerResult(
|
| - *status, IDS_INSTALL_EXISTING_VERSION_LAUNCHED_BASE, nullptr);
|
| - VLOG(1) << "Launching existing system-level chrome instead.";
|
| - base::LaunchProcess(cmd, base::LaunchOptions());
|
| - }
|
| - } else {
|
| - // It's no longer possible for |product| to be anything other than
|
| - // Chrome.
|
| - NOTREACHED();
|
| - }
|
| - return false;
|
| + // This is a new user-level install...
|
| +
|
| + if (system_level_product_state) {
|
| + // ... and the product already exists at system-level.
|
| + LOG(ERROR) << "Already installed version "
|
| + << system_level_product_state->version().GetString()
|
| + << " at system-level conflicts with this one at user-level.";
|
| + // Instruct Google Update to launch the existing system-level Chrome.
|
| + // There should be no error dialog.
|
| + base::FilePath install_path(
|
| + installer::GetChromeInstallPath(true, // system
|
| + browser_dist));
|
| + if (install_path.empty()) {
|
| + // Give up if we failed to construct the install path.
|
| + *status = installer::OS_ERROR;
|
| + installer_state.WriteInstallerResult(*status, IDS_INSTALL_OS_ERROR_BASE,
|
| + nullptr);
|
| + } else {
|
| + *status = installer::EXISTING_VERSION_LAUNCHED;
|
| + base::FilePath chrome_exe = install_path.Append(installer::kChromeExe);
|
| + base::CommandLine cmd(chrome_exe);
|
| + cmd.AppendSwitch(switches::kForceFirstRun);
|
| + installer_state.WriteInstallerResult(
|
| + *status, IDS_INSTALL_EXISTING_VERSION_LAUNCHED_BASE, nullptr);
|
| + VLOG(1) << "Launching existing system-level chrome instead.";
|
| + base::LaunchProcess(cmd, base::LaunchOptions());
|
| }
|
| + return false;
|
| }
|
| }
|
|
|
| @@ -735,50 +589,28 @@ installer::InstallStatus UninstallProducts(
|
| const InstallerState& installer_state,
|
| const base::FilePath& setup_exe,
|
| const base::CommandLine& cmd_line) {
|
| - const Products& products = installer_state.products();
|
| -
|
| // System-level Chrome will be launched via this command if its program gets
|
| // set below.
|
| base::CommandLine system_level_cmd(base::CommandLine::NO_PROGRAM);
|
|
|
| - const Product* chrome =
|
| - installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| - if (chrome) {
|
| - // InstallerState::Initialize always puts Chrome first, and we rely on that
|
| - // here for this reason: if Chrome is in-use, the user will be prompted to
|
| - // confirm uninstallation. Upon cancel, we should not continue with the
|
| - // other products.
|
| - DCHECK(products[0]->is_chrome());
|
| -
|
| - if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) &&
|
| - !installer_state.system_install()) {
|
| - BrowserDistribution* dist = chrome->distribution();
|
| - const base::FilePath system_exe_path(
|
| - installer::GetChromeInstallPath(true, dist)
|
| - .Append(installer::kChromeExe));
|
| - system_level_cmd.SetProgram(system_exe_path);
|
| - }
|
| - }
|
| - if (installer_state.FindProduct(BrowserDistribution::CHROME_BINARIES)) {
|
| - // Chrome Binaries should be last; if something else is cancelled, they
|
| - // should stay.
|
| - DCHECK(products.back()->is_chrome_binaries());
|
| + const Product& chrome = installer_state.product();
|
| + if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) &&
|
| + !installer_state.system_install()) {
|
| + BrowserDistribution* dist = chrome.distribution();
|
| + const base::FilePath system_exe_path(
|
| + installer::GetChromeInstallPath(true, dist)
|
| + .Append(installer::kChromeExe));
|
| + system_level_cmd.SetProgram(system_exe_path);
|
| }
|
|
|
| installer::InstallStatus install_status = installer::UNINSTALL_SUCCESSFUL;
|
| - installer::InstallStatus prod_status = installer::UNKNOWN_STATUS;
|
| const bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall);
|
| const bool remove_all = !cmd_line.HasSwitch(
|
| installer::switches::kDoNotRemoveSharedItems);
|
|
|
| - for (Products::const_iterator it = products.begin();
|
| - install_status != installer::UNINSTALL_CANCELLED && it < products.end();
|
| - ++it) {
|
| - prod_status = UninstallProduct(original_state, installer_state, setup_exe,
|
| - cmd_line, remove_all, force, **it);
|
| - if (prod_status != installer::UNINSTALL_SUCCESSFUL)
|
| - install_status = prod_status;
|
| - }
|
| + install_status =
|
| + UninstallProduct(original_state, installer_state, setup_exe, cmd_line,
|
| + remove_all, force, installer_state.product());
|
|
|
| installer::CleanUpInstallationDirectoryAfterUninstall(
|
| original_state, installer_state, setup_exe, &install_status);
|
| @@ -790,7 +622,7 @@ installer::InstallStatus UninstallProducts(
|
| // Trigger Active Setup if it was requested for the chrome product. This needs
|
| // to be done after the UninstallProduct calls as some of them might
|
| // otherwise terminate the process launched by TriggerActiveSetupCommand().
|
| - if (chrome && cmd_line.HasSwitch(installer::switches::kTriggerActiveSetup))
|
| + if (cmd_line.HasSwitch(installer::switches::kTriggerActiveSetup))
|
| InstallUtil::TriggerActiveSetupCommand();
|
|
|
| if (!system_level_cmd.GetProgram().empty())
|
| @@ -804,54 +636,6 @@ 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";
|
| - installer_state.SetStage(installer::UNINSTALLING_BINARIES);
|
| -
|
| - // Create an InstallerState that represents a force uninstall of Chrome
|
| - // residing with the installed version of the binaries. This will result in
|
| - // removing Chrome and all of its program files and associated registrations
|
| - // (aside from user data).
|
| - const ProductState* binaries_state =
|
| - original_state.GetProductState(installer_state.system_install(),
|
| - BrowserDistribution::CHROME_BINARIES);
|
| - base::CommandLine uninstall_cmd(binaries_state->uninstall_command());
|
| - uninstall_cmd.AppendSwitch(installer::switches::kChrome);
|
| - uninstall_cmd.AppendSwitch(installer::switches::kForceUninstall);
|
| - 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.GetProgram(),
|
| - uninstall_cmd);
|
| -
|
| - // Report that the binaries were uninstalled if they were. This translates
|
| - // into a successful install/update return code.
|
| - if (IsUninstallSuccess(*install_status)) {
|
| - *install_status = installer::UNUSED_BINARIES_UNINSTALLED;
|
| -#if defined(GOOGLE_CHROME_BUILD)
|
| - // Write the result for the sake of Google Update in Google Chrome builds,
|
| - // but skip this for Chromium builds. The reason is a bit icky: Chromium
|
| - // builds lump the "ClientState" and "Clients" keys into a single key. As a
|
| - // consequence, writing this value causes Software\Chromium to be re-created
|
| - // after it was deleted during the uninstall. Google Chrome builds don't
|
| - // suffer this since the two keys are distinct and have different lifetimes.
|
| - installer_state.WriteInstallerResult(*install_status, 0, NULL);
|
| -#endif
|
| - }
|
| -}
|
| -
|
| installer::InstallStatus InstallProducts(
|
| const InstallationState& original_state,
|
| const base::FilePath& setup_exe,
|
| @@ -877,7 +661,7 @@ installer::InstallStatus InstallProducts(
|
| installer_state->set_background_mode(entered_background_mode);
|
| VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
|
|
|
| - if (CheckPreInstallConditions(original_state, installer_state,
|
| + if (CheckPreInstallConditions(original_state, *installer_state,
|
| &install_status)) {
|
| VLOG(1) << "Installing to " << installer_state->target_path().value();
|
| install_status = InstallProductsHelper(
|
| @@ -902,15 +686,8 @@ installer::InstallStatus InstallProducts(
|
| }
|
| }
|
|
|
| - 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);
|
| - }
|
| -
|
| - // Handle installer::UNUSED_BINARIES returned by CheckPreInstallConditions.
|
| - UninstallBinariesIfUnused(original_state, *installer_state, &install_status);
|
| + installer_state->product().distribution()->UpdateInstallStatus(
|
| + system_install, archive_type, install_status);
|
|
|
| return install_status;
|
| }
|
| @@ -1097,18 +874,17 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| // NOTE: Should the work done here, on kConfigureUserSettings, change:
|
| // kActiveSetupVersion in install_worker.cc needs to be increased for Active
|
| // Setup to invoke this again for all users of this install.
|
| - const Product* chrome_install =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| + const Product& chrome_install = installer_state->product();
|
| installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION;
|
| - if (chrome_install && installer_state->system_install()) {
|
| + if (installer_state->system_install()) {
|
| bool force =
|
| cmd_line.HasSwitch(installer::switches::kForceConfigureUserSettings);
|
| installer::HandleActiveSetupForBrowser(installer_state->target_path(),
|
| - *chrome_install, force);
|
| + chrome_install, force);
|
| status = installer::INSTALL_REPAIRED;
|
| } else {
|
| - LOG(DFATAL) << "chrome_install:" << chrome_install
|
| - << ", system_install:" << installer_state->system_install();
|
| + LOG(DFATAL)
|
| + << "--configure-user-settings is incompatible with user-level";
|
| }
|
| *exit_code = InstallUtil::GetInstallReturnCode(status);
|
| } else if (cmd_line.HasSwitch(installer::switches::kRegisterDevChrome)) {
|
| @@ -1117,50 +893,43 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| *exit_code = InstallUtil::GetInstallReturnCode(status);
|
| } else if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser)) {
|
| installer::InstallStatus status = installer::UNKNOWN_STATUS;
|
| - const Product* chrome_install =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| - if (chrome_install) {
|
| - // 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 switch will also
|
| - // register Chrome as a valid handler for a set of URL protocols that
|
| - // Chrome may become the default handler for, either by the user marking
|
| - // Chrome as the default browser, through the Windows Default Programs
|
| - // control panel settings, or through website use of
|
| - // registerProtocolHandler. These protocols are found in
|
| - // ShellUtil::kPotentialProtocolAssociations.
|
| - // The --register-url-protocol will additionally register Chrome as a
|
| - // potential handler for the supplied protocol, and is used if a website
|
| - // registers a handler for a protocol not found in
|
| - // ShellUtil::kPotentialProtocolAssociations.
|
| - // These options should only be used when setup.exe is launched with admin
|
| - // rights. We do not make any user specific changes with this option.
|
| - DCHECK(IsUserAnAdmin());
|
| - base::FilePath chrome_exe(cmd_line.GetSwitchValuePath(
|
| - installer::switches::kRegisterChromeBrowser));
|
| - base::string16 suffix;
|
| - if (cmd_line.HasSwitch(
|
| - installer::switches::kRegisterChromeBrowserSuffix)) {
|
| - suffix = cmd_line.GetSwitchValueNative(
|
| - installer::switches::kRegisterChromeBrowserSuffix);
|
| - }
|
| - if (cmd_line.HasSwitch(installer::switches::kRegisterURLProtocol)) {
|
| - base::string16 protocol = cmd_line.GetSwitchValueNative(
|
| - installer::switches::kRegisterURLProtocol);
|
| - // ShellUtil::RegisterChromeForProtocol performs all registration
|
| - // done by ShellUtil::RegisterChromeBrowser, as well as registering
|
| - // with Windows as capable of handling the supplied protocol.
|
| - if (ShellUtil::RegisterChromeForProtocol(
|
| - chrome_install->distribution(), chrome_exe, suffix, protocol,
|
| - false))
|
| - status = installer::IN_USE_UPDATED;
|
| - } else {
|
| - if (ShellUtil::RegisterChromeBrowser(chrome_install->distribution(),
|
| - chrome_exe, suffix, false))
|
| - status = installer::IN_USE_UPDATED;
|
| - }
|
| + const Product& chrome_install = installer_state->product();
|
| + // 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 switch will also register Chrome as a
|
| + // valid handler for a set of URL protocols that Chrome may become the
|
| + // default handler for, either by the user marking Chrome as the default
|
| + // browser, through the Windows Default Programs control panel settings, or
|
| + // through website use of registerProtocolHandler. These protocols are found
|
| + // in ShellUtil::kPotentialProtocolAssociations. The
|
| + // --register-url-protocol will additionally register Chrome as a potential
|
| + // handler for the supplied protocol, and is used if a website registers a
|
| + // handler for a protocol not found in
|
| + // ShellUtil::kPotentialProtocolAssociations. These options should only be
|
| + // used when setup.exe is launched with admin rights. We do not make any
|
| + // user specific changes with this option.
|
| + DCHECK(IsUserAnAdmin());
|
| + base::FilePath chrome_exe(cmd_line.GetSwitchValuePath(
|
| + installer::switches::kRegisterChromeBrowser));
|
| + base::string16 suffix;
|
| + if (cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowserSuffix)) {
|
| + suffix = cmd_line.GetSwitchValueNative(
|
| + installer::switches::kRegisterChromeBrowserSuffix);
|
| + }
|
| + if (cmd_line.HasSwitch(installer::switches::kRegisterURLProtocol)) {
|
| + base::string16 protocol = cmd_line.GetSwitchValueNative(
|
| + installer::switches::kRegisterURLProtocol);
|
| + // ShellUtil::RegisterChromeForProtocol performs all registration
|
| + // done by ShellUtil::RegisterChromeBrowser, as well as registering
|
| + // with Windows as capable of handling the supplied protocol.
|
| + if (ShellUtil::RegisterChromeForProtocol(chrome_install.distribution(),
|
| + chrome_exe, suffix, protocol,
|
| + false))
|
| + status = installer::IN_USE_UPDATED;
|
| } else {
|
| - LOG(DFATAL) << "Can't register browser - Chrome distribution not found";
|
| + if (ShellUtil::RegisterChromeBrowser(chrome_install.distribution(),
|
| + chrome_exe, suffix, false))
|
| + status = installer::IN_USE_UPDATED;
|
| }
|
| *exit_code = InstallUtil::GetInstallReturnCode(status);
|
| } else if (cmd_line.HasSwitch(installer::switches::kDeleteOldVersions) ||
|
| @@ -1172,10 +941,6 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| if (!setup_singleton) {
|
| *exit_code = installer::SETUP_SINGLETON_ACQUISITION_FAILED;
|
| } 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 {
|
| @@ -1196,33 +961,25 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| installer::switches::kRegisterChromeBrowserSuffix);
|
| }
|
| installer::InstallStatus tmp = installer::UNKNOWN_STATUS;
|
| - const Product* chrome_install =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| - DCHECK(chrome_install);
|
| - if (chrome_install) {
|
| - installer::DeleteChromeRegistrationKeys(*installer_state,
|
| - chrome_install->distribution(), HKEY_LOCAL_MACHINE, suffix, &tmp);
|
| - }
|
| + const Product& chrome_install = installer_state->product();
|
| + installer::DeleteChromeRegistrationKeys(*installer_state,
|
| + chrome_install.distribution(),
|
| + HKEY_LOCAL_MACHINE, suffix, &tmp);
|
| *exit_code = tmp;
|
| } else if (cmd_line.HasSwitch(installer::switches::kOnOsUpgrade)) {
|
| - const Product* chrome_install =
|
| - installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER);
|
| + const Product& chrome_install = installer_state->product();
|
| installer::InstallStatus status = installer::INVALID_STATE_FOR_OPTION;
|
| - if (chrome_install) {
|
| - std::unique_ptr<FileVersionInfo> version_info(
|
| - FileVersionInfo::CreateFileVersionInfo(setup_exe));
|
| - const base::Version installed_version(
|
| - base::UTF16ToUTF8(version_info->product_version()));
|
| - if (installed_version.IsValid()) {
|
| - installer::HandleOsUpgradeForBrowser(*installer_state, *chrome_install,
|
| - installed_version);
|
| - status = installer::INSTALL_REPAIRED;
|
| - } else {
|
| - LOG(DFATAL) << "Failed to extract product version from "
|
| - << setup_exe.value();
|
| - }
|
| + std::unique_ptr<FileVersionInfo> version_info(
|
| + FileVersionInfo::CreateFileVersionInfo(setup_exe));
|
| + const base::Version installed_version(
|
| + base::UTF16ToUTF8(version_info->product_version()));
|
| + if (installed_version.IsValid()) {
|
| + installer::HandleOsUpgradeForBrowser(*installer_state, chrome_install,
|
| + installed_version);
|
| + status = installer::INSTALL_REPAIRED;
|
| } else {
|
| - LOG(DFATAL) << "Chrome product not found.";
|
| + LOG(DFATAL) << "Failed to extract product version from "
|
| + << setup_exe.value();
|
| }
|
| *exit_code = InstallUtil::GetInstallReturnCode(status);
|
| } else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) {
|
| @@ -1238,33 +995,23 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| } else {
|
| // This code is called (via setup.exe relaunch) only if a product is known
|
| // to run user experiments, so no check is required.
|
| - const Products& products = installer_state->products();
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - const Product& product = **it;
|
| - installer::InactiveUserToastExperiment(
|
| - flavor, base::ASCIIToUTF16(experiment_group), product,
|
| - installer_state->target_path());
|
| - }
|
| + installer::InactiveUserToastExperiment(
|
| + flavor, base::ASCIIToUTF16(experiment_group),
|
| + installer_state->product(), installer_state->target_path());
|
| }
|
| } else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) {
|
| - const Products& products = installer_state->products();
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - const Product& product = **it;
|
| - BrowserDistribution* browser_dist = product.distribution();
|
| - // We started as system-level and have been re-launched as user level
|
| - // to continue with the toast experiment.
|
| - base::Version installed_version;
|
| - InstallUtil::GetChromeVersion(browser_dist, true, &installed_version);
|
| - if (!installed_version.IsValid()) {
|
| - LOG(ERROR) << "No installation of "
|
| - << browser_dist->GetDisplayName()
|
| - << " found for system-level toast.";
|
| - } else {
|
| - product.LaunchUserExperiment(
|
| - setup_exe, installer::REENTRY_SYS_UPDATE, true);
|
| - }
|
| + const Product& product = installer_state->product();
|
| + BrowserDistribution* browser_dist = product.distribution();
|
| + // We started as system-level and have been re-launched as user level
|
| + // to continue with the toast experiment.
|
| + base::Version installed_version;
|
| + InstallUtil::GetChromeVersion(browser_dist, true, &installed_version);
|
| + if (!installed_version.IsValid()) {
|
| + LOG(ERROR) << "No installation of " << browser_dist->GetDisplayName()
|
| + << " found for system-level toast.";
|
| + } else {
|
| + product.LaunchUserExperiment(setup_exe, installer::REENTRY_SYS_UPDATE,
|
| + true);
|
| }
|
| } else if (cmd_line.HasSwitch(installer::switches::kPatch)) {
|
| const std::string patch_type_str(
|
| @@ -1308,64 +1055,6 @@ bool HandleNonInstallCmdLineOptions(const base::FilePath& setup_exe,
|
| return handled;
|
| }
|
|
|
| -// 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 base::CommandLine& cmd_line,
|
| - const MasterPreferences& prefs,
|
| - InstallationState* original_state,
|
| - InstallerState* installer_state) {
|
| - // Early exit if not installing or updating.
|
| - if (installer_state->operation() == InstallerState::UNINSTALL)
|
| - 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->SetStage(installer::UNINSTALLING_CHROME_FRAME);
|
| -
|
| - // Uninstall Chrome Frame without touching the multi-install binaries.
|
| - // Simulate the uninstall as coming from the installed version.
|
| - const base::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);
|
| - // Post M32, uninstall_prefs and uninstall_state won't have Chrome Frame in
|
| - // them since they've lost the power to do Chrome Frame installs.
|
| - const Product* chrome_frame_product = uninstall_state.AddProductFromState(
|
| - BrowserDistribution::CHROME_FRAME, *chrome_frame_state);
|
| - 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 {
|
| @@ -1486,28 +1175,14 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
|
| bool proceed_with_installation = true;
|
|
|
| if (!IsDowngradeAllowed(prefs)) {
|
| - uint32_t higher_products = 0;
|
| - static_assert(
|
| - sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES,
|
| - "too many distribution types");
|
| - const Products& products = installer_state.products();
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - const Product& product = **it;
|
| - const ProductState* product_state = original_state.GetProductState(
|
| - system_install, product.distribution()->GetType());
|
| - if (product_state != NULL &&
|
| - (product_state->version().CompareTo(*installer_version) > 0)) {
|
| - LOG(ERROR) << "Higher version of "
|
| - << product.distribution()->GetDisplayName()
|
| - << " is already installed.";
|
| - higher_products |= (1 << product.distribution()->GetType());
|
| - }
|
| - }
|
| -
|
| - if (higher_products != 0) {
|
| - static_assert(BrowserDistribution::NUM_TYPES == 3,
|
| - "add support for new products here");
|
| + const Product& product = installer_state.product();
|
| + const ProductState* product_state = original_state.GetProductState(
|
| + system_install, product.distribution()->GetType());
|
| + if (product_state != NULL &&
|
| + (product_state->version().CompareTo(*installer_version) > 0)) {
|
| + LOG(ERROR) << "Higher version of "
|
| + << product.distribution()->GetDisplayName()
|
| + << " is already installed.";
|
| int message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
|
| proceed_with_installation = false;
|
| install_status = HIGHER_VERSION_EXISTS;
|
| @@ -1543,20 +1218,11 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
|
|
|
| installer_state.SetStage(FINISHING);
|
|
|
| - // Only do Chrome-specific stuff (like launching the browser) if
|
| - // Chrome was specifically requested (rather than being upgraded as
|
| - // part of a multi-install).
|
| - const Product* chrome_install = prefs.install_chrome() ?
|
| - installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) :
|
| - NULL;
|
| + const Product& chrome_install = installer_state.product();
|
|
|
| bool do_not_register_for_update_launch = false;
|
| - if (chrome_install) {
|
| - prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch,
|
| - &do_not_register_for_update_launch);
|
| - } else {
|
| - do_not_register_for_update_launch = true; // Never register.
|
| - }
|
| + prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch,
|
| + &do_not_register_for_update_launch);
|
|
|
| bool write_chrome_launch_string =
|
| (!do_not_register_for_update_launch &&
|
| @@ -1567,22 +1233,17 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
|
|
|
| if (install_status == FIRST_INSTALL_SUCCESS) {
|
| VLOG(1) << "First install successful.";
|
| - if (chrome_install) {
|
| - // We never want to launch Chrome in system level install mode.
|
| - bool do_not_launch_chrome = false;
|
| - prefs.GetBool(master_preferences::kDoNotLaunchChrome,
|
| - &do_not_launch_chrome);
|
| - if (!system_install && !do_not_launch_chrome)
|
| - chrome_install->LaunchChrome(installer_state.target_path());
|
| - }
|
| + // We never want to launch Chrome in system level install mode.
|
| + bool do_not_launch_chrome = false;
|
| + prefs.GetBool(master_preferences::kDoNotLaunchChrome,
|
| + &do_not_launch_chrome);
|
| + if (!system_install && !do_not_launch_chrome)
|
| + chrome_install.LaunchChrome(installer_state.target_path());
|
| } else if ((install_status == NEW_VERSION_UPDATED) ||
|
| (install_status == IN_USE_UPDATED)) {
|
| - const Product* chrome = installer_state.FindProduct(
|
| - BrowserDistribution::CHROME_BROWSER);
|
| - if (chrome != NULL) {
|
| - DCHECK_NE(chrome_exe.value(), base::string16());
|
| - RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe);
|
| - }
|
| + const Product& chrome = installer_state.product();
|
| + DCHECK_NE(chrome_exe.value(), base::string16());
|
| + RemoveChromeLegacyRegistryKeys(chrome.distribution(), chrome_exe);
|
| }
|
| }
|
| }
|
| @@ -1602,12 +1263,8 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
|
| setup_path = installer_state.GetInstallerDirectory(*installer_version)
|
| .Append(setup_path.BaseName());
|
| }
|
| - const Products& products = installer_state.products();
|
| - for (Products::const_iterator it = products.begin(); it < products.end();
|
| - ++it) {
|
| - const Product& product = **it;
|
| - product.LaunchUserExperiment(setup_path, install_status, system_install);
|
| - }
|
| + installer_state.product().LaunchUserExperiment(setup_path, install_status,
|
| + system_install);
|
| }
|
|
|
| // If the installation completed successfully...
|
| @@ -1632,16 +1289,12 @@ InstallStatus InstallProductsHelper(const InstallationState& original_state,
|
| // Only when called by the MSI installer do we need to delay setting
|
| // the DisplayVersion. In other runs, such as those done by the auto-
|
| // update action, we set the value immediately.
|
| - const Product* chrome = installer_state.FindProduct(
|
| - BrowserDistribution::CHROME_BROWSER);
|
| - if (chrome != NULL) {
|
| - // Get the app's MSI Product-ID from an entry in ClientState.
|
| - base::string16 app_guid = FindMsiProductId(installer_state, chrome);
|
| - if (!app_guid.empty()) {
|
| - OverwriteDisplayVersions(app_guid,
|
| - base::UTF8ToUTF16(
|
| - installer_version->GetString()));
|
| - }
|
| + const Product& chrome = installer_state.product();
|
| + // Get the app's MSI Product-ID from an entry in ClientState.
|
| + base::string16 app_guid = FindMsiProductId(installer_state, chrome);
|
| + if (!app_guid.empty()) {
|
| + OverwriteDisplayVersions(
|
| + app_guid, base::UTF8ToUTF16(installer_version->GetString()));
|
| }
|
| }
|
| // Return the path to the directory containing the newly installed
|
| @@ -1694,7 +1347,6 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
|
| const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
|
| VLOG(1) << "Command Line: " << cmd_line.GetCommandLineString();
|
|
|
| - VLOG(1) << "multi install is " << prefs.is_multi_install();
|
| bool system_install = false;
|
| prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install);
|
| VLOG(1) << "system install is " << system_install;
|
| @@ -1744,7 +1396,6 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
|
| // Some command line options don't work with SxS install/uninstall
|
| if (InstallUtil::IsChromeSxSProcess()) {
|
| if (system_install ||
|
| - prefs.is_multi_install() ||
|
| cmd_line.HasSwitch(installer::switches::kSelfDestruct) ||
|
| cmd_line.HasSwitch(installer::switches::kMakeChromeDefault) ||
|
| cmd_line.HasSwitch(installer::switches::kRegisterChromeBrowser) ||
|
| @@ -1811,9 +1462,6 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
|
| return installer::SETUP_SINGLETON_ACQUISITION_FAILED;
|
| }
|
|
|
| - UninstallMultiChromeFrameIfPresent(cmd_line, prefs,
|
| - &original_state, &installer_state);
|
| -
|
| base::FilePath installer_directory;
|
| installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
|
| // If --uninstall option is given, uninstall the identified product(s)
|
| @@ -1825,6 +1473,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
|
| install_status =
|
| InstallProducts(original_state, setup_exe, cmd_line, prefs,
|
| &installer_state, &installer_directory);
|
| + DoLegacyCleanups(installer_state, install_status);
|
| }
|
|
|
| UMA_HISTOGRAM_ENUMERATION("Setup.Install.Result", install_status,
|
|
|