diff options
-rw-r--r-- | chrome/chrome_installer.gypi | 1 | ||||
-rw-r--r-- | chrome/chrome_installer_util.gypi | 2 | ||||
-rw-r--r-- | chrome/installer/setup/install.cc | 56 | ||||
-rw-r--r-- | chrome/installer/setup/setup_main.cc | 28 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.cc | 3 | ||||
-rw-r--r-- | chrome/installer/util/chrome_frame_distribution.cc | 4 | ||||
-rw-r--r-- | chrome/installer/util/google_chrome_distribution.h | 4 | ||||
-rw-r--r-- | chrome/installer/util/helper_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/installer/util/package.cc | 24 | ||||
-rw-r--r-- | chrome/installer/util/package.h | 12 | ||||
-rw-r--r-- | chrome/installer/util/package_properties.cc | 82 | ||||
-rw-r--r-- | chrome/installer/util/package_properties.h | 97 | ||||
-rw-r--r-- | chrome/installer/util/package_properties_unittest.cc | 57 | ||||
-rw-r--r-- | chrome/installer/util/package_unittest.cc | 16 | ||||
-rw-r--r-- | chrome/installer/util/product.cc | 26 | ||||
-rw-r--r-- | chrome/installer/util/product.h | 16 | ||||
-rw-r--r-- | chrome/installer/util/product_unittest.cc | 16 |
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. |