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, |