summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_installer.gypi1
-rw-r--r--chrome/chrome_installer_util.gypi2
-rw-r--r--chrome/installer/setup/install.cc56
-rw-r--r--chrome/installer/setup/setup_main.cc28
-rw-r--r--chrome/installer/setup/uninstall.cc3
-rw-r--r--chrome/installer/util/chrome_frame_distribution.cc4
-rw-r--r--chrome/installer/util/google_chrome_distribution.h4
-rw-r--r--chrome/installer/util/helper_unittest.cc9
-rw-r--r--chrome/installer/util/package.cc24
-rw-r--r--chrome/installer/util/package.h12
-rw-r--r--chrome/installer/util/package_properties.cc82
-rw-r--r--chrome/installer/util/package_properties.h97
-rw-r--r--chrome/installer/util/package_properties_unittest.cc57
-rw-r--r--chrome/installer/util/package_unittest.cc16
-rw-r--r--chrome/installer/util/product.cc26
-rw-r--r--chrome/installer/util/product.h16
-rw-r--r--chrome/installer/util/product_unittest.cc16
17 files changed, 376 insertions, 77 deletions
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index 80cf38d..d2be152 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -93,6 +93,7 @@
'installer/util/lzma_util_unittest.cc',
'installer/util/master_preferences_unittest.cc',
'installer/util/move_tree_work_item_unittest.cc',
+ 'installer/util/package_properties_unittest.cc',
'installer/util/package_unittest.cc',
'installer/util/product_unittest.h',
'installer/util/product_unittest.cc',
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi
index 2842eb3..4ab157c 100644
--- a/chrome/chrome_installer_util.gypi
+++ b/chrome/chrome_installer_util.gypi
@@ -105,6 +105,8 @@
'installer/util/master_preferences.h',
'installer/util/package.h',
'installer/util/package.cc',
+ '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/setup/install.cc b/chrome/installer/setup/install.cc
index 7d3f73e..07cf55d 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -13,6 +13,7 @@
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
@@ -24,6 +25,7 @@
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/package.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/set_reg_value_work_item.h"
#include "chrome/installer/util/shell_util.h"
@@ -39,6 +41,7 @@ namespace {
using installer::Products;
using installer::Product;
using installer::Package;
+using installer::PackageProperties;
using installer::Version;
void AddChromeToMediaPlayerList() {
@@ -269,8 +272,8 @@ bool CreateOrUpdateChromeShortcuts(const FilePath& setup_path,
#endif
FilePath shortcut_path;
- int dir_enum = product.system_level() ? base::DIR_COMMON_START_MENU :
- base::DIR_START_MENU;
+ int dir_enum = product.system_level() ?
+ base::DIR_COMMON_START_MENU : base::DIR_START_MENU;
if (!PathService::Get(dir_enum, &shortcut_path)) {
LOG(ERROR) << "Failed to get location for shortcut.";
return false;
@@ -412,7 +415,8 @@ bool RegisterComDlls(const Package& install,
// it if not.
// If these operations are successful, the function returns true, otherwise
// false.
-bool DoPostInstallTasks(const FilePath& setup_path,
+bool DoPostInstallTasks(bool multi_install,
+ const FilePath& setup_path,
const FilePath& new_chrome_exe,
const Version* current_version,
const Version& new_version,
@@ -442,9 +446,10 @@ bool DoPostInstallTasks(const FilePath& setup_path,
if (InstallUtil::IsChromeSxSProcess())
rename.AppendSwitch(installer::switches::kChromeSxS);
+ std::wstring version_key;
for (size_t i = 0; i < products.size(); ++i) {
BrowserDistribution* dist = products[i]->distribution();
- std::wstring version_key(dist->GetVersionKey());
+ version_key = dist->GetVersionKey();
inuse_list->AddSetRegValueWorkItem(root, version_key,
google_update::kRegOldVersionField,
current_version->GetString(), true);
@@ -459,6 +464,17 @@ bool DoPostInstallTasks(const FilePath& setup_path,
rename.command_line_string(), true);
}
+ if (multi_install) {
+ PackageProperties* props = package.properties();
+ if (props->ReceivesUpdates()) {
+ inuse_list->AddSetRegValueWorkItem(root, props->GetVersionKey(),
+ google_update::kRegOldVersionField,
+ current_version->GetString(), true);
+ // TODO(tommi): We should move the rename command here. We also need to
+ // update Upgrade::SwapNewChromeExeIfPresent.
+ }
+ }
+
if (!inuse_list->Do()) {
LOG(ERROR) << "Couldn't write opv/cmd values to registry.";
inuse_list->Rollback();
@@ -577,6 +593,7 @@ void RegisterChromeOnMachine(const Product& product,
// (typical new install), the function creates package during install
// and removes the whole directory during rollback.
installer::InstallStatus InstallNewVersion(
+ bool multi_install,
const FilePath& setup_path,
const FilePath& archive_path,
const FilePath& src_path,
@@ -651,6 +668,9 @@ installer::InstallStatus InstallNewVersion(
AddInstallerCopyTasks(setup_path, archive_path, temp_dir, new_version,
install_list.get(), package);
+ HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+
+ std::wstring version_key;
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
@@ -659,9 +679,7 @@ installer::InstallStatus InstallNewVersion(
// Create Version key for each distribution (if not already present) and set
// the new product version as the last step.
- HKEY root = product->system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
- std::wstring version_key(product->distribution()->GetVersionKey());
+ version_key = product->distribution()->GetVersionKey();
install_list->AddCreateRegKeyWorkItem(root, version_key);
std::wstring product_name(product->distribution()->GetAppShortCutName());
@@ -679,9 +697,25 @@ installer::InstallStatus InstallNewVersion(
true); // overwrite version
}
+ if (multi_install) {
+ PackageProperties* props = package.properties();
+ if (props->ReceivesUpdates()) {
+ version_key = props->GetVersionKey();
+ install_list->AddCreateRegKeyWorkItem(root, version_key);
+ install_list->AddSetRegValueWorkItem(root, version_key,
+ google_update::kRegVersionField,
+ new_version.GetString(),
+ true); // overwrite version
+ install_list->AddSetRegValueWorkItem(root, version_key,
+ google_update::kRegNameField,
+ ASCIIToWide(installer::PackageProperties::kPackageProductName),
+ true); // overwrite name also
+ }
+ }
+
if (!install_list->Do() ||
- !DoPostInstallTasks(setup_path, new_chrome_exe, current_version->get(),
- new_version, package)) {
+ !DoPostInstallTasks(multi_install, setup_path, new_chrome_exe,
+ current_version->get(), new_version, package)) {
installer::InstallStatus result =
file_util::PathExists(new_chrome_exe) && current_version->get() &&
new_version.IsEqual(*current_version->get()) ?
@@ -735,8 +769,8 @@ installer::InstallStatus InstallOrUpdateChrome(
src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir);
scoped_ptr<Version> existing_version;
- installer::InstallStatus result = InstallNewVersion(setup_path,
- archive_path, src_path, install_temp_path, new_version,
+ installer::InstallStatus result = InstallNewVersion(prefs.is_multi_install(),
+ setup_path, archive_path, src_path, install_temp_path, new_version,
&existing_version, install);
if (!BrowserDistribution::GetInstallReturnCode(result)) {
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 4addd8c..7429600 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -29,16 +29,17 @@
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/delete_tree_work_item.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/html_dialog.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/lzma_util.h"
-#include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
@@ -172,6 +173,7 @@ bool CheckPreInstallConditions(const Package& installation,
DCHECK(products.size());
bool is_first_install = true;
+ bool system_level = installation.system_level();
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
@@ -184,17 +186,17 @@ bool CheckPreInstallConditions(const Package& installation,
// Check to avoid simultaneous per-user and per-machine installs.
scoped_ptr<Version> chrome_version(
- InstallUtil::GetChromeVersion(browser_dist, !product->system_level()));
+ InstallUtil::GetChromeVersion(browser_dist, !system_level));
if (chrome_version.get()) {
LOG(ERROR) << "Already installed version " << chrome_version->GetString()
<< " conflicts with the current install mode.";
- if (!product->system_level() && is_first_install) {
+ if (!system_level && is_first_install) {
// This is user-level install and there is a system-level chrome
// installation. Instruct Omaha to launch the existing one. There
// should be no error dialog.
- FilePath chrome_exe(installer::GetChromeInstallPath(
- !product->system_level(), browser_dist));
+ FilePath chrome_exe(installer::GetChromeInstallPath(!system_level,
+ browser_dist));
if (chrome_exe.empty()) {
// If we failed to construct install path. Give up.
status = installer::OS_ERROR;
@@ -220,12 +222,10 @@ bool CheckPreInstallConditions(const Package& installation,
// This is an update, not an install. Omaha should know the difference
// and not show a dialog.
- status = product->system_level() ?
- installer::USER_LEVEL_INSTALL_EXISTS :
- installer::SYSTEM_LEVEL_INSTALL_EXISTS;
- int str_id = product->system_level() ?
- IDS_INSTALL_USER_LEVEL_EXISTS_BASE :
- IDS_INSTALL_SYSTEM_LEVEL_EXISTS_BASE;
+ 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;
product->WriteInstallerResult(status, str_id, NULL);
return false;
}
@@ -384,7 +384,7 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
prefs.GetBool(
installer::master_preferences::kDoNotLaunchChrome,
&do_not_launch_chrome);
- if (!chrome_install->system_level() && !do_not_launch_chrome)
+ if (!installation.system_level() && !do_not_launch_chrome)
chrome_install->LaunchChrome();
}
} else if ((install_status == installer::NEW_VERSION_UPDATED) ||
@@ -406,7 +406,7 @@ installer::InstallStatus InstallChrome(const CommandLine& cmd_line,
for (size_t i = 0; i < products.size(); ++i) {
const Product* product = products[i];
product->distribution()->LaunchUserExperiment(install_status,
- *installer_version, *product, product->system_level());
+ *installer_version, *product, installation.system_level());
}
}
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 07925a0..703fec6 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -540,8 +540,7 @@ InstallStatus UninstallChrome(const FilePath& setup_path,
// Get the version of installed Chrome (if any)
scoped_ptr<installer::Version>
- installed_version(InstallUtil::GetChromeVersion(browser_dist,
- product.system_level()));
+ installed_version(product.GetInstalledVersion());
// Chrome is not in use so lets uninstall Chrome by deleting various files
// and registry entries. Here we will just make best effort and keep going
diff --git a/chrome/installer/util/chrome_frame_distribution.cc b/chrome/installer/util/chrome_frame_distribution.cc
index 49c8827..20698da 100644
--- a/chrome/installer/util/chrome_frame_distribution.cc
+++ b/chrome/installer/util/chrome_frame_distribution.cc
@@ -36,13 +36,13 @@ std::wstring ChromeFrameDistribution::GetAppGuid() {
std::wstring ChromeFrameDistribution::GetApplicationName() {
const std::wstring& product_name =
- installer::GetLocalizedString(IDS_PRODUCT_FRAME_NAME_BASE);
+ installer::GetLocalizedString(IDS_PRODUCT_FRAME_NAME_BASE);
return product_name;
}
std::wstring ChromeFrameDistribution::GetAlternateApplicationName() {
const std::wstring& product_name =
- installer::GetLocalizedString(IDS_PRODUCT_FRAME_NAME_BASE);
+ installer::GetLocalizedString(IDS_PRODUCT_FRAME_NAME_BASE);
return product_name;
}
diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h
index 6dd0f6b..5ac4835 100644
--- a/chrome/installer/util/google_chrome_distribution.h
+++ b/chrome/installer/util/google_chrome_distribution.h
@@ -79,10 +79,10 @@ class GoogleChromeDistribution : public BrowserDistribution {
virtual void InactiveUserToastExperiment(int flavor,
const installer::Product& installation);
- std::wstring product_guid() { return product_guid_; }
+ const std::wstring& product_guid() { return product_guid_; }
protected:
- void set_product_guid(std::wstring guid) { product_guid_ = guid; }
+ void set_product_guid(const std::wstring& guid) { product_guid_ = guid; }
// Disallow construction from others.
explicit GoogleChromeDistribution(
diff --git a/chrome/installer/util/helper_unittest.cc b/chrome/installer/util/helper_unittest.cc
index b194030..64139cf 100644
--- a/chrome/installer/util/helper_unittest.cc
+++ b/chrome/installer/util/helper_unittest.cc
@@ -13,10 +13,12 @@
#include "base/string_util.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/package.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/version.h"
#include "chrome/installer/util/work_item.h"
#include "testing/gtest/include/gtest/gtest.h"
+using installer::ChromePackageProperties;
using installer::Package;
using installer::Version;
@@ -109,7 +111,8 @@ TEST_F(SetupHelperTest, Delete) {
ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
scoped_ptr<Version> latest_version(Version::GetVersionFromString(L"1.0.4.0"));
- scoped_refptr<Package> package(new Package(chrome_dir));
+ ChromePackageProperties properties;
+ scoped_refptr<Package> package(new Package(true, chrome_dir, &properties));
package->RemoveOldVersionDirectories(*latest_version.get());
// old versions should be gone
@@ -183,7 +186,9 @@ TEST_F(SetupHelperTest, DeleteInUsed) {
ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
scoped_ptr<Version> latest_version(Version::GetVersionFromString(L"1.0.4.0"));
- scoped_refptr<Package> install_path(new Package(chrome_dir));
+ ChromePackageProperties properties;
+ scoped_refptr<Package> install_path(new Package(true, chrome_dir,
+ &properties));
install_path->RemoveOldVersionDirectories(*latest_version.get());
// old versions not in used should be gone
diff --git a/chrome/installer/util/package.cc b/chrome/installer/util/package.cc
index cc94cd6..998dbc6d 100644
--- a/chrome/installer/util/package.cc
+++ b/chrome/installer/util/package.cc
@@ -9,13 +9,17 @@
#include "base/win/registry.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/product.h"
using base::win::RegKey;
namespace installer {
-Package::Package(const FilePath& path) : path_(path) {
+Package::Package(bool system_level, const FilePath& path,
+ PackageProperties* properties)
+ : system_level_(system_level), path_(path), properties_(properties) {
+ DCHECK(properties_);
}
Package::~Package() {
@@ -29,6 +33,10 @@ const Products& Package::products() const {
return products_;
}
+PackageProperties* Package::properties() const {
+ return properties_;
+}
+
bool Package::IsEqual(const FilePath& path) const {
return FilePath::CompareEqualIgnoreCase(path_.value(), path.value());
}
@@ -36,7 +44,6 @@ bool Package::IsEqual(const FilePath& path) const {
void Package::AssociateProduct(const Product* product) {
#ifndef NDEBUG
for (size_t i = 0; i < products_.size(); ++i) {
- DCHECK_EQ(product->system_level(), products_[i]->system_level());
DCHECK_NE(product->distribution()->GetType(),
products_[i]->distribution()->GetType());
}
@@ -45,14 +52,7 @@ void Package::AssociateProduct(const Product* product) {
}
bool Package::system_level() const {
- // Convenience getter that returns the system_level value of the first
- // product for this folder. All distributions must have the same
- // value, so the function also checks this in debug builds.
- if (!products_.size()) {
- NOTREACHED() << "this should not be possible";
- return false;
- }
- return products_[0]->system_level();
+ return system_level_;
}
FilePath Package::GetInstallerDirectory(
@@ -68,10 +68,10 @@ Version* Package::GetCurrentVersion() const {
FilePath new_chrome_exe(path_.Append(installer::kChromeNewExe));
bool new_chrome_exists = file_util::PathExists(new_chrome_exe);
+ HKEY root = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+
for (size_t i = 0; i < products_.size(); ++i) {
const Product* product = products_[i];
- HKEY root = product->system_level() ? HKEY_LOCAL_MACHINE :
- HKEY_CURRENT_USER;
RegKey chrome_key(root, product->distribution()->GetVersionKey().c_str(),
KEY_READ);
std::wstring version;
diff --git a/chrome/installer/util/package.h b/chrome/installer/util/package.h
index c7318e1..8d2af0c 100644
--- a/chrome/installer/util/package.h
+++ b/chrome/installer/util/package.h
@@ -17,6 +17,7 @@ namespace installer {
class Product;
class Version;
+class PackageProperties;
typedef std::vector<scoped_refptr<const Product> > Products;
@@ -25,21 +26,24 @@ typedef std::vector<scoped_refptr<const Product> > Products;
// not vice versa.
class Package : public base::RefCounted<Package> {
public:
- explicit Package(const FilePath& path);
+ Package(bool system_level, const FilePath& path,
+ PackageProperties* properties);
// Returns the path of the installation folder.
const FilePath& path() const;
const Products& products() const;
+ PackageProperties* properties() const;
+
bool system_level() const;
bool IsEqual(const FilePath& path) const;
- void AssociateProduct(const Product* distribution);
+ void AssociateProduct(const Product* product);
// Get path to the installer under Chrome version folder
- // (for example <path>\Google\Chrome\<Version>\installer)
+ // (for example <path>\Google\Chrome\Application\<Version>\Installer)
FilePath GetInstallerDirectory(const Version& version) const;
// Figure out the oldest currently installed version for this package
@@ -58,8 +62,10 @@ class Package : public base::RefCounted<Package> {
void RemoveOldVersionDirectories(const Version& latest_version) const;
protected:
+ bool system_level_;
FilePath path_;
Products products_;
+ PackageProperties* properties_; // Weak reference.
private:
friend class base::RefCounted<Package>;
diff --git a/chrome/installer/util/package_properties.cc b/chrome/installer/util/package_properties.cc
new file mode 100644
index 0000000..702688e
--- /dev/null
+++ b/chrome/installer/util/package_properties.cc
@@ -0,0 +1,82 @@
+// 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/package_properties.h"
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/util_constants.h"
+
+using installer::InstallStatus;
+
+namespace {
+// TODO(tommi): Use google_update::kMultiInstallAppGuid
+const wchar_t kChromePackageGuid[] =
+ L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
+
+std::wstring GetStateKeyForGuid(const wchar_t* guid) {
+ std::wstring key(google_update::kRegPathClientState);
+ key.append(L"\\");
+ key.append(guid);
+ return key;
+}
+
+std::wstring GetVersionKeyForGuid(const wchar_t* guid) {
+ std::wstring key(google_update::kRegPathClients);
+ key.append(L"\\");
+ key.append(guid);
+ return key;
+}
+
+} // end namespace
+
+namespace installer {
+
+const char PackageProperties::kPackageProductName[] = "Chrome binaries";
+
+PackagePropertiesImpl::PackagePropertiesImpl(const wchar_t* guid,
+ const std::wstring& state_key,
+ const std::wstring& version_key)
+ : guid_(guid), state_key_(state_key), version_key_(version_key) {
+}
+
+PackagePropertiesImpl::~PackagePropertiesImpl() {
+}
+
+const std::wstring& PackagePropertiesImpl::GetStateKey() {
+ return state_key_;
+}
+
+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, BrowserDistribution::GetInstallReturnCode(status),
+ guid_);
+}
+
+ChromiumPackageProperties::ChromiumPackageProperties()
+ : PackagePropertiesImpl(L"", L"Software\\Chromium", L"Software\\Chromium") {
+}
+
+ChromiumPackageProperties::~ChromiumPackageProperties() {
+}
+
+ChromePackageProperties::ChromePackageProperties()
+ : PackagePropertiesImpl(kChromePackageGuid,
+ GetStateKeyForGuid(kChromePackageGuid),
+ GetVersionKeyForGuid(kChromePackageGuid)) {
+}
+
+ChromePackageProperties::~ChromePackageProperties() {
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/package_properties.h b/chrome/installer/util/package_properties.h
new file mode 100644
index 0000000..bced0d9
--- /dev/null
+++ b/chrome/installer/util/package_properties.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_PACKAGE_PROPERTIES_H_
+#define CHROME_INSTALLER_UTIL_PACKAGE_PROPERTIES_H_
+#pragma once
+
+#include <windows.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace installer {
+enum InstallStatus;
+};
+
+namespace installer {
+
+// Pure virtual interface that exposes properties of a package installation.
+// A package represents a set of binaries on disk that can be shared by two or
+// more products. Also see the Package class for further details.
+// PackageProperties is comparable to the BrowserDistribution class but the
+// difference is that the BrowserDistribution class represents a product
+// installation whereas PackageProperties represents a package
+// (horizontal vs vertical).
+class PackageProperties {
+ public:
+ PackageProperties() {}
+ virtual ~PackageProperties() {}
+
+ static const char kPackageProductName[];
+
+ // Returns true iff this package will be updated by Omaha.
+ virtual bool ReceivesUpdates() const = 0;
+
+ // Equivalent to BrowserDistribution::GetAppGuid()
+ virtual const std::wstring& GetStateKey() = 0;
+ virtual const std::wstring& GetVersionKey() = 0;
+ virtual void UpdateDiffInstallStatus(bool system_level,
+ bool incremental_install, installer::InstallStatus status) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PackageProperties);
+}; // class PackageProperties
+
+class PackagePropertiesImpl : public PackageProperties {
+ public:
+ explicit PackagePropertiesImpl(const wchar_t* guid,
+ const std::wstring& state_key,
+ const std::wstring& version_key);
+ virtual ~PackagePropertiesImpl();
+
+ virtual const std::wstring& GetStateKey();
+ virtual const std::wstring& GetVersionKey();
+ virtual void UpdateDiffInstallStatus(bool system_level,
+ bool incremental_install, installer::InstallStatus status);
+
+ protected:
+ std::wstring guid_;
+ std::wstring state_key_;
+ std::wstring version_key_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PackagePropertiesImpl);
+}; // class PackagePropertiesImpl
+
+class ChromiumPackageProperties : public PackagePropertiesImpl {
+ public:
+ ChromiumPackageProperties();
+ virtual ~ChromiumPackageProperties();
+
+ virtual bool ReceivesUpdates() const {
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromiumPackageProperties);
+}; // class ChromiumPackageProperties
+
+class ChromePackageProperties : public PackagePropertiesImpl {
+ public:
+ ChromePackageProperties();
+ virtual ~ChromePackageProperties();
+
+ virtual bool ReceivesUpdates() const {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromePackageProperties);
+}; // class ChromePackageProperties
+
+} // 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
new file mode 100644
index 0000000..f1a7cab
--- /dev/null
+++ b/chrome/installer/util/package_properties_unittest.cc
@@ -0,0 +1,57 @@
+// 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 "base/logging.h"
+#include "base/win/registry.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/package_properties.h"
+#include "chrome/installer/util/product_unittest.h"
+#include "chrome/installer/util/util_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::win::RegKey;
+using installer::PackageProperties;
+using installer::ChromePackageProperties;
+using installer::ChromiumPackageProperties;
+
+class PackagePropertiesTest : public testing::Test {
+ protected:
+};
+
+TEST_F(PackagePropertiesTest, Basic) {
+ TempRegKeyOverride::DeleteAllTempKeys();
+ ChromePackageProperties chrome_props;
+ ChromiumPackageProperties chromium_props;
+ PackageProperties* props[] = { &chrome_props, &chromium_props };
+ for (size_t i = 0; i < arraysize(props); ++i) {
+ std::wstring state_key(props[i]->GetStateKey());
+ 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 {
+ TempRegKeyOverride override(HKEY_CURRENT_USER, L"props");
+ RegKey key;
+ EXPECT_TRUE(key.Create(HKEY_CURRENT_USER, state_key.c_str(),
+ KEY_ALL_ACCESS));
+ }
+ TempRegKeyOverride::DeleteAllTempKeys();
+ }
+}
diff --git a/chrome/installer/util/package_unittest.cc b/chrome/installer/util/package_unittest.cc
index 6a83762..c328f9b 100644
--- a/chrome/installer/util/package_unittest.cc
+++ b/chrome/installer/util/package_unittest.cc
@@ -8,6 +8,7 @@
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/package.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/product_unittest.h"
#include "chrome/installer/util/util_constants.h"
@@ -15,6 +16,8 @@
using base::win::RegKey;
using base::win::ScopedHandle;
+using installer::ChromePackageProperties;
+using installer::ChromiumPackageProperties;
using installer::Package;
using installer::Product;
using installer::Version;
@@ -26,7 +29,10 @@ class PackageTest : public TestWithTempDirAndDeleteTempOverrideKeys {
// Tests a few basic things of the Package class. Makes sure that the path
// operations are correct
TEST_F(PackageTest, Basic) {
- scoped_refptr<Package> package(new Package(test_dir_.path()));
+ const bool system_level = true;
+ ChromiumPackageProperties properties;
+ scoped_refptr<Package> package(new Package(system_level, test_dir_.path(),
+ &properties));
EXPECT_EQ(test_dir_.path().value(), package->path().value());
EXPECT_TRUE(package->IsEqual(test_dir_.path()));
EXPECT_EQ(0U, package->products().size());
@@ -95,10 +101,10 @@ TEST_F(PackageTest, WithProduct) {
BrowserDistribution* distribution =
BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER, prefs);
- scoped_refptr<Package> package(new Package(test_dir_.path()));
- scoped_refptr<Product> product(new Product(distribution,
- system_level,
- package.get()));
+ ChromePackageProperties properties;
+ scoped_refptr<Package> package(new Package(system_level, test_dir_.path(),
+ &properties));
+ scoped_refptr<Product> product(new Product(distribution, package.get()));
EXPECT_EQ(1U, package->products().size());
EXPECT_EQ(system_level, package->system_level());
diff --git a/chrome/installer/util/product.cc b/chrome/installer/util/product.cc
index 6565111..3525b8e 100644
--- a/chrome/installer/util/product.cc
+++ b/chrome/installer/util/product.cc
@@ -16,6 +16,7 @@
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/package.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/work_item_list.h"
using base::win::RegKey;
@@ -55,10 +56,8 @@ void WriteInstallerResult(const Products& products,
////////////////////////////////////////////////////////////////////////////////
-Product::Product(BrowserDistribution* distribution, bool system_level,
- Package* package)
+Product::Product(BrowserDistribution* distribution, Package* package)
: distribution_(distribution),
- system_level_(system_level),
package_(package),
msi_(MSI_NOT_CHECKED) {
package_->AssociateProduct(this);
@@ -136,7 +135,7 @@ bool Product::IsMsi() const {
if (!is_msi) {
// We didn't find it in the preferences, try looking in the registry.
- HKEY reg_root = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ HKEY reg_root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
RegKey key;
if (key.Open(reg_root, distribution_->GetStateKey().c_str(), KEY_READ)) {
DWORD msi_value;
@@ -154,7 +153,7 @@ bool Product::IsMsi() const {
bool Product::SetMsiMarker(bool set) const {
bool success = false;
- HKEY reg_root = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ HKEY reg_root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
RegKey client_state_key;
if (client_state_key.Open(reg_root, distribution_->GetStateKey().c_str(),
KEY_READ | KEY_WRITE)) {
@@ -174,7 +173,7 @@ bool Product::SetMsiMarker(bool set) const {
void Product::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;
+ HKEY root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
std::wstring key(distribution_->GetStateKey());
int installer_result = distribution_->GetInstallReturnCode(status) == 0 ?
0 : 1;
@@ -200,12 +199,17 @@ void Product::WriteInstallerResult(
}
Version* Product::GetInstalledVersion() const {
- return InstallUtil::GetChromeVersion(distribution_, system_level_);
+ return InstallUtil::GetChromeVersion(distribution_, system_level());
}
///////////////////////////////////////////////////////////////////////////////
ProductPackageMapping::ProductPackageMapping(bool system_level)
- : system_level_(system_level) {
+#if defined(GOOGLE_CHROME_BUILD)
+ : package_properties_(new ChromePackageProperties()),
+#else
+ : package_properties_(new ChromiumPackageProperties()),
+#endif
+ system_level_(system_level) {
}
const Packages& ProductPackageMapping::packages() const {
@@ -234,12 +238,12 @@ bool ProductPackageMapping::AddDistribution(BrowserDistribution* distribution) {
if (!target_package.get()) {
// create new one and add.
- target_package = new Package(install_package);
+ target_package = new Package(system_level_, install_package,
+ package_properties_.get());
packages_.push_back(target_package);
}
- scoped_refptr<Product> product(
- new Product(distribution, system_level_, target_package));
+ scoped_refptr<Product> product(new Product(distribution, target_package));
#ifndef NDEBUG
for (size_t i = 0; i < products_.size(); ++i) {
DCHECK_EQ(product->IsMsi(), products_[i]->IsMsi());
diff --git a/chrome/installer/util/product.h b/chrome/installer/util/product.h
index 45ee2c2..aa1f1e5 100644
--- a/chrome/installer/util/product.h
+++ b/chrome/installer/util/product.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/package.h"
@@ -22,6 +23,7 @@ namespace installer {
class Product;
class Package;
+class PackageProperties;
class Version;
typedef std::vector<scoped_refptr<Package> > Packages;
@@ -47,23 +49,23 @@ void WriteInstallerResult(const Products& products,
// distribution specific functionality.
class Product : public base::RefCounted<Product> {
public:
- Product(BrowserDistribution* distribution, bool system_level,
- Package* installation_package);
+ Product(BrowserDistribution* distribution, Package* installation_package);
BrowserDistribution* distribution() const {
return distribution_;
}
- bool system_level() const {
- return system_level_;
- }
-
// Returns the install package object for the installation of this product.
// If the product is installed at system level,the function returns a system
// wide location (ProgramFiles\Google). Otherwise it returns a package in a
// user specific location (Users\<user>\Local Settings...)
const Package& package() const;
+ // Convenience getter for package().system_level().
+ bool system_level() const {
+ return package().system_level();
+ }
+
// Returns the path to the directory that holds the user data. This is always
// inside "Users\<user>\Local Settings". Note that this is the default user
// data directory and does not take into account that it can be overriden with
@@ -108,7 +110,6 @@ class Product : public base::RefCounted<Product> {
protected:
BrowserDistribution* distribution_;
scoped_refptr<Package> package_;
- bool system_level_;
mutable enum MsiState {
MSI_NOT_CHECKED,
IS_MSI,
@@ -146,6 +147,7 @@ class ProductPackageMapping {
bool system_level_;
Packages packages_;
Products products_;
+ scoped_ptr<PackageProperties> package_properties_;
private:
DISALLOW_COPY_AND_ASSIGN(ProductPackageMapping);
diff --git a/chrome/installer/util/product_unittest.cc b/chrome/installer/util/product_unittest.cc
index 4b73b7a..992bd4d 100644
--- a/chrome/installer/util/product_unittest.cc
+++ b/chrome/installer/util/product_unittest.cc
@@ -8,11 +8,15 @@
#include "base/scoped_handle.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/package.h"
+#include "chrome/installer/util/package_properties.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/product.h"
using base::win::RegKey;
using base::win::ScopedHandle;
+using installer::ChromePackageProperties;
+using installer::ChromiumPackageProperties;
using installer::Package;
using installer::Product;
using installer::ProductPackageMapping;
@@ -83,11 +87,11 @@ TEST_F(ProductTest, ProductInstallBasic) {
BrowserDistribution* distribution =
BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER, prefs);
- scoped_refptr<Package> package(new Package(test_dir_.path()));
- scoped_refptr<Product> product(new Product(distribution, system_level,
- package.get()));
+ ChromePackageProperties properties;
+ scoped_refptr<Package> package(new Package(system_level, test_dir_.path(),
+ &properties));
+ scoped_refptr<Product> product(new Product(distribution, package.get()));
- EXPECT_EQ(system_level, product->system_level());
FilePath user_data(product->GetUserDataPath());
EXPECT_FALSE(user_data.empty());
EXPECT_NE(std::wstring::npos,
@@ -115,8 +119,8 @@ TEST_F(ProductTest, ProductInstallBasic) {
// Set the MSI marker, delete the objects, create new ones and verify
// that we now see the MSI marker.
EXPECT_TRUE(product->SetMsiMarker(true));
- package = new Package(test_dir_.path());
- product = new Product(distribution, system_level, package.get());
+ package = new Package(system_level, test_dir_.path(), &properties);
+ product = new Product(distribution, package.get());
EXPECT_TRUE(product->IsMsi());
// See if WriteInstallerResult writes anything.