summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-05 03:13:33 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-05 03:13:33 +0000
commita6ea126034ade23d94df94e2b105538152f6d86e (patch)
tree24b3059668f27f4a2e29fca025f77eefe14987a5
parent269bb3a69e402a893bc8d01a99347c7ef6a5a38a (diff)
downloadchromium_src-a6ea126034ade23d94df94e2b105538152f6d86e.zip
chromium_src-a6ea126034ade23d94df94e2b105538152f6d86e.tar.gz
chromium_src-a6ea126034ade23d94df94e2b105538152f6d86e.tar.bz2
- WriteInstallerResult is now back in InstallUtil and only writes the result where it is needed
- WriteInstallerResult is no longer called on uninstall (Google Update doesn't check it on uninstall) - Introduced the poorly named InstallationState (state of the system based on registry inspection) and InstallerState (state of the current operation) classes - Product::GetInstalledVersion and Product::IsInstalled are gone; use InstallationState instead - A few cleanups to make the code comply with the style guide - UpdateDiffInstallStatus has been renamed to UpdateInstallStatus - Chromium builds noop in UpdateInstallStatus (this was always the case for the browser, but now also is for GCF and the multi-installer package). - The -multifail suffixes is now added to/removed from the Google Update "ap" value by UpdateInstallStatus on the basis of multi-install success/failure. - Added code to update the Google Update "ap" value based on the set up products/options installed - ChannelInfo is now an ordered list of modifiers and suffixes. We're careful to keep -full at the end since that was an operating assumption previously. - ActivePackageProperties is a typedef to either the Chrome or Chromium PackageProperties class TEST=Some existing unit tests updated; more new unit tests to follow. BUG=61609 Review URL: http://codereview.chromium.org/5988007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70483 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_installer.gypi1
-rw-r--r--chrome/chrome_installer_util.gypi8
-rw-r--r--chrome/installer/mini_installer/mini_installer.cc1
-rw-r--r--chrome/installer/setup/install.cc138
-rw-r--r--chrome/installer/setup/install.h9
-rw-r--r--chrome/installer/setup/setup_main.cc191
-rw-r--r--chrome/installer/setup/uninstall.cc102
-rw-r--r--chrome/installer/setup/uninstall.h21
-rw-r--r--chrome/installer/util/browser_distribution.cc12
-rw-r--r--chrome/installer/util/browser_distribution.h14
-rw-r--r--chrome/installer/util/channel_info.cc147
-rw-r--r--chrome/installer/util/channel_info.h48
-rw-r--r--chrome/installer/util/channel_info_unittest.cc41
-rw-r--r--chrome/installer/util/chrome_frame_distribution.cc34
-rw-r--r--chrome/installer/util/chrome_frame_distribution.h11
-rw-r--r--chrome/installer/util/google_chrome_distribution.cc19
-rw-r--r--chrome/installer/util/google_chrome_distribution.h7
-rw-r--r--chrome/installer/util/google_chrome_distribution_dummy.cc11
-rw-r--r--chrome/installer/util/google_update_settings.cc60
-rw-r--r--chrome/installer/util/google_update_settings.h21
-rw-r--r--chrome/installer/util/google_update_settings_unittest.cc242
-rw-r--r--chrome/installer/util/install_util.cc30
-rw-r--r--chrome/installer/util/install_util.h10
-rw-r--r--chrome/installer/util/install_util_unittest.cc77
-rw-r--r--chrome/installer/util/installation_state.cc135
-rw-r--r--chrome/installer/util/installation_state.h97
-rw-r--r--chrome/installer/util/installer_state.cc93
-rw-r--r--chrome/installer/util/installer_state.h62
-rw-r--r--chrome/installer/util/package.cc56
-rw-r--r--chrome/installer/util/package.h6
-rw-r--r--chrome/installer/util/package_properties.cc14
-rw-r--r--chrome/installer/util/package_properties.h14
-rw-r--r--chrome/installer/util/package_properties_unittest.cc19
-rw-r--r--chrome/installer/util/package_unittest.cc55
-rw-r--r--chrome/installer/util/product.cc21
-rw-r--r--chrome/installer/util/product.h13
-rw-r--r--chrome/installer/util/product_unittest.cc26
-rw-r--r--chrome/installer/util/util_constants.h74
38 files changed, 1370 insertions, 570 deletions
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index 764b7f8e..5430e69 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -87,6 +87,7 @@
'installer/util/google_chrome_distribution_unittest.cc',
'installer/util/google_update_settings_unittest.cc',
'installer/util/helper_unittest.cc',
+ 'installer/util/install_util_unittest.cc',
'installer/util/installer_util_unittests.rc',
'installer/util/installer_util_unittests_resource.h',
'installer/util/language_selector_unittest.cc',
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi
index b581c41..72601bb 100644
--- a/chrome/chrome_installer_util.gypi
+++ b/chrome/chrome_installer_util.gypi
@@ -41,6 +41,10 @@
'installer/util/helper.h',
'installer/util/install_util.cc',
'installer/util/install_util.h',
+ 'installer/util/installation_state.h',
+ 'installer/util/installation_state.cc',
+ 'installer/util/installer_state.h',
+ 'installer/util/installer_state.cc',
'installer/util/l10n_string_util.cc',
'installer/util/l10n_string_util.h',
'installer/util/language_selector.cc',
@@ -51,6 +55,8 @@
'installer/util/move_tree_work_item.h',
'installer/util/package.h',
'installer/util/package.cc',
+ 'installer/util/package_properties.h',
+ 'installer/util/package_properties.cc',
'installer/util/self_reg_work_item.cc',
'installer/util/self_reg_work_item.h',
'installer/util/set_reg_value_work_item.cc',
@@ -107,8 +113,6 @@
'installer/util/lzma_util.h',
'installer/util/master_preferences.cc',
'installer/util/master_preferences.h',
- 'installer/util/package_properties.h',
- 'installer/util/package_properties.cc',
'installer/util/product.h',
'installer/util/product.cc',
'installer/util/shell_util.cc',
diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc
index bbbcf65..760a70c 100644
--- a/chrome/installer/mini_installer/mini_installer.cc
+++ b/chrome/installer/mini_installer/mini_installer.cc
@@ -649,6 +649,7 @@ int WMain(HMODULE module) {
// any errors here and we try to set the suffix for user level unless
// --system-level is on the command line in which case we set it for system
// level instead. This only applies to the Google Chrome distribution.
+ // TODO(grt): also add -multifail if --multi-install.
SetFullInstallerFlag();
#endif
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 0403257e..ec36f79 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -27,6 +27,8 @@
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/package.h"
@@ -43,6 +45,8 @@
using base::win::RegKey;
using installer::ChannelInfo;
+using installer::InstallerState;
+using installer::InstallationState;
using installer::MasterPreferences;
using installer::Products;
using installer::Product;
@@ -219,6 +223,89 @@ void AddUninstallShortcutWorkItems(const FilePath& setup_path,
}
}
+// Adds work items that make registry adjustments for Google Update. When a
+// product is installed (including overinstall), Google Update will write the
+// channel ("ap") value into either Chrome or Chrome Frame's ClientState key.
+// In the multi-install case, this value is used as the basis upon which the
+// package's channel value is built (by adding the ordered list of installed
+// products and their options).
+void AddGoogleUpdateWorkItems(const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const Package& package,
+ WorkItemList* install_list) {
+ // Is a multi-install product being installed or over-installed?
+ if (installer_state.operation() != InstallerState::MULTI_INSTALL)
+ return;
+
+ const HKEY reg_root = package.system_level() ? HKEY_LOCAL_MACHINE :
+ HKEY_CURRENT_USER;
+ const std::wstring key_path = installer_state.state_key();
+ ChannelInfo channel_info;
+
+ // Update the "ap" value for the product being installed/updated.
+ // It is completely acceptable for there to be no "ap" value or even no
+ // ClientState key. Note that we check the registry rather than
+ // original_state since on a fresh install the "ap" value will be present
+ // sans "pv" value.
+ channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE));
+
+ // This is a multi-install product.
+ bool modified = channel_info.SetMultiInstall(true);
+
+ // Add the appropriate modifiers for all products and their options.
+ Products::const_iterator scan = package.products().begin();
+ const Products::const_iterator end = package.products().end();
+ for (; scan != end; ++scan) {
+ modified |= scan->get()->distribution()->SetChannelFlags(true,
+ &channel_info);
+ }
+
+ // Write the results if needed.
+ if (modified) {
+ install_list->AddSetRegValueWorkItem(reg_root, key_path,
+ google_update::kRegApField,
+ channel_info.value(), true);
+ }
+
+ // Synchronize the other products and the package with this one.
+ std::wstring other_key;
+ std::vector<std::wstring> keys;
+
+ keys.reserve(package.products().size());
+ other_key = package.properties()->GetStateKey();
+ if (other_key != key_path)
+ keys.push_back(other_key);
+ scan = package.products().begin();
+ for (; scan != end; ++scan) {
+ other_key = scan->get()->distribution()->GetStateKey();
+ if (other_key != key_path)
+ keys.push_back(other_key);
+ }
+
+ RegKey key;
+ ChannelInfo other_info;
+ std::vector<std::wstring>::const_iterator kscan = keys.begin();
+ std::vector<std::wstring>::const_iterator kend = keys.end();
+ for (; kscan != kend; ++kscan) {
+ // Handle the case where the ClientState key doesn't exist by creating it.
+ // This takes care of the multi-installer's package key, which is not
+ // created by Google Update for us.
+ if (!key.Open(reg_root, kscan->c_str(), KEY_QUERY_VALUE) ||
+ !other_info.Initialize(key)) {
+ other_info.set_value(std::wstring());
+ }
+ if (!other_info.Equals(channel_info)) {
+ if (!key.Valid())
+ install_list->AddCreateRegKeyWorkItem(reg_root, *kscan);
+ install_list->AddSetRegValueWorkItem(reg_root, *kscan,
+ google_update::kRegApField,
+ channel_info.value(), true);
+ }
+ }
+ // TODO(grt): check for other keys/values we should put in the package's
+ // ClientState and/or Clients key.
+}
+
// This is called when an MSI installation is run. It may be that a user is
// attempting to install the MSI on top of a non-MSI managed installation.
// If so, try and remove any existing uninstallation shortcuts, as we want the
@@ -693,6 +780,8 @@ void AddProductSpecificWorkItems(bool install,
// (typical new install), the function creates package during install
// and removes the whole directory during rollback.
installer::InstallStatus InstallNewVersion(
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
bool multi_install,
const FilePath& setup_path,
const FilePath& archive_path,
@@ -799,6 +888,10 @@ installer::InstallStatus InstallNewVersion(
// each product.
AddProductSpecificWorkItems(true, setup_path, new_version, package,
install_list.get());
+
+ AddGoogleUpdateWorkItems(original_state, installer_state, package,
+ install_list.get());
+
// Append the tasks that run after the installation.
AppendPostInstallTasks(multi_install,
setup_path,
@@ -852,6 +945,8 @@ installer::InstallStatus InstallNewVersion(
namespace installer {
installer::InstallStatus InstallOrUpdateProduct(
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
const FilePath& setup_path, const FilePath& archive_path,
const FilePath& install_temp_path, const FilePath& prefs_path,
const installer::MasterPreferences& prefs, const Version& new_version,
@@ -860,9 +955,9 @@ installer::InstallStatus InstallOrUpdateProduct(
src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir);
scoped_ptr<Version> existing_version;
- installer::InstallStatus result = InstallNewVersion(prefs.is_multi_install(),
- setup_path, archive_path, src_path, install_temp_path, new_version,
- &existing_version, install);
+ installer::InstallStatus result = InstallNewVersion(original_state,
+ installer_state, prefs.is_multi_install(), setup_path, archive_path,
+ src_path, install_temp_path, new_version, &existing_version, install);
if (!InstallUtil::GetInstallReturnCode(result)) {
if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty())
@@ -1007,9 +1102,12 @@ void AddChromeFrameWorkItems(bool install,
// uninstallation command line does not include the --chrome-frame switch
// so that uninstalling Chrome will no longer uninstall Chrome Frame.
- list->AddDeleteRegValueWorkItem(root,
- product.package().properties()->GetStateKey(),
- installer::kChromeFrameReadyModeField, false);
+ if (RegKey(root, product.package().properties()->GetStateKey().c_str(),
+ KEY_QUERY_VALUE).Valid()) {
+ list->AddDeleteRegValueWorkItem(root,
+ product.package().properties()->GetStateKey(),
+ installer::kChromeFrameReadyModeField, false);
+ }
const Product* chrome = installer::FindProduct(product.package().products(),
BrowserDistribution::CHROME_BROWSER);
@@ -1045,7 +1143,8 @@ void AddChromeFrameWorkItems(bool install,
}
}
-InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line) {
+InstallStatus ChromeFrameReadyModeOptIn(const InstallerState& installer_state,
+ const CommandLine& cmd_line) {
VLOG(1) << "Opting into Chrome Frame";
InstallStatus status = INSTALL_REPAIRED;
@@ -1059,11 +1158,7 @@ InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line) {
BrowserDistribution* chrome = BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER, prefs);
-#if defined(GOOGLE_CHROME_BUILD)
- ChromePackageProperties package_properties;
-#else
- ChromiumPackageProperties package_properties;
-#endif
+ ActivePackageProperties package_properties;
// Remove ChromeFrameReadyMode, update Chrome's uninstallation commands to
// only uninstall Chrome, and add an entry to the Add/Remove Programs
@@ -1074,21 +1169,28 @@ InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line) {
LOG(ERROR) << "Conflicting installations";
status = NON_MULTI_INSTALLATION_EXISTS;
} else {
+ InstallationState original_state;
+ original_state.Initialize(prefs);
+
scoped_refptr<Package> package(new Package(prefs.is_multi_install(),
system_install, path, &package_properties));
scoped_refptr<Product> cf_product(new Product(cf, package));
DCHECK(cf_product->ShouldCreateUninstallEntry() || cf_product->IsMsi());
scoped_refptr<Product> chrome_product(new Product(chrome, package));
-
- const Version* version = cf_product->GetInstalledVersion();
+ const ProductState* product_state =
+ original_state.GetProductState(system_install, cf->GetType());
+ if (product_state == NULL) {
+ LOG(ERROR) << "No Chrome Frame installation found for opt-in.";
+ return CHROME_NOT_INSTALLED;
+ }
scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
// This creates the uninstallation entry for GCF.
- AddUninstallShortcutWorkItems(cmd_line.GetProgram(), *version,
- item_list.get(), *cf_product.get());
+ AddUninstallShortcutWorkItems(cmd_line.GetProgram(),
+ product_state->version(), item_list.get(), *cf_product.get());
// This updates the Chrome uninstallation entries.
- AddUninstallShortcutWorkItems(cmd_line.GetProgram(), *version,
- item_list.get(), *chrome_product.get());
+ AddUninstallShortcutWorkItems(cmd_line.GetProgram(),
+ product_state->version(), item_list.get(), *chrome_product.get());
// Add a work item to delete the ChromeFrameReadyMode registry value.
HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
diff --git a/chrome/installer/setup/install.h b/chrome/installer/setup/install.h
index 7d21a24..40225c0 100644
--- a/chrome/installer/setup/install.h
+++ b/chrome/installer/setup/install.h
@@ -22,6 +22,8 @@ class WorkItemList;
namespace installer {
+class InstallationState;
+class InstallerState;
class Package;
// This function installs or updates a new version of Chrome. It returns
@@ -41,7 +43,9 @@ class Package;
//
// Note: since caller unpacks Chrome to install_temp_path\source, the caller
// is responsible for cleaning up install_temp_path.
-installer::InstallStatus InstallOrUpdateProduct(
+InstallStatus InstallOrUpdateProduct(
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
const FilePath& setup_path, const FilePath& archive_path,
const FilePath& install_temp_path, const FilePath& prefs_path,
const installer::MasterPreferences& prefs, const Version& new_version,
@@ -77,7 +81,8 @@ void AddChromeFrameWorkItems(bool install, const FilePath& setup_path,
// Removes the ChromeFrameReadyMode flag from the registry, updates Chrome's
// uninstallation commands to only uninstall Chrome, and adds an entry to the
// Add/Remove Programs list for GCF.
-InstallStatus ChromeFrameReadyModeOptIn(const CommandLine& cmd_line);
+InstallStatus ChromeFrameReadyModeOptIn(const InstallerState& installer_state,
+ const CommandLine& cmd_line);
} // namespace installer
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 48f0f1c..cc47f7b 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -37,6 +37,8 @@
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/html_dialog.h"
#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installer_state.h"
+#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/lzma_util.h"
@@ -48,8 +50,11 @@
#include "installer_util_strings.h" // NOLINT
+using installer::InstallerState;
+using installer::InstallationState;
using installer::Product;
using installer::ProductPackageMapping;
+using installer::ProductState;
using installer::Products;
using installer::Package;
using installer::Packages;
@@ -178,28 +183,32 @@ installer::InstallStatus RenameChromeExecutables(
return ret;
}
-bool CheckPreInstallConditions(const Package& installation,
- installer::InstallStatus& status) {
+bool CheckPreInstallConditions(const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const Package& installation,
+ const MasterPreferences& prefs,
+ installer::InstallStatus* status) {
const Products& products = installation.products();
DCHECK(products.size());
- bool is_first_install = true;
- bool system_level = installation.system_level();
+ bool is_first_install;
+ const bool system_level = installation.system_level();
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
BrowserDistribution* browser_dist = product->distribution();
- // TODO(tommi): If the current install is for a different distribution than
- // that might already be installed, then this check is incorrect.
- if (product->IsInstalled())
+ const ProductState* product_state =
+ original_state.GetProductState(system_level, browser_dist->GetType());
+ if (product_state != NULL)
is_first_install = false;
// Check to avoid simultaneous per-user and per-machine installs.
- scoped_ptr<Version> chrome_version(
- InstallUtil::GetChromeVersion(browser_dist, !system_level));
+ const ProductState* other_state =
+ original_state.GetProductState(!system_level, browser_dist->GetType());
- if (chrome_version.get()) {
- LOG(ERROR) << "Already installed version " << chrome_version->GetString()
+ 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
@@ -209,15 +218,17 @@ bool CheckPreInstallConditions(const Package& installation,
browser_dist));
if (chrome_exe.empty()) {
// If we failed to construct install path. Give up.
- status = installer::OS_ERROR;
- installation.WriteInstallerResult(status, IDS_INSTALL_OS_ERROR_BASE,
- NULL);
+ *status = installer::OS_ERROR;
+ InstallUtil::WriteInstallerResult(system_level,
+ installer_state.state_key(), *status, IDS_INSTALL_OS_ERROR_BASE,
+ NULL);
} else {
- status = installer::EXISTING_VERSION_LAUNCHED;
+ *status = installer::EXISTING_VERSION_LAUNCHED;
chrome_exe = chrome_exe.Append(installer::kChromeExe);
CommandLine cmd(chrome_exe);
cmd.AppendSwitch(switches::kFirstRun);
- installation.WriteInstallerResult(status, 0, NULL);
+ InstallUtil::WriteInstallerResult(system_level,
+ installer_state.state_key(), *status, 0, NULL);
VLOG(1) << "Launching existing system-level chrome instead.";
base::LaunchApp(cmd, false, false, NULL);
}
@@ -232,11 +243,12 @@ bool CheckPreInstallConditions(const Package& installation,
// This is an update, not an install. Omaha should know the difference
// and not show a dialog.
- status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS :
- installer::SYSTEM_LEVEL_INSTALL_EXISTS;
+ *status = system_level ? installer::USER_LEVEL_INSTALL_EXISTS :
+ installer::SYSTEM_LEVEL_INSTALL_EXISTS;
int str_id = system_level ? IDS_INSTALL_USER_LEVEL_EXISTS_BASE :
IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE;
- installation.WriteInstallerResult(status, str_id, NULL);
+ InstallUtil::WriteInstallerResult(system_level,
+ installer_state.state_key(), *status, str_id, NULL);
return false;
}
}
@@ -249,9 +261,10 @@ bool CheckPreInstallConditions(const Package& installation,
!file_util::Delete(installation.path(), true)) {
LOG(ERROR) << "Installation directory " << installation.path().value()
<< " exists and can not be deleted.";
- status = installer::INSTALL_DIR_IN_USE;
+ *status = installer::INSTALL_DIR_IN_USE;
int str_id = IDS_INSTALL_DIR_IN_USE_BASE;
- installation.WriteInstallerResult(status, str_id, NULL);
+ InstallUtil::WriteInstallerResult(system_level,
+ installer_state.state_key(), *status, str_id, NULL);
return false;
}
}
@@ -259,10 +272,13 @@ bool CheckPreInstallConditions(const Package& installation,
return true;
}
-installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
- const Package& installation, const MasterPreferences& prefs) {
+installer::InstallStatus InstallChrome(const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const CommandLine& cmd_line, const Package& installation,
+ const MasterPreferences& prefs) {
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
- if (!CheckPreInstallConditions(installation, install_status))
+ if (!CheckPreInstallConditions(original_state, installer_state, installation,
+ prefs, &install_status))
return install_status;
// For install the default location for chrome.packed.7z is in current
@@ -276,7 +292,6 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
installer::switches::kInstallArchive);
}
VLOG(1) << "Archive found to install Chrome " << archive.value();
- bool system_level = installation.system_level();
const Products& products = installation.products();
// Create a temp folder where we will unpack Chrome archive. If it fails,
@@ -284,7 +299,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
FilePath temp_path;
if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) {
LOG(ERROR) << "Could not create temporary path.";
- installation.WriteInstallerResult(installer::TEMP_DIR_FAILED,
+ InstallUtil::WriteInstallerResult(installer_state.system_install(),
+ installer_state.state_key(), installer::TEMP_DIR_FAILED,
IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL);
return installer::TEMP_DIR_FAILED;
}
@@ -295,7 +311,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
if (UnPackArchive(archive, installation, temp_path, unpack_path,
incremental_install)) {
install_status = installer::UNCOMPRESSION_FAILED;
- installation.WriteInstallerResult(install_status,
+ InstallUtil::WriteInstallerResult(installer_state.system_install(),
+ installer_state.state_key(), install_status,
IDS_INSTALL_UNCOMPRESSION_FAILED_BASE, NULL);
} else {
VLOG(1) << "unpacked to " << unpack_path.value();
@@ -305,7 +322,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
if (!installer_version.get()) {
LOG(ERROR) << "Did not find any valid version in installer.";
install_status = installer::INVALID_ARCHIVE;
- installation.WriteInstallerResult(install_status,
+ InstallUtil::WriteInstallerResult(installer_state.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
@@ -317,8 +335,11 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
bool higher_version_installed = false;
for (size_t i = 0; i < installation.products().size(); ++i) {
const Product* product = installation.products()[i];
- const Version* v = product->GetInstalledVersion();
- if (v != NULL && (v->CompareTo(*installer_version) > 0)) {
+ const ProductState* product_state =
+ original_state.GetProductState(installer_state.system_install(),
+ product->distribution()->GetType());
+ if (product_state != NULL &&
+ (product_state->version().CompareTo(*installer_version) > 0)) {
LOG(ERROR) << "Higher version is already installed.";
higher_version_installed = true;
install_status = installer::HIGHER_VERSION_EXISTS;
@@ -326,10 +347,12 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
if (product->is_chrome()) {
// TODO(robertshield): We should take the installer result text
// strings from the Product.
- installation.WriteInstallerResult(install_status,
+ InstallUtil::WriteInstallerResult(installer_state.system_install(),
+ installer_state.state_key(), install_status,
IDS_INSTALL_HIGHER_VERSION_BASE, NULL);
} else {
- installation.WriteInstallerResult(install_status,
+ InstallUtil::WriteInstallerResult(installer_state.system_install(),
+ installer_state.state_key(), install_status,
IDS_INSTALL_HIGHER_VERSION_CF_BASE, NULL);
}
}
@@ -341,8 +364,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive));
FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
installer::switches::kInstallerData));
- install_status = installer::InstallOrUpdateProduct(
- cmd_line.GetProgram(), archive_to_copy, temp_path,
+ install_status = installer::InstallOrUpdateProduct(original_state,
+ installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path,
prefs_source_path, prefs, *installer_version, installation);
int install_msg_base = IDS_INSTALL_FAILED_BASE;
@@ -382,7 +405,8 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
bool write_chrome_launch_string = (!value) &&
(install_status != installer::IN_USE_UPDATED);
- installation.WriteInstallerResult(install_status, install_msg_base,
+ InstallUtil::WriteInstallerResult(installer_state.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) {
@@ -448,31 +472,41 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
- product->distribution()->UpdateDiffInstallStatus(system_level,
- incremental_install, install_status);
+ 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,
+ install_status);
}
return install_status;
}
-installer::InstallStatus UninstallProduct(const CommandLine& cmd_line,
- const Product& product) {
+installer::InstallStatus UninstallProduct(
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const CommandLine& cmd_line,
+ const Product& product) {
bool force = cmd_line.HasSwitch(installer::switches::kForceUninstall);
- if (product.IsInstalled()) {
+ const ProductState* product_state =
+ original_state.GetProductState(installer_state.system_install(),
+ product.distribution()->GetType());
+ if (product_state != NULL) {
VLOG(1) << "version on the system: "
- << product.GetInstalledVersion()->GetString();
+ << product_state->version().GetString();
} else if (!force) {
LOG(ERROR) << "No Chrome installation found for uninstall.";
- product.package().WriteInstallerResult(installer::CHROME_NOT_INSTALLED,
- IDS_UNINSTALL_FAILED_BASE, NULL);
return installer::CHROME_NOT_INSTALLED;
}
bool remove_all = !cmd_line.HasSwitch(
installer::switches::kDoNotRemoveSharedItems);
- return installer::UninstallProduct(cmd_line.GetProgram(), product, remove_all,
- force, cmd_line);
+ return installer::UninstallProduct(original_state, installer_state,
+ cmd_line.GetProgram(), product, remove_all, force, cmd_line);
}
installer::InstallStatus ShowEULADialog(const std::wstring& inner_frame) {
@@ -506,9 +540,10 @@ installer::InstallStatus ShowEULADialog(const std::wstring& inner_frame) {
// 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 CommandLine& cmd_line,
- int& exit_code,
- const ProductPackageMapping& installs) {
+bool HandleNonInstallCmdLineOptions(const InstallerState& installer_state,
+ const CommandLine& cmd_line,
+ const ProductPackageMapping& installs,
+ int* exit_code) {
DCHECK(installs.products().size());
bool handled = true;
// TODO(tommi): Split these checks up into functions and use a data driven
@@ -539,11 +574,12 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
}
}
- exit_code = InstallUtil::GetInstallReturnCode(status);
- if (exit_code) {
+ *exit_code = InstallUtil::GetInstallReturnCode(status);
+ if (*exit_code) {
LOG(WARNING) << "setup.exe patching failed.";
- installs.packages()[0]->WriteInstallerResult(status,
- IDS_SETUP_PATCH_FAILED_BASE, NULL);
+ InstallUtil::WriteInstallerResult(installer_state.system_install(),
+ installer_state.state_key(), status, IDS_SETUP_PATCH_FAILED_BASE,
+ NULL);
}
file_util::Delete(temp_path, true);
} else if (cmd_line.HasSwitch(installer::switches::kShowEula)) {
@@ -551,8 +587,8 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
// then the dialog is shown and regardless of the outcome setup exits here.
std::wstring inner_frame =
cmd_line.GetSwitchValueNative(installer::switches::kShowEula);
- exit_code = ShowEULADialog(inner_frame);
- if (installer::EULA_REJECTED != exit_code)
+ *exit_code = ShowEULADialog(inner_frame);
+ if (installer::EULA_REJECTED != *exit_code)
GoogleUpdateSettings::SetEULAConsent(*installs.packages()[0].get(), true);
} else if (cmd_line.HasSwitch(
installer::switches::kRegisterChromeBrowser)) {
@@ -573,11 +609,11 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
suffix = cmd_line.GetSwitchValueNative(
installer::switches::kRegisterChromeBrowserSuffix);
}
- exit_code = ShellUtil::RegisterChromeBrowser(
+ *exit_code = ShellUtil::RegisterChromeBrowser(
chrome_install->distribution(), chrome_exe, suffix, false);
} else {
LOG(ERROR) << "Can't register browser - Chrome distribution not found";
- exit_code = installer::UNKNOWN_STATUS;
+ *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
@@ -585,7 +621,7 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
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(*packages[i].get());
} else if (cmd_line.HasSwitch(
installer::switches::kRemoveChromeRegistration)) {
// This is almost reverse of --register-chrome-browser option above.
@@ -606,7 +642,7 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
installer::DeleteChromeRegistrationKeys(chrome_install->distribution(),
HKEY_LOCAL_MACHINE, suffix, tmp);
}
- exit_code = tmp;
+ *exit_code = tmp;
} else if (cmd_line.HasSwitch(installer::switches::kInactiveUserToast)) {
// Launch the inactive user toast experiment.
int flavor = -1;
@@ -614,7 +650,7 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
installer::switches::kInactiveUserToast), &flavor);
DCHECK_NE(-1, flavor);
if (flavor == -1) {
- exit_code = installer::UNKNOWN_STATUS;
+ *exit_code = installer::UNKNOWN_STATUS;
} else {
const Products& products = installs.products();
for (size_t i = 0; i < products.size(); ++i) {
@@ -637,8 +673,8 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
}
} else if (cmd_line.HasSwitch(
installer::switches::kChromeFrameReadyModeOptIn)) {
- exit_code = InstallUtil::GetInstallReturnCode(
- installer::ChromeFrameReadyModeOptIn(cmd_line));
+ *exit_code = InstallUtil::GetInstallReturnCode(
+ installer::ChromeFrameReadyModeOptIn(installer_state, cmd_line));
} else {
handled = false;
}
@@ -835,17 +871,27 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad(
InitializeCrashReporting(system_install));
+ InstallationState original_state;
+ original_state.Initialize(prefs);
+
+ InstallerState installer_state;
+ installer_state.Initialize(prefs, original_state);
+
ProductPackageMapping installations(prefs.is_multi_install(), system_install);
if (!PopulateInstallations(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;
if (prefs.is_multi_install()) {
+ // TODO(grt): create a new string for this condition.
status = installer::NON_MULTI_INSTALLATION_EXISTS;
} else {
+ // TODO(grt): create a new string for this condition.
status = installer::MULTI_INSTALLATION_EXISTS;
}
LOG(ERROR) << "Failed to populate installations: " << status;
+ InstallUtil::WriteInstallerResult(system_install,
+ installer_state.state_key(), status, NULL, NULL);
return status;
}
@@ -853,15 +899,17 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
// error message and get out.
if (!InstallUtil::IsOSSupported()) {
LOG(ERROR) << "Chrome only supports Windows XP or later.";
- installations.packages()[0]->WriteInstallerResult(
- installer::OS_NOT_SUPPORTED, IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL);
+ InstallUtil::WriteInstallerResult(system_install,
+ installer_state.state_key(), installer::OS_NOT_SUPPORTED,
+ IDS_INSTALL_OS_NOT_SUPPORTED_BASE, NULL);
return installer::OS_NOT_SUPPORTED;
}
// Initialize COM for use later.
AutoCom auto_com;
if (!auto_com.Init(system_install)) {
- installations.packages()[0]->WriteInstallerResult(installer::OS_ERROR,
+ InstallUtil::WriteInstallerResult(system_install,
+ installer_state.state_key(), installer::OS_ERROR,
IDS_INSTALL_OS_ERROR_BASE, NULL);
return installer::OS_ERROR;
}
@@ -882,7 +930,8 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
}
int exit_code = 0;
- if (HandleNonInstallCmdLineOptions(cmd_line, exit_code, installations))
+ if (HandleNonInstallCmdLineOptions(installer_state, cmd_line, installations,
+ &exit_code))
return exit_code;
if (system_install && !IsUserAnAdmin()) {
@@ -898,9 +947,9 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
return exit_code;
} else {
LOG(ERROR) << "Non admin user can not install system level Chrome.";
- installations.packages()[0]->WriteInstallerResult(
- installer::INSUFFICIENT_RIGHTS, IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE,
- NULL);
+ InstallUtil::WriteInstallerResult(system_install,
+ installer_state.state_key(), installer::INSUFFICIENT_RIGHTS,
+ IDS_INSTALL_INSUFFICIENT_RIGHTS_BASE, NULL);
return installer::INSUFFICIENT_RIGHTS;
}
}
@@ -911,14 +960,16 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
// If --uninstall option is given, uninstall chrome
if (is_uninstall) {
for (size_t i = 0; i < installations.products().size(); ++i) {
- install_status = UninstallProduct(cmd_line, *installations.products()[i]);
+ install_status = UninstallProduct(original_state, installer_state,
+ cmd_line, *installations.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(cmd_line, *packages[i].get(), prefs);
+ install_status = InstallChrome(original_state, installer_state, cmd_line,
+ *packages[i].get(), prefs);
}
}
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 0b1aa79..0d3d193 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -20,9 +20,13 @@
#include "chrome/installer/setup/install.h"
#include "chrome/installer/setup/setup_constants.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/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/shell_util.h"
@@ -34,6 +38,67 @@
using base::win::RegKey;
using installer::InstallStatus;
+namespace {
+
+// Makes appropriate changes to the Google Update "ap" value in the registry.
+// Specifically, removes the flags associated with this product ("-chrome" or
+// "-chromeframe[-CEEE][-readymode]") from the "ap" values for all other
+// installed products and for the multi-installer package.
+void ProcessGoogleUpdateItems(
+ const installer::InstallationState& original_state,
+ const installer::Product& product) {
+ const bool system_level = product.system_level();
+ BrowserDistribution* distribution = product.distribution();
+ const HKEY reg_root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ const installer::ProductState* product_state =
+ original_state.GetProductState(system_level, distribution->GetType());
+ DCHECK(product_state != NULL);
+ installer::ChannelInfo channel_info;
+
+ // Remove product's flags from the channel value.
+ channel_info.set_value(product_state->channel().value());
+ const bool modified = distribution->SetChannelFlags(false, &channel_info);
+
+ // Apply the new channel value to all other products and to the multi package.
+ if (modified) {
+ BrowserDistribution::Type other_dist_type =
+ (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) ?
+ BrowserDistribution::CHROME_FRAME :
+ BrowserDistribution::CHROME_BROWSER;
+ BrowserDistribution* other_dist =
+ BrowserDistribution::GetSpecificDistribution(other_dist_type,
+ installer::MasterPreferences::ForCurrentProcess());
+ scoped_ptr<WorkItemList>
+ update_list(WorkItem::CreateNoRollbackWorkItemList());
+
+ product_state = original_state.GetProductState(system_level,
+ other_dist_type);
+ if (installer::IsInstalledAsMulti(system_level, other_dist) &&
+ !product_state->channel().Equals(channel_info)) {
+ update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(),
+ google_update::kRegApField, channel_info.value(), true);
+ } else {
+ VLOG(1) << other_dist->GetApplicationName()
+ << "'s ap value is unexpectedly up to date.";
+ }
+
+ product_state = original_state.GetMultiPackageState(system_level);
+ DCHECK(product_state != NULL);
+ if (!product_state->channel().Equals(channel_info)) {
+ update_list->AddSetRegValueWorkItem(reg_root,
+ product.package().properties()->GetStateKey(),
+ google_update::kRegApField, channel_info.value(), true);
+ } else {
+ VLOG(1) << "Multi-install package's ap value is unexpectedly up to date.";
+ }
+
+ bool success = update_list->Do();
+ LOG_IF(ERROR, !success) << "Failed updating channel values.";
+ }
+}
+
+} // namespace
+
namespace installer {
// This functions checks for any Chrome instances that are
@@ -477,18 +542,21 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt";
}
bool ProcessChromeFrameWorkItems(const FilePath& setup_path,
- const Product& product) {
+ const Product& product,
+ const ProductState* product_state) {
if (!product.is_chrome_frame())
return false;
- const Version* version = product.GetInstalledVersion();
+ DCHECK(product_state != NULL);
scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
- AddChromeFrameWorkItems(false, setup_path, *version, product,
+ AddChromeFrameWorkItems(false, setup_path, product_state->version(), product,
item_list.get());
return item_list->Do();
}
-InstallStatus UninstallProduct(const FilePath& setup_path,
+InstallStatus UninstallProduct(const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const FilePath& setup_path,
const Product& product,
bool remove_all,
bool force_uninstall,
@@ -571,8 +639,16 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
InstallStatus ret = installer::UNKNOWN_STATUS;
DeleteChromeRegistrationKeys(product.distribution(), reg_root, suffix, ret);
+ // Get the state of the installed product (if any)
+ const ProductState* product_state =
+ original_state.GetProductState(installer_state.system_install(),
+ browser_dist->GetType());
+
if (!is_chrome)
- ProcessChromeFrameWorkItems(setup_path, product);
+ ProcessChromeFrameWorkItems(setup_path, product, product_state);
+
+ if (product.package().multi_install())
+ ProcessGoogleUpdateItems(original_state, product);
// For user level install also we end up creating some keys in HKLM if user
// sets Chrome as default browser. So delete those as well (needs admin).
@@ -582,9 +658,6 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
suffix, ret);
}
- // Get the version of the installed product (if any)
- const Version* installed_version = product.GetInstalledVersion();
-
// Delete shared registry keys as well (these require admin rights) if
// remove_all option is specified.
if (remove_all) {
@@ -596,15 +669,14 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
std::wstring reg_path(installer::kMediaPlayerRegPath);
file_util::AppendToPath(&reg_path, installer::kChromeExe);
InstallUtil::DeleteRegistryKey(hklm_key, reg_path);
- hklm_key.Close();
}
// Unregister any dll servers that we may have registered for this
// product.
- if (installed_version != NULL) {
+ if (product_state != NULL) {
std::vector<FilePath> com_dll_list(browser_dist->GetComDllList());
FilePath dll_folder = product.package().path().Append(
- UTF8ToWide(installed_version->GetString()));
+ UTF8ToWide(product_state->version().GetString()));
scoped_ptr<WorkItemList> unreg_work_item_list(
WorkItem::CreateWorkItemList());
@@ -626,7 +698,7 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
CloseChromeFrameHelperProcess();
}
- if (installed_version == NULL)
+ if (product_state == NULL)
return installer::UNINSTALL_SUCCESSFUL;
// Finally delete all the files from Chrome folder after moving setup.exe
@@ -661,9 +733,9 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
// need to move setup.exe out of the install folder.
// TODO(tommi): What if the temp folder is on a different volume?
MoveSetupOutOfInstallFolder(product.package(), setup_path,
- *installed_version);
+ product_state->version());
delete_result = DeleteFilesAndFolders(product.package(),
- *installed_version);
+ product_state->version());
}
if (delete_profile)
@@ -677,7 +749,7 @@ InstallStatus UninstallProduct(const FilePath& setup_path,
if (!force_uninstall) {
VLOG(1) << "Uninstallation complete. Launching Uninstall survey.";
- browser_dist->DoPostUninstallOperations(*installed_version,
+ browser_dist->DoPostUninstallOperations(product_state->version(),
backup_state_file, distribution_data);
}
diff --git a/chrome/installer/setup/uninstall.h b/chrome/installer/setup/uninstall.h
index 274f55e..a3f1ec1 100644
--- a/chrome/installer/setup/uninstall.h
+++ b/chrome/installer/setup/uninstall.h
@@ -8,22 +8,26 @@
#define CHROME_INSTALLER_SETUP_UNINSTALL_H_
#pragma once
-#include <string>
-
#include <shlobj.h>
+#include <string>
+
#include "base/command_line.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/util_constants.h"
namespace installer {
+
+class InstallationState;
+class InstallerState;
+
// This function removes all Chrome registration related keys. It returns true
// if successful, otherwise false. The error code is set in |exit_code|.
// |root| is the registry root (HKLM|HKCU) and |browser_entry_suffix| is the
// suffix for default browser entry name in the registry (optional).
bool DeleteChromeRegistrationKeys(BrowserDistribution* dist, HKEY root,
const std::wstring& browser_entry_suffix,
- installer::InstallStatus& exit_code);
+ InstallStatus& exit_code);
// Removes any legacy registry keys from earlier versions of Chrome that are no
// longer needed. This is used during autoupdate since we don't do full
@@ -33,6 +37,8 @@ void RemoveLegacyRegistryKeys(BrowserDistribution* dist);
// This function uninstalls a product. Hence we came up with this awesome
// name for it.
//
+// original_state: The installation state of all products on the system.
+// installer_state: State associated with this operation.
// setup_path: Path to the executable (setup.exe) as it will be copied
// to temp folder before deleting Chrome folder.
// dist: Represents the distribution to be uninstalled.
@@ -42,8 +48,13 @@ void RemoveLegacyRegistryKeys(BrowserDistribution* dist);
// cmd_line: CommandLine that contains information about the command that
// was used to launch current uninstaller.
installer::InstallStatus UninstallProduct(
- const FilePath& setup_path, const Product& dist, bool remove_all,
- bool force_uninstall, const CommandLine& cmd_line);
+ const InstallationState& original_state,
+ const InstallerState& installer_state,
+ const FilePath& setup_path,
+ const Product& dist,
+ bool remove_all,
+ bool force_uninstall,
+ const CommandLine& cmd_line);
} // namespace installer_setup
diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc
index d684c97..05f3c04 100644
--- a/chrome/installer/util/browser_distribution.cc
+++ b/chrome/installer/util/browser_distribution.cc
@@ -33,7 +33,6 @@ namespace {
// The BrowserDistribution objects are never freed.
BrowserDistribution* g_browser_distribution = NULL;
BrowserDistribution* g_chrome_frame_distribution = NULL;
-BrowserDistribution* g_ceee_distribution = NULL;
// Returns true if currently running in npchrome_frame.dll
bool IsChromeFrameModule() {
@@ -203,8 +202,9 @@ bool BrowserDistribution::GetChromeChannel(std::wstring* channel) {
return false;
}
-void BrowserDistribution::UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status) {
+void BrowserDistribution::UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status) {
}
void BrowserDistribution::LaunchUserExperiment(
@@ -236,3 +236,9 @@ void BrowserDistribution::AppendUninstallCommandLineFlags(
bool BrowserDistribution::ShouldCreateUninstallEntry() {
return true;
}
+
+bool BrowserDistribution::SetChannelFlags(
+ bool set,
+ installer::ChannelInfo* channel_info) {
+ return false;
+}
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h
index a967116..1f6a1c9 100644
--- a/chrome/installer/util/browser_distribution.h
+++ b/chrome/installer/util/browser_distribution.h
@@ -23,10 +23,9 @@
class CommandLine;
namespace installer {
-class Product;
-}
-namespace installer {
+class ChannelInfo;
class MasterPreferences;
+class Product;
}
class BrowserDistribution {
@@ -91,8 +90,9 @@ class BrowserDistribution {
virtual bool GetChromeChannel(std::wstring* channel);
- virtual void UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status);
+ virtual void UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status);
// After an install or upgrade the user might qualify to participate in an
// experiment. This function determines if the user qualifies and if so it
@@ -128,6 +128,10 @@ class BrowserDistribution {
// Add/Remove Programs dialog for this distribution.
virtual bool ShouldCreateUninstallEntry();
+ // Adds or removes product-specific flags in |channel_info|. Returns true if
+ // |channel_info| is modified.
+ virtual bool SetChannelFlags(bool set, installer::ChannelInfo* channel_info);
+
protected:
explicit BrowserDistribution(const installer::MasterPreferences& prefs);
diff --git a/chrome/installer/util/channel_info.cc b/chrome/installer/util/channel_info.cc
index 4acc4d4..fd8c6b5 100644
--- a/chrome/installer/util/channel_info.cc
+++ b/chrome/installer/util/channel_info.cc
@@ -15,8 +15,12 @@ namespace {
const wchar_t kChannelBeta[] = L"beta";
const wchar_t kChannelDev[] = L"dev";
const wchar_t kModCeee[] = L"-CEEE";
-const wchar_t kModFullInstall[] = L"-full";
+const wchar_t kModChrome[] = L"-chrome";
+const wchar_t kModChromeFrame[] = L"-chromeframe";
const wchar_t kModMultiInstall[] = L"-multi";
+const wchar_t kModReadyMode[] = L"-readymode";
+const wchar_t kSfxFull[] = L"-full";
+const wchar_t kSfxMultiFail[] = L"-multifail";
const wchar_t* const kChannels[] = {
kChannelBeta,
@@ -24,44 +28,93 @@ const wchar_t* const kChannels[] = {
};
const wchar_t* const kModifiers[] = {
+ kModMultiInstall,
+ kModChrome,
+ kModChromeFrame,
kModCeee,
- kModFullInstall,
- kModMultiInstall
+ kModReadyMode,
+ kSfxMultiFail,
+ kSfxFull
};
-} // namespace
+enum ModifierIndex {
+ MOD_MULTI_INSTALL,
+ MOD_CHROME,
+ MOD_CHROME_FRAME,
+ MOD_CEEE,
+ MOD_READY_MODE,
+ SFX_MULTI_FAIL,
+ SFX_FULL,
+ NUM_MODIFIERS
+};
-namespace installer {
+COMPILE_ASSERT(NUM_MODIFIERS == arraysize(kModifiers),
+ kModifiers_disagrees_with_ModifierIndex_comma_they_must_match_bang);
+
+// Returns true if the modifier is found, in which case |position| holds the
+// location at which the modifier was found.
+bool FindModifier(ModifierIndex index,
+ const std::wstring& ap_value,
+ std::wstring::size_type* position) {
+ DCHECK(position != NULL);
+ std::wstring::size_type mod_length =
+ std::wstring::traits_type::length(kModifiers[index]);
+ for (std::wstring::size_type pos = 0; ; ) {
+ *position = ap_value.find(kModifiers[index], pos, mod_length);
+ if (*position == std::wstring::npos)
+ break;
+ // The modifier must be either at the end of the string or followed by -.
+ pos = *position + mod_length;
+ if (pos == ap_value.size() || ap_value[pos] == L'-')
+ return true;
+ }
+ return false;
+}
-// static
-bool ChannelInfo::HasModifier(const wchar_t* modifier,
- const std::wstring& ap_value) {
- DCHECK(modifier);
- return ap_value.find(modifier) != std::wstring::npos;
+bool HasModifier(ModifierIndex index, const std::wstring& ap_value) {
+ DCHECK(index >= 0 && index < NUM_MODIFIERS);
+ std::wstring::size_type position;
+ return FindModifier(index, ap_value, &position);
+}
+
+std::wstring::size_type FindInsertionPoint(ModifierIndex index,
+ const std::wstring& ap_value) {
+ // Return the location of the next modifier.
+ std::wstring::size_type result;
+
+ for (int scan = index + 1; scan < NUM_MODIFIERS; ++scan) {
+ if (FindModifier(static_cast<ModifierIndex>(scan), ap_value, &result))
+ return result;
+ }
+
+ return ap_value.size();
}
// Returns true if |ap_value| is modified.
-// static
-bool ChannelInfo::SetModifier(const wchar_t* modifier,
- bool set,
- std::wstring* ap_value) {
- DCHECK(modifier);
+bool SetModifier(ModifierIndex index, bool set, std::wstring* ap_value) {
+ DCHECK(index >= 0 && index < NUM_MODIFIERS);
DCHECK(ap_value);
- std::wstring::size_type position = ap_value->find(modifier);
+ std::wstring::size_type position;
+ bool have_modifier = FindModifier(index, *ap_value, &position);
if (set) {
- if (position == std::wstring::npos) {
- ap_value->append(modifier);
+ if (!have_modifier) {
+ ap_value->insert(FindInsertionPoint(index, *ap_value), kModifiers[index]);
return true;
}
} else {
- if (position != std::wstring::npos) {
- ap_value->erase(position, std::wstring::traits_type::length(modifier));
+ if (have_modifier) {
+ ap_value->erase(position,
+ std::wstring::traits_type::length(kModifiers[index]));
return true;
}
}
return false;
}
+} // namespace
+
+namespace installer {
+
bool ChannelInfo::Initialize(const RegKey& key) {
return key.ReadValue(google_update::kRegApField, &value_);
}
@@ -87,10 +140,8 @@ bool ChannelInfo::GetChannelName(std::wstring* channel_name) const {
// There may be modifiers present. Strip them off and see if we're left
// with the empty string (stable channel).
std::wstring tmp_value = value_;
- for (const wchar_t* const* scan = &kModifiers[0],
- *const *end = &kModifiers[arraysize(kModifiers)]; scan != end;
- ++scan) {
- SetModifier(*scan, false, &tmp_value);
+ for (int i = 0; i != NUM_MODIFIERS; ++i) {
+ SetModifier(static_cast<ModifierIndex>(i), false, &tmp_value);
}
if (tmp_value.empty()) {
channel_name->erase();
@@ -102,27 +153,59 @@ bool ChannelInfo::GetChannelName(std::wstring* channel_name) const {
}
bool ChannelInfo::IsCeee() const {
- return HasModifier(kModCeee, value_);
+ return HasModifier(MOD_CEEE, value_);
}
bool ChannelInfo::SetCeee(bool value) {
- return SetModifier(kModCeee, value, &value_);
+ return SetModifier(MOD_CEEE, value, &value_);
}
-bool ChannelInfo::IsFullInstall() const {
- return HasModifier(kModFullInstall, value_);
+bool ChannelInfo::IsChrome() const {
+ return HasModifier(MOD_CHROME, value_);
}
-bool ChannelInfo::SetFullInstall(bool value) {
- return SetModifier(kModFullInstall, value, &value_);
+bool ChannelInfo::SetChrome(bool value) {
+ return SetModifier(MOD_CHROME, value, &value_);
+}
+
+bool ChannelInfo::IsChromeFrame() const {
+ return HasModifier(MOD_CHROME_FRAME, value_);
+}
+
+bool ChannelInfo::SetChromeFrame(bool value) {
+ return SetModifier(MOD_CHROME_FRAME, value, &value_);
}
bool ChannelInfo::IsMultiInstall() const {
- return HasModifier(kModMultiInstall, value_);
+ return HasModifier(MOD_MULTI_INSTALL, value_);
}
bool ChannelInfo::SetMultiInstall(bool value) {
- return SetModifier(kModMultiInstall, value, &value_);
+ return SetModifier(MOD_MULTI_INSTALL, value, &value_);
+}
+
+bool ChannelInfo::IsReadyMode() const {
+ return HasModifier(MOD_READY_MODE, value_);
+}
+
+bool ChannelInfo::SetReadyMode(bool value) {
+ return SetModifier(MOD_READY_MODE, value, &value_);
+}
+
+bool ChannelInfo::HasFullSuffix() const {
+ return HasModifier(SFX_FULL, value_);
+}
+
+bool ChannelInfo::SetFullSuffix(bool value) {
+ return SetModifier(SFX_FULL, value, &value_);
+}
+
+bool ChannelInfo::HasMultiFailSuffix() const {
+ return HasModifier(SFX_MULTI_FAIL, value_);
+}
+
+bool ChannelInfo::SetMultiFailSuffix(bool value) {
+ return SetModifier(SFX_MULTI_FAIL, value, &value_);
}
} // namespace installer
diff --git a/chrome/installer/util/channel_info.h b/chrome/installer/util/channel_info.h
index 5ba919a..7954e1c 100644
--- a/chrome/installer/util/channel_info.h
+++ b/chrome/installer/util/channel_info.h
@@ -16,8 +16,8 @@ class RegKey;
namespace installer {
-// A helper class for parsing and modifying the Omaha additional parameter
-// ("ap") client state value for a product.
+// A helper class for parsing and modifying the Google Update additional
+// parameter ("ap") client state value for a product.
class ChannelInfo {
public:
@@ -31,6 +31,9 @@ class ChannelInfo {
const std::wstring& value() const { return value_; }
void set_value(const std::wstring& value) { value_ = value; }
+ bool Equals(const ChannelInfo& other) const {
+ return value_ == other.value_;
+ }
// Determines the update channel for the value. Possible |channel_name|
// results are the empty string (stable channel), "beta", and "dev". Returns
@@ -45,12 +48,19 @@ class ChannelInfo {
// modified.
bool SetCeee(bool value);
- // Returns true if the -full modifier is present in the value.
- bool IsFullInstall() const;
+ // Returns true if the -chrome modifier is present in the value.
+ bool IsChrome() const;
- // Adds or removes the -full modifier, returning true if the value is
+ // Adds or removes the -chrome modifier, returning true if the value is
// modified.
- bool SetFullInstall(bool value);
+ bool SetChrome(bool value);
+
+ // Returns true if the -chromeframe modifier is present in the value.
+ bool IsChromeFrame() const;
+
+ // Adds or removes the -chromeframe modifier, returning true if the value is
+ // modified.
+ bool SetChromeFrame(bool value);
// Returns true if the -multi modifier is present in the value.
bool IsMultiInstall() const;
@@ -59,12 +69,28 @@ class ChannelInfo {
// modified.
bool SetMultiInstall(bool value);
- private:
- static bool HasModifier(const wchar_t* modifier,
- const std::wstring& ap_value);
- static bool SetModifier(const wchar_t* modifier, bool set,
- std::wstring* ap_value);
+ // Returns true if the -readymode modifier is present in the value.
+ bool IsReadyMode() const;
+
+ // Adds or removes the -readymode modifier, returning true if the value is
+ // modified.
+ bool SetReadyMode(bool value);
+
+ // Returns true if the -full suffix is present in the value.
+ bool HasFullSuffix() const;
+ // Adds or removes the -full suffix, returning true if the value is
+ // modified.
+ bool SetFullSuffix(bool value);
+
+ // Returns true if the -multifail suffix is present in the value.
+ bool HasMultiFailSuffix() const;
+
+ // Adds or removes the -multifail suffix, returning true if the value is
+ // modified.
+ bool SetMultiFailSuffix(bool value);
+
+ private:
std::wstring value_;
}; // class ChannelInfo
diff --git a/chrome/installer/util/channel_info_unittest.cc b/chrome/installer/util/channel_info_unittest.cc
index f5ea4bb..febc33a 100644
--- a/chrome/installer/util/channel_info_unittest.cc
+++ b/chrome/installer/util/channel_info_unittest.cc
@@ -90,31 +90,31 @@ TEST(ChannelInfoTest, FullInstall) {
installer::ChannelInfo ci;
ci.set_value(L"");
- EXPECT_TRUE(ci.SetFullInstall(true));
- EXPECT_TRUE(ci.IsFullInstall());
+ EXPECT_TRUE(ci.SetFullSuffix(true));
+ EXPECT_TRUE(ci.HasFullSuffix());
EXPECT_EQ(L"-full", ci.value());
- EXPECT_FALSE(ci.SetFullInstall(true));
- EXPECT_TRUE(ci.IsFullInstall());
+ EXPECT_FALSE(ci.SetFullSuffix(true));
+ EXPECT_TRUE(ci.HasFullSuffix());
EXPECT_EQ(L"-full", ci.value());
- EXPECT_TRUE(ci.SetFullInstall(false));
- EXPECT_FALSE(ci.IsFullInstall());
+ EXPECT_TRUE(ci.SetFullSuffix(false));
+ EXPECT_FALSE(ci.HasFullSuffix());
EXPECT_EQ(L"", ci.value());
- EXPECT_FALSE(ci.SetFullInstall(false));
- EXPECT_FALSE(ci.IsFullInstall());
+ EXPECT_FALSE(ci.SetFullSuffix(false));
+ EXPECT_FALSE(ci.HasFullSuffix());
EXPECT_EQ(L"", ci.value());
ci.set_value(L"2.0-beta");
- EXPECT_TRUE(ci.SetFullInstall(true));
- EXPECT_TRUE(ci.IsFullInstall());
+ EXPECT_TRUE(ci.SetFullSuffix(true));
+ EXPECT_TRUE(ci.HasFullSuffix());
EXPECT_EQ(L"2.0-beta-full", ci.value());
- EXPECT_FALSE(ci.SetFullInstall(true));
- EXPECT_TRUE(ci.IsFullInstall());
+ EXPECT_FALSE(ci.SetFullSuffix(true));
+ EXPECT_TRUE(ci.HasFullSuffix());
EXPECT_EQ(L"2.0-beta-full", ci.value());
- EXPECT_TRUE(ci.SetFullInstall(false));
- EXPECT_FALSE(ci.IsFullInstall());
+ EXPECT_TRUE(ci.SetFullSuffix(false));
+ EXPECT_FALSE(ci.HasFullSuffix());
EXPECT_EQ(L"2.0-beta", ci.value());
- EXPECT_FALSE(ci.SetFullInstall(false));
- EXPECT_FALSE(ci.IsFullInstall());
+ EXPECT_FALSE(ci.SetFullSuffix(false));
+ EXPECT_FALSE(ci.HasFullSuffix());
EXPECT_EQ(L"2.0-beta", ci.value());
}
@@ -149,3 +149,12 @@ TEST(ChannelInfoTest, MultiInstall) {
EXPECT_FALSE(ci.IsMultiInstall());
EXPECT_EQ(L"2.0-beta", ci.value());
}
+
+TEST(ChannelInfoTest, Combinations) {
+ installer::ChannelInfo ci;
+
+ ci.set_value(L"2.0-beta-chromeframe");
+ EXPECT_FALSE(ci.IsChrome());
+ ci.set_value(L"2.0-beta-chromeframe-chrome");
+ EXPECT_TRUE(ci.IsChrome());
+}
diff --git a/chrome/installer/util/chrome_frame_distribution.cc b/chrome/installer/util/chrome_frame_distribution.cc
index 9d643c4..73aa3f6 100644
--- a/chrome/installer/util/chrome_frame_distribution.cc
+++ b/chrome/installer/util/chrome_frame_distribution.cc
@@ -12,6 +12,7 @@
#include <string>
#include "base/string_util.h"
+#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/helper.h"
@@ -141,11 +142,14 @@ bool ChromeFrameDistribution::CanSetAsDefault() {
return false;
}
-void ChromeFrameDistribution::UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status) {
- GoogleUpdateSettings::UpdateDiffInstallStatus(system_install,
- incremental_install, InstallUtil::GetInstallReturnCode(install_status),
- kChromeFrameGuid);
+void ChromeFrameDistribution::UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status) {
+#if defined(GOOGLE_CHROME_BUILD)
+ GoogleUpdateSettings::UpdateInstallStatus(system_install,
+ incremental_install, multi_install,
+ InstallUtil::GetInstallReturnCode(install_status), kChromeFrameGuid);
+#endif
}
std::vector<FilePath> ChromeFrameDistribution::GetKeyFiles() {
@@ -185,3 +189,23 @@ bool ChromeFrameDistribution::ShouldCreateUninstallEntry() {
// add an entry to the add/remove dialog.
return !ready_mode_;
}
+
+bool ChromeFrameDistribution::SetChannelFlags(
+ bool set,
+ installer::ChannelInfo* channel_info) {
+#if defined(GOOGLE_CHROME_BUILD)
+ DCHECK(channel_info);
+ bool modified = channel_info->SetChromeFrame(set);
+
+ // Always remove the options if we're called to remove flags.
+ if (!set || ceee_)
+ modified |= channel_info->SetCeee(set);
+
+ if (!set || ready_mode_)
+ modified |= channel_info->SetReadyMode(set);
+
+ return modified;
+#else
+ return false;
+#endif
+}
diff --git a/chrome/installer/util/chrome_frame_distribution.h b/chrome/installer/util/chrome_frame_distribution.h
index 94df4bd..f34cc86 100644
--- a/chrome/installer/util/chrome_frame_distribution.h
+++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -10,6 +10,7 @@
#pragma once
#include <string>
+#include <vector>
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/util_constants.h"
@@ -50,11 +51,9 @@ class ChromeFrameDistribution : public BrowserDistribution {
virtual bool CanSetAsDefault();
- // This is the point at which the Google Chrome installer removes the Google
- // Update ap value. We implement this simply to have the same behaviour re.
- // the ap value.
- virtual void UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status);
+ virtual void UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status);
virtual std::vector<FilePath> GetKeyFiles();
@@ -64,6 +63,8 @@ class ChromeFrameDistribution : public BrowserDistribution {
virtual bool ShouldCreateUninstallEntry();
+ virtual bool SetChannelFlags(bool set, installer::ChannelInfo* channel_info);
+
protected:
friend class BrowserDistribution;
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc
index 99c47f9..f1010f5 100644
--- a/chrome/installer/util/google_chrome_distribution.cc
+++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -26,6 +26,7 @@
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/result_codes.h"
+#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
@@ -500,11 +501,12 @@ std::wstring GoogleChromeDistribution::GetVersionKey() {
// - If we are currently running full installer, we remove this magic
// string (if it is present) regardless of whether installer failed or not.
// There is no fall-back for full installer :)
-void GoogleChromeDistribution::UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status) {
- GoogleUpdateSettings::UpdateDiffInstallStatus(system_install,
- incremental_install, InstallUtil::GetInstallReturnCode(install_status),
- product_guid().c_str());
+void GoogleChromeDistribution::UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status) {
+ GoogleUpdateSettings::UpdateInstallStatus(system_install,
+ incremental_install, multi_install,
+ InstallUtil::GetInstallReturnCode(install_status), product_guid());
}
// The functions below are not used by the 64-bit Windows binary -
@@ -686,3 +688,10 @@ void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
base::LaunchApp(cmd, false, false, NULL);
}
#endif
+
+bool GoogleChromeDistribution::SetChannelFlags(
+ bool set,
+ installer::ChannelInfo* channel_info) {
+ DCHECK(channel_info);
+ return channel_info->SetChrome(set);
+}
diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h
index 006ed13..f4feb6e 100644
--- a/chrome/installer/util/google_chrome_distribution.h
+++ b/chrome/installer/util/google_chrome_distribution.h
@@ -65,8 +65,9 @@ class GoogleChromeDistribution : public BrowserDistribution {
virtual std::wstring GetVersionKey();
- virtual void UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status);
+ virtual void UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status);
virtual void LaunchUserExperiment(installer::InstallStatus status,
const Version& version,
@@ -81,6 +82,8 @@ class GoogleChromeDistribution : public BrowserDistribution {
const std::wstring& product_guid() { return product_guid_; }
+ virtual bool SetChannelFlags(bool set, installer::ChannelInfo* channel_info);
+
protected:
void set_product_guid(const std::wstring& guid) { product_guid_ = guid; }
diff --git a/chrome/installer/util/google_chrome_distribution_dummy.cc b/chrome/installer/util/google_chrome_distribution_dummy.cc
index 370fec8..4d16c68 100644
--- a/chrome/installer/util/google_chrome_distribution_dummy.cc
+++ b/chrome/installer/util/google_chrome_distribution_dummy.cc
@@ -100,8 +100,9 @@ std::wstring GoogleChromeDistribution::GetVersionKey() {
return std::wstring();
}
-void GoogleChromeDistribution::UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, installer::InstallStatus install_status) {
+void GoogleChromeDistribution::UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status) {
NOTREACHED();
}
@@ -134,3 +135,9 @@ bool GoogleChromeDistribution::BuildUninstallMetricsString(
return false;
}
+bool GoogleChromeDistribution::SetChannelFlags(
+ bool set,
+ installer::ChannelInfo* channel_info) {
+ NOTREACHED();
+ return false;
+}
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 8621e9f..1e1d5e3 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -237,8 +237,8 @@ bool GoogleUpdateSettings::GetChromeChannel(bool system_install,
return true;
}
-void GoogleUpdateSettings::UpdateDiffInstallStatus(bool system_install,
- bool incremental_install, int install_return_code,
+void GoogleUpdateSettings::UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install, int install_return_code,
const std::wstring& product_guid) {
HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
@@ -247,54 +247,70 @@ void GoogleUpdateSettings::UpdateDiffInstallStatus(bool system_install,
std::wstring reg_key(google_update::kRegPathClientState);
reg_key.append(L"\\");
reg_key.append(product_guid);
- if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
+ if (!key.Open(reg_root, reg_key.c_str(), KEY_QUERY_VALUE | KEY_SET_VALUE) ||
!channel_info.Initialize(key)) {
VLOG(1) << "Application key not found.";
- if (!incremental_install || !install_return_code) {
+ if (!incremental_install && !multi_install || !install_return_code) {
VLOG(1) << "Returning without changing application key.";
- key.Close();
return;
} else if (!key.Valid()) {
reg_key.assign(google_update::kRegPathClientState);
- if (!key.Open(reg_root, reg_key.c_str(), KEY_ALL_ACCESS) ||
- !key.CreateKey(product_guid.c_str(), KEY_ALL_ACCESS)) {
+ if (!key.Open(reg_root, reg_key.c_str(), KEY_CREATE_SUB_KEY) ||
+ !key.CreateKey(product_guid.c_str(), KEY_SET_VALUE)) {
LOG(ERROR) << "Failed to create application key.";
- key.Close();
return;
}
}
}
- if (UpdateGoogleUpdateApKey(incremental_install, install_return_code,
- &channel_info) &&
+ if (UpdateGoogleUpdateApKey(incremental_install, multi_install,
+ install_return_code, &channel_info) &&
!channel_info.Write(&key)) {
LOG(ERROR) << "Failed to write value " << channel_info.value()
<< " to the registry field " << google_update::kRegApField;
}
- key.Close();
}
bool GoogleUpdateSettings::UpdateGoogleUpdateApKey(
- bool diff_install, int install_return_code,
+ bool diff_install, bool multi_install, int install_return_code,
installer::ChannelInfo* value) {
+ bool modified = false;
+
if (!diff_install || !install_return_code) {
- if (value->SetFullInstall(false)) {
- VLOG(1) << "Removed incremental installer failure key; new value: "
+ if (value->SetFullSuffix(false)) {
+ VLOG(1) << "Removed incremental installer failure key; "
+ "switching to channel: "
<< value->value();
- return true;
+ modified = true;
}
- } else if (diff_install && install_return_code) {
- if (value->SetFullInstall(true)) {
- VLOG(1) << "Incremental installer failed, setting failure key; "
- "new value: "
+ } else {
+ if (value->SetFullSuffix(true)) {
+ VLOG(1) << "Incremental installer failed; switching to channel: "
<< value->value();
- return true;
+ modified = true;
} else {
- VLOG(1) << "Incremental installer failure key already set.";
+ VLOG(1) << "Incremental installer failure; already on channel: "
+ << value->value();
}
}
- return false;
+ if (!multi_install || !install_return_code) {
+ if (value->SetMultiFailSuffix(false)) {
+ VLOG(1) << "Removed multi-install failure key; switching to channel: "
+ << value->value();
+ modified = true;
+ }
+ } else {
+ if (value->SetMultiFailSuffix(true)) {
+ VLOG(1) << "Multi-install failed; switching to channel: "
+ << value->value();
+ modified = true;
+ } else {
+ VLOG(1) << "Multi-install failed; already on channel: " << value->value();
+ }
+ }
+
+ return modified;
}
int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h
index 0ac8991..36e020c 100644
--- a/chrome/installer/util/google_update_settings.h
+++ b/chrome/installer/util/google_update_settings.h
@@ -90,10 +90,22 @@ class GoogleUpdateSettings {
// on success, channel contains one of "", "unknown", "dev" or "beta".
static bool GetChromeChannel(bool system_install, std::wstring* channel);
- static void UpdateDiffInstallStatus(bool system_install,
- bool incremental_install,
- int install_return_code,
- const std::wstring& product_guid);
+ // This method changes the Google Update "ap" value to move the installation
+ // on to or off of one of the recovery channels.
+ // - If incremental installer fails we append a magic string ("-full"), if
+ // it is not present already, so that Google Update server next time will send
+ // full installer to update Chrome on the local machine
+ // - If we are currently running full installer, we remove this magic
+ // string (if it is present) regardless of whether installer failed or not.
+ // There is no fall-back for full installer :)
+ // - If multi-install fails we append -multifail; otherwise, we remove it
+ // (i.e., success or single-install).
+ // |state_key| should be obtained via InstallerState::state_key().
+ static void UpdateInstallStatus(bool system_install,
+ bool incremental_install,
+ bool multi_install,
+ int install_return_code,
+ const std::wstring& product_guid);
// This method updates the value for Google Update "ap" key for Chrome
// based on whether we are doing incremental install (or not) and whether
@@ -109,6 +121,7 @@ class GoogleUpdateSettings {
// value: current value of Google Update "ap" key.
// Returns true if |value| is modified.
static bool UpdateGoogleUpdateApKey(bool diff_install,
+ bool multi_install,
int install_return_code,
installer::ChannelInfo* value);
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 672e589..d041d12 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -5,6 +5,9 @@
#include <windows.h>
#include <shlwapi.h> // For SHDeleteKey.
+#include <functional>
+#include <map>
+
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/win/registry.h"
@@ -20,6 +23,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::win::RegKey;
+using installer::ChannelInfo;
namespace {
@@ -217,120 +221,114 @@ TEST_F(GoogleUpdateSettingsTest, CurrentChromeChannelVariousApValuesUser) {
TestCurrentChromeChannelWithVariousApValues(USER_INSTALL);
}
+// Run through all combinations of diff vs. full install, single vs. multi
+// install, success and failure results, and a fistfull of initial "ap" values
+// checking that the expected final "ap" value is generated by
+// GoogleUpdateSettings::UpdateGoogleUpdateApKey.
TEST_F(GoogleUpdateSettingsTest, UpdateGoogleUpdateApKey) {
- installer::InstallStatus s = installer::FIRST_INSTALL_SUCCESS;
- installer::InstallStatus f = installer::INSTALL_FAILED;
-
- // Incremental Installer that worked.
- installer::ChannelInfo v;
- v.set_value(L"");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
-
- v.set_value(L"-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, s, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
-
- // Incremental Installer that failed.
- v.set_value(L"");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"-full");
-
- v.set_value(L"1.1");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"1.1-full");
-
- v.set_value(L"1.1-dev");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"1.1-dev-full");
-
- v.set_value(L"-full");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"-full");
-
- v.set_value(L"1.1-full");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"1.1-full");
-
- v.set_value(L"1.1-dev-full");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(true, f, &v));
- EXPECT_EQ(v.value(), L"1.1-dev-full");
-
- // Full Installer that worked.
- v.set_value(L"");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
-
- v.set_value(L"-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, s, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
-
- // Full Installer that failed.
- v.set_value(L"");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev");
- EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
-
- v.set_value(L"-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"");
-
- v.set_value(L"1.1-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"1.1");
-
- v.set_value(L"1.1-dev-full");
- EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(false, f, &v));
- EXPECT_EQ(v.value(), L"1.1-dev");
+ const bool is_multi[] = {
+ false,
+ true
+ };
+ const bool is_diff[] = {
+ false,
+ true
+ };
+ const int results[] = {
+ installer::FIRST_INSTALL_SUCCESS,
+ installer::INSTALL_FAILED
+ };
+ const wchar_t* const plain[] = {
+ L"",
+ L"1.1",
+ L"1.1-dev"
+ };
+ const wchar_t* const full[] = {
+ L"-full",
+ L"1.1-full",
+ L"1.1-dev-full"
+ };
+ COMPILE_ASSERT(arraysize(full) == arraysize(plain), bad_full_array_size);
+ const wchar_t* const multifail[] = {
+ L"-multifail",
+ L"1.1-multifail",
+ L"1.1-dev-multifail"
+ };
+ COMPILE_ASSERT(arraysize(multifail) == arraysize(plain),
+ bad_multifail_array_size);
+ const wchar_t* const multifail_full[] = {
+ L"-multifail-full",
+ L"1.1-multifail-full",
+ L"1.1-dev-multifail-full"
+ };
+ COMPILE_ASSERT(arraysize(multifail_full) == arraysize(plain),
+ bad_multifail_full_array_size);
+ const wchar_t* const* input_arrays[] = {
+ plain,
+ full,
+ multifail,
+ multifail_full
+ };
+ ChannelInfo v;
+ for (int multi_idx = 0; multi_idx < arraysize(is_multi); ++multi_idx) {
+ const bool multi = is_multi[multi_idx];
+ for (int diff_idx = 0; diff_idx < arraysize(is_diff); ++diff_idx) {
+ const bool diff = is_diff[diff_idx];
+ for (int result_idx = 0; result_idx < arraysize(results); ++result_idx) {
+ const int result = results[result_idx];
+ const wchar_t* const* outputs;
+ if (result == installer::FIRST_INSTALL_SUCCESS || !multi && !diff)
+ outputs = plain;
+ else if (!multi && diff)
+ outputs = full;
+ else if (multi && !diff)
+ outputs = multifail;
+ else
+ outputs = multifail_full;
+
+ for (int inputs_idx = 0; inputs_idx < arraysize(input_arrays);
+ ++inputs_idx) {
+ const wchar_t* const* inputs = input_arrays[inputs_idx];
+ for (int input_idx = 0; input_idx < arraysize(plain); ++input_idx) {
+ const wchar_t* input = inputs[input_idx];
+ const wchar_t* output = outputs[input_idx];
+
+ v.set_value(input);
+ if (output == v.value()) {
+ EXPECT_FALSE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(
+ diff, multi, result, &v))
+ << "diff: " << diff
+ << ", multi: " << multi
+ << ", result: " << result
+ << ", input ap value: " << input;
+ } else {
+ EXPECT_TRUE(GoogleUpdateSettings::UpdateGoogleUpdateApKey(
+ diff, multi, result, &v))
+ << "diff: " << diff
+ << ", multi: " << multi
+ << ", result: " << result
+ << ", input ap value: " << input;
+ }
+ EXPECT_EQ(output, v.value())
+ << "diff: " << diff
+ << ", multi: " << multi
+ << ", result: " << result
+ << ", input ap value: " << input;
+ }
+ }
+ }
+ }
+ }
}
-TEST_F(GoogleUpdateSettingsTest, UpdateDiffInstallStatusTest) {
+TEST_F(GoogleUpdateSettingsTest, UpdateInstallStatusTest) {
scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
// Test incremental install failure
ASSERT_TRUE(CreateApKey(work_item_list.get(), L""))
<< "Failed to create ap key.";
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, true,
- installer::INSTALL_FAILED,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, true, false,
+ installer::INSTALL_FAILED,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"-full");
work_item_list->Rollback();
@@ -338,9 +336,9 @@ TEST_F(GoogleUpdateSettingsTest, UpdateDiffInstallStatusTest) {
// Test incremental install success
ASSERT_TRUE(CreateApKey(work_item_list.get(), L""))
<< "Failed to create ap key.";
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, true,
- installer::FIRST_INSTALL_SUCCESS,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, true, false,
+ installer::FIRST_INSTALL_SUCCESS,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"");
work_item_list->Rollback();
@@ -348,9 +346,9 @@ TEST_F(GoogleUpdateSettingsTest, UpdateDiffInstallStatusTest) {
// Test full install failure
ASSERT_TRUE(CreateApKey(work_item_list.get(), L"-full"))
<< "Failed to create ap key.";
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, false,
- installer::INSTALL_FAILED,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, false, false,
+ installer::INSTALL_FAILED,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"");
work_item_list->Rollback();
@@ -358,9 +356,9 @@ TEST_F(GoogleUpdateSettingsTest, UpdateDiffInstallStatusTest) {
// Test full install success
ASSERT_TRUE(CreateApKey(work_item_list.get(), L"-full"))
<< "Failed to create ap key.";
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, false,
- installer::FIRST_INSTALL_SUCCESS,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, false, false,
+ installer::FIRST_INSTALL_SUCCESS,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"");
work_item_list->Rollback();
@@ -378,14 +376,14 @@ TEST_F(GoogleUpdateSettingsTest, UpdateDiffInstallStatusTest) {
ap_key_deleted = true;
}
// try differential installer
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, true,
- installer::INSTALL_FAILED,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, true, false,
+ installer::INSTALL_FAILED,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"-full");
// try full installer now
- GoogleUpdateSettings::UpdateDiffInstallStatus(false, false,
- installer::INSTALL_FAILED,
- kTestProductGuid);
+ GoogleUpdateSettings::UpdateInstallStatus(false, false, false,
+ installer::INSTALL_FAILED,
+ kTestProductGuid);
EXPECT_STREQ(ReadApKeyValue().c_str(), L"");
// Now cleanup to leave the system in unchanged state.
// - Diff installer creates an ap key if it didnt exist, so delete this ap key
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 2592429..2223b15 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -34,7 +34,7 @@ using installer::MasterPreferences;
bool InstallUtil::ExecuteExeAsAdmin(const CommandLine& cmd, DWORD* exit_code) {
FilePath::StringType program(cmd.GetProgram().value());
DCHECK(!program.empty());
- DCHECK(program[0] != '\"');
+ DCHECK_NE(program[0], L'\"');
CommandLine::StringType params(cmd.command_line_string());
if (params[0] == '"') {
@@ -110,6 +110,34 @@ bool InstallUtil::IsOSSupported() {
(version == base::win::VERSION_XP && major >= 2);
}
+void InstallUtil::WriteInstallerResult(bool system_install,
+ const std::wstring& state_key,
+ installer::InstallStatus status,
+ int string_resource_id,
+ const std::wstring* const launch_cmd) {
+ const HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ int installer_result = (GetInstallReturnCode(status) == 0) ? 0 : 1;
+ scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
+ install_list->AddCreateRegKeyWorkItem(root, state_key);
+ install_list->AddSetRegValueWorkItem(root, state_key,
+ installer::kInstallerResult,
+ installer_result, true);
+ install_list->AddSetRegValueWorkItem(root, state_key,
+ installer::kInstallerError, status,
+ true);
+ if (string_resource_id != 0) {
+ std::wstring msg = installer::GetLocalizedString(string_resource_id);
+ install_list->AddSetRegValueWorkItem(root, state_key,
+ installer::kInstallerResultUIString, msg, true);
+ }
+ if (launch_cmd != NULL && !launch_cmd->empty()) {
+ install_list->AddSetRegValueWorkItem(root, state_key,
+ installer::kInstallerSuccessLaunchCmdLine, *launch_cmd, true);
+ }
+ if (!install_list->Do())
+ LOG(ERROR) << "Failed to record installer error information in registry.";
+}
+
bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {
wchar_t program_files_path[MAX_PATH] = {0};
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index 0d20932..f2ba551 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -54,6 +54,16 @@ class InstallUtil {
// This function checks if the current OS is supported for Chromium.
static bool IsOSSupported();
+ // This function sets installer error information in registry so that Google
+ // Update can read it and display to the user. |state_key| should be
+ // obtained via the state_key method of an InstallerState instance created
+ // before the machine state is modified by the installer.
+ static void WriteInstallerResult(bool system_install,
+ const std::wstring& state_key,
+ installer::InstallStatus status,
+ int string_resource_id,
+ const std::wstring* const launch_cmd);
+
// Returns true if this installation path is per user, otherwise returns
// false (per machine install, meaning: the exe_path contains path to
// Program Files).
diff --git a/chrome/installer/util/install_util_unittest.cc b/chrome/installer/util/install_util_unittest.cc
new file mode 100644
index 0000000..95e0c3d
--- /dev/null
+++ b/chrome/installer/util/install_util_unittest.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/win/registry.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/product_unittest.h"
+
+using base::win::RegKey;
+using installer::InstallationState;
+using installer::InstallerState;
+using installer::MasterPreferences;
+
+class InstallUtilTest : public TestWithTempDirAndDeleteTempOverrideKeys {
+ protected:
+};
+
+TEST_F(InstallUtilTest, InstallerResult) {
+ const bool system_level = true;
+ bool multi_install = false;
+ HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+
+ RegKey key;
+ std::wstring launch_cmd = L"hey diddle diddle";
+ std::wstring value;
+
+ // check results for a fresh install of single Chrome
+ {
+ TempRegKeyOverride override(root, L"root_inst_res");
+ const MasterPreferences prefs(
+ CommandLine::FromString(L"setup.exe --system-level"));
+ InstallationState machine_state;
+ machine_state.Initialize(prefs);
+ InstallerState state;
+ state.Initialize(prefs, machine_state);
+ InstallUtil::WriteInstallerResult(system_level, state.state_key(),
+ installer::FIRST_INSTALL_SUCCESS, 0, &launch_cmd);
+ BrowserDistribution* distribution =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
+ EXPECT_TRUE(key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
+ EXPECT_TRUE(key.ReadValue(installer::kInstallerSuccessLaunchCmdLine,
+ &value));
+ EXPECT_EQ(launch_cmd, value);
+ }
+ TempRegKeyOverride::DeleteAllTempKeys();
+
+ // check results for a fresh install of multi Chrome
+ {
+ TempRegKeyOverride override(root, L"root_inst_res");
+ const MasterPreferences prefs(
+ CommandLine::FromString(
+ L"setup.exe --system-level --multi-install --chrome"));
+ InstallationState machine_state;
+ machine_state.Initialize(prefs);
+ InstallerState state;
+ state.Initialize(prefs, machine_state);
+ InstallUtil::WriteInstallerResult(system_level, state.state_key(),
+ installer::FIRST_INSTALL_SUCCESS, 0, &launch_cmd);
+ BrowserDistribution* distribution =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
+ EXPECT_TRUE(key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
+ EXPECT_TRUE(key.ReadValue(installer::kInstallerSuccessLaunchCmdLine,
+ &value));
+ EXPECT_EQ(launch_cmd, value);
+ key.Close();
+ }
+ TempRegKeyOverride::DeleteAllTempKeys();
+}
diff --git a/chrome/installer/util/installation_state.cc b/chrome/installer/util/installation_state.cc
new file mode 100644
index 0000000..5db624e
--- /dev/null
+++ b/chrome/installer/util/installation_state.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/installer/util/installation_state.h"
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "base/version.h"
+#include "base/win/registry.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/package_properties.h"
+
+namespace installer {
+
+ProductState::ProductState() {
+}
+
+void ProductState::Initialize(bool system_install,
+ const std::wstring& version_key,
+ const std::wstring& state_key) {
+ const HKEY root_key = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ base::win::RegKey key(root_key, version_key.c_str(), KEY_QUERY_VALUE);
+ std::wstring version_str;
+ if (key.ReadValue(google_update::kRegVersionField, &version_str)) {
+ version_.reset(Version::GetVersionFromString(WideToASCII(version_str)));
+ if (version_.get() != NULL) {
+ // The product is installed. Check for the channel value (absent if not
+ // installed/managed by Google Update).
+ if (!key.Open(root_key, state_key.c_str(), KEY_QUERY_VALUE) ||
+ !channel_.Initialize(key)) {
+ channel_.set_value(std::wstring());
+ }
+ }
+ } else {
+ version_.reset();
+ }
+}
+
+const Version& ProductState::version() const {
+ DCHECK(version_.get() != NULL);
+ return *version_;
+}
+
+void ProductState::CopyFrom(const ProductState& other) {
+ channel_.set_value(other.channel_.value());
+ if (other.version_.get() == NULL)
+ version_.reset();
+ else
+ version_.reset(other.version_->Clone());
+}
+
+InstallationState::InstallationState() {
+}
+
+// static
+int InstallationState::IndexFromDistType(BrowserDistribution::Type type) {
+ COMPILE_ASSERT(BrowserDistribution::CHROME_BROWSER == CHROME_BROWSER_INDEX,
+ unexpected_chrome_browser_distribution_value_);
+ COMPILE_ASSERT(BrowserDistribution::CHROME_FRAME == CHROME_FRAME_INDEX,
+ unexpected_chrome_frame_distribution_value_);
+ DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
+ type == BrowserDistribution::CHROME_FRAME);
+ return type;
+}
+
+void InstallationState::Initialize(const MasterPreferences& prefs) {
+ BrowserDistribution* distribution;
+
+ distribution = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER, prefs);
+ InitializeProduct(false, distribution, &user_products_[CHROME_BROWSER_INDEX]);
+ InitializeProduct(true, distribution,
+ &system_products_[CHROME_BROWSER_INDEX]);
+
+ distribution = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME, prefs);
+ InitializeProduct(false, distribution, &user_products_[CHROME_FRAME_INDEX]);
+ InitializeProduct(true, distribution, &system_products_[CHROME_FRAME_INDEX]);
+
+ ActivePackageProperties package_properties;
+ InitializeMultiPackage(false, package_properties,
+ &user_products_[MULTI_PACKAGE_INDEX]);
+ InitializeMultiPackage(true, package_properties,
+ &system_products_[MULTI_PACKAGE_INDEX]);
+}
+
+// static
+void InstallationState::InitializeProduct(bool system_install,
+ BrowserDistribution* distribution,
+ ProductState* product) {
+ product->Initialize(system_install, distribution->GetVersionKey(),
+ distribution->GetStateKey());
+}
+
+// static
+void InstallationState::InitializeMultiPackage(bool system_install,
+ PackageProperties& properties,
+ ProductState* product) {
+ product->Initialize(system_install, properties.GetVersionKey(),
+ properties.GetStateKey());
+}
+
+const ProductState* InstallationState::GetMultiPackageState(
+ bool system_install) const {
+ const ProductState& product_state =
+ (system_install ? system_products_ : user_products_)[MULTI_PACKAGE_INDEX];
+ return product_state.version_.get() == NULL ? NULL : &product_state;
+}
+
+// Included for testing.
+void InstallationState::SetMultiPackageState(bool system_install,
+ const ProductState& package_state) {
+ ProductState& target =
+ (system_install ? system_products_ : user_products_)[MULTI_PACKAGE_INDEX];
+ target.CopyFrom(package_state);
+}
+
+const ProductState* InstallationState::GetProductState(
+ bool system_install,
+ BrowserDistribution::Type type) const {
+ const ProductState& product_state = (system_install ? system_products_ :
+ user_products_)[IndexFromDistType(type)];
+ return product_state.version_.get() == NULL ? NULL : &product_state;
+}
+
+// Included for testing.
+void InstallationState::SetProductState(bool system_install,
+ BrowserDistribution::Type type, const ProductState& product_state) {
+ ProductState& target = (system_install ? system_products_ :
+ user_products_)[IndexFromDistType(type)];
+ target.CopyFrom(product_state);
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/installation_state.h b/chrome/installer/util/installation_state.h
new file mode 100644
index 0000000..29a4006
--- /dev/null
+++ b/chrome/installer/util/installation_state.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_INSTALLER_UTIL_INSTALLATION_STATE_H_
+#define CHROME_INSTALLER_UTIL_INSTALLATION_STATE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/channel_info.h"
+
+class Version;
+
+namespace installer {
+
+class InstallationState;
+class MasterPreferences;
+class PackageProperties;
+
+class ProductState {
+ public:
+ ProductState();
+ void Initialize(bool system_install,
+ const std::wstring& version_key,
+ const std::wstring& state_key);
+
+ const ChannelInfo& channel() const { return channel_; }
+ ChannelInfo& channel() { return channel_; }
+
+ const Version& version() const;
+ // Takes ownership of |version|.
+ void set_version(Version* version) { version_.reset(version); }
+
+ void CopyFrom(const ProductState& other);
+
+ private:
+ friend class InstallationState;
+
+ ChannelInfo channel_;
+ scoped_ptr<Version> version_;
+ DISALLOW_COPY_AND_ASSIGN(ProductState);
+}; // class ProductState
+
+// Encapsulates the state of all products on the system.
+class InstallationState {
+ public:
+ InstallationState();
+
+ // Initializes |this| with the machine's current state.
+ void Initialize(const MasterPreferences& prefs);
+
+ // Returns the state of the multi-installer package or NULL if no
+ // multi-install products are installed.
+ const ProductState* GetMultiPackageState(bool system_install) const;
+
+ // Sets the state of the multi-installer package; intended for tests.
+ void SetMultiPackageState(bool system_install,
+ const ProductState& package_state);
+
+ // Returns the state of a product or NULL if not installed.
+ const ProductState* GetProductState(bool system_install,
+ BrowserDistribution::Type type) const;
+
+ // Sets the state of a product; indended for tests.
+ void SetProductState(bool system_install,
+ BrowserDistribution::Type type,
+ const ProductState& product_state);
+
+ private:
+ enum {
+ CHROME_BROWSER_INDEX,
+ CHROME_FRAME_INDEX,
+ MULTI_PACKAGE_INDEX,
+ NUM_PRODUCTS
+ };
+
+ static int IndexFromDistType(BrowserDistribution::Type type);
+ static void InitializeProduct(bool system_install,
+ BrowserDistribution* distribution,
+ ProductState* product);
+ static void InitializeMultiPackage(bool system_install,
+ PackageProperties& properties,
+ ProductState* product);
+
+ ProductState user_products_[NUM_PRODUCTS];
+ ProductState system_products_[NUM_PRODUCTS];
+
+ DISALLOW_COPY_AND_ASSIGN(InstallationState);
+}; // class InstallationState
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_INSTALLATION_STATE_H_
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
new file mode 100644
index 0000000..fd396da
--- /dev/null
+++ b/chrome/installer/util/installer_state.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/installer/util/installer_state.h"
+
+#include "base/logging.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/master_preferences_constants.h"
+#include "chrome/installer/util/package_properties.h"
+
+namespace installer {
+
+bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
+ const InstallationState& machine_state) {
+ // First, is the package present?
+ const ProductState* package =
+ machine_state.GetMultiPackageState(system_install_);
+ if (package == NULL) {
+ // The multi-install package has not been installed, so it certainly isn't
+ // being updated.
+ return false;
+ }
+
+ BrowserDistribution::Type types[2];
+ size_t num_types = 0;
+ if (prefs.install_chrome())
+ types[num_types++] = BrowserDistribution::CHROME_BROWSER;
+ if (prefs.install_chrome_frame())
+ types[num_types++] = BrowserDistribution::CHROME_FRAME;
+
+ for (const BrowserDistribution::Type* scan = &types[0],
+ *end = &types[num_types]; scan != end; ++scan) {
+ const ProductState* product =
+ machine_state.GetProductState(system_install_, *scan);
+ if (product == NULL) {
+ VLOG(2) << "It seems that distribution type " << *scan
+ << " is being installed for the first time.";
+ return false;
+ }
+ if (!product->channel().Equals(package->channel())) {
+ VLOG(2) << "It seems that distribution type " << *scan
+ << " is being over installed.";
+ return false;
+ }
+ }
+
+ VLOG(2) << "It seems that the package is being updated.";
+
+ return true;
+}
+
+InstallerState::InstallerState() : operation_(UNINITIALIZED) {
+}
+
+void InstallerState::Initialize(const MasterPreferences& prefs,
+ const InstallationState& machine_state) {
+ if (!prefs.GetBool(installer::master_preferences::kSystemLevel,
+ &system_install_))
+ system_install_ = false;
+
+ BrowserDistribution* operand = NULL;
+
+ if (!prefs.is_multi_install()) {
+ // For a single-install, the current browser dist is the operand.
+ operand = BrowserDistribution::GetDistribution();
+ operation_ = SINGLE_INSTALL_OR_UPDATE;
+ } else if (IsMultiInstallUpdate(prefs, machine_state)) {
+ // Updates driven by Google Update take place under the multi-installer's
+ // app guid.
+ installer::ActivePackageProperties package_properties;
+ operation_ = MULTI_UPDATE;
+ state_key_ = package_properties.GetStateKey();
+ } else {
+ // Initial and over installs will always take place under one of the
+ // product app guids. Chrome Frame's will be used if only Chrome Frame
+ // is being installed. In all other cases, Chrome's is used.
+ operand = BrowserDistribution::GetSpecificDistribution(
+ prefs.install_chrome() ?
+ BrowserDistribution::CHROME_BROWSER :
+ BrowserDistribution::CHROME_FRAME,
+ prefs);
+ operation_ = MULTI_INSTALL;
+ }
+
+ if (operand != NULL) {
+ install_operand_ = operand->GetType();
+ state_key_ = operand->GetStateKey();
+ }
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/installer_state.h b/chrome/installer/util/installer_state.h
new file mode 100644
index 0000000..214ae45
--- /dev/null
+++ b/chrome/installer/util/installer_state.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_INSTALLER_UTIL_INSTALLER_STATE_H_
+#define CHROME_INSTALLER_UTIL_INSTALLER_STATE_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "chrome/installer/util/browser_distribution.h"
+
+namespace installer {
+
+class InstallationState;
+class MasterPreferences;
+
+// Encapsulates the state of the current installation operation. Only valid
+// for installs and upgrades (not for uninstalls or non-install commands)
+class InstallerState {
+ public:
+ enum Operation {
+ UNINITIALIZED,
+ SINGLE_INSTALL_OR_UPDATE,
+ MULTI_INSTALL,
+ MULTI_UPDATE,
+ };
+
+ InstallerState();
+
+ // Initializes |this| based on the current operation.
+ void Initialize(const MasterPreferences& prefs,
+ const InstallationState& machine_state);
+
+ // true if system-level, false if user-level.
+ bool system_install() const { return system_install_; }
+
+ Operation operation() const { return operation_; }
+
+ BrowserDistribution::Type GetInstallOperand() const {
+ return install_operand_;
+ }
+
+ // The ClientState key by which we interact with Google Update.
+ const std::wstring& state_key() const { return state_key_; }
+
+ private:
+ bool IsMultiInstallUpdate(const MasterPreferences& prefs,
+ const InstallationState& machine_state);
+
+ Operation operation_;
+ BrowserDistribution::Type install_operand_;
+ std::wstring state_key_;
+ bool system_install_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstallerState);
+}; // class InstallerState
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_INSTALLER_STATE_H_
diff --git a/chrome/installer/util/package.cc b/chrome/installer/util/package.cc
index 6e88a30..3122cef 100644
--- a/chrome/installer/util/package.cc
+++ b/chrome/installer/util/package.cc
@@ -9,12 +9,9 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
-#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
-#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/product.h"
@@ -22,35 +19,8 @@
#include "chrome/installer/util/work_item_list.h"
using base::win::RegKey;
-using installer::ChannelInfo;
using installer::MasterPreferences;
-namespace {
-
-void AddInstallerResult(HKEY root,
- const std::wstring& key,
- int installer_result,
- installer::InstallStatus status,
- const std::wstring& msg,
- const std::wstring* const launch_cmd,
- WorkItemList* install_list) {
- install_list->AddCreateRegKeyWorkItem(root, key);
- install_list->AddSetRegValueWorkItem(root, key, installer::kInstallerResult,
- installer_result, true);
- install_list->AddSetRegValueWorkItem(root, key, installer::kInstallerError,
- status, true);
- if (!msg.empty()) {
- install_list->AddSetRegValueWorkItem(root, key,
- installer::kInstallerResultUIString, msg, true);
- }
- if (launch_cmd != NULL && !launch_cmd->empty()) {
- install_list->AddSetRegValueWorkItem(root, key,
- installer::kInstallerSuccessLaunchCmdLine, *launch_cmd, true);
- }
-}
-
-} // namespace
-
namespace installer {
Package::Package(bool multi_install, bool system_level, const FilePath& path,
@@ -214,31 +184,5 @@ size_t Package::GetMultiInstallDependencyCount() const {
return ret;
}
-void Package::WriteInstallerResult(installer::InstallStatus status,
- int string_resource_id,
- const std::wstring* const launch_cmd) const {
- HKEY root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- int installer_result = InstallUtil::GetInstallReturnCode(status) == 0 ? 0 : 1;
- std::wstring msg;
- scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
-
- if (string_resource_id != 0)
- msg = installer::GetLocalizedString(string_resource_id);
-
- for (Products::const_iterator scan = products_.begin(), end = products_.end();
- scan != end; ++scan) {
- const Product& product = *(scan->get());
- AddInstallerResult(root, product.distribution()->GetStateKey(),
- installer_result, status, msg, launch_cmd,
- install_list.get());
- }
- if (multi_install_ && properties_->ReceivesUpdates()) {
- AddInstallerResult(root, properties_->GetStateKey(), installer_result,
- status, msg, launch_cmd, install_list.get());
- }
- if (!install_list->Do())
- LOG(ERROR) << "Failed to record installer error information in registry.";
-}
-
} // namespace installer
diff --git a/chrome/installer/util/package.h b/chrome/installer/util/package.h
index c54c13d..d523fc2 100644
--- a/chrome/installer/util/package.h
+++ b/chrome/installer/util/package.h
@@ -71,12 +71,6 @@ class Package : public base::RefCounted<Package> {
// system_level() value.
size_t GetMultiInstallDependencyCount() const;
- // Sets installer error information in registry so that Google Update can read
- // it and display it to the user.
- void WriteInstallerResult(installer::InstallStatus status,
- int string_resource_id,
- const std::wstring* const launch_cmd) const;
-
protected:
bool multi_install_;
bool system_level_;
diff --git a/chrome/installer/util/package_properties.cc b/chrome/installer/util/package_properties.cc
index 814fc9e..2ab87cb 100644
--- a/chrome/installer/util/package_properties.cc
+++ b/chrome/installer/util/package_properties.cc
@@ -54,11 +54,15 @@ const std::wstring& PackagePropertiesImpl::GetVersionKey() {
return version_key_;
}
-void PackagePropertiesImpl::UpdateDiffInstallStatus(bool system_level,
- bool incremental_install,
- InstallStatus status) {
- GoogleUpdateSettings::UpdateDiffInstallStatus(system_level,
- incremental_install, InstallUtil::GetInstallReturnCode(status), guid_);
+void PackagePropertiesImpl::UpdateInstallStatus(bool system_level,
+ bool incremental_install,
+ bool multi_install,
+ InstallStatus status) {
+ if (ReceivesUpdates()) {
+ GoogleUpdateSettings::UpdateInstallStatus(system_level,
+ incremental_install, multi_install,
+ InstallUtil::GetInstallReturnCode(status), guid_);
+ }
}
ChromiumPackageProperties::ChromiumPackageProperties()
diff --git a/chrome/installer/util/package_properties.h b/chrome/installer/util/package_properties.h
index e3444da..a3f7714 100644
--- a/chrome/installer/util/package_properties.h
+++ b/chrome/installer/util/package_properties.h
@@ -39,8 +39,8 @@ class PackageProperties {
virtual const std::wstring& GetStateKey() = 0;
virtual const std::wstring& GetStateMediumKey() = 0;
virtual const std::wstring& GetVersionKey() = 0;
- virtual void UpdateDiffInstallStatus(bool system_level,
- bool incremental_install, installer::InstallStatus status) = 0;
+ virtual void UpdateInstallStatus(bool system_level, bool incremental_install,
+ bool multi_install, installer::InstallStatus status) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PackageProperties);
@@ -57,8 +57,8 @@ class PackagePropertiesImpl : public PackageProperties {
virtual const std::wstring& GetStateKey();
virtual const std::wstring& GetStateMediumKey();
virtual const std::wstring& GetVersionKey();
- virtual void UpdateDiffInstallStatus(bool system_level,
- bool incremental_install, installer::InstallStatus status);
+ virtual void UpdateInstallStatus(bool system_level, bool incremental_install,
+ bool multi_install, installer::InstallStatus status);
protected:
std::wstring guid_;
@@ -96,6 +96,12 @@ class ChromePackageProperties : public PackagePropertiesImpl {
DISALLOW_COPY_AND_ASSIGN(ChromePackageProperties);
}; // class ChromePackageProperties
+#if defined(GOOGLE_CHROME_BUILD)
+typedef ChromePackageProperties ActivePackageProperties;
+#else
+typedef ChromiumPackageProperties ActivePackageProperties;
+#endif
+
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_PACKAGE_PROPERTIES_H_
diff --git a/chrome/installer/util/package_properties_unittest.cc b/chrome/installer/util/package_properties_unittest.cc
index f1a7cab..6b6618d 100644
--- a/chrome/installer/util/package_properties_unittest.cc
+++ b/chrome/installer/util/package_properties_unittest.cc
@@ -29,24 +29,7 @@ TEST_F(PackagePropertiesTest, Basic) {
EXPECT_FALSE(state_key.empty());
std::wstring version_key(props[i]->GetVersionKey());
EXPECT_FALSE(version_key.empty());
- if (props[i]->ReceivesUpdates()) {
- HKEY roots[] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
- for (size_t j = 0; j < arraysize(roots); ++j) {
- {
- TempRegKeyOverride override(roots[j], L"props");
- RegKey key;
- EXPECT_TRUE(key.Create(roots[j], state_key.c_str(), KEY_ALL_ACCESS));
- EXPECT_TRUE(key.WriteValue(google_update::kRegApField, L""));
- props[i]->UpdateDiffInstallStatus(roots[j] == HKEY_LOCAL_MACHINE,
- true,
- installer::INSTALL_FAILED);
- std::wstring value;
- key.ReadValue(google_update::kRegApField, &value);
- EXPECT_FALSE(value.empty());
- }
- TempRegKeyOverride::DeleteAllTempKeys();
- }
- } else {
+ if (!props[i]->ReceivesUpdates()) {
TempRegKeyOverride override(HKEY_CURRENT_USER, L"props");
RegKey key;
EXPECT_TRUE(key.Create(HKEY_CURRENT_USER, state_key.c_str(),
diff --git a/chrome/installer/util/package_unittest.cc b/chrome/installer/util/package_unittest.cc
index e2a9bb6..851f188 100644
--- a/chrome/installer/util/package_unittest.cc
+++ b/chrome/installer/util/package_unittest.cc
@@ -187,58 +187,3 @@ TEST_F(PackageTest, Dependency) {
SetUninstallArguments(root, cf, multi_uninstall_cmd);
EXPECT_EQ(2U, package->GetMultiInstallDependencyCount());
}
-
-TEST_F(PackageTest, InstallerResult) {
- const bool system_level = true;
- bool multi_install = false;
- HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
-
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
- ChromePackageProperties properties;
- BrowserDistribution* distribution =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- scoped_refptr<Package> package(new Package(multi_install, system_level,
- test_dir_.path(), &properties));
- scoped_refptr<Product> product(new Product(distribution, package.get()));
- RegKey key;
- std::wstring launch_cmd = L"hey diddle diddle";
- std::wstring value;
-
- // check results for single Chrome
- {
- TempRegKeyOverride override(root, L"root_inst_res");
- package->WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS, 0,
- &launch_cmd);
- EXPECT_TRUE(key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
- EXPECT_TRUE(key.ReadValue(installer::kInstallerSuccessLaunchCmdLine,
- &value));
- EXPECT_EQ(launch_cmd, value);
- key.Close();
- }
- TempRegKeyOverride::DeleteAllTempKeys();
-
- // check results for multi Chrome
- multi_install = true;
- package = new Package(multi_install, system_level, test_dir_.path(),
- &properties);
- product = new Product(distribution, package.get());
- {
- TempRegKeyOverride override(root, L"root_inst_res");
- package->WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS, 0,
- &launch_cmd);
- EXPECT_TRUE(key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
- EXPECT_TRUE(key.ReadValue(installer::kInstallerSuccessLaunchCmdLine,
- &value));
- EXPECT_EQ(launch_cmd, value);
- EXPECT_EQ(properties.ReceivesUpdates(),
- key.Open(root, properties.GetStateKey().c_str(), KEY_READ));
- if (properties.ReceivesUpdates()) {
- EXPECT_TRUE(key.ReadValue(installer::kInstallerSuccessLaunchCmdLine,
- &value));
- EXPECT_EQ(launch_cmd, value);
- }
- key.Close();
- }
- TempRegKeyOverride::DeleteAllTempKeys();
-}
diff --git a/chrome/installer/util/product.cc b/chrome/installer/util/product.cc
index 43f371a..bddd7d8 100644
--- a/chrome/installer/util/product.cc
+++ b/chrome/installer/util/product.cc
@@ -161,21 +161,6 @@ bool Product::SetMsiMarker(bool set) const {
return success;
}
-const Version* Product::GetInstalledVersion() const {
- if ((cache_state_ & VERSION) == 0) {
- DCHECK(installed_version_.get() == NULL);
- installed_version_.reset(InstallUtil::GetChromeVersion(distribution_,
- system_level()));
- cache_state_ |= VERSION;
- }
-
- return installed_version_.get();
-}
-
-bool Product::IsInstalled() const {
- return GetInstalledVersion() != NULL;
-}
-
bool Product::ShouldCreateUninstallEntry() const {
if (IsMsi()) {
// MSI installations will manage their own uninstall shortcuts.
@@ -188,11 +173,7 @@ bool Product::ShouldCreateUninstallEntry() const {
///////////////////////////////////////////////////////////////////////////////
ProductPackageMapping::ProductPackageMapping(bool multi_install,
bool system_level)
-#if defined(GOOGLE_CHROME_BUILD)
- : package_properties_(new ChromePackageProperties()),
-#else
- : package_properties_(new ChromiumPackageProperties()),
-#endif
+ : package_properties_(new ActivePackageProperties()),
multi_install_(multi_install),
system_level_(system_level) {
}
diff --git a/chrome/installer/util/product.h b/chrome/installer/util/product.h
index 36362af..28361df 100644
--- a/chrome/installer/util/product.h
+++ b/chrome/installer/util/product.h
@@ -14,7 +14,6 @@
#include "chrome/installer/util/package.h"
class CommandLine;
-class Version;
namespace installer {
class MasterPreferences;
@@ -98,27 +97,17 @@ class Product : public base::RefCounted<Product> {
// ClientState key.
bool SetMsiMarker(bool set) const;
- // Find the version of this product installed on the system by checking the
- // Google Update registry key. Returns the version or NULL if no version is
- // found. The returned Version object is owned by |this| Product instance.
- const Version* GetInstalledVersion() const;
-
// Returns true if setup should create an entry in the Add/Remove list
// of installed applications.
bool ShouldCreateUninstallEntry() const;
- // Returns true if the product is already installed.
- bool IsInstalled() const;
-
protected:
enum CacheStateFlags {
- MSI_STATE = 0x01,
- VERSION = 0x02
+ MSI_STATE = 0x01
};
BrowserDistribution* distribution_;
scoped_refptr<Package> package_;
- mutable scoped_ptr<Version> installed_version_;
mutable bool msi_;
mutable uint8 cache_state_;
diff --git a/chrome/installer/util/product_unittest.cc b/chrome/installer/util/product_unittest.cc
index 0e928bc..b6f8f27 100644
--- a/chrome/installer/util/product_unittest.cc
+++ b/chrome/installer/util/product_unittest.cc
@@ -9,6 +9,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/package.h"
#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/master_preferences.h"
@@ -126,8 +127,12 @@ TEST_F(ProductTest, ProductInstallBasic) {
EXPECT_TRUE(product->IsMsi());
// There should be no installed version in the registry.
- EXPECT_FALSE(product->IsInstalled());
- EXPECT_TRUE(product->GetInstalledVersion() == NULL);
+ {
+ installer::InstallationState state;
+ state.Initialize(prefs);
+ EXPECT_TRUE(state.GetProductState(system_level,
+ distribution->GetType()) == NULL);
+ }
// Let's pretend chrome is installed.
RegKey version_key(root, distribution->GetVersionKey().c_str(),
@@ -140,14 +145,15 @@ TEST_F(ProductTest, ProductInstallBasic) {
version_key.WriteValue(google_update::kRegVersionField,
UTF8ToWide(current_version->GetString()).c_str());
- package = new Package(multi_install, system_level, test_dir_.path(),
- &properties);
- product = new Product(distribution, package.get());
- const Version* installed(product->GetInstalledVersion());
- EXPECT_TRUE(product->IsInstalled());
- EXPECT_TRUE(installed != NULL);
- if (installed) {
- EXPECT_TRUE(installed->Equals(*current_version.get()));
+ {
+ installer::InstallationState state;
+ state.Initialize(prefs);
+ const installer::ProductState* prod_state =
+ state.GetProductState(system_level, distribution->GetType());
+ EXPECT_TRUE(prod_state != NULL);
+ if (prod_state != NULL) {
+ EXPECT_TRUE(prod_state->version().Equals(*current_version.get()));
+ }
}
}
}
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 0028c78..96bfb8a 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -13,44 +13,44 @@ namespace installer {
// Return status of installer
enum InstallStatus {
- FIRST_INSTALL_SUCCESS, // 0. Successfully installed Chrome for the first time
- INSTALL_REPAIRED, // 1. Same version reinstalled for repair
- NEW_VERSION_UPDATED, // 2. Chrome successfully updated to new version
+ FIRST_INSTALL_SUCCESS, // 0. Successfully installed Chrome for the first time
+ INSTALL_REPAIRED, // 1. Same version reinstalled for repair
+ NEW_VERSION_UPDATED, // 2. Chrome successfully updated to new version
EXISTING_VERSION_LAUNCHED, // 3. No work done, just launched existing chrome
- HIGHER_VERSION_EXISTS, // 4. Higher version of Chrome already exists
- USER_LEVEL_INSTALL_EXISTS, // 5. User level install already exists
- SYSTEM_LEVEL_INSTALL_EXISTS, // 6. Machine level install already exists
- INSTALL_FAILED, // 7. Install/update failed
- SETUP_PATCH_FAILED, // 8. Failed to patch setup.exe
- OS_NOT_SUPPORTED, // 9. Current OS not supported
- OS_ERROR, // 10. OS API call failed
- TEMP_DIR_FAILED, // 11. Unable to get Temp directory
- UNCOMPRESSION_FAILED, // 12. Failed to uncompress Chrome archive
- INVALID_ARCHIVE, // 13. Something wrong with the installer archive
- INSUFFICIENT_RIGHTS, // 14. User trying system level install is not Admin
- CHROME_NOT_INSTALLED, // 15. Chrome not installed (returned in case of
- // uninstall)
- CHROME_RUNNING, // 16. Chrome currently running (when trying to
- // uninstall)
- UNINSTALL_CONFIRMED, // 17. User has confirmed Chrome uninstall
+ HIGHER_VERSION_EXISTS, // 4. Higher version of Chrome already exists
+ USER_LEVEL_INSTALL_EXISTS, // 5. User level install already exists
+ SYSTEM_LEVEL_INSTALL_EXISTS, // 6. Machine level install already exists
+ INSTALL_FAILED, // 7. Install/update failed
+ SETUP_PATCH_FAILED, // 8. Failed to patch setup.exe
+ OS_NOT_SUPPORTED, // 9. Current OS not supported
+ OS_ERROR, // 10. OS API call failed
+ TEMP_DIR_FAILED, // 11. Unable to get Temp directory
+ UNCOMPRESSION_FAILED, // 12. Failed to uncompress Chrome archive
+ INVALID_ARCHIVE, // 13. Something wrong with the installer archive
+ INSUFFICIENT_RIGHTS, // 14. User trying system level install is not Admin
+ CHROME_NOT_INSTALLED, // 15. Chrome not installed (returned in case of
+ // uninstall)
+ CHROME_RUNNING, // 16. Chrome currently running (when trying to
+ // uninstall)
+ UNINSTALL_CONFIRMED, // 17. User has confirmed Chrome uninstall
UNINSTALL_DELETE_PROFILE, // 18. User confirmed uninstall and profile deletion
- UNINSTALL_SUCCESSFUL, // 19. Chrome successfully uninstalled
- UNINSTALL_FAILED, // 20. Chrome uninstallation failed
- UNINSTALL_CANCELLED, // 21. User cancelled Chrome uninstallation
- UNKNOWN_STATUS, // 22. Unknown status (this should never happen)
- RENAME_SUCCESSFUL, // 23. Rename of new_chrome.exe to chrome.exe worked
- RENAME_FAILED, // 24. Rename of new_chrome.exe failed
- EULA_REJECTED, // 25. EULA dialog was not accepted by user.
- EULA_ACCEPTED, // 26. EULA dialog was accepted by user.
- EULA_ACCEPTED_OPT_IN, // 27. EULA accepted wtih the crash optin selected.
- INSTALL_DIR_IN_USE, // 28. Installation directory is in use by another
- // process
- UNINSTALL_REQUIRES_REBOOT, // 29. Uninstallation required a reboot.
- IN_USE_UPDATED, // 30. Chrome successfully updated but old version
- // running
- SAME_VERSION_REPAIR_FAILED, // 31. Chrome repair failed as Chrome was running
- REENTRY_SYS_UPDATE, // 32. Setup has been re-launched as the interactive
- // user
+ UNINSTALL_SUCCESSFUL, // 19. Chrome successfully uninstalled
+ UNINSTALL_FAILED, // 20. Chrome uninstallation failed
+ UNINSTALL_CANCELLED, // 21. User cancelled Chrome uninstallation
+ UNKNOWN_STATUS, // 22. Unknown status (this should never happen)
+ RENAME_SUCCESSFUL, // 23. Rename of new_chrome.exe to chrome.exe worked
+ RENAME_FAILED, // 24. Rename of new_chrome.exe failed
+ EULA_REJECTED, // 25. EULA dialog was not accepted by user.
+ EULA_ACCEPTED, // 26. EULA dialog was accepted by user.
+ EULA_ACCEPTED_OPT_IN, // 27. EULA accepted wtih the crash optin selected.
+ INSTALL_DIR_IN_USE, // 28. Installation directory is in use by another
+ // process
+ UNINSTALL_REQUIRES_REBOOT, // 29. Uninstallation required a reboot.
+ IN_USE_UPDATED, // 30. Chrome successfully updated but old version
+ // running
+ SAME_VERSION_REPAIR_FAILED, // 31. Chrome repair failed as Chrome was running
+ REENTRY_SYS_UPDATE, // 32. Setup has been re-launched as the interactive
+ // user
SXS_OPTION_NOT_SUPPORTED, // 33. The chrome-sxs option provided does not work
// with other command line options.
NON_MULTI_INSTALLATION_EXISTS, // 34. We tried to do a multi-install but
@@ -129,7 +129,7 @@ extern const wchar_t kUninstallInstallationDate[];
extern const char kUninstallMetricsName[];
extern const wchar_t kUninstallStringField[];
-// Used by ProductInstall::WriteInstallerResult.
+// Used by InstallUtil::WriteInstallerResult.
extern const wchar_t kInstallerResult[];
extern const wchar_t kInstallerError[];
extern const wchar_t kInstallerResultUIString[];