Chromium Code Reviews| 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..ec1c0d9e1521551d9bc5bd38ca4ec99bdba6353a 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,16 @@ 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) << "system_install:" << installer_state->system_install(); |
|
huangs
2017/01/03 07:26:05
installer_state->system_install() would always be
grt (UTC plus 2)
2017/01/03 13:04:30
Nice! Rejiggered.
|
| } |
| *exit_code = InstallUtil::GetInstallReturnCode(status); |
| } else if (cmd_line.HasSwitch(installer::switches::kRegisterDevChrome)) { |
| @@ -1117,50 +892,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 +940,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 +960,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 +994,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 +1054,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 +1174,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 +1217,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 +1232,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 +1262,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 +1288,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 +1346,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 +1395,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 +1461,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 +1472,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); |
|
huangs
2017/01/03 07:26:05
Would it be more robust to do legacy cleanup befor
grt (UTC plus 2)
2017/01/03 13:04:30
I don't think so, as it should only be done when t
|
| } |
| UMA_HISTOGRAM_ENUMERATION("Setup.Install.Result", install_status, |