Index: chrome/installer/setup/setup_main.cc |
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc |
index eb59d175a630b57a8153b5bbdcb399353f9375f4..95490b029e6811753a12c4a130e0a8a913acd3f5 100644 |
--- a/chrome/installer/setup/setup_main.cc |
+++ b/chrome/installer/setup/setup_main.cc |
@@ -217,27 +217,13 @@ installer::InstallStatus RenameChromeExecutables( |
install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) |
->set_ignore_failure(true); |
- // Collect the set of distributions we need to update, which is the |
- // multi-install binaries (if this is a multi-install operation) and all |
- // products we're operating on. |
- BrowserDistribution* dists[BrowserDistribution::NUM_TYPES]; |
- int num_dists = 0; |
- // First, add the multi-install binaries, if relevant. |
- if (installer_state->is_multi_install()) |
- dists[num_dists++] = installer_state->multi_package_binaries_distribution(); |
- // Next, add all products we're operating on. std::transform can handily do |
- // this for us, but this is discouraged as being too tricky. |
- const Products& products = installer_state->products(); |
- for (Products::size_type i = 0; i < products.size(); ++i) { |
- dists[num_dists++] = products[i]->distribution(); |
- } |
- |
// Add work items to delete the "opv", "cpv", and "cmd" values from all |
- // distributions. |
+ // products we're operating on (which including the multi-install binaries). |
+ const Products& products = installer_state->products(); |
HKEY reg_root = installer_state->root_key(); |
string16 version_key; |
- for (int i = 0; i < num_dists; ++i) { |
- version_key = dists[i]->GetVersionKey(); |
+ for (size_t i = 0; i < products.size(); ++i) { |
+ version_key = products[i]->distribution()->GetVersionKey(); |
install_list->AddDeleteRegValueWorkItem( |
reg_root, version_key, google_update::kRegOldVersionField); |
install_list->AddDeleteRegValueWorkItem( |
@@ -383,14 +369,23 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, |
original_state.GetProductState( |
true, // system |
BrowserDistribution::CHROME_BINARIES)) { |
+ VLOG(1) << "Installing/updating Application Host without binaries."; |
return true; |
} else { |
+ // Somehow the binaries were present when the quick-enable app host |
+ // command was run, but now they appear to be missing. |
+ // TODO(erikwright): should the binaries be implicitly added? |
+ LOG(ERROR) << "Cannot install Application Host without binaries."; |
+ *status = installer::APP_HOST_REQUIRES_BINARIES; |
+ installer_state->WriteInstallerResult(*status, 0, NULL); |
return false; |
} |
} else { |
// Every other scenario requires the binaries to be installed/updated |
- // simultaneous to the main product. |
- return false; |
+ // along with the main product. This will only be hit if |
+ // --multi-install is given with no products. See |
+ // CheckPreInstallConditions for handling of this case. |
+ return true; |
} |
} |
@@ -417,10 +412,10 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, |
VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; |
} |
} |
- } else if (chrome_state != NULL) { |
- // Chrome Frame 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. |
+ } else if (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. |
scoped_ptr<Product> multi_chrome(new Product( |
BrowserDistribution::GetSpecificDistribution( |
BrowserDistribution::CHROME_BROWSER))); |
@@ -440,8 +435,6 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, |
// Fail if we're installing Chrome Frame when a single-install of it is |
// already installed. |
- // TODO(grt): Add support for migration of Chrome Frame from single- to |
- // multi-install. |
if (chrome_frame && cf_state && !cf_state->is_multi_install()) { |
LOG(ERROR) << "Cannot migrate existing Chrome Frame installation to " |
<< "multi-install."; |
@@ -453,13 +446,6 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, |
} else { |
// This is a non-multi installation. |
- // It isn't possible to stuff two products into a single-install |
- // InstallerState. Abort the process here in debug builds just in case |
- // someone finds a way. |
- DCHECK_EQ(1U, products.size()); |
- if (products.size() != 1) |
- return false; |
- |
// Check for an existing installation of the product. |
const ProductState* product_state = original_state.GetProductState( |
system_level, products[0]->distribution()->GetType()); |
@@ -475,25 +461,36 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, |
return false; |
} |
} |
- |
} |
return true; |
} |
+// Checks app host pre-install conditions, specifically that this is a |
+// user-level multi-install. When the pre-install conditions are not |
+// satisfied, the result is written to the registry (via WriteInstallerResult), |
+// |status| is set appropriately, and false is returned. |
bool CheckAppHostPreconditions(const InstallationState& original_state, |
- InstallerState* installer_state) { |
- if (!installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) |
- return true; |
+ InstallerState* installer_state, |
+ installer::InstallStatus* status) { |
+ if (installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) { |
- if (!installer_state->is_multi_install()) { |
- VLOG(1) << "Application Host may only be installed in multi-install mode."; |
- return false; |
- } |
+ if (!installer_state->is_multi_install()) { |
+ LOG(DFATAL) << "Application Host requires multi install"; |
+ *status = installer::APP_HOST_REQUIRES_MULTI_INSTALL; |
+ // No message string since there is nothing a user can do. |
+ installer_state->WriteInstallerResult(*status, 0, NULL); |
+ return false; |
+ } |
+ |
+ if (installer_state->system_install()) { |
+ LOG(DFATAL) << "Application Host may only be installed at user-level."; |
+ *status = installer::APP_HOST_REQUIRES_USER_LEVEL; |
+ // No message string since there is nothing a user can do. |
+ installer_state->WriteInstallerResult(*status, 0, NULL); |
+ return false; |
+ } |
- if (installer_state->system_install()) { |
- VLOG(1) << "Application Host may only be installed at user-level."; |
- return false; |
} |
return true; |
@@ -511,11 +508,19 @@ bool CheckAppHostPreconditions(const InstallationState& original_state, |
bool CheckPreInstallConditions(const InstallationState& original_state, |
InstallerState* installer_state, |
installer::InstallStatus* status) { |
- if (!CheckAppHostPreconditions(original_state, installer_state)) |
+ if (!CheckAppHostPreconditions(original_state, installer_state, status)) { |
+ DCHECK_NE(*status, installer::UNKNOWN_STATUS); |
return false; |
+ } |
+ |
+ // 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 (!CheckMultiInstallConditions(original_state, installer_state, status)) |
+ if (!CheckMultiInstallConditions(original_state, installer_state, status)) { |
+ DCHECK_NE(*status, installer::UNKNOWN_STATUS); |
return false; |
+ } |
const Products& products = installer_state->products(); |
if (products.empty()) { |
@@ -528,16 +533,18 @@ bool CheckPreInstallConditions(const InstallationState& original_state, |
return false; |
} |
- // 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. |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
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 = |
@@ -873,6 +880,9 @@ installer::InstallStatus InstallProducts( |
VLOG(1) << "Installing to " << installer_state->target_path().value(); |
install_status = InstallProductsHelper( |
original_state, cmd_line, prefs, *installer_state, &archive_type); |
+ } else { |
+ // CheckPreInstallConditions must set the status on failure. |
+ DCHECK_NE(install_status, installer::UNKNOWN_STATUS); |
} |
const Products& products = installer_state->products(); |
@@ -882,10 +892,6 @@ installer::InstallStatus InstallProducts( |
product->distribution()->UpdateInstallStatus( |
system_install, archive_type, install_status); |
} |
- if (installer_state->is_multi_install()) { |
- installer_state->multi_package_binaries_distribution()->UpdateInstallStatus( |
- system_install, archive_type, install_status); |
- } |
installer_state->UpdateStage(installer::NO_STAGE); |
return install_status; |
@@ -1464,7 +1470,13 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, |
} else if (is_uninstall) { |
// Only show the message box if Chrome Frame was the only product being |
// uninstalled. |
- if (installer_state.products().size() == 1U) { |
+ const Products& products = installer_state.products(); |
+ int num_products = 0; |
+ for (size_t i = 0; i < products.size(); ++i) { |
+ if (!products[i]->is_chrome_binaries()) |
+ ++num_products; |
+ } |
+ if (num_products == 1U) { |
::MessageBoxW(NULL, |
installer::GetLocalizedString( |
IDS_UNINSTALL_COMPLETE_BASE).c_str(), |