Index: chrome/installer/setup/setup_main.cc |
=================================================================== |
--- chrome/installer/setup/setup_main.cc (revision 71802) |
+++ chrome/installer/setup/setup_main.cc (working copy) |
@@ -20,6 +20,7 @@ |
#include "base/string_util.h" |
#include "base/utf_string_conversions.h" |
#include "base/values.h" |
+#include "base/win/registry.h" |
#include "base/win/scoped_handle.h" |
#include "base/win/win_util.h" |
#include "base/win/windows_version.h" |
@@ -31,6 +32,7 @@ |
#include "chrome/installer/setup/setup_util.h" |
#include "chrome/installer/setup/uninstall.h" |
#include "chrome/installer/util/browser_distribution.h" |
+#include "chrome/installer/util/channel_info.h" |
#include "chrome/installer/util/delete_after_reboot_helper.h" |
#include "chrome/installer/util/delete_tree_work_item.h" |
#include "chrome/installer/util/google_update_settings.h" |
@@ -45,7 +47,6 @@ |
#include "chrome/installer/util/lzma_util.h" |
#include "chrome/installer/util/master_preferences.h" |
#include "chrome/installer/util/master_preferences_constants.h" |
-#include "chrome/installer/util/package_properties.h" |
#include "chrome/installer/util/shell_util.h" |
#include "chrome/installer/util/util_constants.h" |
@@ -54,11 +55,8 @@ |
using installer::InstallerState; |
using installer::InstallationState; |
using installer::Product; |
-using installer::ProductPackageMapping; |
using installer::ProductState; |
using installer::Products; |
-using installer::Package; |
-using installer::Packages; |
using installer::MasterPreferences; |
const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; |
@@ -83,7 +81,7 @@ |
// present on the system already. As the final step the new archive file |
// is unpacked in the path specified by parameter "output_directory". |
DWORD UnPackArchive(const FilePath& archive, |
- const Package& installation, |
+ const InstallerState& installer_state, |
const FilePath& temp_path, |
const FilePath& output_directory, |
bool& incremental_install) { |
@@ -98,7 +96,7 @@ |
FilePath uncompressed_archive(temp_path.Append(installer::kChromeArchive)); |
scoped_ptr<Version> archive_version( |
- installer::GetVersionFromArchiveDir(installation.path())); |
+ installer::GetVersionFromArchiveDir(installer_state.target_path())); |
// Check if this is differential update and if it is, patch it to the |
// installer archive that should already be on the machine. We assume |
@@ -112,7 +110,7 @@ |
return installer::CHROME_NOT_INSTALLED; |
} |
- FilePath existing_archive(installation.path().Append( |
+ FilePath existing_archive(installer_state.target_path().Append( |
UTF8ToWide(archive_version->GetString()))); |
existing_archive = existing_archive.Append(installer::kInstallerDir); |
existing_archive = existing_archive.Append(installer::kChromeArchive); |
@@ -136,12 +134,11 @@ |
// system and a key called 'opv' in the registry. This function will move |
// new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. |
installer::InstallStatus RenameChromeExecutables( |
- const Package& installation) { |
- FilePath chrome_exe(installation.path().Append(installer::kChromeExe)); |
- FilePath chrome_old_exe(installation.path().Append( |
- installer::kChromeOldExe)); |
- FilePath chrome_new_exe(installation.path().Append( |
- installer::kChromeNewExe)); |
+ const InstallerState& installer_state) { |
+ const FilePath &target_path = installer_state.target_path(); |
+ FilePath chrome_exe(target_path.Append(installer::kChromeExe)); |
+ FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); |
+ FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); |
scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
install_list->AddDeleteTreeWorkItem(chrome_old_exe); |
@@ -158,9 +155,8 @@ |
std::wstring()); |
install_list->AddDeleteTreeWorkItem(chrome_new_exe); |
- HKEY reg_root = installation.system_level() ? HKEY_LOCAL_MACHINE : |
- HKEY_CURRENT_USER; |
- const Products& products = installation.products(); |
+ HKEY reg_root = installer_state.root_key(); |
+ const Products& products = installer_state.products(); |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
BrowserDistribution* browser_dist = product->distribution(); |
@@ -182,44 +178,160 @@ |
return ret; |
} |
+// 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. The supported multi-install |
+// modes are: |
+// --multi-install --chrome --chrome-frame --ready-mode |
+// - If a non-multi Chrome Frame installation is present, Chrome Frame is |
+// removed from |installer_state|'s list of products (thereby preserving |
+// the existing SxS install). |
+// - If a multi Chrome Frame installation is present, its options are |
+// preserved (i.e., the --ready-mode command-line option is ignored). |
+// --multi-install --chrome-frame |
+// - If a non-multi Chrome Frame installation is present, fail. |
+// - If a Chrome installation on a different channel is present, fail. |
+// - If a Chrome installation is present, add it to the set of products to |
+// install. |
+// 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. |
bool CheckPreInstallConditions(const InstallationState& original_state, |
- const InstallerState& installer_state, |
- const Package& installation, |
const MasterPreferences& prefs, |
+ InstallerState* installer_state, |
installer::InstallStatus* status) { |
- const Products& products = installation.products(); |
+ const Products& products = installer_state->products(); |
DCHECK(products.size()); |
bool is_first_install = true; |
- const bool system_level = installation.system_level(); |
+ const bool system_level = installer_state->system_install(); |
+ if (installer_state->multi_install()) { |
+ const Product* chrome = |
+ installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
+ const Product* chrome_frame = |
+ installer_state->FindProduct(BrowserDistribution::CHROME_FRAME); |
+ const ProductState* cf_state = |
+ original_state.GetProductState(system_level, |
+ BrowserDistribution::CHROME_FRAME); |
+ if (chrome != NULL) { |
+ if (chrome_frame != NULL && |
+ chrome_frame->HasOption(installer::kOptionReadyMode)) { |
+ // We're being asked to install Chrome with Chrome Frame in ready-mode. |
+ // This is an optimistic operation: if a SxS install of Chrome Frame |
+ // is already present, don't touch it; if a multi-install of Chrome |
+ // Frame is present, preserve its settings (ready-mode, CEEE). |
+ if (cf_state != NULL) { |
+ installer_state->RemoveProduct(chrome_frame); |
+ chrome_frame = NULL; |
+ if (cf_state->multi_install()) { |
+ chrome_frame = installer_state->AddProductFromState( |
+ BrowserDistribution::CHROME_FRAME, *cf_state); |
+ VLOG(1) << "Upgrading existing multi-install " |
+ << chrome_frame->distribution()->GetApplicationName() |
+ << " rather than installing in ready-mode."; |
+ } else { |
+ VLOG(1) << "Skipping upgrade of single-install Chrome Frame rather " |
+ "than installing in ready-mode."; |
+ } |
+ } else { |
+ VLOG(1) << "Performing initial install of Chrome Frame ready-mode."; |
+ } |
+ } |
+ } else if (chrome_frame != NULL) { |
+ // We're being asked to install or update Chrome Frame alone. Fail if a |
+ // single-install of Chrome Frame is already installed. |
+ // TODO(grt): Add support for migration of Chrome Frame from single- to |
+ // multi-install. |
+ if (cf_state != NULL && !cf_state->multi_install()) { |
+ *status = installer::NON_MULTI_INSTALLATION_EXISTS; |
+ InstallUtil::WriteInstallerResult(system_level, |
+ installer_state->state_key(), *status, |
+ IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
+ return false; |
+ } |
+ const ProductState* chrome_state = |
+ original_state.GetProductState(system_level, |
+ BrowserDistribution::CHROME_BROWSER); |
+ if (chrome_state != NULL) { |
+ base::win::RegKey key; |
tommi (sloooow) - chröme
2011/01/21 21:45:17
if ready-mode is being installed you need to check
grt (UTC plus 2)
2011/01/24 16:07:02
Done. Thanks for the patch you sent for doing thi
|
+ installer::ChannelInfo cf_channel; |
+ // Chrome Frame may not yet be installed, so peek into the registry |
+ // directly to see what channel Google Update has specified. There will |
+ // be no value if we're not being managed by Google Update. |
+ if (key.Open(installer_state->root_key(), |
+ chrome_frame->distribution()->GetStateKey().c_str(), |
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) { |
+ cf_channel.Initialize(key); |
+ } |
+ // Fail if Chrome is already installed but is on a different update |
+ // channel. |
+ if (!cf_channel.EqualsBaseOf(chrome_state->channel())) { |
+ *status = installer::CONFLICTING_CHANNEL_EXISTS; |
+ InstallUtil::WriteInstallerResult(system_level, |
+ installer_state->state_key(), *status, |
+ IDS_INSTALL_CONFLICTING_CHANNEL_EXISTS_BASE, NULL); |
+ return false; |
+ } |
+ // Otherwise, add Chrome to the set of products so that it is updated, |
+ // too. |
+ chrome = installer_state->AddProductFromState( |
tommi (sloooow) - chröme
2011/01/21 21:45:17
is there a missing check for multi first?
grt (UTC plus 2)
2011/01/24 16:07:02
In this case, we'll transition an existing single
|
+ BrowserDistribution::CHROME_BROWSER, *chrome_state); |
+ VLOG(1) << "Upgrading existing multi-install " |
+ << chrome->distribution()->GetApplicationName() |
+ << " along with " |
+ << chrome_frame->distribution()->GetApplicationName(); |
+ } |
tommi (sloooow) - chröme
2011/01/21 21:45:17
} else {
Check if ready-mode is being asked for.
grt (UTC plus 2)
2011/01/24 16:07:02
Done.
|
+ } |
+ } |
tommi (sloooow) - chröme
2011/01/21 21:45:17
} else {
abort if ready-mode is specified?
abo
grt (UTC plus 2)
2011/01/24 16:07:02
For the former, setup.exe currently silently ignor
tommi (sloooow) - chröme
2011/01/24 19:39:39
Hmm.. maybe we should just log a warning for now.
grt (UTC plus 2)
2011/01/25 03:09:39
Done.
|
+ |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
BrowserDistribution* browser_dist = product->distribution(); |
+ |
+ // Ensure that existing installs are of the same package type. |
const ProductState* product_state = |
original_state.GetProductState(system_level, browser_dist->GetType()); |
- if (product_state != NULL) |
+ if (product_state != NULL) { |
is_first_install = false; |
+ // Is the existing install's package type the same as this run? |
+ if (installer_state->multi_install()) { |
+ if (!product_state->multi_install()) { |
+ *status = installer::NON_MULTI_INSTALLATION_EXISTS; |
+ InstallUtil::WriteInstallerResult(system_level, |
+ installer_state->state_key(), *status, |
+ IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
+ return false; |
+ } |
+ } else { |
+ if (product_state->multi_install()) { |
+ *status = installer::MULTI_INSTALLATION_EXISTS; |
+ InstallUtil::WriteInstallerResult(system_level, |
+ installer_state->state_key(), *status, |
+ IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE, NULL); |
+ return false; |
+ } |
+ } |
+ } |
// Check to avoid simultaneous per-user and per-machine installs. |
const ProductState* other_state = |
original_state.GetProductState(!system_level, browser_dist->GetType()); |
- |
if (other_state != NULL) { |
LOG(ERROR) << "Already installed version " |
<< other_state->version().GetString() |
<< " conflicts with the current install mode."; |
if (!system_level && is_first_install && product->is_chrome()) { |
// This is user-level install and there is a system-level chrome |
- // installation. Instruct Omaha to launch the existing one. There |
- // should be no error dialog. |
+ // installation. Instruct Google Update to launch the existing one. |
+ // There should be no error dialog. |
FilePath chrome_exe(installer::GetChromeInstallPath(!system_level, |
browser_dist)); |
if (chrome_exe.empty()) { |
// If we failed to construct install path. Give up. |
*status = installer::OS_ERROR; |
InstallUtil::WriteInstallerResult(system_level, |
- installer_state.state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, |
+ installer_state->state_key(), *status, IDS_INSTALL_OS_ERROR_BASE, |
NULL); |
} else { |
*status = installer::EXISTING_VERSION_LAUNCHED; |
@@ -227,7 +339,7 @@ |
CommandLine cmd(chrome_exe); |
cmd.AppendSwitch(switches::kFirstRun); |
InstallUtil::WriteInstallerResult(system_level, |
- installer_state.state_key(), *status, 0, NULL); |
+ installer_state->state_key(), *status, 0, NULL); |
VLOG(1) << "Launching existing system-level chrome instead."; |
base::LaunchApp(cmd, false, false, NULL); |
} |
@@ -237,7 +349,7 @@ |
// If the following compile assert fires it means that the InstallStatus |
// enumeration changed which will break the contract between the old |
// chrome installed and the new setup.exe that is trying to upgrade. |
- COMPILE_ASSERT(installer::SXS_OPTION_NOT_SUPPORTED == 33, |
+ COMPILE_ASSERT(installer::CONFLICTING_CHANNEL_EXISTS == 39, |
dont_change_enum); |
// This is an update, not an install. Omaha should know the difference |
@@ -247,23 +359,47 @@ |
int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE : |
IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE; |
InstallUtil::WriteInstallerResult(system_level, |
- installer_state.state_key(), *status, str_id, NULL); |
+ installer_state->state_key(), *status, str_id, NULL); |
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. |
+ if (installer_state->multi_install()) { |
+ BrowserDistribution::Type product_checks[] = { |
+ BrowserDistribution::CHROME_BROWSER, |
+ BrowserDistribution::CHROME_FRAME |
+ }; |
+ |
+ for (size_t i = 0; i < arraysize(product_checks); ++i) { |
+ BrowserDistribution::Type type = product_checks[i]; |
+ if (!installer_state->FindProduct(type)) { |
+ const ProductState* state = |
+ original_state.GetProductState(system_level, type); |
+ if ((state != NULL) && state->multi_install()) { |
+ installer_state->AddProductFromState(type, *state); |
+ VLOG(1) << "Product already installed and must be included: " |
+ << BrowserDistribution::GetSpecificDistribution( |
+ type)->GetApplicationName(); |
+ } |
+ } |
+ } |
+ } |
+ |
// If no previous installation of Chrome, make sure installation directory |
// either does not exist or can be deleted (i.e. is not locked by some other |
// process). |
if (is_first_install) { |
- if (file_util::PathExists(installation.path()) && |
- !file_util::Delete(installation.path(), true)) { |
- LOG(ERROR) << "Installation directory " << installation.path().value() |
+ if (file_util::PathExists(installer_state->target_path()) && |
+ !file_util::Delete(installer_state->target_path(), true)) { |
+ LOG(ERROR) << "Installation directory " |
+ << installer_state->target_path().value() |
<< " exists and can not be deleted."; |
*status = installer::INSTALL_DIR_IN_USE; |
int str_id = IDS_INSTALL_DIR_IN_USE_BASE; |
InstallUtil::WriteInstallerResult(system_level, |
- installer_state.state_key(), *status, str_id, NULL); |
+ installer_state->state_key(), *status, str_id, NULL); |
return false; |
} |
} |
@@ -271,13 +407,15 @@ |
return true; |
} |
tommi (sloooow) - chröme
2011/01/21 21:45:17
just a general comment on this function. It's get
grt (UTC plus 2)
2011/01/24 16:07:02
Totally. For now, I've pulled out two funcs.
|
-installer::InstallStatus InstallChrome(const InstallationState& original_state, |
- const InstallerState& installer_state, |
- const CommandLine& cmd_line, const Package& installation, |
- const MasterPreferences& prefs) { |
+installer::InstallStatus InstallProducts( |
+ const InstallationState& original_state, |
+ const CommandLine& cmd_line, |
+ const MasterPreferences& prefs, |
+ InstallerState* installer_state) { |
+ const bool system_install = installer_state->system_install(); |
installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
- if (!CheckPreInstallConditions(original_state, installer_state, installation, |
- prefs, &install_status)) |
+ if (!CheckPreInstallConditions(original_state, prefs, installer_state, |
+ &install_status)) |
return install_status; |
// For install the default location for chrome.packed.7z is in current |
@@ -291,15 +429,15 @@ |
installer::switches::kInstallArchive); |
} |
VLOG(1) << "Archive found to install Chrome " << archive.value(); |
- const Products& products = installation.products(); |
+ const Products& products = installer_state->products(); |
// Create a temp folder where we will unpack Chrome archive. If it fails, |
// then we are doomed, so return immediately and no cleanup is required. |
FilePath temp_path; |
if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) { |
LOG(ERROR) << "Could not create temporary path."; |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), installer::TEMP_DIR_FAILED, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), installer::TEMP_DIR_FAILED, |
IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL); |
return installer::TEMP_DIR_FAILED; |
} |
@@ -307,11 +445,11 @@ |
FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir)); |
bool incremental_install = false; |
- if (UnPackArchive(archive, installation, temp_path, unpack_path, |
+ if (UnPackArchive(archive, *installer_state, temp_path, unpack_path, |
incremental_install)) { |
install_status = installer::UNCOMPRESSION_FAILED; |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), install_status, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), install_status, |
IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL); |
} else { |
VLOG(1) << "unpacked to " << unpack_path.value(); |
@@ -321,8 +459,8 @@ |
if (!installer_version.get()) { |
LOG(ERROR) << "Did not find any valid version in installer."; |
install_status = installer::INVALID_ARCHIVE; |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), install_status, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), install_status, |
IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL); |
} else { |
// TODO(tommi): Move towards having only a single version that is common |
@@ -332,10 +470,10 @@ |
// (or rather must) be upgraded. |
VLOG(1) << "version to install: " << installer_version->GetString(); |
bool higher_version_installed = false; |
- for (size_t i = 0; i < installation.products().size(); ++i) { |
- const Product* product = installation.products()[i]; |
+ for (size_t i = 0; i < installer_state->products().size(); ++i) { |
+ const Product* product = installer_state->products()[i]; |
const ProductState* product_state = |
- original_state.GetProductState(installer_state.system_install(), |
+ original_state.GetProductState(system_install, |
product->distribution()->GetType()); |
if (product_state != NULL && |
(product_state->version().CompareTo(*installer_version) > 0)) { |
@@ -346,12 +484,12 @@ |
if (product->is_chrome()) { |
// TODO(robertshield): We should take the installer result text |
// strings from the Product. |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), install_status, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), install_status, |
IDS_INSTALL_HIGHER_VERSION_BASE, NULL); |
} else { |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), install_status, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), install_status, |
IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL); |
} |
} |
@@ -364,25 +502,25 @@ |
FilePath prefs_source_path(cmd_line.GetSwitchValueNative( |
installer::switches::kInstallerData)); |
install_status = installer::InstallOrUpdateProduct(original_state, |
- installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, |
- prefs_source_path, prefs, *installer_version, installation); |
+ *installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path, |
+ prefs_source_path, prefs, *installer_version); |
int install_msg_base = IDS_INSTALL_FAILED_BASE; |
std::wstring chrome_exe; |
if (install_status == installer::SAME_VERSION_REPAIR_FAILED) { |
- if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { |
+ if (installer_state->FindProduct(BrowserDistribution::CHROME_FRAME)) { |
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE; |
} else { |
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE; |
} |
} else if (install_status != installer::INSTALL_FAILED) { |
- if (installation.path().empty()) { |
+ if (installer_state->target_path().empty()) { |
// If we failed to construct install path, it means the OS call to |
// get %ProgramFiles% or %AppData% failed. Report this as failure. |
install_msg_base = IDS_INSTALL_OS_ERROR_BASE; |
install_status = installer::OS_ERROR; |
} else { |
- chrome_exe = installation.path() |
+ chrome_exe = installer_state->target_path() |
.Append(installer::kChromeExe).value(); |
chrome_exe = L"\"" + chrome_exe + L"\""; |
install_msg_base = 0; |
@@ -390,7 +528,7 @@ |
} |
const Product* chrome_install = |
- FindProduct(products, BrowserDistribution::CHROME_BROWSER); |
+ installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER); |
bool value = false; |
if (chrome_install) { |
@@ -404,8 +542,8 @@ |
bool write_chrome_launch_string = (!value) && |
(install_status != installer::IN_USE_UPDATED); |
- InstallUtil::WriteInstallerResult(installer_state.system_install(), |
- installer_state.state_key(), install_status, install_msg_base, |
+ InstallUtil::WriteInstallerResult(system_install, |
+ installer_state->state_key(), install_status, install_msg_base, |
write_chrome_launch_string ? &chrome_exe : NULL); |
if (install_status == installer::FIRST_INSTALL_SUCCESS) { |
@@ -416,8 +554,8 @@ |
prefs.GetBool( |
installer::master_preferences::kDoNotLaunchChrome, |
&do_not_launch_chrome); |
- if (!installation.system_level() && !do_not_launch_chrome) |
- chrome_install->LaunchChrome(); |
+ if (!system_install && !do_not_launch_chrome) |
+ chrome_install->LaunchChrome(installer_state->target_path()); |
} |
} else if ((install_status == installer::NEW_VERSION_UPDATED) || |
(install_status == installer::IN_USE_UPDATED)) { |
@@ -438,7 +576,7 @@ |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
product->distribution()->LaunchUserExperiment(install_status, |
- *installer_version, *product, installation.system_level()); |
+ *installer_version, *product, system_install); |
} |
} |
@@ -472,14 +610,13 @@ |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
product->distribution()->UpdateInstallStatus( |
- installer_state.system_install(), incremental_install, |
- prefs.is_multi_install(), install_status); |
- } |
- if (prefs.is_multi_install()) { |
- installation.properties()->UpdateInstallStatus( |
- installer_state.system_install(), incremental_install, true, |
+ system_install, incremental_install, prefs.is_multi_install(), |
install_status); |
} |
+ if (installer_state->multi_install()) { |
+ installer_state->multi_package_binaries_distribution()->UpdateInstallStatus( |
+ system_install, incremental_install, true, install_status); |
+ } |
return install_status; |
} |
@@ -539,11 +676,10 @@ |
// various tasks other than installation (renaming chrome.exe, showing eula |
// among others). This function returns true if any such command line option |
// has been found and processed (so setup.exe should exit at that point). |
-bool HandleNonInstallCmdLineOptions(const InstallerState& installer_state, |
+bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, |
const CommandLine& cmd_line, |
- const ProductPackageMapping& installs, |
+ const InstallerState& installer_state, |
int* exit_code) { |
- DCHECK(installs.products().size()); |
bool handled = true; |
// TODO(tommi): Split these checks up into functions and use a data driven |
// map of switch->function. |
@@ -588,12 +724,11 @@ |
cmd_line.GetSwitchValueNative(installer::switches::kShowEula); |
*exit_code = ShowEULADialog(inner_frame); |
if (installer::EULA_REJECTED != *exit_code) |
- GoogleUpdateSettings::SetEULAConsent(*installs.packages()[0].get(), true); |
+ GoogleUpdateSettings::SetEULAConsent(installer_state, true); |
} else if (cmd_line.HasSwitch( |
installer::switches::kRegisterChromeBrowser)) { |
const Product* chrome_install = |
- FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); |
- DCHECK(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 |
@@ -611,16 +746,13 @@ |
*exit_code = ShellUtil::RegisterChromeBrowser( |
chrome_install->distribution(), chrome_exe, suffix, false); |
} else { |
- LOG(ERROR) << "Can't register browser - Chrome distribution not found"; |
+ LOG(DFATAL) << "Can't register browser - Chrome distribution not found"; |
*exit_code = installer::UNKNOWN_STATUS; |
} |
} else if (cmd_line.HasSwitch(installer::switches::kRenameChromeExe)) { |
// If --rename-chrome-exe is specified, we want to rename the executables |
// and exit. |
- const Packages& packages = installs.packages(); |
- DCHECK_EQ(1U, packages.size()); |
- for (size_t i = 0; i < packages.size(); ++i) |
- *exit_code = RenameChromeExecutables(*packages[i].get()); |
+ *exit_code = RenameChromeExecutables(installer_state); |
} else if (cmd_line.HasSwitch( |
installer::switches::kRemoveChromeRegistration)) { |
// This is almost reverse of --register-chrome-browser option above. |
@@ -635,7 +767,7 @@ |
} |
installer::InstallStatus tmp = installer::UNKNOWN_STATUS; |
const Product* chrome_install = |
- FindProduct(installs.products(), BrowserDistribution::CHROME_BROWSER); |
+ installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
DCHECK(chrome_install); |
if (chrome_install) { |
installer::DeleteChromeRegistrationKeys(chrome_install->distribution(), |
@@ -651,37 +783,41 @@ |
if (flavor == -1) { |
*exit_code = installer::UNKNOWN_STATUS; |
} else { |
- const Products& products = installs.products(); |
+ const Products& products = installer_state.products(); |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
BrowserDistribution* browser_dist = product->distribution(); |
- browser_dist->InactiveUserToastExperiment(flavor, *product); |
+ browser_dist->InactiveUserToastExperiment(flavor, *product, |
+ installer_state.target_path()); |
} |
} |
} else if (cmd_line.HasSwitch(installer::switches::kSystemLevelToast)) { |
- const Products& products = installs.products(); |
+ const Products& products = installer_state.products(); |
for (size_t i = 0; i < products.size(); ++i) { |
const Product* product = products[i]; |
BrowserDistribution* browser_dist = product->distribution(); |
// We started as system-level and have been re-launched as user level |
// to continue with the toast experiment. |
scoped_ptr<Version> installed_version( |
- InstallUtil::GetChromeVersion(browser_dist, installs.system_level())); |
+ InstallUtil::GetChromeVersion(browser_dist, |
+ installer_state.system_install())); |
browser_dist->LaunchUserExperiment(installer::REENTRY_SYS_UPDATE, |
*installed_version, *product, true); |
} |
} else if (cmd_line.HasSwitch( |
installer::switches::kChromeFrameReadyModeOptIn)) { |
*exit_code = InstallUtil::GetInstallReturnCode( |
- installer::ChromeFrameReadyModeOptIn(installer_state, cmd_line)); |
+ installer::ChromeFrameReadyModeOptIn(original_state, installer_state)); |
} else if (cmd_line.HasSwitch( |
installer::switches::kChromeFrameReadyModeTempOptOut)) { |
*exit_code = InstallUtil::GetInstallReturnCode( |
- installer::ChromeFrameReadyModeTempOptOut(cmd_line)); |
+ installer::ChromeFrameReadyModeTempOptOut(original_state, |
+ installer_state)); |
} else if (cmd_line.HasSwitch( |
installer::switches::kChromeFrameReadyModeEndTempOptOut)) { |
*exit_code = InstallUtil::GetInstallReturnCode( |
- installer::ChromeFrameReadyModeEndTempOptOut(cmd_line)); |
+ installer::ChromeFrameReadyModeEndTempOptOut(original_state, |
+ installer_state)); |
} else { |
handled = false; |
} |
@@ -743,55 +879,10 @@ |
bool initialized_; |
}; |
-bool PopulateInstallations(bool for_uninstall, |
- const MasterPreferences& prefs, |
- ProductPackageMapping* installations) { |
- DCHECK(installations); |
- bool success = true; |
- bool implicit_chrome_install = false; |
- bool implicit_gcf_install = false; |
- // See what products are already installed in multi mode. |
- // When we do multi installs, we must upgrade all installations in sync since |
- // they share the binaries. Be careful to not do this when we're uninstalling |
- // a product. |
- if (prefs.is_multi_install() && !for_uninstall) { |
- struct CheckInstall { |
- bool* installed; |
- BrowserDistribution::Type type; |
- } product_checks[] = { |
- {&implicit_chrome_install, BrowserDistribution::CHROME_BROWSER}, |
- {&implicit_gcf_install, BrowserDistribution::CHROME_FRAME}, |
- }; |
- for (size_t i = 0; i < arraysize(product_checks); ++i) { |
- BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( |
- product_checks[i].type, prefs); |
- *product_checks[i].installed = installer::IsInstalledAsMulti( |
- installations->system_level(), dist); |
- LOG_IF(INFO, *product_checks[i].installed) |
- << "Product already installed and must be included: " |
- << dist->GetApplicationName(); |
- } |
- } |
- if (prefs.install_chrome() || implicit_chrome_install) { |
- VLOG(1) << (for_uninstall ? "Uninstall" : "Install") |
- << " distribution: Chrome"; |
- success = installations->AddDistribution( |
- BrowserDistribution::CHROME_BROWSER, prefs); |
- } |
- |
- if (success && (prefs.install_chrome_frame() || implicit_gcf_install)) { |
- VLOG(1) << (for_uninstall ? "Uninstall" : "Install") |
- << " distribution: Chrome Frame"; |
- success = installations->AddDistribution( |
- BrowserDistribution::CHROME_FRAME, prefs); |
- } |
- return success; |
-} |
- |
// Returns the Custom information for the client identified by the exe path |
// passed in. This information is used for crash reporting. |
google_breakpad::CustomClientInfo* GetCustomInfo(const wchar_t* exe_path) { |
@@ -883,28 +974,12 @@ |
InitializeCrashReporting(system_install)); |
InstallationState original_state; |
- original_state.Initialize(prefs); |
+ original_state.Initialize(); |
InstallerState installer_state; |
- installer_state.Initialize(prefs, original_state); |
+ installer_state.Initialize(cmd_line, prefs, original_state); |
const bool is_uninstall = cmd_line.HasSwitch(installer::switches::kUninstall); |
- ProductPackageMapping installations(prefs.is_multi_install(), system_install); |
- if (!PopulateInstallations(is_uninstall, prefs, &installations)) { |
- // Currently this can only fail if one of the installations is a multi and |
- // a pre-existing single installation exists or vice versa. |
- installer::InstallStatus status = installer::NON_MULTI_INSTALLATION_EXISTS; |
- int string_id = IDS_INSTALL_NON_MULTI_INSTALLATION_EXISTS_BASE; |
- if (!prefs.is_multi_install()) { |
- status = installer::MULTI_INSTALLATION_EXISTS; |
- string_id = IDS_INSTALL_MULTI_INSTALLATION_EXISTS_BASE; |
- } |
- LOG(ERROR) << "Failed to populate installations: " << status; |
- InstallUtil::WriteInstallerResult(system_install, |
- installer_state.state_key(), status, string_id, NULL); |
- return status; |
- } |
- |
// Check to make sure current system is WinXP or later. If not, log |
// error message and get out. |
if (!InstallUtil::IsOSSupported()) { |
@@ -940,8 +1015,8 @@ |
} |
int exit_code = 0; |
- if (HandleNonInstallCmdLineOptions(installer_state, cmd_line, installations, |
- &exit_code)) |
+ if (HandleNonInstallCmdLineOptions(original_state, cmd_line, installer_state, |
+ &exit_code)) |
return exit_code; |
if (system_install && !IsUserAnAdmin()) { |
@@ -965,24 +1040,22 @@ |
} |
installer::InstallStatus install_status = installer::UNKNOWN_STATUS; |
- // If --uninstall option is given, uninstall chrome |
+ // If --uninstall option is given, uninstall the identified product(s) |
if (is_uninstall) { |
- for (size_t i = 0; i < installations.products().size(); ++i) { |
+ const Products& products = installer_state.products(); |
+ for (size_t i = 0; i < products.size(); ++i) { |
install_status = UninstallProduct(original_state, installer_state, |
- cmd_line, *installations.products()[i]); |
+ cmd_line, *products[i]); |
} |
} else { |
// If --uninstall option is not specified, we assume it is install case. |
- const Packages& packages = installations.packages(); |
- VLOG(1) << "Installing to " << packages.size() << " target paths"; |
- for (size_t i = 0; i < packages.size(); ++i) { |
- install_status = InstallChrome(original_state, installer_state, cmd_line, |
- *packages[i].get(), prefs); |
- } |
+ VLOG(1) << "Installing to " << installer_state.target_path().value(); |
+ install_status = InstallProducts(original_state, cmd_line, prefs, |
+ &installer_state); |
} |
const Product* cf_install = |
- FindProduct(installations.products(), BrowserDistribution::CHROME_FRAME); |
+ installer_state.FindProduct(BrowserDistribution::CHROME_FRAME); |
if (cf_install && |
!cmd_line.HasSwitch(installer::switches::kForceUninstall)) { |
@@ -991,7 +1064,7 @@ |
} else if (is_uninstall) { |
// Only show the message box if Chrome Frame was the only product being |
// uninstalled. |
- if (installations.products().size() == 1U) { |
+ if (installer_state.products().size() == 1U) { |
::MessageBoxW(NULL, |
installer::GetLocalizedString( |
IDS_UNINSTALL_COMPLETE_BASE).c_str(), |
@@ -1005,17 +1078,11 @@ |
// MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will |
// rollback the action. If we're uninstalling we want to avoid this, so always |
// report success, squashing any more informative return codes. |
- // TODO(tommi): Fix this loop when IsMsi has been moved out of the Product |
- // class. |
- for (size_t i = 0; i < installations.products().size(); ++i) { |
- const Product* product = installations.products()[i]; |
- if (!(product->IsMsi() && is_uninstall)) { |
- // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
- // to pass through, since this is only returned on uninstall which is |
- // never invoked directly by Google Update. |
- return_code = InstallUtil::GetInstallReturnCode(install_status); |
- } |
- } |
+ if (!(installer_state.msi() && is_uninstall)) |
+ // Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT |
+ // to pass through, since this is only returned on uninstall which is |
+ // never invoked directly by Google Update. |
+ return_code = InstallUtil::GetInstallReturnCode(install_status); |
VLOG(1) << "Installation complete, returning: " << return_code; |