summaryrefslogtreecommitdiffstats
path: root/chrome/installer/util
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 16:44:37 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 16:44:37 +0000
commitf0260d27d34e40f2e619fb7a16dcd7f9d63fc683 (patch)
tree7e7c9e83bbd2f67b4bbbe11d076c7cc70abd8855 /chrome/installer/util
parentce7937429f63f3d966346fcd973d720f268cd888 (diff)
downloadchromium_src-f0260d27d34e40f2e619fb7a16dcd7f9d63fc683.zip
chromium_src-f0260d27d34e40f2e619fb7a16dcd7f9d63fc683.tar.gz
chromium_src-f0260d27d34e40f2e619fb7a16dcd7f9d63fc683.tar.bz2
More installer refactoring in the interest of fixing some bugs and cleaning things up:
- Introduced ProductOperations: an interface implemented for each product that takes care of product-specific functions. Each Product owns an instance and delegates certain operations to it. - Removed the use of MasterPreferences by BrowserDistribution so that the former isn't needed outside of the installer. - Replaced PackageProperties with a new BrowserDistribution type (CHROME_BINARIES) - Plumbed the concept of InstallerState more thoroughly through installer - Removed ProductPackageMapping and Package - Moved more registry read ops into ProductState - Validation of products to be installed is now done in CheckPreInstallConditions - Ignore --chrome-frame --ready-mode if chrome is also being installed/updated and a SxS GCF is found (chrome is updated). - Migrates existing single-install Chrome to multi-install where appropriate. - Fixes update to Chrome's uninstallation arguments when Chrome Frame is uninstalled. - Removed dead code from install.cc. - Added code to update products' "ap" values when ready-mode is accepted. - Skip post-install things such as launching the browser when Chrome was implicitly added to the install/upgrade process by virtue of being part of a multi-install. BUG=61609 TEST=run the installer, see it work. existing tests in installer_util_unittests have been updated; new tests are included for ProductState, ChannelInfo, etc. Review URL: http://codereview.chromium.org/6288009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72497 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer/util')
-rw-r--r--chrome/installer/util/browser_distribution.cc92
-rw-r--r--chrome/installer/util/browser_distribution.h40
-rw-r--r--chrome/installer/util/browser_distribution_unittest.cc22
-rw-r--r--chrome/installer/util/channel_info.cc12
-rw-r--r--chrome/installer/util/channel_info.h4
-rw-r--r--chrome/installer/util/channel_info_unittest.cc36
-rw-r--r--chrome/installer/util/chrome_browser_operations.cc82
-rw-r--r--chrome/installer/util/chrome_browser_operations.h54
-rw-r--r--chrome/installer/util/chrome_browser_sxs_operations.cc22
-rw-r--r--chrome/installer/util/chrome_browser_sxs_operations.h33
-rw-r--r--chrome/installer/util/chrome_frame_distribution.cc94
-rw-r--r--chrome/installer/util/chrome_frame_distribution.h20
-rw-r--r--chrome/installer/util/chrome_frame_operations.cc148
-rw-r--r--chrome/installer/util/chrome_frame_operations.h58
-rw-r--r--chrome/installer/util/chromium_binaries_distribution.cc105
-rw-r--r--chrome/installer/util/chromium_binaries_distribution.h64
-rw-r--r--chrome/installer/util/google_chrome_binaries_distribution.cc56
-rw-r--r--chrome/installer/util/google_chrome_binaries_distribution.h38
-rw-r--r--chrome/installer/util/google_chrome_distribution.cc18
-rw-r--r--chrome/installer/util/google_chrome_distribution.h8
-rw-r--r--chrome/installer/util/google_chrome_distribution_dummy.cc15
-rw-r--r--chrome/installer/util/google_chrome_distribution_unittest.cc6
-rw-r--r--chrome/installer/util/google_chrome_sxs_distribution.cc13
-rw-r--r--chrome/installer/util/google_chrome_sxs_distribution.h4
-rw-r--r--chrome/installer/util/google_update_settings.cc40
-rw-r--r--chrome/installer/util/google_update_settings.h4
-rw-r--r--chrome/installer/util/google_update_settings_unittest.cc46
-rw-r--r--chrome/installer/util/helper.cc107
-rw-r--r--chrome/installer/util/helper.h27
-rw-r--r--chrome/installer/util/helper_unittest.cc204
-rw-r--r--chrome/installer/util/install_util.cc26
-rw-r--r--chrome/installer/util/install_util.h12
-rw-r--r--chrome/installer/util/install_util_unittest.cc47
-rw-r--r--chrome/installer/util/installation_state.cc140
-rw-r--r--chrome/installer/util/installation_state.h77
-rw-r--r--chrome/installer/util/installer_state.cc385
-rw-r--r--chrome/installer/util/installer_state.h148
-rw-r--r--chrome/installer/util/installer_state_unittest.cc327
-rw-r--r--chrome/installer/util/package.cc188
-rw-r--r--chrome/installer/util/package.h90
-rw-r--r--chrome/installer/util/package_properties.cc94
-rw-r--r--chrome/installer/util/package_properties.h109
-rw-r--r--chrome/installer/util/package_properties_unittest.cc40
-rw-r--r--chrome/installer/util/package_unittest.cc190
-rw-r--r--chrome/installer/util/product.cc189
-rw-r--r--chrome/installer/util/product.h122
-rw-r--r--chrome/installer/util/product_operations.h74
-rw-r--r--chrome/installer/util/product_state_unittest.cc416
-rw-r--r--chrome/installer/util/product_unittest.cc129
-rw-r--r--chrome/installer/util/util_constants.cc4
-rw-r--r--chrome/installer/util/util_constants.h8
51 files changed, 2536 insertions, 1751 deletions
diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc
index 4387b51..be452c5 100644
--- a/chrome/installer/util/browser_distribution.cc
+++ b/chrome/installer/util/browser_distribution.cc
@@ -17,7 +17,9 @@
#include "base/win/registry.h"
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/chrome_frame_distribution.h"
+#include "chrome/installer/util/chromium_binaries_distribution.h"
#include "chrome/installer/util/google_chrome_distribution.h"
+#include "chrome/installer/util/google_chrome_binaries_distribution.h"
#include "chrome/installer/util/google_chrome_sxs_distribution.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/l10n_string_util.h"
@@ -31,6 +33,7 @@ namespace {
// The BrowserDistribution objects are never freed.
BrowserDistribution* g_browser_distribution = NULL;
BrowserDistribution* g_chrome_frame_distribution = NULL;
+BrowserDistribution* g_binaries_distribution = NULL;
// Returns true if currently running in npchrome_frame.dll
bool IsChromeFrameModule() {
@@ -59,17 +62,19 @@ BrowserDistribution::Type GetCurrentDistributionType() {
} // end namespace
-BrowserDistribution::BrowserDistribution(
- const installer::MasterPreferences& prefs)
- : type_(BrowserDistribution::CHROME_BROWSER) {
+BrowserDistribution::BrowserDistribution()
+ : type_(CHROME_BROWSER) {
+}
+
+BrowserDistribution::BrowserDistribution(Type type)
+ : type_(type) {
}
template<class DistributionClass>
BrowserDistribution* BrowserDistribution::GetOrCreateBrowserDistribution(
- const installer::MasterPreferences& prefs,
BrowserDistribution** dist) {
if (!*dist) {
- DistributionClass* temp = new DistributionClass(prefs);
+ DistributionClass* temp = new DistributionClass();
if (base::subtle::NoBarrier_CompareAndSwap(
reinterpret_cast<base::subtle::AtomicWord*>(dist), NULL,
reinterpret_cast<base::subtle::AtomicWord>(temp)) != NULL)
@@ -80,33 +85,43 @@ BrowserDistribution* BrowserDistribution::GetOrCreateBrowserDistribution(
}
BrowserDistribution* BrowserDistribution::GetDistribution() {
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
- return GetSpecificDistribution(GetCurrentDistributionType(), prefs);
+ return GetSpecificDistribution(GetCurrentDistributionType());
}
// static
BrowserDistribution* BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::Type type,
- const installer::MasterPreferences& prefs) {
+ BrowserDistribution::Type type) {
BrowserDistribution* dist = NULL;
- if (type == CHROME_FRAME) {
- dist = GetOrCreateBrowserDistribution<ChromeFrameDistribution>(
- prefs, &g_chrome_frame_distribution);
- } else {
- DCHECK_EQ(CHROME_BROWSER, type);
+ switch (type) {
+ case CHROME_BROWSER:
+#if defined(GOOGLE_CHROME_BUILD)
+ if (InstallUtil::IsChromeSxSProcess()) {
+ dist = GetOrCreateBrowserDistribution<GoogleChromeSxSDistribution>(
+ &g_browser_distribution);
+ } else {
+ dist = GetOrCreateBrowserDistribution<GoogleChromeDistribution>(
+ &g_browser_distribution);
+ }
+#else
+ dist = GetOrCreateBrowserDistribution<BrowserDistribution>(
+ &g_browser_distribution);
+#endif
+ break;
+
+ case CHROME_FRAME:
+ dist = GetOrCreateBrowserDistribution<ChromeFrameDistribution>(
+ &g_chrome_frame_distribution);
+ break;
+
+ default:
+ DCHECK_EQ(CHROME_BINARIES, type);
#if defined(GOOGLE_CHROME_BUILD)
- if (InstallUtil::IsChromeSxSProcess()) {
- dist = GetOrCreateBrowserDistribution<GoogleChromeSxSDistribution>(
- prefs, &g_browser_distribution);
- } else {
- dist = GetOrCreateBrowserDistribution<GoogleChromeDistribution>(
- prefs, &g_browser_distribution);
- }
+ dist = GetOrCreateBrowserDistribution<GoogleChromeBinariesDistribution>(
+ &g_binaries_distribution);
#else
- dist = GetOrCreateBrowserDistribution<BrowserDistribution>(
- prefs, &g_browser_distribution);
+ dist = GetOrCreateBrowserDistribution<ChromiumBinariesDistribution>(
+ &g_binaries_distribution);
#endif
}
@@ -212,31 +227,6 @@ void BrowserDistribution::LaunchUserExperiment(
void BrowserDistribution::InactiveUserToastExperiment(int flavor,
- const installer::Product& installation) {
-}
-
-std::vector<FilePath> BrowserDistribution::GetKeyFiles() {
- std::vector<FilePath> key_files;
- key_files.push_back(FilePath(installer::kChromeDll));
- return key_files;
-}
-
-std::vector<FilePath> BrowserDistribution::GetComDllList() {
- return std::vector<FilePath>();
-}
-
-void BrowserDistribution::AppendUninstallCommandLineFlags(
- CommandLine* cmd_line) {
- DCHECK(cmd_line);
- cmd_line->AppendSwitch(installer::switches::kChrome);
-}
-
-bool BrowserDistribution::ShouldCreateUninstallEntry() {
- return true;
-}
-
-bool BrowserDistribution::SetChannelFlags(
- bool set,
- installer::ChannelInfo* channel_info) {
- return false;
+ const installer::Product& installation,
+ const FilePath& application_path) {
}
diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h
index 1f6a1c9..3fb1ded 100644
--- a/chrome/installer/util/browser_distribution.h
+++ b/chrome/installer/util/browser_distribution.h
@@ -35,12 +35,12 @@ class BrowserDistribution {
enum Type {
CHROME_BROWSER,
CHROME_FRAME,
+ CHROME_BINARIES,
};
static BrowserDistribution* GetDistribution();
- static BrowserDistribution* GetSpecificDistribution(
- Type type, const installer::MasterPreferences& prefs);
+ static BrowserDistribution* GetSpecificDistribution(Type type);
Type GetType() const { return type_; }
@@ -104,45 +104,21 @@ class BrowserDistribution {
// The user has qualified for the inactive user toast experiment and this
// function just performs it.
virtual void InactiveUserToastExperiment(int flavor,
- const installer::Product& installation);
-
- // A key-file is a file such as a DLL on Windows that is expected to be
- // in use when the product is being used. For example "chrome.dll" for
- // Chrome. Before attempting to delete an installation directory during
- // an uninstallation, the uninstaller will check if any one of a potential
- // set of key files is in use and if they are, abort the delete operation.
- // Only if none of the key files are in use, can the folder be deleted.
- // Note that this function does not return a full path to the key file(s),
- // only (a) file name(s).
- virtual std::vector<FilePath> GetKeyFiles();
-
- // Returns the list of Com Dlls that this product cares about having
- // registered and unregistered. The list may be empty.
- virtual std::vector<FilePath> GetComDllList();
-
- // Given a command line, appends the set of uninstall flags the uninstaller
- // for this distribution will require.
- virtual void AppendUninstallCommandLineFlags(CommandLine* cmd_line);
-
- // Returns true if install should create an uninstallation entry in the
- // 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);
+ const installer::Product& installation,
+ const FilePath& application_path);
protected:
- explicit BrowserDistribution(const installer::MasterPreferences& prefs);
+ explicit BrowserDistribution(Type type);
template<class DistributionClass>
static BrowserDistribution* GetOrCreateBrowserDistribution(
- const installer::MasterPreferences& prefs,
BrowserDistribution** dist);
- Type type_;
+ const Type type_;
private:
+ BrowserDistribution();
+
DISALLOW_COPY_AND_ASSIGN(BrowserDistribution);
};
diff --git a/chrome/installer/util/browser_distribution_unittest.cc b/chrome/installer/util/browser_distribution_unittest.cc
index f35ad3f..61c9652 100644
--- a/chrome/installer/util/browser_distribution_unittest.cc
+++ b/chrome/installer/util/browser_distribution_unittest.cc
@@ -5,7 +5,6 @@
// Unit tests for BrowserDistribution class.
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/shell_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,21 +24,14 @@ class BrowserDistributionTest : public testing::Test {
// The distribution strings should not be empty. The unit tests are not linking
// with the chrome resources so we cannot test official build.
TEST(BrowserDistributionTest, StringsTest) {
- struct browser_test_type {
- BrowserDistribution::Type type;
- bool has_com_dlls;
- } browser_tests[] = {
- { BrowserDistribution::CHROME_BROWSER, false },
- { BrowserDistribution::CHROME_FRAME, true },
+ BrowserDistribution::Type browser_tests[] = {
+ BrowserDistribution::CHROME_BROWSER,
+ BrowserDistribution::CHROME_FRAME,
};
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
-
for (int i = 0; i < arraysize(browser_tests); ++i) {
BrowserDistribution* dist =
- BrowserDistribution::GetSpecificDistribution(browser_tests[i].type,
- prefs);
+ BrowserDistribution::GetSpecificDistribution(browser_tests[i]);
ASSERT_TRUE(dist != NULL);
std::wstring name = dist->GetApplicationName();
EXPECT_FALSE(name.empty());
@@ -47,12 +39,6 @@ TEST(BrowserDistributionTest, StringsTest) {
EXPECT_FALSE(desc.empty());
std::wstring alt_name = dist->GetAlternateApplicationName();
EXPECT_FALSE(alt_name.empty());
- std::vector<FilePath> com_dlls(dist->GetComDllList());
- if (browser_tests[i].has_com_dlls) {
- EXPECT_FALSE(com_dlls.empty());
- } else {
- EXPECT_TRUE(com_dlls.empty());
- }
}
}
diff --git a/chrome/installer/util/channel_info.cc b/chrome/installer/util/channel_info.cc
index 4abcb70..98f54d8 100644
--- a/chrome/installer/util/channel_info.cc
+++ b/chrome/installer/util/channel_info.cc
@@ -153,6 +153,18 @@ bool ChannelInfo::GetChannelName(std::wstring* channel_name) const {
return false;
}
+bool ChannelInfo::EqualsBaseOf(const ChannelInfo& other) const {
+ std::wstring::size_type this_base_end;
+ std::wstring::size_type other_base_end;
+
+ if (!FindModifier(MOD_MULTI_INSTALL, value_, &this_base_end))
+ this_base_end = FindInsertionPoint(MOD_MULTI_INSTALL, value_);
+ if (!FindModifier(MOD_MULTI_INSTALL, other.value_, &other_base_end))
+ other_base_end = FindInsertionPoint(MOD_MULTI_INSTALL, other.value_);
+ return value_.compare(0, this_base_end,
+ other.value_.c_str(), other_base_end) == 0;
+}
+
bool ChannelInfo::IsCeee() const {
return HasModifier(MOD_CEEE, value_);
}
diff --git a/chrome/installer/util/channel_info.h b/chrome/installer/util/channel_info.h
index 7954e1c..a5b895d 100644
--- a/chrome/installer/util/channel_info.h
+++ b/chrome/installer/util/channel_info.h
@@ -41,6 +41,10 @@ class ChannelInfo {
// determined.
bool GetChannelName(std::wstring* channel_name) const;
+ // Returns true if this object and |other| have a common base (that which
+ // remains when all modifiers and suffixes are omitted).
+ bool EqualsBaseOf(const ChannelInfo& other) const;
+
// Returns true if the -CEEE modifier is present in the value.
bool IsCeee() const;
diff --git a/chrome/installer/util/channel_info_unittest.cc b/chrome/installer/util/channel_info_unittest.cc
index febc33a..5c03040 100644
--- a/chrome/installer/util/channel_info_unittest.cc
+++ b/chrome/installer/util/channel_info_unittest.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
+#include "base/basictypes.h"
#include "chrome/installer/util/channel_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -158,3 +161,36 @@ TEST(ChannelInfoTest, Combinations) {
ci.set_value(L"2.0-beta-chromeframe-chrome");
EXPECT_TRUE(ci.IsChrome());
}
+
+TEST(ChannelInfoTest, EqualsBaseOf) {
+ installer::ChannelInfo ci1;
+ installer::ChannelInfo ci2;
+
+ std::pair<std::wstring, std::wstring> trues[] = {
+ std::make_pair(std::wstring(L""), std::wstring(L"")),
+ std::make_pair(std::wstring(L"2.0-beta"), std::wstring(L"2.0-beta")),
+ std::make_pair(std::wstring(L"-full"), std::wstring(L"-full")),
+ std::make_pair(std::wstring(L""), std::wstring(L"-multi"))
+ };
+ for (int i = 0; i < arraysize(trues); ++i) {
+ std::pair<std::wstring, std::wstring>& the_pair = trues[i];
+ ci1.set_value(the_pair.first);
+ ci2.set_value(the_pair.second);
+ EXPECT_TRUE(ci1.EqualsBaseOf(ci2)) << the_pair.first << " "
+ << the_pair.second;
+ }
+
+ std::pair<std::wstring, std::wstring> falses[] = {
+ std::make_pair(std::wstring(L""), std::wstring(L"2.0-beta")),
+ std::make_pair(std::wstring(L"2.0-gamma"), std::wstring(L"2.0-beta")),
+ std::make_pair(std::wstring(L"spam-full"), std::wstring(L"-full")),
+ std::make_pair(std::wstring(L"multi"), std::wstring(L"-multi"))
+ };
+ for (int i = 0; i < arraysize(falses); ++i) {
+ std::pair<std::wstring, std::wstring>& the_pair = falses[i];
+ ci1.set_value(the_pair.first);
+ ci2.set_value(the_pair.second);
+ EXPECT_FALSE(ci1.EqualsBaseOf(ci2)) << the_pair.first << " "
+ << the_pair.second;
+ }
+}
diff --git a/chrome/installer/util/chrome_browser_operations.cc b/chrome/installer/util/chrome_browser_operations.cc
new file mode 100644
index 0000000..c4acd5c
--- /dev/null
+++ b/chrome/installer/util/chrome_browser_operations.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 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/chrome_browser_operations.h"
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/channel_info.h"
+#include "chrome/installer/util/helper.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/master_preferences_constants.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace installer {
+
+void ChromeBrowserOperations::ReadOptions(
+ const MasterPreferences& prefs,
+ std::set<std::wstring>* options) const {
+ DCHECK(options);
+
+ bool pref_value;
+
+ if (prefs.GetBool(master_preferences::kMultiInstall, &pref_value) &&
+ pref_value) {
+ options->insert(kOptionMultiInstall);
+ }
+}
+
+void ChromeBrowserOperations::ReadOptions(
+ const CommandLine& uninstall_command,
+ std::set<std::wstring>* options) const {
+ DCHECK(options);
+
+ if (uninstall_command.HasSwitch(switches::kMultiInstall))
+ options->insert(kOptionMultiInstall);
+}
+
+void ChromeBrowserOperations::AddKeyFiles(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* key_files) const {
+ DCHECK(key_files);
+ key_files->push_back(FilePath(installer::kChromeDll));
+}
+
+void ChromeBrowserOperations::AddComDllList(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* com_dll_list) const {
+}
+
+void ChromeBrowserOperations::AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const {
+ DCHECK(uninstall_command);
+
+ if (options.find(kOptionMultiInstall) != options.end()) {
+ if (!uninstall_command->HasSwitch(switches::kMultiInstall))
+ uninstall_command->AppendSwitch(switches::kMultiInstall);
+ uninstall_command->AppendSwitch(switches::kChrome);
+ }
+}
+
+bool ChromeBrowserOperations::SetChannelFlags(
+ const std::set<std::wstring>& options,
+ bool set,
+ ChannelInfo* channel_info) const {
+#if defined(GOOGLE_CHROME_BUILD)
+ DCHECK(channel_info);
+ return channel_info->SetChrome(set);
+#else
+ return false;
+#endif
+}
+
+bool ChromeBrowserOperations::ShouldCreateUninstallEntry(
+ const std::set<std::wstring>& options) const {
+ return true;
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/chrome_browser_operations.h b/chrome/installer/util/chrome_browser_operations.h
new file mode 100644
index 0000000..5628b7d
--- /dev/null
+++ b/chrome/installer/util/chrome_browser_operations.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2011 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_CHROME_BROWSER_OPERATIONS_H_
+#define CHROME_INSTALLER_UTIL_CHROME_BROWSER_OPERATIONS_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/installer/util/product_operations.h"
+
+namespace installer {
+
+// Operations specific to Chrome; see ProductOperations for general info.
+class ChromeBrowserOperations : public ProductOperations {
+ public:
+ ChromeBrowserOperations() {}
+
+ virtual void ReadOptions(const MasterPreferences& prefs,
+ std::set<std::wstring>* options) const OVERRIDE;
+
+ virtual void ReadOptions(const CommandLine& uninstall_command,
+ std::set<std::wstring>* options) const OVERRIDE;
+
+ virtual void AddKeyFiles(const std::set<std::wstring>& options,
+ std::vector<FilePath>* key_files) const OVERRIDE;
+
+ virtual void AddComDllList(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* com_dll_list) const OVERRIDE;
+
+ virtual void AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const OVERRIDE;
+
+ virtual bool SetChannelFlags(const std::set<std::wstring>& options,
+ bool set,
+ ChannelInfo* channel_info) const OVERRIDE;
+
+ virtual bool ShouldCreateUninstallEntry(
+ const std::set<std::wstring>& options) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeBrowserOperations);
+};
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_CHROME_BROWSER_OPERATIONS_H_
diff --git a/chrome/installer/util/chrome_browser_sxs_operations.cc b/chrome/installer/util/chrome_browser_sxs_operations.cc
new file mode 100644
index 0000000..6c7fd81
--- /dev/null
+++ b/chrome/installer/util/chrome_browser_sxs_operations.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 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/chrome_browser_sxs_operations.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace installer {
+
+void ChromeBrowserSxSOperations::AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const {
+ DCHECK(uninstall_command);
+
+ uninstall_command->AppendSwitch(switches::kChromeSxS);
+ ChromeBrowserOperations::AppendProductFlags(options, uninstall_command);
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/chrome_browser_sxs_operations.h b/chrome/installer/util/chrome_browser_sxs_operations.h
new file mode 100644
index 0000000..de6101e
--- /dev/null
+++ b/chrome/installer/util/chrome_browser_sxs_operations.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 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_CHROME_BROWSER_SXS_OPERATIONS_H_
+#define CHROME_INSTALLER_UTIL_CHROME_BROWSER_SXS_OPERATIONS_H_
+#pragma once
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/installer/util/chrome_browser_operations.h"
+
+namespace installer {
+
+// Operations specific to Chrome SxS; see ProductOperations for general info.
+class ChromeBrowserSxSOperations : public ChromeBrowserOperations {
+ public:
+ ChromeBrowserSxSOperations() {}
+
+ virtual void AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeBrowserSxSOperations);
+};
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_CHROME_BROWSER_SXS_OPERATIONS_H_
diff --git a/chrome/installer/util/chrome_frame_distribution.cc b/chrome/installer/util/chrome_frame_distribution.cc
index 2507f1d..86a1abc 100644
--- a/chrome/installer/util/chrome_frame_distribution.cc
+++ b/chrome/installer/util/chrome_frame_distribution.cc
@@ -18,8 +18,6 @@
#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/master_preferences_constants.h"
#include "installer_util_strings.h" // NOLINT
@@ -27,38 +25,8 @@ namespace {
const wchar_t kChromeFrameGuid[] = L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
}
-ChromeFrameDistribution::ChromeFrameDistribution(
- const installer::MasterPreferences& prefs)
- : BrowserDistribution(prefs), ceee_(prefs.install_ceee()),
- ready_mode_(false) {
- type_ = BrowserDistribution::CHROME_FRAME;
- prefs.GetBool(installer::master_preferences::kChromeFrameReadyMode,
- &ready_mode_);
-
- bool system_install = false;
- prefs.GetBool(installer::master_preferences::kSystemLevel, &system_install);
-
- // See if Chrome Frame is already installed. If so, we must make sure that
- // the ceee and ready mode flags match.
- CommandLine uninstall(CommandLine::NO_PROGRAM);
- if (installer::GetUninstallSwitches(system_install, this, &uninstall)) {
- if (!ceee_ && uninstall.HasSwitch(installer::switches::kCeee)) {
- LOG(INFO) << "CEEE is not specified on the command line but CEEE is "
- "already installed. Implicitly enabling CEEE.";
- ceee_ = true;
- }
-
- // If the user has already opted in to CF, we shouldn't set the ready-mode
- // flag. If we don't do this, we might have two entries in the Add/Remove
- // Programs list that can uninstall GCF.
- if (ready_mode_) {
- if (!uninstall.HasSwitch(installer::switches::kChromeFrameReadyMode)) {
- LOG(INFO) << "Ready mode was specified on the command line but GCF "
- "is already fully installed. Ignoring command line.";
- ready_mode_ = false;
- }
- }
- }
+ChromeFrameDistribution::ChromeFrameDistribution()
+ : BrowserDistribution(CHROME_FRAME) {
}
std::wstring ChromeFrameDistribution::GetAppGuid() {
@@ -146,61 +114,3 @@ void ChromeFrameDistribution::UpdateInstallStatus(bool system_install,
InstallUtil::GetInstallReturnCode(install_status), kChromeFrameGuid);
#endif
}
-
-std::vector<FilePath> ChromeFrameDistribution::GetKeyFiles() {
- std::vector<FilePath> key_files;
- key_files.push_back(FilePath(installer::kChromeFrameDll));
- if (ceee_) {
- key_files.push_back(FilePath(installer::kCeeeIeDll));
- key_files.push_back(FilePath(installer::kCeeeBrokerExe));
- }
- return key_files;
-}
-
-std::vector<FilePath> ChromeFrameDistribution::GetComDllList() {
- std::vector<FilePath> dll_list;
- dll_list.push_back(FilePath(installer::kChromeFrameDll));
- if (ceee_) {
- dll_list.push_back(FilePath(installer::kCeeeInstallHelperDll));
- dll_list.push_back(FilePath(installer::kCeeeIeDll));
- }
- return dll_list;
-}
-
-void ChromeFrameDistribution::AppendUninstallCommandLineFlags(
- CommandLine* cmd_line) {
- DCHECK(cmd_line);
- cmd_line->AppendSwitch(installer::switches::kChromeFrame);
-
- if (ceee_)
- cmd_line->AppendSwitch(installer::switches::kCeee);
-
- if (ready_mode_)
- cmd_line->AppendSwitch(installer::switches::kChromeFrameReadyMode);
-}
-
-bool ChromeFrameDistribution::ShouldCreateUninstallEntry() {
- // If Chrome Frame is being installed in ready mode, then we will not
- // 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 f34cc86..043dc68 100644
--- a/chrome/installer/util/chrome_frame_distribution.h
+++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -55,29 +55,11 @@ class ChromeFrameDistribution : public BrowserDistribution {
bool incremental_install, bool multi_install,
installer::InstallStatus install_status);
- virtual std::vector<FilePath> GetKeyFiles();
-
- virtual std::vector<FilePath> GetComDllList();
-
- virtual void AppendUninstallCommandLineFlags(CommandLine* cmd_line);
-
- virtual bool ShouldCreateUninstallEntry();
-
- virtual bool SetChannelFlags(bool set, installer::ChannelInfo* channel_info);
-
protected:
friend class BrowserDistribution;
// Disallow construction from non-friends.
- explicit ChromeFrameDistribution(
- const installer::MasterPreferences& prefs);
-
- // Determines whether this Chrome Frame distribution is being used to work
- // with CEEE bits as well.
- bool ceee_;
-
- // True when Chrome Frame is installed in ready mode (users have to opt in).
- bool ready_mode_;
+ ChromeFrameDistribution();
};
#endif // CHROME_INSTALLER_UTIL_CHROME_FRAME_DISTRIBUTION_H_
diff --git a/chrome/installer/util/chrome_frame_operations.cc b/chrome/installer/util/chrome_frame_operations.cc
new file mode 100644
index 0000000..4ab5b2a
--- /dev/null
+++ b/chrome/installer/util/chrome_frame_operations.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2011 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/chrome_frame_operations.h"
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/channel_info.h"
+#include "chrome/installer/util/helper.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/master_preferences_constants.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace installer {
+
+// Remove ready-mode if not multi-install.
+void ChromeFrameOperations::NormalizeOptions(
+ std::set<std::wstring>* options) const {
+ std::set<std::wstring>::iterator ready_mode(options->find(kOptionReadyMode));
+ if (ready_mode != options->end() &&
+ options->find(kOptionMultiInstall) == options->end()) {
+ LOG(WARNING) << "--ready-mode option does not apply when --multi-install "
+ "is not also specified; ignoring.";
+ options->erase(ready_mode);
+ }
+}
+
+void ChromeFrameOperations::ReadOptions(
+ const MasterPreferences& prefs,
+ std::set<std::wstring>* options) const {
+ DCHECK(options);
+
+ static const struct PrefToOption {
+ const char* pref_name;
+ const wchar_t* option_name;
+ } map[] = {
+ { master_preferences::kCeee, kOptionCeee },
+ { master_preferences::kChromeFrameReadyMode, kOptionReadyMode },
+ { master_preferences::kMultiInstall, kOptionMultiInstall }
+ };
+
+ bool pref_value;
+
+ for (const PrefToOption* scan = &map[0], *end = &map[arraysize(map)];
+ scan != end; ++scan) {
+ if (prefs.GetBool(scan->pref_name, &pref_value) && pref_value)
+ options->insert(scan->option_name);
+ }
+
+ NormalizeOptions(options);
+}
+
+void ChromeFrameOperations::ReadOptions(
+ const CommandLine& uninstall_command,
+ std::set<std::wstring>* options) const {
+ DCHECK(options);
+
+ static const struct FlagToOption {
+ const char* flag_name;
+ const wchar_t* option_name;
+ } map[] = {
+ { switches::kCeee, kOptionCeee },
+ { switches::kChromeFrameReadyMode, kOptionReadyMode },
+ { switches::kMultiInstall, kOptionMultiInstall }
+ };
+
+ for (const FlagToOption* scan = &map[0], *end = &map[arraysize(map)];
+ scan != end; ++scan) {
+ if (uninstall_command.HasSwitch(scan->flag_name))
+ options->insert(scan->option_name);
+ }
+
+ NormalizeOptions(options);
+}
+
+void ChromeFrameOperations::AddKeyFiles(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* key_files) const {
+ DCHECK(key_files);
+ key_files->push_back(FilePath(installer::kChromeFrameDll));
+ if (options.find(kOptionCeee) != options.end()) {
+ key_files->push_back(FilePath(installer::kCeeeIeDll));
+ key_files->push_back(FilePath(installer::kCeeeBrokerExe));
+ }
+}
+
+void ChromeFrameOperations::AddComDllList(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* com_dll_list) const {
+ DCHECK(com_dll_list);
+ std::vector<FilePath> dll_list;
+ com_dll_list->push_back(FilePath(installer::kChromeFrameDll));
+ if (options.find(kOptionCeee) != options.end()) {
+ com_dll_list->push_back(FilePath(installer::kCeeeInstallHelperDll));
+ com_dll_list->push_back(FilePath(installer::kCeeeIeDll));
+ }
+}
+
+void ChromeFrameOperations::AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const {
+ DCHECK(uninstall_command);
+ uninstall_command->AppendSwitch(switches::kChromeFrame);
+
+ if (options.find(kOptionCeee) != options.end())
+ uninstall_command->AppendSwitch(switches::kCeee);
+
+ if (options.find(kOptionMultiInstall) != options.end()) {
+ if (!uninstall_command->HasSwitch(switches::kMultiInstall))
+ uninstall_command->AppendSwitch(switches::kMultiInstall);
+
+ // ready-mode is only supported in multi-installs of Chrome Frame.
+ if (options.find(kOptionReadyMode) != options.end())
+ uninstall_command->AppendSwitch(switches::kChromeFrameReadyMode);
+ }
+}
+
+bool ChromeFrameOperations::SetChannelFlags(
+ const std::set<std::wstring>& options,
+ bool set,
+ ChannelInfo* channel_info) const {
+#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 or if the
+ // corresponding option isn't set.
+ modified |= channel_info->SetCeee(
+ set && options.find(kOptionCeee) != options.end());
+
+ modified |= channel_info->SetReadyMode(
+ set && options.find(kOptionReadyMode) != options.end());
+
+ return modified;
+#else
+ return false;
+#endif
+}
+
+bool ChromeFrameOperations::ShouldCreateUninstallEntry(
+ const std::set<std::wstring>& options) const {
+ return options.find(kOptionReadyMode) == options.end();
+}
+
+} // namespace installer
diff --git a/chrome/installer/util/chrome_frame_operations.h b/chrome/installer/util/chrome_frame_operations.h
new file mode 100644
index 0000000..267eef6
--- /dev/null
+++ b/chrome/installer/util/chrome_frame_operations.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2011 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_CHROME_FRAME_OPERATIONS_H_
+#define CHROME_INSTALLER_UTIL_CHROME_FRAME_OPERATIONS_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/compiler_specific.h"
+#include "chrome/installer/util/product_operations.h"
+
+namespace installer {
+
+// Operations specific to Chrome Frame; see ProductOperations for general info.
+class ChromeFrameOperations : public ProductOperations {
+ public:
+ ChromeFrameOperations() {}
+
+ virtual void ReadOptions(const MasterPreferences& prefs,
+ std::set<std::wstring>* options) const OVERRIDE;
+
+ virtual void ReadOptions(const CommandLine& uninstall_command,
+ std::set<std::wstring>* options) const OVERRIDE;
+
+ virtual void AddKeyFiles(const std::set<std::wstring>& options,
+ std::vector<FilePath>* key_files) const OVERRIDE;
+
+ virtual void AddComDllList(
+ const std::set<std::wstring>& options,
+ std::vector<FilePath>* com_dll_list) const OVERRIDE;
+
+ virtual void AppendProductFlags(
+ const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const OVERRIDE;
+
+ virtual bool SetChannelFlags(const std::set<std::wstring>& options,
+ bool set,
+ ChannelInfo* channel_info) const OVERRIDE;
+
+ virtual bool ShouldCreateUninstallEntry(
+ const std::set<std::wstring>& options) const OVERRIDE;
+
+ protected:
+ void NormalizeOptions(std::set<std::wstring>* options) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeFrameOperations);
+};
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_CHROME_FRAME_OPERATIONS_H_
diff --git a/chrome/installer/util/chromium_binaries_distribution.cc b/chrome/installer/util/chromium_binaries_distribution.cc
new file mode 100644
index 0000000..8e39ffb
--- /dev/null
+++ b/chrome/installer/util/chromium_binaries_distribution.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2011 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.
+//
+// This file declares a class that contains various method related to branding.
+
+#include "chrome/installer/util/google_chrome_binaries_distribution.h"
+
+#include "base/logging.h"
+
+namespace {
+
+const wchar_t kChromiumBinariesName[] = L"Chromium Binaries";
+
+} // namespace
+
+ChromiumBinariesDistribution::ChromiumBinariesDistribution()
+ : BrowserDistribution(CHROME_BINARIES),
+ browser_distribution_(
+ BrowserDistribution::GetSpecificDistribution(CHROME_BROWSER)) {
+}
+
+std::wstring ChromiumBinariesDistribution::GetAppGuid() {
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetApplicationName() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetAppShortCutName() {
+ return kChromiumBinariesName;
+}
+
+std::wstring ChromiumBinariesDistribution::GetAlternateApplicationName() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetBrowserAppId() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetInstallSubDir() {
+ return browser_distribution_->GetInstallSubDir();
+}
+
+std::wstring ChromiumBinariesDistribution::GetPublisherName() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetAppDescription() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetLongAppDescription() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::string ChromiumBinariesDistribution::GetSafeBrowsingName() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::string();
+}
+
+std::wstring ChromiumBinariesDistribution::GetStateKey() {
+ return std::wstring(L"Software\\").append(kChromiumBinariesName);
+}
+
+std::wstring ChromiumBinariesDistribution::GetStateMediumKey() {
+ return std::wstring(L"Software\\").append(kChromiumBinariesName);
+}
+
+std::wstring ChromiumBinariesDistribution::GetUninstallLinkName() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetUninstallRegPath() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return std::wstring();
+}
+
+std::wstring ChromiumBinariesDistribution::GetVersionKey() {
+ return std::wstring(L"Software\\").append(kChromiumBinariesName);
+}
+
+bool ChromiumBinariesDistribution::CanSetAsDefault() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return false;
+}
+
+int ChromiumBinariesDistribution::GetIconIndex() {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return 0;
+}
+
+bool ChromiumBinariesDistribution::GetChromeChannel(std::wstring* channel) {
+ NOTREACHED() << "GetApplicationName unsupported";
+ return false;
+}
diff --git a/chrome/installer/util/chromium_binaries_distribution.h b/chrome/installer/util/chromium_binaries_distribution.h
new file mode 100644
index 0000000..6ee0c4f
--- /dev/null
+++ b/chrome/installer/util/chromium_binaries_distribution.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2011 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.
+//
+// This file declares a class that contains various method related to branding.
+
+#ifndef CHROME_INSTALLER_UTIL_CHROMIUM_BINARIES_DISTRIBUTION_H_
+#define CHROME_INSTALLER_UTIL_CHROMIUM_BINARIES_DISTRIBUTION_H_
+#pragma once
+
+#include <string>
+
+#include "chrome/installer/util/browser_distribution.h"
+
+class ChromiumBinariesDistribution : public BrowserDistribution {
+ public:
+ virtual std::wstring GetAppGuid();
+
+ virtual std::wstring GetApplicationName();
+
+ virtual std::wstring GetAppShortCutName();
+
+ virtual std::wstring GetAlternateApplicationName();
+
+ virtual std::wstring GetBrowserAppId();
+
+ virtual std::wstring GetInstallSubDir();
+
+ virtual std::wstring GetPublisherName();
+
+ virtual std::wstring GetAppDescription();
+
+ virtual std::wstring GetLongAppDescription();
+
+ virtual std::string GetSafeBrowsingName();
+
+ virtual std::wstring GetStateKey();
+
+ virtual std::wstring GetStateMediumKey();
+
+ virtual std::wstring GetUninstallLinkName();
+
+ virtual std::wstring GetUninstallRegPath();
+
+ virtual std::wstring GetVersionKey();
+
+ virtual bool CanSetAsDefault();
+
+ virtual int GetIconIndex();
+
+ virtual bool GetChromeChannel(std::wstring* channel);
+
+ protected:
+ friend class BrowserDistribution;
+
+ ChromiumBinariesDistribution();
+
+ BrowserDistribution* browser_distribution_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromiumBinariesDistribution);
+};
+
+#endif // CHROME_INSTALLER_UTIL_CHROMIUM_BINARIES_DISTRIBUTION_H_
diff --git a/chrome/installer/util/google_chrome_binaries_distribution.cc b/chrome/installer/util/google_chrome_binaries_distribution.cc
new file mode 100644
index 0000000..00229bf
--- /dev/null
+++ b/chrome/installer/util/google_chrome_binaries_distribution.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 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.
+//
+// This file declares a class that contains various method related to branding.
+
+#include "chrome/installer/util/google_chrome_binaries_distribution.h"
+
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/install_util.h"
+
+namespace {
+
+const wchar_t kChromeBinariesGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
+const wchar_t kChromeBinariesName[] = L"Google Chrome binaries";
+
+} // namespace
+
+GoogleChromeBinariesDistribution::GoogleChromeBinariesDistribution()
+ : ChromiumBinariesDistribution() {
+}
+
+std::wstring GoogleChromeBinariesDistribution::GetAppGuid() {
+ return kChromeBinariesGuid;
+}
+
+std::wstring GoogleChromeBinariesDistribution::GetAppShortCutName() {
+ return kChromeBinariesName;
+}
+
+std::wstring GoogleChromeBinariesDistribution::GetStateKey() {
+ return std::wstring(google_update::kRegPathClientState)
+ .append(1, L'\\')
+ .append(kChromeBinariesGuid);
+}
+
+std::wstring GoogleChromeBinariesDistribution::GetStateMediumKey() {
+ return std::wstring(google_update::kRegPathClientStateMedium)
+ .append(1, L'\\')
+ .append(kChromeBinariesGuid);
+}
+
+std::wstring GoogleChromeBinariesDistribution::GetVersionKey() {
+ return std::wstring(google_update::kRegPathClients)
+ .append(1, L'\\')
+ .append(kChromeBinariesGuid);
+}
+
+void GoogleChromeBinariesDistribution::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), kChromeBinariesGuid);
+}
diff --git a/chrome/installer/util/google_chrome_binaries_distribution.h b/chrome/installer/util/google_chrome_binaries_distribution.h
new file mode 100644
index 0000000..3ddbf34
--- /dev/null
+++ b/chrome/installer/util/google_chrome_binaries_distribution.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 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.
+//
+// This file declares a class that contains various method related to branding.
+
+#ifndef CHROME_INSTALLER_UTIL_GOOGLE_CHROME_BINARIES_DISTRIBUTION_H_
+#define CHROME_INSTALLER_UTIL_GOOGLE_CHROME_BINARIES_DISTRIBUTION_H_
+#pragma once
+
+#include "chrome/installer/util/chromium_binaries_distribution.h"
+
+class GoogleChromeBinariesDistribution : public ChromiumBinariesDistribution {
+ public:
+ virtual std::wstring GetAppGuid();
+
+ virtual std::wstring GetAppShortCutName();
+
+ virtual std::wstring GetStateKey();
+
+ virtual std::wstring GetStateMediumKey();
+
+ virtual std::wstring GetVersionKey();
+
+ virtual void UpdateInstallStatus(bool system_install,
+ bool incremental_install, bool multi_install,
+ installer::InstallStatus install_status);
+
+ protected:
+ friend class BrowserDistribution;
+
+ GoogleChromeBinariesDistribution();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GoogleChromeBinariesDistribution);
+};
+
+#endif // CHROME_INSTALLER_UTIL_GOOGLE_CHROME_BINARIES_DISTRIBUTION_H_
diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc
index e0ab343..300ee1d 100644
--- a/chrome/installer/util/google_chrome_distribution.cc
+++ b/chrome/installer/util/google_chrome_distribution.cc
@@ -253,9 +253,9 @@ bool RelaunchSetupAsConsoleUser(const std::string& flag) {
} // namespace
-GoogleChromeDistribution::GoogleChromeDistribution(
- const installer::MasterPreferences& prefs)
- : BrowserDistribution(prefs), product_guid_(kChromeGuid) {
+GoogleChromeDistribution::GoogleChromeDistribution()
+ : BrowserDistribution(CHROME_BROWSER),
+ product_guid_(kChromeGuid) {
}
// The functions below are not used by the 64-bit Windows binary -
@@ -633,7 +633,8 @@ void GoogleChromeDistribution::LaunchUserExperiment(
// User qualifies for the experiment. Launch chrome with --try-chrome=flavor.
void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
- const installer::Product& installation) {
+ const installer::Product& installation,
+ const FilePath& application_path) {
bool has_welcome_url = (flavor == 0);
// Possibly add a url to launch depending on the experiment flavor.
CommandLine options(CommandLine::NO_PROGRAM);
@@ -651,7 +652,7 @@ void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
}
// Launch chrome now. It will show the toast UI.
int32 exit_code = 0;
- if (!installation.LaunchChromeAndWait(options, &exit_code))
+ if (!installation.LaunchChromeAndWait(application_path, options, &exit_code))
return;
// The chrome process has exited, figure out what happened.
@@ -688,10 +689,3 @@ 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 038d27b..9610518 100644
--- a/chrome/installer/util/google_chrome_distribution.h
+++ b/chrome/installer/util/google_chrome_distribution.h
@@ -79,18 +79,16 @@ class GoogleChromeDistribution : public BrowserDistribution {
// toast experiment. It will use chrome to show the UI and it will record the
// outcome in the registry.
virtual void InactiveUserToastExperiment(int flavor,
- const installer::Product& installation);
+ const installer::Product& installation,
+ const FilePath& application_path);
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; }
// Disallow construction from others.
- explicit GoogleChromeDistribution(
- const installer::MasterPreferences& prefs);
+ GoogleChromeDistribution();
private:
friend class BrowserDistribution;
diff --git a/chrome/installer/util/google_chrome_distribution_dummy.cc b/chrome/installer/util/google_chrome_distribution_dummy.cc
index 1b515d9..9b022be 100644
--- a/chrome/installer/util/google_chrome_distribution_dummy.cc
+++ b/chrome/installer/util/google_chrome_distribution_dummy.cc
@@ -15,9 +15,8 @@
#include "base/file_path.h"
#include "base/logging.h"
-GoogleChromeDistribution::GoogleChromeDistribution(
- const installer::MasterPreferences& prefs)
- : BrowserDistribution(prefs) {
+GoogleChromeDistribution::GoogleChromeDistribution()
+ : BrowserDistribution(CHROME_BROWSER) {
}
void GoogleChromeDistribution::DoPostUninstallOperations(
@@ -114,7 +113,8 @@ void GoogleChromeDistribution::LaunchUserExperiment(
}
void GoogleChromeDistribution::InactiveUserToastExperiment(int flavor,
- const installer::Product& installation) {
+ const installer::Product& installation,
+ const FilePath& application_path) {
NOTREACHED();
}
@@ -135,10 +135,3 @@ bool GoogleChromeDistribution::BuildUninstallMetricsString(
NOTREACHED();
return false;
}
-
-bool GoogleChromeDistribution::SetChannelFlags(
- bool set,
- installer::ChannelInfo* channel_info) {
- NOTREACHED();
- return false;
-}
diff --git a/chrome/installer/util/google_chrome_distribution_unittest.cc b/chrome/installer/util/google_chrome_distribution_unittest.cc
index 1222ff3..ed566ea 100644
--- a/chrome/installer/util/google_chrome_distribution_unittest.cc
+++ b/chrome/installer/util/google_chrome_distribution_unittest.cc
@@ -11,7 +11,6 @@
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_chrome_distribution.h"
-#include "chrome/installer/util/master_preferences.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(GOOGLE_CHROME_BUILD)
@@ -52,12 +51,9 @@ TEST(GoogleChromeDistTest, TestExtractUninstallMetrics) {
ASSERT_TRUE(root.get());
std::wstring uninstall_metrics_string;
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
-
GoogleChromeDistribution* dist = static_cast<GoogleChromeDistribution*>(
BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs));
+ BrowserDistribution::CHROME_BROWSER));
EXPECT_TRUE(
dist->ExtractUninstallMetrics(*static_cast<DictionaryValue*>(root.get()),
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.cc b/chrome/installer/util/google_chrome_sxs_distribution.cc
index 9461a52..9ea35f1 100644
--- a/chrome/installer/util/google_chrome_sxs_distribution.cc
+++ b/chrome/installer/util/google_chrome_sxs_distribution.cc
@@ -9,7 +9,7 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "installer_util_strings.h"
+#include "installer_util_strings.h" // NOLINT
namespace {
@@ -20,9 +20,8 @@ const int kSxSIconIndex = 4;
} // namespace
-GoogleChromeSxSDistribution::GoogleChromeSxSDistribution(
- const installer::MasterPreferences& prefs)
- : GoogleChromeDistribution(prefs) {
+GoogleChromeSxSDistribution::GoogleChromeSxSDistribution()
+ : GoogleChromeDistribution() {
GoogleChromeDistribution::set_product_guid(kChromeSxSGuid);
}
@@ -62,9 +61,3 @@ bool GoogleChromeSxSDistribution::GetChromeChannel(std::wstring* channel) {
std::wstring GoogleChromeSxSDistribution::ChannelName() {
return kChannelName;
}
-
-void GoogleChromeSxSDistribution::AppendUninstallCommandLineFlags(
- CommandLine* cmd_line) {
- DCHECK(cmd_line);
- cmd_line->AppendSwitch(installer::switches::kChromeSxS);
-}
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.h b/chrome/installer/util/google_chrome_sxs_distribution.h
index 7088c56..10df80a 100644
--- a/chrome/installer/util/google_chrome_sxs_distribution.h
+++ b/chrome/installer/util/google_chrome_sxs_distribution.h
@@ -32,13 +32,11 @@ class GoogleChromeSxSDistribution : public GoogleChromeDistribution {
virtual bool GetChromeChannel(std::wstring* channel);
// returns the channel name for GoogleChromeSxSDistribution
static std::wstring ChannelName();
- virtual void AppendUninstallCommandLineFlags(CommandLine* cmd_line);
private:
friend class BrowserDistribution;
// Disallow construction from non-friends.
- explicit GoogleChromeSxSDistribution(
- const installer::MasterPreferences& prefs);
+ GoogleChromeSxSDistribution();
};
#endif // CHROME_INSTALLER_UTIL_GOOGLE_CHROME_SXS_DISTRIBUTION_H_
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 44ee0f0..76d13d2 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -17,11 +17,11 @@
#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/package.h"
-#include "chrome/installer/util/package_properties.h"
+#include "chrome/installer/util/installer_state.h"
#include "chrome/installer/util/product.h"
using base::win::RegKey;
+using installer::InstallerState;
namespace {
@@ -126,33 +126,43 @@ bool GoogleUpdateSettings::SetMetricsId(const std::wstring& metrics_id) {
}
bool GoogleUpdateSettings::SetEULAConsent(
- const installer::Package& package,
+ const InstallerState& installer_state,
bool consented) {
// If this is a multi install, Google Update will have put eulaaccepted=0 into
// the ClientState key of the multi-installer. Conduct a brief search for
// this value and store the consent in the corresponding location.
- HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
-
- std::wstring reg_path = package.properties()->GetStateMediumKey();
- EulaSearchResult status = HasEULASetting(
- root, package.properties()->GetStateKey(), !consented);
+ HKEY root = installer_state.root_key();
+ EulaSearchResult status = NO_SETTING;
+ std::wstring reg_path;
+ std::wstring fallback_reg_path;
+
+ if (installer_state.package_type() == InstallerState::MULTI_PACKAGE) {
+ BrowserDistribution* binaries_dist =
+ installer_state.multi_package_binaries_distribution();
+ fallback_reg_path = reg_path = binaries_dist->GetStateMediumKey();
+ status = HasEULASetting(root, binaries_dist->GetStateKey(), !consented);
+ }
if (status != FOUND_SAME_SETTING) {
EulaSearchResult new_status = NO_SETTING;
- installer::Products::const_iterator scan = package.products().begin();
- installer::Products::const_iterator end = package.products().end();
+ installer::Products::const_iterator scan =
+ installer_state.products().begin();
+ installer::Products::const_iterator end =
+ installer_state.products().end();
for (; status != FOUND_SAME_SETTING && scan != end; ++scan) {
- const installer::Product& product = *(scan->get());
- new_status = HasEULASetting(root, product.distribution()->GetStateKey(),
+ if (fallback_reg_path.empty())
+ fallback_reg_path = (*scan)->distribution()->GetStateMediumKey();
+ new_status = HasEULASetting(root, (*scan)->distribution()->GetStateKey(),
!consented);
if (new_status > status) {
status = new_status;
- reg_path = product.distribution()->GetStateMediumKey();
+ reg_path = (*scan)->distribution()->GetStateMediumKey();
}
}
if (status == NO_SETTING) {
LOG(WARNING)
- << "eulaaccepted value not found; setting consent on package";
- reg_path = package.properties()->GetStateMediumKey();
+ << "eulaaccepted value not found; setting consent in key "
+ << fallback_reg_path;
+ reg_path = fallback_reg_path;
}
}
RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE);
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h
index 36e020c..12b5fa5 100644
--- a/chrome/installer/util/google_update_settings.h
+++ b/chrome/installer/util/google_update_settings.h
@@ -12,7 +12,7 @@
namespace installer {
class ChannelInfo;
-class Package;
+class InstallerState;
}
// This class provides accessors to the Google Update 'ClientState' information
@@ -38,7 +38,7 @@ class GoogleUpdateSettings {
// Sets the machine-wide EULA consented flag required on OEM installs.
// Returns false if the setting could not be recorded.
- static bool SetEULAConsent(const installer::Package& package,
+ static bool SetEULAConsent(const installer::InstallerState& installer_state,
bool consented);
// Returns the last time chrome was run in days. It uses a recorded value
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 96a6dae..2234192 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -15,9 +15,9 @@
#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/installation_state.h"
+#include "chrome/installer/util/installer_state.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/work_item_list.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -404,28 +404,32 @@ TEST_F(GoogleUpdateSettingsTest, UpdateInstallStatusTest) {
}
TEST_F(GoogleUpdateSettingsTest, SetEULAConsent) {
- const bool multi_install = false;
+ const bool multi_install = true;
const bool system_level = true;
- HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
-
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
- installer::ChromePackageProperties properties;
- BrowserDistribution* distribution =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- scoped_refptr<installer::Package> package(
- new installer::Package(multi_install, system_level, FilePath(),
- &properties));
- scoped_refptr<installer::Product> product(
- new installer::Product(distribution, package.get()));
+ CommandLine cmd_line = CommandLine::FromString(
+ std::wstring(L"setup.exe") +
+ (multi_install ? L" --multi-install --chrome" : L"") +
+ (system_level ? L" --system-level" : L""));
+ installer::MasterPreferences prefs(cmd_line);
+ installer::InstallationState machine_state;
+ machine_state.Initialize();
+ installer::InstallerState installer_state;
+ installer_state.Initialize(cmd_line, prefs, machine_state);
+ HKEY root = installer_state.root_key();
+
RegKey key;
DWORD value;
+ BrowserDistribution* binaries =
+ installer_state.multi_package_binaries_distribution();
+ EXPECT_EQ(BrowserDistribution::CHROME_BINARIES, binaries->GetType());
+ BrowserDistribution* chrome =
+ installer_state.products()[0]->distribution();
+ EXPECT_EQ(BrowserDistribution::CHROME_BROWSER, chrome->GetType());
// By default, eulaconsent ends up on the package.
- EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(*package.get(), true));
+ EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(installer_state, true));
EXPECT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE, properties.GetStateMediumKey().c_str(),
+ key.Open(HKEY_LOCAL_MACHINE, binaries->GetStateMediumKey().c_str(),
KEY_QUERY_VALUE | KEY_SET_VALUE));
EXPECT_EQ(ERROR_SUCCESS,
key.ReadValueDW(google_update::kRegEULAAceptedField, &value));
@@ -435,14 +439,14 @@ TEST_F(GoogleUpdateSettingsTest, SetEULAConsent) {
// But it will end up on the product if needed
EXPECT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_LOCAL_MACHINE, distribution->GetStateKey().c_str(),
+ key.Create(HKEY_LOCAL_MACHINE, chrome->GetStateKey().c_str(),
KEY_SET_VALUE));
EXPECT_EQ(ERROR_SUCCESS,
key.WriteValue(google_update::kRegEULAAceptedField,
static_cast<DWORD>(0)));
- EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(*package.get(), true));
+ EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(installer_state, true));
EXPECT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE, distribution->GetStateMediumKey().c_str(),
+ key.Open(HKEY_LOCAL_MACHINE, chrome->GetStateMediumKey().c_str(),
KEY_QUERY_VALUE | KEY_SET_VALUE));
EXPECT_EQ(ERROR_SUCCESS,
key.ReadValueDW(google_update::kRegEULAAceptedField, &value));
diff --git a/chrome/installer/util/helper.cc b/chrome/installer/util/helper.cc
index 6cddf25..82f8a36 100644
--- a/chrome/installer/util/helper.cc
+++ b/chrome/installer/util/helper.cc
@@ -4,17 +4,13 @@
#include "chrome/installer/util/helper.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
#include "base/logging.h"
+#include "base/file_path.h"
#include "base/path_service.h"
-#include "base/win/registry.h"
#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/install_util.h"
-#include "chrome/installer/util/master_preferences.h"
-#include "chrome/installer/util/package_properties.h"
-
-using base::win::RegKey;
+#include "chrome/installer/util/util_constants.h"
namespace {
@@ -40,101 +36,32 @@ FilePath GetChromeInstallBasePath(bool system,
namespace installer {
-bool IsInstalledAsMulti(bool system_install, BrowserDistribution* dist) {
- bool installed_as_multi = false;
- CommandLine cmd(CommandLine::NO_PROGRAM);
- if (GetUninstallSwitches(system_install, dist, &cmd))
- installed_as_multi = cmd.HasSwitch(installer::switches::kMultiInstall);
- return installed_as_multi;
-}
-
-bool GetUninstallSwitches(bool system_install, BrowserDistribution* dist,
- CommandLine* cmd_line_switches) {
- scoped_ptr<Version> installed(InstallUtil::GetChromeVersion(dist,
- system_install));
- if (installed.get()) {
- HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- RegKey key(root, dist->GetStateKey().c_str(), KEY_READ);
- if (key.Valid()) {
- std::wstring args;
- key.ReadValue(installer::kUninstallArgumentsField, &args);
- if (!args.empty()) {
- args.insert(0, L"foo.exe ");
- *cmd_line_switches = CommandLine::FromString(args);
- } else {
- LOG(ERROR) << "No uninstallation arguments for "
- << dist->GetApplicationName();
- installed.reset();
- }
- } else {
- LOG(ERROR) << "Product looks to be installed but we can't access the "
- "state key: " << dist->GetApplicationName();
- installed.reset();
- }
- }
-
- return installed.get() != NULL;
-}
-
FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist) {
- return GetChromeInstallBasePath(system_install, dist,
- installer::kInstallBinaryDir);
+ return GetChromeInstallBasePath(system_install, dist, kInstallBinaryDir);
}
FilePath GetChromeUserDataPath(BrowserDistribution* dist) {
return GetChromeInstallBasePath(false, dist, kInstallUserDataDir);
}
-FilePath GetChromeFrameInstallPath(bool multi_install, bool system_install,
- BrowserDistribution* dist) {
- DCHECK_EQ(BrowserDistribution::CHROME_FRAME, dist->GetType());
-
- scoped_ptr<Version> installed_version(
- InstallUtil::GetChromeVersion(dist, system_install));
-
- if (!multi_install) {
- // Check if Chrome Frame is installed as multi. If it is, return an empty
- // path and log an error.
- if (installed_version.get() && IsInstalledAsMulti(system_install, dist)) {
- LOG(ERROR) << "Cannot install Chrome Frame in single mode as a multi mode"
- " installation already exists.";
- return FilePath();
- }
- VLOG(1) << "Chrome Frame will be installed as 'single'";
- return GetChromeInstallPath(system_install, dist);
- }
-
- // TODO(tommi): If Chrome Frame is installed as single and the installed
- // channel is older than the one we're installing, we should migrate
- // CF to Chrome's install folder and change its channel.
+BrowserDistribution* GetBinariesDistribution(bool system_install) {
+ BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+ ProductState state;
- // Multi install. Check if Chrome Frame is already installed.
- // If CF is installed as single (i.e. not multi), we will return an empty
- // path (for now). Otherwise, if CF is not installed or if it is installed
- // as multi, we will return Chrome's install folder.
- if (installed_version.get() && !IsInstalledAsMulti(system_install, dist)) {
- LOG(ERROR) << "Cannot install Chrome Frame in multi mode as a single mode"
- " installation already exists.";
- return FilePath();
+ // If we're part of a multi-install, we need to poll using the multi-installer
+ // package's app guid rather than the browser's or Chrome Frame's app guid.
+ // If we can't read the app's state from the registry, assume it isn't
+ // multi-installed.
+ if (state.Initialize(system_install, dist) && state.is_multi_install()) {
+ return BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BINARIES);
+ } else {
+ return dist;
}
-
- // Return Chrome's installation folder.
- VLOG(1) << "Chrome Frame will be installed as 'multi'";
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
- BrowserDistribution* chrome =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- return GetChromeInstallPath(system_install, chrome);
}
std::wstring GetAppGuidForUpdates(bool system_install) {
- BrowserDistribution* dist = BrowserDistribution::GetDistribution();
-
- // If we're part of a multi-install, we need to poll using the multi-installer
- // package's app guid rather than the browser's or Chrome Frame's app guid.
- return IsInstalledAsMulti(system_install, dist) ?
- ActivePackageProperties().GetAppGuid() :
- dist->GetAppGuid();
+ return GetBinariesDistribution(system_install)->GetAppGuid();
}
} // namespace installer.
diff --git a/chrome/installer/util/helper.h b/chrome/installer/util/helper.h
index bcee4c6..fa996b6 100644
--- a/chrome/installer/util/helper.h
+++ b/chrome/installer/util/helper.h
@@ -16,17 +16,6 @@ class FilePath;
namespace installer {
-// Checks if a distribution is currently installed as part of a multi-install.
-bool IsInstalledAsMulti(bool system_install, BrowserDistribution* dist);
-
-// Retrieves the command line switches for uninstalling the distribution.
-// Note that the returned CommandLine object does not include a "program".
-// Only the switches should be used.
-// Returns true if the product is installed and the uninstall switches
-// were successfully retrieved, otherwise false.
-bool GetUninstallSwitches(bool system_install, BrowserDistribution* dist,
- CommandLine* cmd_line_switches);
-
// This function returns the install path for Chrome depending on whether its
// system wide install or user specific install.
// system_install: if true, the function returns system wide location
@@ -40,18 +29,10 @@ FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist);
// that it can be overriden with a command line parameter.
FilePath GetChromeUserDataPath(BrowserDistribution* dist);
-// This is a workaround while we unify Chrome and Chrome Frame installation
-// folders. Right now, Chrome Frame can be installed into two different
-// folders: 1) A special "Chrome Frame" folder next to Chrome's folder
-// 2) The same folder as Chrome is installed into.
-// Right now this function will only return Chrome's installation folder
-// if Chrome Frame is not already installed or if Chrome Frame is installed
-// in multi_install mode.
-// If multi_install is false or if CF is installed in single mode, then the
-// returned path will be the "Chrome Frame" subfolder of either the user or
-// system default installation folders.
-FilePath GetChromeFrameInstallPath(bool multi_install, bool system_install,
- BrowserDistribution* dist);
+// Returns the distribution corresponding to the current process's binaries.
+// In the case of a multi-install product, this will be the CHROME_BINARIES
+// distribution.
+BrowserDistribution* GetBinariesDistribution(bool system_install);
// Returns the app guid under which the current process receives updates from
// Google Update.
diff --git a/chrome/installer/util/helper_unittest.cc b/chrome/installer/util/helper_unittest.cc
deleted file mode 100644
index 48b2476..0000000
--- a/chrome/installer/util/helper_unittest.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2006-2008 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 <windows.h>
-
-#include <fstream>
-
-#include "base/base_paths.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/process_util.h"
-#include "base/string_util.h"
-#include "base/version.h"
-#include "chrome/installer/util/helper.h"
-#include "chrome/installer/util/package.h"
-#include "chrome/installer/util/package_properties.h"
-#include "chrome/installer/util/work_item.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using installer::ChromePackageProperties;
-using installer::Package;
-
-namespace {
- class SetupHelperTest : public testing::Test {
- protected:
- virtual void SetUp() {
- // Name a subdirectory of the user temp directory.
- ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
- test_dir_ = test_dir_.AppendASCII("SetupHelperTest");
-
- // Create a fresh, empty copy of this test directory.
- file_util::Delete(test_dir_, true);
- file_util::CreateDirectoryW(test_dir_);
- ASSERT_TRUE(file_util::PathExists(test_dir_));
- }
-
- virtual void TearDown() {
- logging::CloseLogFile();
- // Clean up test directory
- ASSERT_TRUE(file_util::Delete(test_dir_, true));
- ASSERT_FALSE(file_util::PathExists(test_dir_));
- }
-
- // the path to temporary directory used to contain the test operations
- FilePath test_dir_;
- };
-
- // Simple function to dump some text into a new file.
- void CreateTextFile(const std::wstring& filename,
- const std::wstring& contents) {
- std::ofstream file;
- file.open(filename.c_str());
- ASSERT_TRUE(file.is_open());
- file << contents;
- file.close();
- }
-
- wchar_t text_content_1[] = L"delete me";
- wchar_t text_content_2[] = L"delete me as well";
-};
-
-// Delete version directories. Everything lower than the given version
-// should be deleted.
-TEST_F(SetupHelperTest, Delete) {
- // Create a Chrome dir
- FilePath chrome_dir(test_dir_);
- chrome_dir = chrome_dir.AppendASCII("chrome");
- file_util::CreateDirectory(chrome_dir);
- ASSERT_TRUE(file_util::PathExists(chrome_dir));
-
- FilePath chrome_dir_1(chrome_dir);
- chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0");
- file_util::CreateDirectory(chrome_dir_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_1));
-
- FilePath chrome_dir_2(chrome_dir);
- chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0");
- file_util::CreateDirectory(chrome_dir_2);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_2));
-
- FilePath chrome_dir_3(chrome_dir);
- chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0");
- file_util::CreateDirectory(chrome_dir_3);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_3));
-
- FilePath chrome_dir_4(chrome_dir);
- chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0");
- file_util::CreateDirectory(chrome_dir_4);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_4));
-
- FilePath chrome_dll_1(chrome_dir_1);
- chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_1.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_1));
-
- FilePath chrome_dll_2(chrome_dir_2);
- chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_2.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_2));
-
- FilePath chrome_dll_3(chrome_dir_3);
- chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_3.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_3));
-
- FilePath chrome_dll_4(chrome_dir_4);
- chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_4.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
-
- scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
- ChromePackageProperties properties;
- scoped_refptr<Package> package(new Package(false, true, chrome_dir,
- &properties));
- package->RemoveOldVersionDirectories(*latest_version.get());
-
- // old versions should be gone
- EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
- EXPECT_FALSE(file_util::PathExists(chrome_dir_2));
- EXPECT_FALSE(file_util::PathExists(chrome_dir_3));
- // the latest version should stay
- EXPECT_TRUE(file_util::PathExists(chrome_dll_4));
-}
-
-// Delete older version directories, keeping the one in used intact.
-TEST_F(SetupHelperTest, DeleteInUsed) {
- // Create a Chrome dir
- FilePath chrome_dir(test_dir_);
- chrome_dir = chrome_dir.AppendASCII("chrome");
- file_util::CreateDirectory(chrome_dir);
- ASSERT_TRUE(file_util::PathExists(chrome_dir));
-
- FilePath chrome_dir_1(chrome_dir);
- chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0");
- file_util::CreateDirectory(chrome_dir_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_1));
-
- FilePath chrome_dir_2(chrome_dir);
- chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0");
- file_util::CreateDirectory(chrome_dir_2);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_2));
-
- FilePath chrome_dir_3(chrome_dir);
- chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0");
- file_util::CreateDirectory(chrome_dir_3);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_3));
-
- FilePath chrome_dir_4(chrome_dir);
- chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0");
- file_util::CreateDirectory(chrome_dir_4);
- ASSERT_TRUE(file_util::PathExists(chrome_dir_4));
-
- FilePath chrome_dll_1(chrome_dir_1);
- chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_1.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_1));
-
- FilePath chrome_dll_2(chrome_dir_2);
- chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_2.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_2));
-
- // Open the file to make it in use.
- std::ofstream file;
- file.open(chrome_dll_2.value().c_str());
-
- FilePath chrome_othera_2(chrome_dir_2);
- chrome_othera_2 = chrome_othera_2.AppendASCII("othera.dll");
- CreateTextFile(chrome_othera_2.value(), text_content_2);
- ASSERT_TRUE(file_util::PathExists(chrome_othera_2));
-
- FilePath chrome_otherb_2(chrome_dir_2);
- chrome_otherb_2 = chrome_otherb_2.AppendASCII("otherb.dll");
- CreateTextFile(chrome_otherb_2.value(), text_content_2);
- ASSERT_TRUE(file_util::PathExists(chrome_otherb_2));
-
- FilePath chrome_dll_3(chrome_dir_3);
- chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_3.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_3));
-
- FilePath chrome_dll_4(chrome_dir_4);
- chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll");
- CreateTextFile(chrome_dll_4.value(), text_content_1);
- ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
-
- scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
- ChromePackageProperties properties;
- scoped_refptr<Package> install_path(new Package(false, true, chrome_dir,
- &properties));
- install_path->RemoveOldVersionDirectories(*latest_version.get());
-
- // old versions not in used should be gone
- EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
- EXPECT_FALSE(file_util::PathExists(chrome_dir_3));
- // every thing under in used version should stay
- EXPECT_TRUE(file_util::PathExists(chrome_dir_2));
- EXPECT_TRUE(file_util::PathExists(chrome_dll_2));
- EXPECT_TRUE(file_util::PathExists(chrome_othera_2));
- EXPECT_TRUE(file_util::PathExists(chrome_otherb_2));
- // the latest version should stay
- EXPECT_TRUE(file_util::PathExists(chrome_dll_4));
-}
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 0e598dd..48af659 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -12,24 +12,24 @@
#include <algorithm>
+#include "base/command_line.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/values.h"
+#include "base/version.h"
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
-#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/work_item_list.h"
using base::win::RegKey;
-using installer::MasterPreferences;
bool InstallUtil::ExecuteExeAsAdmin(const CommandLine& cmd, DWORD* exit_code) {
FilePath::StringType program(cmd.GetProgram().value());
@@ -240,3 +240,25 @@ int InstallUtil::GetInstallReturnCode(installer::InstallStatus status) {
return status;
}
}
+
+// static
+void InstallUtil::MakeUninstallCommand(const std::wstring& exe_path,
+ const std::wstring& arguments,
+ CommandLine* command_line) {
+ const bool no_program = exe_path.empty();
+
+ // Return a bunch of nothingness.
+ if (no_program && arguments.empty()) {
+ *command_line = CommandLine(CommandLine::NO_PROGRAM);
+ } else {
+ // Form a full command line string.
+ std::wstring command;
+ command.append(1, L'"')
+ .append(no_program ? L"" : exe_path)
+ .append(L"\" ")
+ .append(arguments);
+
+ // If we have a program name, return this complete command line.
+ *command_line = CommandLine::FromString(command);
+ }
+}
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index f2ba551..1912c09 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -15,13 +15,12 @@
#include <string>
#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/version.h"
-#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/util_constants.h"
-class WorkItemList;
class BrowserDistribution;
+class CommandLine;
+class Version;
+class WorkItemList;
namespace base {
namespace win {
@@ -107,6 +106,11 @@ class InstallUtil {
// Returns zero on install success, or an InstallStatus value otherwise.
static int GetInstallReturnCode(installer::InstallStatus install_status);
+ // Composes |exe_path| and |arguments| into |command_line|.
+ static void MakeUninstallCommand(const std::wstring& exe_path,
+ const std::wstring& arguments,
+ CommandLine* command_line);
+
private:
DISALLOW_COPY_AND_ASSIGN(InstallUtil);
};
diff --git a/chrome/installer/util/install_util_unittest.cc b/chrome/installer/util/install_util_unittest.cc
index b0e05ba..a5cb86f 100644
--- a/chrome/installer/util/install_util_unittest.cc
+++ b/chrome/installer/util/install_util_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <string>
+#include <utility>
#include "base/command_line.h"
#include "base/win/registry.h"
@@ -34,17 +35,17 @@ TEST_F(InstallUtilTest, InstallerResult) {
// 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"));
+ CommandLine cmd_line = CommandLine::FromString(L"setup.exe --system-level");
+ const MasterPreferences prefs(cmd_line);
InstallationState machine_state;
- machine_state.Initialize(prefs);
+ machine_state.Initialize();
InstallerState state;
- state.Initialize(prefs, machine_state);
+ state.Initialize(cmd_line, 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);
+ BrowserDistribution::CHROME_BROWSER);
EXPECT_EQ(ERROR_SUCCESS,
key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
EXPECT_EQ(ERROR_SUCCESS,
@@ -56,18 +57,18 @@ TEST_F(InstallUtilTest, InstallerResult) {
// 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"));
+ CommandLine cmd_line = CommandLine::FromString(
+ L"setup.exe --system-level --multi-install --chrome");
+ const MasterPreferences prefs(cmd_line);
InstallationState machine_state;
- machine_state.Initialize(prefs);
+ machine_state.Initialize();
InstallerState state;
- state.Initialize(prefs, machine_state);
+ state.Initialize(cmd_line, 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);
+ BrowserDistribution::CHROME_BROWSER);
EXPECT_EQ(ERROR_SUCCESS,
key.Open(root, distribution->GetStateKey().c_str(), KEY_READ));
EXPECT_EQ(ERROR_SUCCESS,
@@ -77,3 +78,27 @@ TEST_F(InstallUtilTest, InstallerResult) {
}
TempRegKeyOverride::DeleteAllTempKeys();
}
+
+TEST_F(InstallUtilTest, MakeUninstallCommand) {
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+
+ std::pair<std::wstring, std::wstring> params[] = {
+ std::make_pair(std::wstring(L""), std::wstring(L"")),
+ std::make_pair(std::wstring(L""), std::wstring(L"--do-something --silly")),
+ std::make_pair(std::wstring(L"spam.exe"), std::wstring(L"")),
+ std::make_pair(std::wstring(L"spam.exe"),
+ std::wstring(L"--do-something --silly")),
+ };
+ for (int i = 0; i < arraysize(params); ++i) {
+ std::pair<std::wstring, std::wstring>& param = params[i];
+ InstallUtil::MakeUninstallCommand(param.first, param.second, &command_line);
+ EXPECT_EQ(param.first, command_line.GetProgram().value());
+ if (param.second.empty()) {
+ EXPECT_EQ(0U, command_line.GetSwitchCount());
+ } else {
+ EXPECT_EQ(2U, command_line.GetSwitchCount());
+ EXPECT_TRUE(command_line.HasSwitch("do-something"));
+ EXPECT_TRUE(command_line.HasSwitch("silly"));
+ }
+ }
+}
diff --git a/chrome/installer/util/installation_state.cc b/chrome/installer/util/installation_state.cc
index c0ab82d..f766195 100644
--- a/chrome/installer/util/installation_state.cc
+++ b/chrome/installer/util/installation_state.cc
@@ -9,33 +9,82 @@
#include "base/version.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/install_util.h"
namespace installer {
-ProductState::ProductState() {
+ProductState::ProductState()
+ : uninstall_command_(CommandLine::NO_PROGRAM),
+ msi_(false),
+ multi_install_(false) {
}
-void ProductState::Initialize(bool system_install,
- const std::wstring& version_key,
- const std::wstring& state_key) {
+bool ProductState::Initialize(bool system_install,
+ BrowserDistribution::Type type) {
+ return Initialize(system_install,
+ BrowserDistribution::GetSpecificDistribution(type));
+}
+
+bool ProductState::Initialize(bool system_install,
+ BrowserDistribution* distribution) {
+ const std::wstring version_key(distribution->GetVersionKey());
+ const std::wstring state_key(distribution->GetStateKey());
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)
- == ERROR_SUCCESS) {
+ if (key.ReadValue(google_update::kRegVersionField,
+ &version_str) == ERROR_SUCCESS) {
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) !=
- ERROR_SUCCESS) || !channel_.Initialize(key)) {
- channel_.set_value(std::wstring());
+ // The product is installed.
+ if (key.ReadValue(google_update::kRegOldVersionField,
+ &version_str) == ERROR_SUCCESS) {
+ old_version_.reset(
+ Version::GetVersionFromString(WideToASCII(version_str)));
+ } else {
+ old_version_.reset();
+ }
+ if (key.ReadValue(google_update::kRegRenameCmdField,
+ &rename_cmd_) != ERROR_SUCCESS)
+ rename_cmd_.clear();
+ // Read from the ClientState key.
+ channel_.set_value(std::wstring());
+ uninstall_command_ = CommandLine(CommandLine::NO_PROGRAM);
+ msi_ = false;
+ multi_install_ = false;
+ if (key.Open(root_key, state_key.c_str(),
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+ std::wstring setup_path;
+ std::wstring uninstall_arguments;
+ // "ap" will be absent if not managed by Google Update.
+ channel_.Initialize(key);
+ // "UninstallString" will be absent for the multi-installer package.
+ key.ReadValue(kUninstallStringField, &setup_path);
+ // "UninstallArguments" will be absent for the multi-installer package.
+ key.ReadValue(kUninstallArgumentsField, &uninstall_arguments);
+ InstallUtil::MakeUninstallCommand(setup_path, uninstall_arguments,
+ &uninstall_command_);
+ // "msi" may be absent, 0 or 1
+ DWORD dw_value = 0;
+ msi_ = (key.ReadValueDW(google_update::kRegMSIField,
+ &dw_value) == ERROR_SUCCESS) && (dw_value != 0);
+ // Multi-install is implied or is derived from the command-line.
+ if (distribution->GetType() == BrowserDistribution::CHROME_BINARIES) {
+ multi_install_ = true;
+ } else {
+ multi_install_ = uninstall_command_.HasSwitch(
+ switches::kMultiInstall);
+ }
}
}
} else {
version_.reset();
}
+ return version_.get() != NULL;
+}
+
+FilePath ProductState::GetSetupPath() const {
+ return uninstall_command_.GetProgram();
}
const Version& ProductState::version() const {
@@ -43,12 +92,17 @@ const Version& ProductState::version() const {
return *version_;
}
-void ProductState::CopyFrom(const ProductState& other) {
+ProductState& ProductState::CopyFrom(const ProductState& other) {
channel_.set_value(other.channel_.value());
- if (other.version_.get() == NULL)
- version_.reset();
- else
- version_.reset(other.version_->Clone());
+ version_.reset(other.version_.get() == NULL ? NULL : other.version_->Clone());
+ old_version_.reset(
+ other.old_version_.get() == NULL ? NULL : other.old_version_->Clone());
+ rename_cmd_ = other.rename_cmd_;
+ uninstall_command_ = other.uninstall_command_;
+ msi_ = other.msi_;
+ multi_install_ = other.multi_install_;
+
+ return *this;
}
InstallationState::InstallationState() {
@@ -60,53 +114,31 @@ int InstallationState::IndexFromDistType(BrowserDistribution::Type type) {
unexpected_chrome_browser_distribution_value_);
COMPILE_ASSERT(BrowserDistribution::CHROME_FRAME == CHROME_FRAME_INDEX,
unexpected_chrome_frame_distribution_value_);
+ COMPILE_ASSERT(BrowserDistribution::CHROME_BINARIES == CHROME_BINARIES_INDEX,
+ unexpected_chrome_frame_distribution_value_);
DCHECK(type == BrowserDistribution::CHROME_BROWSER ||
- type == BrowserDistribution::CHROME_FRAME);
+ type == BrowserDistribution::CHROME_FRAME ||
+ type == BrowserDistribution::CHROME_BINARIES);
return type;
}
-void InstallationState::Initialize(const MasterPreferences& prefs) {
+void InstallationState::Initialize() {
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]);
+ BrowserDistribution::CHROME_BROWSER);
+ user_products_[CHROME_BROWSER_INDEX].Initialize(false, distribution);
+ system_products_[CHROME_BROWSER_INDEX].Initialize(true, distribution);
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]);
-}
+ BrowserDistribution::CHROME_FRAME);
+ user_products_[CHROME_FRAME_INDEX].Initialize(false, distribution);
+ system_products_[CHROME_FRAME_INDEX].Initialize(true, distribution);
-// 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;
+ distribution = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BINARIES);
+ user_products_[CHROME_BINARIES_INDEX].Initialize(false, distribution);
+ system_products_[CHROME_BINARIES_INDEX].Initialize(true, distribution);
}
const ProductState* InstallationState::GetProductState(
diff --git a/chrome/installer/util/installation_state.h b/chrome/installer/util/installation_state.h
index 3657c62..817e0af 100644
--- a/chrome/installer/util/installation_state.h
+++ b/chrome/installer/util/installation_state.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -9,6 +9,8 @@
#include <string>
#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
#include "base/scoped_ptr.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/channel_info.h"
@@ -19,44 +21,75 @@ namespace installer {
class InstallationState;
class MasterPreferences;
-class PackageProperties;
+// A representation of a product's state on the machine based on the contents
+// of the Windows registry.
+// TODO(grt): Pull this out into its own file.
class ProductState {
public:
ProductState();
- void Initialize(bool system_install,
- const std::wstring& version_key,
- const std::wstring& state_key);
+ // Returns true if the product is installed (i.e., the product's Clients key
+ // exists and has a "pv" value); false otherwise.
+ bool Initialize(bool system_install,
+ BrowserDistribution::Type type);
+ bool Initialize(bool system_install,
+ BrowserDistribution* distribution);
+
+ // Returns the product's channel info (i.e., the Google Update "ap" value).
const ChannelInfo& channel() const { return channel_; }
- ChannelInfo& channel() { return channel_; }
+ // Returns the path to the product's "setup.exe"; may be empty.
+ FilePath GetSetupPath() const;
+
+ // Returns the product's version. This method may only be called on an
+ // instance that has been initialized for an installed product.
const Version& version() const;
- // Takes ownership of |version|.
- void set_version(Version* version) { version_.reset(version); }
- void CopyFrom(const ProductState& other);
+ // Returns the current version of the product if a new version is awaiting
+ // update; may be NULL. Ownership of a returned value is not passed to the
+ // caller.
+ const Version* old_version() const { return old_version_.get(); }
- private:
- friend class InstallationState;
+ // Returns the command to be used to update to the new version that is
+ // awaiting update; may be empty.
+ const std::wstring& rename_cmd() const { return rename_cmd_; }
+
+ // True if the "msi" value in the ClientState key is present and non-zero.
+ bool is_msi() const { return msi_; }
+
+ // The command to uninstall the product; may be empty.
+ const CommandLine& uninstall_command() const { return uninstall_command_; }
+
+ // True if |uninstall_command| contains --multi-install.
+ bool is_multi_install() const { return multi_install_; }
+
+ // Returns this object a la operator=().
+ ProductState& CopyFrom(const ProductState& other);
+ protected:
ChannelInfo channel_;
scoped_ptr<Version> version_;
+ scoped_ptr<Version> old_version_;
+ std::wstring rename_cmd_;
+ CommandLine uninstall_command_;
+ bool msi_;
+ bool multi_install_;
+
+ private:
+ friend class InstallationState;
+
DISALLOW_COPY_AND_ASSIGN(ProductState);
}; // class ProductState
// Encapsulates the state of all products on the system.
+// TODO(grt): Rename this to MachineState and put it in its own file.
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.
- // Caller does NOT assume ownership of returned pointer.
- const ProductState* GetMultiPackageState(bool system_install) const;
+ // Initializes this object with the machine's current state.
+ void Initialize();
// Returns the state of a product or NULL if not installed.
// Caller does NOT assume ownership of returned pointer.
@@ -67,17 +100,11 @@ class InstallationState {
enum {
CHROME_BROWSER_INDEX,
CHROME_FRAME_INDEX,
- MULTI_PACKAGE_INDEX,
+ CHROME_BINARIES_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];
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
index 69d2841..9137b29 100644
--- a/chrome/installer/util/installer_state.cc
+++ b/chrome/installer/util/installer_state.cc
@@ -4,11 +4,23 @@
#include "chrome/installer/util/installer_state.h"
+#include <algorithm>
+#include <functional>
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/installer/util/delete_tree_work_item.h"
+#include "chrome/installer/util/helper.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"
+#include "chrome/installer/util/product.h"
+#include "chrome/installer/util/work_item.h"
namespace installer {
@@ -16,7 +28,8 @@ bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
const InstallationState& machine_state) {
// First, is the package present?
const ProductState* package =
- machine_state.GetMultiPackageState(system_install_);
+ machine_state.GetProductState(level_ == SYSTEM_LEVEL,
+ BrowserDistribution::CHROME_BINARIES);
if (package == NULL) {
// The multi-install package has not been installed, so it certainly isn't
// being updated.
@@ -33,7 +46,7 @@ bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
for (const BrowserDistribution::Type* scan = &types[0],
*end = &types[num_types]; scan != end; ++scan) {
const ProductState* product =
- machine_state.GetProductState(system_install_, *scan);
+ machine_state.GetProductState(level_ == SYSTEM_LEVEL, *scan);
if (product == NULL) {
VLOG(2) << "It seems that distribution type " << *scan
<< " is being installed for the first time.";
@@ -51,42 +64,382 @@ bool InstallerState::IsMultiInstallUpdate(const MasterPreferences& prefs,
return true;
}
-InstallerState::InstallerState() : operation_(UNINITIALIZED) {
+InstallerState::InstallerState()
+ : operation_(UNINITIALIZED),
+ multi_package_distribution_(NULL),
+ level_(UNKNOWN_LEVEL),
+ package_type_(UNKNOWN_PACKAGE_TYPE),
+ root_key_(NULL),
+ msi_(false),
+ verbose_logging_(false) {
+}
+
+InstallerState::InstallerState(Level level)
+ : operation_(UNINITIALIZED),
+ multi_package_distribution_(NULL),
+ level_(UNKNOWN_LEVEL),
+ package_type_(UNKNOWN_PACKAGE_TYPE),
+ root_key_(NULL),
+ msi_(false),
+ verbose_logging_(false) {
+ // Use set_level() so that root_key_ is updated properly.
+ set_level(level);
}
-void InstallerState::Initialize(const MasterPreferences& prefs,
+void InstallerState::Initialize(const CommandLine& command_line,
+ const MasterPreferences& prefs,
const InstallationState& machine_state) {
- if (!prefs.GetBool(installer::master_preferences::kSystemLevel,
- &system_install_))
- system_install_ = false;
+ bool pref_bool;
+ if (!prefs.GetBool(master_preferences::kSystemLevel, &pref_bool))
+ pref_bool = false;
+ set_level(pref_bool ? SYSTEM_LEVEL : USER_LEVEL);
+
+ if (!prefs.GetBool(master_preferences::kVerboseLogging, &verbose_logging_))
+ verbose_logging_ = false;
+
+ if (!prefs.GetBool(master_preferences::kMultiInstall, &pref_bool))
+ pref_bool = false;
+ set_package_type(pref_bool ? MULTI_PACKAGE : SINGLE_PACKAGE);
+
+ if (!prefs.GetBool(master_preferences::kMsi, &msi_))
+ msi_ = false;
+
+ const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
+
+ if (prefs.install_chrome()) {
+ Product* p =
+ AddProductFromPreferences(BrowserDistribution::CHROME_BROWSER, prefs,
+ machine_state);
+ VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
+ << " distribution: " << p->distribution()->GetApplicationName();
+ }
+ if (prefs.install_chrome_frame()) {
+ Product* p =
+ AddProductFromPreferences(BrowserDistribution::CHROME_FRAME, prefs,
+ machine_state);
+ VLOG(1) << (is_uninstall ? "Uninstall" : "Install")
+ << " distribution: " << p->distribution()->GetApplicationName();
+ }
BrowserDistribution* operand = NULL;
- if (!prefs.is_multi_install()) {
+ if (is_uninstall) {
+ operation_ = UNINSTALL;
+ } else 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;
+ operand = multi_package_distribution_;
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.
+ operation_ = MULTI_INSTALL;
+ }
+
+ if (operand == NULL) {
operand = BrowserDistribution::GetSpecificDistribution(
prefs.install_chrome() ?
BrowserDistribution::CHROME_BROWSER :
- BrowserDistribution::CHROME_FRAME,
- prefs);
- operation_ = MULTI_INSTALL;
+ BrowserDistribution::CHROME_FRAME);
}
- if (operand != NULL) {
- state_key_ = operand->GetStateKey();
+ state_key_ = operand->GetStateKey();
+}
+
+void InstallerState::set_level(Level level) {
+ level_ = level;
+ switch (level) {
+ case USER_LEVEL:
+ root_key_ = HKEY_CURRENT_USER;
+ break;
+ case SYSTEM_LEVEL:
+ root_key_ = HKEY_LOCAL_MACHINE;
+ break;
+ default:
+ DCHECK(level == UNKNOWN_LEVEL);
+ level_ = UNKNOWN_LEVEL;
+ root_key_ = NULL;
+ break;
+ }
+}
+
+void InstallerState::set_package_type(PackageType type) {
+ package_type_ = type;
+ switch (type) {
+ case SINGLE_PACKAGE:
+ multi_package_distribution_ = NULL;
+ break;
+ case MULTI_PACKAGE:
+ multi_package_distribution_ =
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BINARIES);
+ break;
+ default:
+ DCHECK(type == UNKNOWN_PACKAGE_TYPE);
+ package_type_ = UNKNOWN_PACKAGE_TYPE;
+ multi_package_distribution_ = NULL;
+ break;
+ }
+}
+
+// Returns the Chrome binaries directory for multi-install or |dist|'s directory
+// otherwise.
+FilePath InstallerState::GetDefaultProductInstallPath(
+ BrowserDistribution* dist) const {
+ DCHECK(dist);
+ DCHECK(package_type_ != UNKNOWN_PACKAGE_TYPE);
+
+ if (package_type_ == SINGLE_PACKAGE) {
+ return GetChromeInstallPath(system_install(), dist);
+ } else {
+ return GetChromeInstallPath(system_install(),
+ BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BINARIES));
+ }
+}
+
+// Evaluates a product's eligibility for participation in this operation.
+// We never expect these checks to fail, hence they all terminate the process in
+// debug builds. See the log messages for details.
+bool InstallerState::CanAddProduct(const Product& product,
+ const FilePath* product_dir) const {
+ switch (package_type_) {
+ case SINGLE_PACKAGE:
+ if (!products_.empty()) {
+ LOG(DFATAL) << "Cannot process more than one single-install product.";
+ return false;
+ }
+ break;
+ case MULTI_PACKAGE:
+ if (!product.HasOption(kOptionMultiInstall)) {
+ LOG(DFATAL) << "Cannot process a single-install product with a "
+ "multi-install state.";
+ return false;
+ }
+ if (FindProduct(product.distribution()->GetType()) != NULL) {
+ LOG(DFATAL) << "Cannot process more than one product of the same type.";
+ return false;
+ }
+ if (!target_path_.empty()) {
+ FilePath default_dir;
+ if (product_dir == NULL)
+ default_dir = GetDefaultProductInstallPath(product.distribution());
+ if (!FilePath::CompareEqualIgnoreCase(
+ (product_dir == NULL ? default_dir : *product_dir).value(),
+ target_path_.value())) {
+ LOG(DFATAL) << "Cannot process products in different directories.";
+ return false;
+ }
+ }
+ break;
+ default:
+ DCHECK_EQ(UNKNOWN_PACKAGE_TYPE, package_type_);
+ break;
+ }
+ return true;
+}
+
+// Adds |product|, installed in |product_dir| to this object's collection. If
+// |product_dir| is NULL, the product's default install location is used.
+// Returns NULL if |product| is incompatible with this object. Otherwise,
+// returns a pointer to the product (ownership is held by this object).
+Product* InstallerState::AddProductInDirectory(const FilePath* product_dir,
+ scoped_ptr<Product>* product) {
+ DCHECK(product != NULL);
+ DCHECK(product->get() != NULL);
+ const Product& the_product = *product->get();
+
+ if (!CanAddProduct(the_product, product_dir))
+ return NULL;
+
+ if (package_type_ == UNKNOWN_PACKAGE_TYPE) {
+ set_package_type(the_product.HasOption(kOptionMultiInstall) ?
+ MULTI_PACKAGE : SINGLE_PACKAGE);
+ }
+
+ if (target_path_.empty()) {
+ if (product_dir == NULL)
+ target_path_ = GetDefaultProductInstallPath(the_product.distribution());
+ else
+ target_path_ = *product_dir;
+ }
+
+ if (state_key_.empty())
+ state_key_ = the_product.distribution()->GetStateKey();
+
+ products_.push_back(product->release());
+ return products_[products_->size() - 1];
+}
+
+Product* InstallerState::AddProduct(scoped_ptr<Product>* product) {
+ return AddProductInDirectory(NULL, product);
+}
+
+// Adds a product of type |distribution_type| constructed on the basis of
+// |prefs|, setting this object's msi flag if the product is represented in
+// |machine_state| and is msi-installed. Returns the product that was added,
+// or NULL if |state| is incompatible with this object. Ownership is not passed
+// to the caller.
+Product* InstallerState::AddProductFromPreferences(
+ BrowserDistribution::Type distribution_type,
+ const MasterPreferences& prefs,
+ const InstallationState& machine_state) {
+ scoped_ptr<Product> product_ptr(
+ new Product(BrowserDistribution::GetSpecificDistribution(
+ distribution_type)));
+ product_ptr->InitializeFromPreferences(prefs);
+
+ Product* product = AddProductInDirectory(NULL, &product_ptr);
+
+ if (product != NULL && !msi_) {
+ const ProductState* product_state = machine_state.GetProductState(
+ system_install(), distribution_type);
+ if (product_state != NULL)
+ msi_ = product_state->is_msi();
+ }
+
+ return product;
+}
+
+Product* InstallerState::AddProductFromState(
+ BrowserDistribution::Type type,
+ const ProductState& state) {
+ scoped_ptr<Product> product_ptr(
+ new Product(BrowserDistribution::GetSpecificDistribution(type)));
+ product_ptr->InitializeFromUninstallCommand(state.uninstall_command());
+
+ // Strip off <version>/Installer/setup.exe; see GetInstallerDirectory().
+ FilePath product_dir = state.GetSetupPath().DirName().DirName().DirName();
+
+ Product* product = AddProductInDirectory(&product_dir, &product_ptr);
+
+ if (product != NULL)
+ msi_ |= state.is_msi();
+
+ return product;
+}
+
+bool InstallerState::system_install() const {
+ DCHECK(level_ == USER_LEVEL || level_ == SYSTEM_LEVEL);
+ return level_ == SYSTEM_LEVEL;
+}
+
+bool InstallerState::is_multi_install() const {
+ DCHECK(package_type_ == SINGLE_PACKAGE || package_type_ == MULTI_PACKAGE);
+ return package_type_ != SINGLE_PACKAGE;
+}
+
+bool InstallerState::RemoveProduct(const Product* product) {
+ ScopedVector<Product>::iterator it =
+ std::find(products_.begin(), products_.end(), product);
+ if (it != products_.end()) {
+ products_->erase(it);
+ return true;
+ }
+ return false;
+}
+
+const Product* InstallerState::FindProduct(
+ BrowserDistribution::Type distribution_type) const {
+ for (Products::const_iterator scan = products_.begin(), end = products_.end();
+ scan != end; ++scan) {
+ if ((*scan)->is_type(distribution_type))
+ return *scan;
+ }
+ return NULL;
+}
+
+Version* InstallerState::GetCurrentVersion(
+ const InstallationState& machine_state) const {
+ DCHECK(!products_.empty());
+ scoped_ptr<Version> current_version;
+ const BrowserDistribution::Type prod_type = (package_type_ == MULTI_PACKAGE) ?
+ BrowserDistribution::CHROME_BINARIES :
+ products_[0]->distribution()->GetType();
+ const ProductState* product_state =
+ machine_state.GetProductState(level_ == SYSTEM_LEVEL, prod_type);
+
+ if (product_state != NULL) {
+ const Version* version = NULL;
+
+ // Be aware that there might be a pending "new_chrome.exe" already in the
+ // installation path. If so, we use old_version, which holds the version of
+ // "chrome.exe" itself.
+ if (file_util::PathExists(target_path().Append(kChromeNewExe)))
+ version = product_state->old_version();
+
+ if (version == NULL)
+ version = &product_state->version();
+
+ current_version.reset(version->Clone());
+ }
+
+ return current_version.release();
+}
+
+FilePath InstallerState::GetInstallerDirectory(const Version& version) const {
+ return target_path().Append(ASCIIToWide(version.GetString()))
+ .Append(kInstallerDir);
+}
+
+void InstallerState::RemoveOldVersionDirectories(
+ const Version& latest_version) const {
+ file_util::FileEnumerator version_enum(target_path(), false,
+ file_util::FileEnumerator::DIRECTORIES);
+ scoped_ptr<Version> version;
+ std::vector<FilePath> key_files;
+
+ // We try to delete all directories whose versions are lower than
+ // latest_version.
+ FilePath next_version = version_enum.Next();
+ while (!next_version.empty()) {
+ file_util::FileEnumerator::FindInfo find_data = {0};
+ version_enum.GetFindInfo(&find_data);
+ VLOG(1) << "directory found: " << find_data.cFileName;
+ version.reset(Version::GetVersionFromString(
+ WideToASCII(find_data.cFileName)));
+ if (version.get() && latest_version.CompareTo(*version) > 0) {
+ key_files.clear();
+ std::for_each(products_.begin(), products_.end(),
+ std::bind2nd(std::mem_fun(&Product::AddKeyFiles),
+ &key_files));
+ const std::vector<FilePath>::iterator end = key_files.end();
+ for (std::vector<FilePath>::iterator scan = key_files.begin();
+ scan != end; ++scan) {
+ *scan = next_version.Append(*scan);
+ }
+
+ VLOG(1) << "Deleting directory: " << next_version.value();
+
+ scoped_ptr<WorkItem> item(
+ WorkItem::CreateDeleteTreeWorkItem(next_version, key_files));
+ if (!item->Do())
+ item->Rollback();
+ }
+
+ next_version = version_enum.Next();
+ }
+}
+
+void InstallerState::AddComDllList(std::vector<FilePath>* com_dll_list) const {
+ std::for_each(products_.begin(), products_.end(),
+ std::bind2nd(std::mem_fun(&Product::AddComDllList),
+ com_dll_list));
+}
+
+bool InstallerState::SetChannelFlags(bool set,
+ ChannelInfo* channel_info) const {
+ bool modified = false;
+ for (Products::const_iterator scan = products_.begin(), end = products_.end();
+ scan != end; ++scan) {
+ modified |= (*scan)->SetChannelFlags(set, channel_info);
}
+ return modified;
}
} // namespace installer
diff --git a/chrome/installer/util/installer_state.h b/chrome/installer/util/installer_state.h
index 0bc2a5f..0b4ea0b 100644
--- a/chrome/installer/util/installer_state.h
+++ b/chrome/installer/util/installer_state.h
@@ -7,47 +7,183 @@
#pragma once
#include <string>
+#include <vector>
#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_vector.h"
#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/product.h"
+
+#if defined(OS_WIN)
+#include <windows.h> // NOLINT
+#endif
+
+class CommandLine;
+class Version;
namespace installer {
+class ChannelInfo;
class InstallationState;
class MasterPreferences;
+class ProductState;
+
+typedef std::vector<Product*> Products;
+
// Encapsulates the state of the current installation operation. Only valid
-// for installs and upgrades (not for uninstalls or non-install commands)
+// for installs and upgrades (not for uninstalls or non-install commands).
+// TODO(grt): Rename to InstallerEngine/Conductor or somesuch?
class InstallerState {
public:
+ enum Level {
+ UNKNOWN_LEVEL,
+ USER_LEVEL,
+ SYSTEM_LEVEL
+ };
+
+ enum PackageType {
+ UNKNOWN_PACKAGE_TYPE,
+ SINGLE_PACKAGE,
+ MULTI_PACKAGE
+ };
+
enum Operation {
UNINITIALIZED,
SINGLE_INSTALL_OR_UPDATE,
MULTI_INSTALL,
MULTI_UPDATE,
+ UNINSTALL
};
+ // Constructs an uninitialized instance; see Initialize().
InstallerState();
- // Initializes |this| based on the current operation.
- void Initialize(const MasterPreferences& prefs,
+ // Constructs an initialized but empty instance.
+ explicit InstallerState(Level level);
+
+ // Initializes this object based on the current operation.
+ void Initialize(const CommandLine& command_line,
+ const MasterPreferences& prefs,
const InstallationState& machine_state);
- // true if system-level, false if user-level.
- bool system_install() const { return system_install_; }
+ // Adds a product constructed on the basis of |state|, setting this object's
+ // msi flag if |state| is msi-installed. Returns the product that was added,
+ // or NULL if |state| is incompatible with this object. Ownership is not
+ // passed to the caller.
+ Product* AddProductFromState(BrowserDistribution::Type type,
+ const ProductState& state);
+
+ // Returns the product that was added, or NULL if |product| is incompatible
+ // with this object. Ownership of |product| is taken by this object, while
+ // ownership of the return value is not passed to the caller.
+ Product* AddProduct(scoped_ptr<Product>* product);
+
+ // Removes |product| from the set of products to be operated on. The object
+ // pointed to by |product| is freed. Returns false if |product| is not
+ // present in the set.
+ bool RemoveProduct(const Product* product);
+
+ // The level (user or system) of this operation.
+ Level level() const { return level_; }
+ // The package type (single or multi) of this operation.
+ PackageType package_type() const { return package_type_; }
+
+ // An identifier of this operation.
Operation operation() const { return operation_; }
+ // A convenience method returning level() == SYSTEM_LEVEL.
+ // TODO(grt): Eradicate the bool in favor of the enum.
+ bool system_install() const;
+
+ // A convenience method returning package_type() == MULTI_PACKAGE.
+ // TODO(grt): Eradicate the bool in favor of the enum.
+ bool is_multi_install() const;
+
+ // The full path to the place where the operand resides.
+ const FilePath& target_path() const { return target_path_; }
+
+ // True if the "msi" preference is set or if a product with the "msi" state
+ // flag is set is to be operated on.
+ bool is_msi() const { return msi_; }
+
+ // True if the --verbose-logging command-line flag is set or if the
+ // verbose_logging master preferences option is true.
+ bool verbose_logging() const { return verbose_logging_; }
+
+#if defined(OS_WIN)
+ HKEY root_key() const { return root_key_; }
+#endif
+
// The ClientState key by which we interact with Google Update.
const std::wstring& state_key() const { return state_key_; }
+ // Returns the BrowserDistribution instance corresponding to the binaries for
+ // this run if we're operating on a multi-package product.
+ BrowserDistribution* multi_package_binaries_distribution() const {
+ DCHECK(package_type_ == MULTI_PACKAGE);
+ DCHECK(multi_package_distribution_ != NULL);
+ return multi_package_distribution_;
+ }
+
+ const Products& products() const { return products_.get(); }
+
+ // Returns the product of the desired type, or NULL if none found.
+ const Product* FindProduct(BrowserDistribution::Type distribution_type) const;
+
+ // Returns the currently installed version in |target_path|, or NULL if no
+ // products are installed. Ownership is passed to the caller.
+ Version* GetCurrentVersion(const InstallationState& machine_state) const;
+
+ // Returns the path to the installer under Chrome version folder
+ // (for example <target_path>\Google\Chrome\Application\<Version>\Installer)
+ FilePath GetInstallerDirectory(const Version& version) const;
+
+ // Try to delete all directories whose versions are lower than
+ // |latest_version|.
+ void RemoveOldVersionDirectories(const Version& latest_version) const;
+
+ // Adds to |com_dll_list| the list of COM DLLs that are to be registered
+ // and/or unregistered. The list may be empty.
+ void AddComDllList(std::vector<FilePath>* com_dll_list) const;
+
+ bool SetChannelFlags(bool set, ChannelInfo* channel_info) const;
+
protected:
+ FilePath GetDefaultProductInstallPath(BrowserDistribution* dist) const;
+ bool CanAddProduct(const Product& product, const FilePath* product_dir) const;
+ Product* AddProductInDirectory(const FilePath* product_dir,
+ scoped_ptr<Product>* product);
+ Product* AddProductFromPreferences(
+ BrowserDistribution::Type distribution_type,
+ const MasterPreferences& prefs,
+ const InstallationState& machine_state);
bool IsMultiInstallUpdate(const MasterPreferences& prefs,
const InstallationState& machine_state);
+ // Sets this object's level and updates the root_key_ accordingly.
+ void set_level(Level level);
+
+ // Sets this object's package type and updates the multi_package_distribution_
+ // accordingly.
+ void set_package_type(PackageType type);
+
Operation operation_;
+ FilePath target_path_;
std::wstring state_key_;
- bool system_install_;
+ ScopedVector<Product> products_;
+ BrowserDistribution* multi_package_distribution_;
+ Level level_;
+ PackageType package_type_;
+#if defined(OS_WIN)
+ HKEY root_key_;
+#endif
+ bool msi_;
+ bool verbose_logging_;
private:
DISALLOW_COPY_AND_ASSIGN(InstallerState);
diff --git a/chrome/installer/util/installer_state_unittest.cc b/chrome/installer/util/installer_state_unittest.cc
new file mode 100644
index 0000000..25efc07
--- /dev/null
+++ b/chrome/installer/util/installer_state_unittest.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2011 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 <windows.h>
+
+#include <fstream>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/version.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_handle.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/helper.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/product_unittest.h"
+#include "chrome/installer/util/work_item.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class InstallerStateTest : public TestWithTempDirAndDeleteTempOverrideKeys {
+ protected:
+};
+
+// An installer state on which we can tweak the target path.
+class MockInstallerState : public installer::InstallerState {
+ public:
+ MockInstallerState() : InstallerState() { }
+ void set_target_path(const FilePath& target_path) {
+ target_path_ = target_path;
+ }
+};
+
+// Simple function to dump some text into a new file.
+void CreateTextFile(const std::wstring& filename,
+ const std::wstring& contents) {
+ std::ofstream file;
+ file.open(filename.c_str());
+ ASSERT_TRUE(file.is_open());
+ file << contents;
+ file.close();
+}
+
+void BuildSingleChromeState(const FilePath& target_dir,
+ MockInstallerState* installer_state) {
+ CommandLine cmd_line = CommandLine::FromString(L"setup.exe");
+ installer::MasterPreferences prefs(cmd_line);
+ installer::InstallationState machine_state;
+ machine_state.Initialize();
+ installer_state->Initialize(cmd_line, prefs, machine_state);
+ installer_state->set_target_path(target_dir);
+ EXPECT_TRUE(installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER)
+ != NULL);
+ EXPECT_TRUE(installer_state->FindProduct(BrowserDistribution::CHROME_FRAME)
+ == NULL);
+}
+
+wchar_t text_content_1[] = L"delete me";
+wchar_t text_content_2[] = L"delete me as well";
+
+// Delete version directories. Everything lower than the given version
+// should be deleted.
+TEST_F(InstallerStateTest, Delete) {
+ // TODO(grt): move common stuff into the test fixture.
+ // Create a Chrome dir
+ FilePath chrome_dir(test_dir_.path());
+ chrome_dir = chrome_dir.AppendASCII("chrome");
+ file_util::CreateDirectory(chrome_dir);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir));
+
+ FilePath chrome_dir_1(chrome_dir);
+ chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0");
+ file_util::CreateDirectory(chrome_dir_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_1));
+
+ FilePath chrome_dir_2(chrome_dir);
+ chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0");
+ file_util::CreateDirectory(chrome_dir_2);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_2));
+
+ FilePath chrome_dir_3(chrome_dir);
+ chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0");
+ file_util::CreateDirectory(chrome_dir_3);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_3));
+
+ FilePath chrome_dir_4(chrome_dir);
+ chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0");
+ file_util::CreateDirectory(chrome_dir_4);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_4));
+
+ FilePath chrome_dll_1(chrome_dir_1);
+ chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_1.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_1));
+
+ FilePath chrome_dll_2(chrome_dir_2);
+ chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_2.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_2));
+
+ FilePath chrome_dll_3(chrome_dir_3);
+ chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_3.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_3));
+
+ FilePath chrome_dll_4(chrome_dir_4);
+ chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_4.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
+
+ MockInstallerState installer_state;
+ BuildSingleChromeState(chrome_dir, &installer_state);
+ scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
+ installer_state.RemoveOldVersionDirectories(*latest_version.get());
+
+ // old versions should be gone
+ EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
+ EXPECT_FALSE(file_util::PathExists(chrome_dir_2));
+ EXPECT_FALSE(file_util::PathExists(chrome_dir_3));
+ // the latest version should stay
+ EXPECT_TRUE(file_util::PathExists(chrome_dll_4));
+}
+
+// Delete older version directories, keeping the one in used intact.
+TEST_F(InstallerStateTest, DeleteInUsed) {
+ // Create a Chrome dir
+ FilePath chrome_dir(test_dir_.path());
+ chrome_dir = chrome_dir.AppendASCII("chrome");
+ file_util::CreateDirectory(chrome_dir);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir));
+
+ FilePath chrome_dir_1(chrome_dir);
+ chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0");
+ file_util::CreateDirectory(chrome_dir_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_1));
+
+ FilePath chrome_dir_2(chrome_dir);
+ chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0");
+ file_util::CreateDirectory(chrome_dir_2);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_2));
+
+ FilePath chrome_dir_3(chrome_dir);
+ chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0");
+ file_util::CreateDirectory(chrome_dir_3);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_3));
+
+ FilePath chrome_dir_4(chrome_dir);
+ chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0");
+ file_util::CreateDirectory(chrome_dir_4);
+ ASSERT_TRUE(file_util::PathExists(chrome_dir_4));
+
+ FilePath chrome_dll_1(chrome_dir_1);
+ chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_1.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_1));
+
+ FilePath chrome_dll_2(chrome_dir_2);
+ chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_2.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_2));
+
+ // Open the file to make it in use.
+ std::ofstream file;
+ file.open(chrome_dll_2.value().c_str());
+
+ FilePath chrome_othera_2(chrome_dir_2);
+ chrome_othera_2 = chrome_othera_2.AppendASCII("othera.dll");
+ CreateTextFile(chrome_othera_2.value(), text_content_2);
+ ASSERT_TRUE(file_util::PathExists(chrome_othera_2));
+
+ FilePath chrome_otherb_2(chrome_dir_2);
+ chrome_otherb_2 = chrome_otherb_2.AppendASCII("otherb.dll");
+ CreateTextFile(chrome_otherb_2.value(), text_content_2);
+ ASSERT_TRUE(file_util::PathExists(chrome_otherb_2));
+
+ FilePath chrome_dll_3(chrome_dir_3);
+ chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_3.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_3));
+
+ FilePath chrome_dll_4(chrome_dir_4);
+ chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll");
+ CreateTextFile(chrome_dll_4.value(), text_content_1);
+ ASSERT_TRUE(file_util::PathExists(chrome_dll_4));
+
+ MockInstallerState installer_state;
+ BuildSingleChromeState(chrome_dir, &installer_state);
+ scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
+ installer_state.RemoveOldVersionDirectories(*latest_version.get());
+
+ // old versions not in used should be gone
+ EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
+ EXPECT_FALSE(file_util::PathExists(chrome_dir_3));
+ // every thing under in used version should stay
+ EXPECT_TRUE(file_util::PathExists(chrome_dir_2));
+ EXPECT_TRUE(file_util::PathExists(chrome_dll_2));
+ EXPECT_TRUE(file_util::PathExists(chrome_othera_2));
+ EXPECT_TRUE(file_util::PathExists(chrome_otherb_2));
+ // the latest version should stay
+ EXPECT_TRUE(file_util::PathExists(chrome_dll_4));
+}
+
+// Tests a few basic things of the Package class. Makes sure that the path
+// operations are correct
+TEST_F(InstallerStateTest, Basic) {
+ const bool multi_install = false;
+ const bool system_level = true;
+ CommandLine cmd_line = CommandLine::FromString(
+ std::wstring(L"setup.exe") +
+ (multi_install ? L" --multi-install --chrome" : L"") +
+ (system_level ? L" --system-level" : L""));
+ installer::MasterPreferences prefs(cmd_line);
+ installer::InstallationState machine_state;
+ machine_state.Initialize();
+ MockInstallerState installer_state;
+ installer_state.Initialize(cmd_line, prefs, machine_state);
+ installer_state.set_target_path(test_dir_.path());
+ EXPECT_EQ(test_dir_.path().value(), installer_state.target_path().value());
+ EXPECT_EQ(1U, installer_state.products().size());
+
+ const char kOldVersion[] = "1.2.3.4";
+ const char kNewVersion[] = "2.3.4.5";
+
+ scoped_ptr<Version> new_version(Version::GetVersionFromString(kNewVersion));
+ scoped_ptr<Version> old_version(Version::GetVersionFromString(kOldVersion));
+ ASSERT_TRUE(new_version.get() != NULL);
+ ASSERT_TRUE(old_version.get() != NULL);
+
+ FilePath installer_dir(
+ installer_state.GetInstallerDirectory(*new_version.get()));
+ EXPECT_FALSE(installer_dir.empty());
+
+ FilePath new_version_dir(installer_state.target_path().Append(
+ UTF8ToWide(new_version->GetString())));
+ FilePath old_version_dir(installer_state.target_path().Append(
+ UTF8ToWide(old_version->GetString())));
+
+ EXPECT_FALSE(file_util::PathExists(new_version_dir));
+ EXPECT_FALSE(file_util::PathExists(old_version_dir));
+
+ EXPECT_FALSE(file_util::PathExists(installer_dir));
+ file_util::CreateDirectory(installer_dir);
+ EXPECT_TRUE(file_util::PathExists(new_version_dir));
+
+ file_util::CreateDirectory(old_version_dir);
+ EXPECT_TRUE(file_util::PathExists(old_version_dir));
+
+ // Create a fake chrome.dll key file in the old version directory. This
+ // should prevent the old version directory from getting deleted.
+ FilePath old_chrome_dll(old_version_dir.Append(installer::kChromeDll));
+ EXPECT_FALSE(file_util::PathExists(old_chrome_dll));
+
+ // Hold on to the file exclusively to prevent the directory from
+ // being deleted.
+ base::win::ScopedHandle file(
+ ::CreateFile(old_chrome_dll.value().c_str(), GENERIC_READ,
+ 0, NULL, OPEN_ALWAYS, 0, NULL));
+ EXPECT_TRUE(file.IsValid());
+ EXPECT_TRUE(file_util::PathExists(old_chrome_dll));
+
+ installer_state.RemoveOldVersionDirectories(*new_version.get());
+ // The old directory should still exist.
+ EXPECT_TRUE(file_util::PathExists(old_version_dir));
+ EXPECT_TRUE(file_util::PathExists(new_version_dir));
+
+ // Now close the file handle to make it possible to delete our key file.
+ file.Close();
+
+ installer_state.RemoveOldVersionDirectories(*new_version.get());
+ // The new directory should still exist.
+ EXPECT_TRUE(file_util::PathExists(new_version_dir));
+
+ // Now, the old directory and key file should be gone.
+ EXPECT_FALSE(file_util::PathExists(old_chrome_dll));
+ EXPECT_FALSE(file_util::PathExists(old_version_dir));
+}
+
+TEST_F(InstallerStateTest, WithProduct) {
+ const bool multi_install = false;
+ const bool system_level = true;
+ CommandLine cmd_line = CommandLine::FromString(
+ std::wstring(L"setup.exe") +
+ (multi_install ? L" --multi-install --chrome" : L"") +
+ (system_level ? L" --system-level" : L""));
+ installer::MasterPreferences prefs(cmd_line);
+ installer::InstallationState machine_state;
+ machine_state.Initialize();
+ MockInstallerState installer_state;
+ installer_state.Initialize(cmd_line, prefs, machine_state);
+ installer_state.set_target_path(test_dir_.path());
+ EXPECT_EQ(1U, installer_state.products().size());
+ EXPECT_EQ(system_level, installer_state.system_install());
+
+ const char kCurrentVersion[] = "1.2.3.4";
+ scoped_ptr<Version> current_version(
+ Version::GetVersionFromString(kCurrentVersion));
+
+ HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ EXPECT_EQ(root, installer_state.root_key());
+ {
+ TempRegKeyOverride override(root, L"root_pit");
+ BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER);
+ base::win::RegKey chrome_key(root, dist->GetVersionKey().c_str(),
+ KEY_ALL_ACCESS);
+ EXPECT_TRUE(chrome_key.Valid());
+ if (chrome_key.Valid()) {
+ chrome_key.WriteValue(google_update::kRegVersionField,
+ UTF8ToWide(current_version->GetString()).c_str());
+ machine_state.Initialize();
+ // TODO(tommi): Also test for when there exists a new_chrome.exe.
+ scoped_ptr<Version> found_version(installer_state.GetCurrentVersion(
+ machine_state));
+ EXPECT_TRUE(found_version.get() != NULL);
+ if (found_version.get()) {
+ EXPECT_TRUE(current_version->Equals(*found_version));
+ }
+ }
+ }
+}
diff --git a/chrome/installer/util/package.cc b/chrome/installer/util/package.cc
deleted file mode 100644
index 3122cef..0000000
--- a/chrome/installer/util/package.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// 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.h"
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#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/helper.h"
-#include "chrome/installer/util/master_preferences.h"
-#include "chrome/installer/util/package_properties.h"
-#include "chrome/installer/util/product.h"
-#include "chrome/installer/util/util_constants.h"
-#include "chrome/installer/util/work_item_list.h"
-
-using base::win::RegKey;
-using installer::MasterPreferences;
-
-namespace installer {
-
-Package::Package(bool multi_install, bool system_level, const FilePath& path,
- PackageProperties* properties)
- : multi_install_(multi_install),
- system_level_(system_level),
- path_(path),
- properties_(properties) {
- DCHECK(properties_);
-}
-
-Package::~Package() {
-}
-
-const FilePath& Package::path() const {
- return path_;
-}
-
-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());
-}
-
-void Package::AssociateProduct(const Product* product) {
-#ifndef NDEBUG
- for (size_t i = 0; i < products_.size(); ++i) {
- DCHECK_NE(product->distribution()->GetType(),
- products_[i]->distribution()->GetType());
- }
-#endif
- products_.push_back(product);
-}
-
-bool Package::multi_install() const {
- return multi_install_;
-}
-
-bool Package::system_level() const {
- return system_level_;
-}
-
-FilePath Package::GetInstallerDirectory(
- const Version& version) const {
- return path_.Append(UTF8ToWide(version.GetString()))
- .Append(installer::kInstallerDir);
-}
-
-Version* Package::GetCurrentVersion() const {
- scoped_ptr<Version> current_version;
- // Be aware that there might be a pending "new_chrome.exe" already in the
- // installation path.
- 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];
- RegKey chrome_key(root, product->distribution()->GetVersionKey().c_str(),
- KEY_READ);
- std::wstring version;
- if (new_chrome_exists)
- chrome_key.ReadValue(google_update::kRegOldVersionField, &version);
-
- if (version.empty())
- chrome_key.ReadValue(google_update::kRegVersionField, &version);
-
- if (!version.empty()) {
- scoped_ptr<Version> this_version(Version::GetVersionFromString(
- WideToASCII(version)));
- if (this_version.get()) {
- if (!current_version.get() ||
- (current_version->CompareTo(*this_version) > 0)) {
- current_version.reset(this_version.release());
- } else if (current_version.get()) {
- DCHECK_EQ(current_version->GetString(), this_version->GetString())
- << "found distributions of different versions in the same "
- "installation folder!";
- }
- }
- }
- }
-
- return current_version.release();
-}
-
-void Package::RemoveOldVersionDirectories(
- const Version& latest_version) const {
- file_util::FileEnumerator version_enum(path_, false,
- file_util::FileEnumerator::DIRECTORIES);
- scoped_ptr<Version> version;
-
- // We try to delete all directories whose versions are lower than
- // latest_version.
- FilePath next_version = version_enum.Next();
- while (!next_version.empty()) {
- file_util::FileEnumerator::FindInfo find_data = {0};
- version_enum.GetFindInfo(&find_data);
- VLOG(1) << "directory found: " << find_data.cFileName;
- version.reset(Version::GetVersionFromString(
- WideToASCII(find_data.cFileName)));
- if (version.get() && (latest_version.CompareTo(*version) > 0)) {
- std::vector<FilePath> key_files;
- for (Products::const_iterator it = products_.begin();
- it != products_.end(); ++it) {
- BrowserDistribution* dist = it->get()->distribution();
- std::vector<FilePath> dist_key_files(dist->GetKeyFiles());
- std::vector<FilePath>::const_iterator key_file_iter(
- dist_key_files.begin());
- for (; key_file_iter != dist_key_files.end(); ++key_file_iter) {
- key_files.push_back(next_version.Append(*key_file_iter));
- }
- }
-
- VLOG(1) << "Deleting directory: " << next_version.value();
-
- scoped_ptr<DeleteTreeWorkItem> item(
- WorkItem::CreateDeleteTreeWorkItem(next_version, key_files));
- if (!item->Do())
- item->Rollback();
- }
-
- next_version = version_enum.Next();
- }
-}
-
-size_t Package::GetMultiInstallDependencyCount() const {
- BrowserDistribution::Type product_types[] = {
- BrowserDistribution::CHROME_BROWSER,
- BrowserDistribution::CHROME_FRAME,
- };
-
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
- HKEY root_key = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
-
- size_t ret = 0;
-
- for (int i = 0; i < arraysize(product_types); ++i) {
- BrowserDistribution* dist =
- BrowserDistribution::GetSpecificDistribution(product_types[i], prefs);
- // First see if the product is installed by checking its version key.
- // If the key doesn't exist, the product isn't installed.
- RegKey version_key(root_key, dist->GetVersionKey().c_str(), KEY_READ);
- if (!version_key.Valid()) {
- VLOG(1) << "Product not installed: " << dist->GetApplicationName();
- } else {
- if (installer::IsInstalledAsMulti(system_level_, dist)) {
- VLOG(1) << "Product dependency: " << dist->GetApplicationName();
- ++ret;
- }
- }
- }
-
- return ret;
-}
-
-} // namespace installer
-
diff --git a/chrome/installer/util/package.h b/chrome/installer/util/package.h
deleted file mode 100644
index d523fc2..0000000
--- a/chrome/installer/util/package.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// 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_H_
-#define CHROME_INSTALLER_UTIL_PACKAGE_H_
-#pragma once
-
-#include <vector>
-
-#include "base/file_path.h"
-#include "base/ref_counted.h"
-
-class CommandLine;
-class Version;
-
-namespace installer {
-
-enum InstallStatus;
-class Product;
-class PackageProperties;
-
-typedef std::vector<scoped_refptr<const Product> > Products;
-
-// Represents a physical installation. An instance of this class is associated
-// with one or more Product instances. Product objects can share a Package but
-// not vice versa.
-class Package : public base::RefCounted<Package> {
- public:
- Package(bool multi_install, 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 multi_install() const;
-
- bool system_level() const;
-
- bool IsEqual(const FilePath& path) const;
-
- void AssociateProduct(const Product* product);
-
- // Get path to the installer under Chrome version folder
- // (for example <path>\Google\Chrome\Application\<Version>\Installer)
- FilePath GetInstallerDirectory(const Version& version) const;
-
- // Figure out the oldest currently installed version for this package
- // Returns NULL if none is found. Caller is responsible for freeing
- // the returned Version object if valid.
- // The function DCHECKs if it finds that not all products in this
- // folder have the same current version.
- Version* GetCurrentVersion() const;
-
- // Tries to remove all previous version directories (after a new Chrome
- // update). If an instance of Chrome with older version is still running
- // on the system, its corresponding version directory will be left intact.
- // (The version directory is subject for removal again during next update.)
- //
- // latest_version: the latest version of Chrome installed.
- void RemoveOldVersionDirectories(const Version& latest_version) const;
-
- // Returns how many installed products depend on the binaries currently
- // in the installation path.
- // Note: The function counts only products that are installed as part of
- // a multi install installation and only products that have the same
- // system_level() value.
- size_t GetMultiInstallDependencyCount() const;
-
- protected:
- bool multi_install_;
- bool system_level_;
- FilePath path_;
- Products products_;
- PackageProperties* properties_; // Weak reference.
-
- private:
- friend class base::RefCounted<Package>;
- ~Package();
-
- DISALLOW_COPY_AND_ASSIGN(Package);
-};
-
-} // namespace installer
-
-#endif // CHROME_INSTALLER_UTIL_PACKAGE_H_
diff --git a/chrome/installer/util/package_properties.cc b/chrome/installer/util/package_properties.cc
deleted file mode 100644
index e33c2f9..0000000
--- a/chrome/installer/util/package_properties.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2011 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/install_util.h"
-#include "chrome/installer/util/util_constants.h"
-
-namespace {
-
-const wchar_t kChromePackageGuid[] =
- L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
-
-std::wstring GetKeyForGuid(const wchar_t* base_key, const wchar_t* guid) {
- std::wstring key(base_key);
- 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& state_medium_key,
- const std::wstring& version_key)
- : guid_(guid), state_key_(state_key), state_medium_key_(state_medium_key),
- version_key_(version_key) {
-}
-
-PackagePropertiesImpl::~PackagePropertiesImpl() {
-}
-
-const std::wstring& PackagePropertiesImpl::GetAppGuid() {
- return guid_;
-}
-
-const std::wstring& PackagePropertiesImpl::GetStateKey() {
- return state_key_;
-}
-
-const std::wstring& PackagePropertiesImpl::GetStateMediumKey() {
- return state_medium_key_;
-}
-
-const std::wstring& PackagePropertiesImpl::GetVersionKey() {
- return version_key_;
-}
-
-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()
- : PackagePropertiesImpl(L"", L"Software\\Chromium", L"Software\\Chromium",
- L"Software\\Chromium") {
-}
-
-ChromiumPackageProperties::~ChromiumPackageProperties() {
-}
-
-ChromePackageProperties::ChromePackageProperties()
- : PackagePropertiesImpl(
- kChromePackageGuid,
- GetKeyForGuid(google_update::kRegPathClientState,
- kChromePackageGuid),
- GetKeyForGuid(google_update::kRegPathClientStateMedium,
- kChromePackageGuid),
- GetKeyForGuid(google_update::kRegPathClients,
- kChromePackageGuid)) {
-}
-
-ChromePackageProperties::~ChromePackageProperties() {
-}
-
-} // namespace installer
diff --git a/chrome/installer/util/package_properties.h b/chrome/installer/util/package_properties.h
deleted file mode 100644
index 5fd5e5f5..0000000
--- a/chrome/installer/util/package_properties.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2011 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 Google Update.
- virtual bool ReceivesUpdates() const = 0;
-
- // Equivalent to BrowserDistribution::GetAppGuid()
- virtual const std::wstring& GetAppGuid() = 0;
- virtual const std::wstring& GetStateKey() = 0;
- virtual const std::wstring& GetStateMediumKey() = 0;
- virtual const std::wstring& GetVersionKey() = 0;
- virtual void UpdateInstallStatus(bool system_level, bool incremental_install,
- bool multi_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& state_medium_key,
- const std::wstring& version_key);
- virtual ~PackagePropertiesImpl();
-
- virtual const std::wstring& GetAppGuid();
- virtual const std::wstring& GetStateKey();
- virtual const std::wstring& GetStateMediumKey();
- virtual const std::wstring& GetVersionKey();
- virtual void UpdateInstallStatus(bool system_level, bool incremental_install,
- bool multi_install, installer::InstallStatus status);
-
- protected:
- std::wstring guid_;
- std::wstring state_key_;
- std::wstring state_medium_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
-
-#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
deleted file mode 100644
index 000cc72..0000000
--- a/chrome/installer/util/package_properties_unittest.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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()) {
- TempRegKeyOverride override(HKEY_CURRENT_USER, L"props");
- RegKey key;
- EXPECT_EQ(ERROR_SUCCESS,
- 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
deleted file mode 100644
index ea696a7..0000000
--- a/chrome/installer/util/package_unittest.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2011 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/command_line.h"
-#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "chrome/installer/util/browser_distribution.h"
-#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"
-
-using base::win::RegKey;
-using installer::ChromePackageProperties;
-using installer::ChromiumPackageProperties;
-using installer::Package;
-using installer::Product;
-using installer::MasterPreferences;
-
-class PackageTest : public TestWithTempDirAndDeleteTempOverrideKeys {
- protected:
-};
-
-// Tests a few basic things of the Package class. Makes sure that the path
-// operations are correct
-TEST_F(PackageTest, Basic) {
- const bool multi_install = false;
- const bool system_level = true;
- ChromiumPackageProperties properties;
- scoped_refptr<Package> package(new Package(multi_install, 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());
-
- const char kOldVersion[] = "1.2.3.4";
- const char kNewVersion[] = "2.3.4.5";
-
- scoped_ptr<Version> new_version(Version::GetVersionFromString(kNewVersion));
- scoped_ptr<Version> old_version(Version::GetVersionFromString(kOldVersion));
- ASSERT_TRUE(new_version.get() != NULL);
- ASSERT_TRUE(old_version.get() != NULL);
-
- FilePath installer_dir(package->GetInstallerDirectory(*new_version.get()));
- EXPECT_FALSE(installer_dir.empty());
-
- FilePath new_version_dir(package->path().Append(
- UTF8ToWide(new_version->GetString())));
- FilePath old_version_dir(package->path().Append(
- UTF8ToWide(old_version->GetString())));
-
- EXPECT_FALSE(file_util::PathExists(new_version_dir));
- EXPECT_FALSE(file_util::PathExists(old_version_dir));
-
- EXPECT_FALSE(file_util::PathExists(installer_dir));
- file_util::CreateDirectory(installer_dir);
- EXPECT_TRUE(file_util::PathExists(new_version_dir));
-
- file_util::CreateDirectory(old_version_dir);
- EXPECT_TRUE(file_util::PathExists(old_version_dir));
-
- // Create a fake chrome.dll key file in the old version directory. This
- // should prevent the old version directory from getting deleted.
- FilePath old_chrome_dll(old_version_dir.Append(installer::kChromeDll));
- EXPECT_FALSE(file_util::PathExists(old_chrome_dll));
-
- // Hold on to the file exclusively to prevent the directory from
- // being deleted.
- base::win::ScopedHandle file(
- ::CreateFile(old_chrome_dll.value().c_str(), GENERIC_READ,
- 0, NULL, OPEN_ALWAYS, 0, NULL));
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file_util::PathExists(old_chrome_dll));
-
- package->RemoveOldVersionDirectories(*new_version.get());
- // The old directory should still exist.
- EXPECT_TRUE(file_util::PathExists(old_version_dir));
- EXPECT_TRUE(file_util::PathExists(new_version_dir));
-
- // Now close the file handle to make it possible to delete our key file.
- file.Close();
-
- package->RemoveOldVersionDirectories(*new_version.get());
- // The new directory should still exist.
- EXPECT_TRUE(file_util::PathExists(new_version_dir));
-
- // Now, the old directory and key file should be gone.
- EXPECT_FALSE(file_util::PathExists(old_chrome_dll));
- EXPECT_FALSE(file_util::PathExists(old_version_dir));
-}
-
-TEST_F(PackageTest, WithProduct) {
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
-
- // TODO(tommi): We should mock this and use our mocked distribution.
- const bool multi_install = false;
- const bool system_level = true;
- BrowserDistribution* distribution =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- ChromePackageProperties properties;
- scoped_refptr<Package> package(new Package(multi_install, 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());
-
- const char kCurrentVersion[] = "1.2.3.4";
- scoped_ptr<Version> current_version(
- Version::GetVersionFromString(kCurrentVersion));
-
- HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- {
- TempRegKeyOverride override(root, L"root_pit");
- RegKey chrome_key(root, distribution->GetVersionKey().c_str(),
- KEY_ALL_ACCESS);
- EXPECT_TRUE(chrome_key.Valid());
- if (chrome_key.Valid()) {
- chrome_key.WriteValue(google_update::kRegVersionField,
- UTF8ToWide(current_version->GetString()).c_str());
- // TODO(tommi): Also test for when there exists a new_chrome.exe.
- scoped_ptr<Version> found_version(package->GetCurrentVersion());
- EXPECT_TRUE(found_version.get() != NULL);
- if (found_version.get()) {
- EXPECT_TRUE(current_version->Equals(*found_version));
- }
- }
- }
-}
-
-namespace {
-bool SetUninstallArguments(HKEY root, BrowserDistribution* dist,
- const CommandLine& args) {
- RegKey key(root, dist->GetStateKey().c_str(), KEY_ALL_ACCESS);
- return (key.WriteValue(installer::kUninstallArgumentsField,
- args.command_line_string().c_str()) == ERROR_SUCCESS);
-}
-
-bool SetInstalledVersion(HKEY root, BrowserDistribution* dist,
- const std::wstring& version) {
- RegKey key(root, dist->GetVersionKey().c_str(), KEY_ALL_ACCESS);
- return (key.WriteValue(google_update::kRegVersionField, version.c_str()) ==
- ERROR_SUCCESS);
-}
-} // end namespace
-
-TEST_F(PackageTest, Dependency) {
- const bool multi_install = false;
- const bool system_level = true;
- HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- TempRegKeyOverride override(root, L"root_dep");
-
- ChromePackageProperties properties;
- scoped_refptr<Package> package(new Package(multi_install, system_level,
- test_dir_.path(), &properties));
- EXPECT_EQ(0U, package->GetMultiInstallDependencyCount());
-
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
-
- BrowserDistribution* chrome = BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_FRAME, prefs);
-
- CommandLine multi_uninstall_cmd(CommandLine::NO_PROGRAM);
- multi_uninstall_cmd.AppendSwitch(installer::switches::kUninstall);
- multi_uninstall_cmd.AppendSwitch(installer::switches::kMultiInstall);
-
- CommandLine single_uninstall_cmd(CommandLine::NO_PROGRAM);
- single_uninstall_cmd.AppendSwitch(installer::switches::kUninstall);
-
- // "install" Chrome.
- SetUninstallArguments(root, chrome, multi_uninstall_cmd);
- SetInstalledVersion(root, chrome, L"1.2.3.4");
- EXPECT_EQ(1U, package->GetMultiInstallDependencyCount());
-
- // "install" Chrome Frame without multi-install.
- SetUninstallArguments(root, cf, single_uninstall_cmd);
- SetInstalledVersion(root, cf, L"1.2.3.4");
- EXPECT_EQ(1U, package->GetMultiInstallDependencyCount());
-
- // "install" Chrome Frame with multi-install.
- SetUninstallArguments(root, cf, multi_uninstall_cmd);
- EXPECT_EQ(2U, package->GetMultiInstallDependencyCount());
-}
diff --git a/chrome/installer/util/product.cc b/chrome/installer/util/product.cc
index de56027..a1e99f6 100644
--- a/chrome/installer/util/product.cc
+++ b/chrome/installer/util/product.cc
@@ -10,74 +10,70 @@
#include "base/logging.h"
#include "base/process_util.h"
#include "base/win/registry.h"
+#include "chrome/installer/util/chrome_browser_operations.h"
+#include "chrome/installer/util/chrome_browser_sxs_operations.h"
+#include "chrome/installer/util/chrome_frame_operations.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/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
-#include "chrome/installer/util/package_properties.h"
+#include "chrome/installer/util/product_operations.h"
using base::win::RegKey;
using installer::MasterPreferences;
-namespace {
-class ProductIsOfType {
- public:
- explicit ProductIsOfType(BrowserDistribution::Type type)
- : type_(type) { }
- bool operator()(
- const scoped_refptr<const installer::Product>& pi) const {
- return pi->distribution()->GetType() == type_;
- }
- private:
- BrowserDistribution::Type type_;
-}; // class ProductIsOfType
-} // end namespace
-
namespace installer {
-const Product* FindProduct(const Products& products,
- BrowserDistribution::Type type) {
- Products::const_iterator i =
- std::find_if(products.begin(), products.end(), ProductIsOfType(type));
- return i == products.end() ? NULL : *i;
+Product::Product(BrowserDistribution* distribution)
+ : distribution_(distribution) {
+ switch (distribution->GetType()) {
+ case BrowserDistribution::CHROME_BROWSER:
+ operations_.reset(InstallUtil::IsChromeSxSProcess() ?
+ new ChromeBrowserSxSOperations() :
+ new ChromeBrowserOperations());
+ break;
+ case BrowserDistribution::CHROME_FRAME:
+ operations_.reset(new ChromeFrameOperations());
+ break;
+ default:
+ NOTREACHED() << "Unsupported BrowserDistribution::Type: "
+ << distribution->GetType();
+ }
}
-////////////////////////////////////////////////////////////////////////////////
+Product::~Product() {
+}
-Product::Product(BrowserDistribution* distribution, Package* package)
- : distribution_(distribution),
- package_(package),
- msi_(false),
- cache_state_(0) {
- package_->AssociateProduct(this);
+void Product::InitializeFromPreferences(const MasterPreferences& prefs) {
+ operations_->ReadOptions(prefs, &options_);
}
-const Package& Product::package() const {
- return *package_.get();
+void Product::InitializeFromUninstallCommand(
+ const CommandLine& uninstall_command) {
+ operations_->ReadOptions(uninstall_command, &options_);
}
FilePath Product::GetUserDataPath() const {
return GetChromeUserDataPath(distribution_);
}
-bool Product::LaunchChrome() const {
- const FilePath& install_package = package_->path();
- bool success = !install_package.empty();
+bool Product::LaunchChrome(const FilePath& application_path) const {
+ bool success = !application_path.empty();
if (success) {
- CommandLine cmd(install_package.Append(installer::kChromeExe));
+ CommandLine cmd(application_path.Append(installer::kChromeExe));
success = base::LaunchApp(cmd, false, false, NULL);
}
return success;
}
-bool Product::LaunchChromeAndWait(const CommandLine& options,
+bool Product::LaunchChromeAndWait(const FilePath& application_path,
+ const CommandLine& options,
int32* exit_code) const {
- const FilePath& install_package = package_->path();
- if (install_package.empty())
+ if (application_path.empty())
return false;
- CommandLine cmd(install_package.Append(installer::kChromeExe));
+ CommandLine cmd(application_path.Append(installer::kChromeExe));
cmd.AppendArguments(options, false);
bool success = false;
@@ -113,36 +109,8 @@ bool Product::LaunchChromeAndWait(const CommandLine& options,
return success;
}
-bool Product::IsMsi() const {
- if ((cache_state_ & MSI_STATE) == 0) {
- msi_ = false; // Covers failure cases below.
-
- const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess();
-
- bool is_msi = false;
- prefs.GetBool(installer::master_preferences::kMsi, &is_msi);
-
- 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;
- RegKey key;
- if (key.Open(reg_root, distribution_->GetStateKey().c_str(),
- KEY_READ) == ERROR_SUCCESS) {
- DWORD msi_value = 0;
- key.ReadValueDW(google_update::kRegMSIField, &msi_value);
- msi_ = msi_value != 0;
- }
- } else {
- msi_ = true;
- }
- cache_state_ |= MSI_STATE;
- }
-
- return msi_;
-}
-
-bool Product::SetMsiMarker(bool set) const {
- HKEY reg_root = system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+bool Product::SetMsiMarker(bool system_install, bool set) const {
+ HKEY reg_root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
RegKey client_state_key;
LONG result = client_state_key.Open(reg_root,
distribution_->GetStateKey().c_str(), KEY_READ | KEY_WRITE);
@@ -158,92 +126,23 @@ bool Product::SetMsiMarker(bool set) const {
}
bool Product::ShouldCreateUninstallEntry() const {
- if (IsMsi()) {
- // MSI installations will manage their own uninstall shortcuts.
- return false;
- }
-
- return distribution_->ShouldCreateUninstallEntry();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-ProductPackageMapping::ProductPackageMapping(bool multi_install,
- bool system_level)
- : package_properties_(new ActivePackageProperties()),
- multi_install_(multi_install),
- system_level_(system_level) {
+ return operations_->ShouldCreateUninstallEntry(options_);
}
-const Packages& ProductPackageMapping::packages() const {
- return packages_;
+void Product::AddKeyFiles(std::vector<FilePath>* key_files) const {
+ operations_->AddKeyFiles(options_, key_files);
}
-const Products& ProductPackageMapping::products() const {
- return products_;
+void Product::AddComDllList(std::vector<FilePath>* com_dll_list) const {
+ operations_->AddComDllList(options_, com_dll_list);
}
-bool ProductPackageMapping::AddDistribution(BrowserDistribution* distribution) {
- DCHECK(distribution);
- // Each product type can be added exactly once.
- DCHECK(FindProduct(products_, distribution->GetType()) == NULL);
-
- FilePath install_package;
- if (distribution->GetType() == BrowserDistribution::CHROME_BROWSER) {
- install_package = GetChromeInstallPath(system_level_, distribution);
- } else {
- DCHECK_EQ(BrowserDistribution::CHROME_FRAME, distribution->GetType());
- install_package = GetChromeFrameInstallPath(multi_install_, system_level_,
- distribution);
- }
-
- if (install_package.empty()) {
- LOG(ERROR) << "Got an empty installation path for "
- << distribution->GetApplicationName()
- << ". It's likely that there's a conflicting "
- "installation present";
- return false;
- }
-
- scoped_refptr<Package> target_package;
- for (size_t i = 0; i < packages_.size(); ++i) {
- if (packages_[i]->IsEqual(install_package)) {
- // Use an existing Package.
- target_package = packages_[i];
- break;
- }
- }
-
- if (!target_package.get()) {
- DCHECK(packages_.empty()) << "Multiple packages per run unsupported.";
- // create new one and add.
- target_package = new Package(multi_install_, system_level_, install_package,
- package_properties_.get());
- packages_.push_back(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());
- }
-#endif
- products_.push_back(product);
-
- return true;
+void Product::AppendProductFlags(CommandLine* command_line) const {
+ operations_->AppendProductFlags(options_, command_line);
}
-bool ProductPackageMapping::AddDistribution(
- BrowserDistribution::Type type,
- const MasterPreferences& prefs) {
- BrowserDistribution* distribution =
- BrowserDistribution::GetSpecificDistribution(type, prefs);
- if (!distribution) {
- NOTREACHED();
- return false;
- }
-
- return AddDistribution(distribution);
+bool Product::SetChannelFlags(bool set, ChannelInfo* channel_info) const {
+ return operations_->SetChannelFlags(options_, set, channel_info);
}
} // namespace installer
-
diff --git a/chrome/installer/util/product.h b/chrome/installer/util/product.h
index 28361df..86d3fca 100644
--- a/chrome/installer/util/product.h
+++ b/chrome/installer/util/product.h
@@ -6,30 +6,20 @@
#define CHROME_INSTALLER_UTIL_PRODUCT_H_
#pragma once
+#include <set>
+#include <string>
#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"
class CommandLine;
namespace installer {
-class MasterPreferences;
-}
-
-namespace installer {
+class MasterPreferences;
class Product;
-class Package;
-class PackageProperties;
-
-typedef std::vector<scoped_refptr<Package> > Packages;
-typedef std::vector<scoped_refptr<const Product> > Products;
-
-const Product* FindProduct(const Products& products,
- BrowserDistribution::Type type);
+class ProductOperations;
// Represents an installation of a specific product which has a one-to-one
// relation to a BrowserDistribution. A product has registry settings, related
@@ -40,23 +30,22 @@ const Product* FindProduct(const Products& products,
// the future, as we move away from global functions and towards a data driven
// installation, each distribution could derive from this class and provide
// distribution specific functionality.
-class Product : public base::RefCounted<Product> {
+class Product {
public:
- Product(BrowserDistribution* distribution, Package* installation_package);
+ explicit Product(BrowserDistribution* distribution);
+
+ ~Product();
+
+ void InitializeFromPreferences(const MasterPreferences& prefs);
+
+ void InitializeFromUninstallCommand(const CommandLine& uninstall_command);
BrowserDistribution* distribution() const {
return distribution_;
}
- // 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();
+ bool is_type(BrowserDistribution::Type type) const {
+ return distribution_->GetType() == type;
}
bool is_chrome() const {
@@ -67,6 +56,18 @@ class Product : public base::RefCounted<Product> {
return distribution_->GetType() == BrowserDistribution::CHROME_FRAME;
}
+ bool HasOption(const std::wstring& option) const {
+ return options_.find(option) != options_.end();
+ }
+
+ // Returns true if the set of options is mutated by this operation.
+ bool SetOption(const std::wstring& option, bool set) {
+ if (set)
+ return options_.insert(option).second;
+ else
+ return options_.erase(option) != 0;
+ }
+
// 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
@@ -74,7 +75,7 @@ class Product : public base::RefCounted<Product> {
FilePath GetUserDataPath() const;
// Launches Chrome without waiting for it to exit.
- bool LaunchChrome() const;
+ bool LaunchChrome(const FilePath& application_path) const;
// Launches Chrome with given command line, waits for Chrome indefinitely
// (until it terminates), and gets the process exit code if available.
@@ -82,77 +83,44 @@ class Product : public base::RefCounted<Product> {
// The status of Chrome at the return of the function is given by exit_code.
// NOTE: The 'options' CommandLine object should only contain parameters.
// The program part will be ignored.
- bool LaunchChromeAndWait(const CommandLine& options, int32* exit_code) const;
-
- // Returns true if this setup process is running as an install managed by an
- // MSI wrapper. There are three things that are checked:
- // 1) the presence of --msi on the command line
- // 2) the presence of "msi": true in the master preferences file
- // 3) the presence of a DWORD value in the ClientState key called msi with
- // value 1
- bool IsMsi() const;
+ bool LaunchChromeAndWait(const FilePath& application_path,
+ const CommandLine& options,
+ int32* exit_code) const;
// Sets the boolean MSI marker for this installation if set is true or clears
// it otherwise. The MSI marker is stored in the registry under the
// ClientState key.
- bool SetMsiMarker(bool set) const;
+ bool SetMsiMarker(bool system_install, bool set) const;
// Returns true if setup should create an entry in the Add/Remove list
// of installed applications.
bool ShouldCreateUninstallEntry() const;
+ // See ProductOperations::AddKeyFiles.
+ void AddKeyFiles(std::vector<FilePath>* key_files) const;
+
+ // See ProductOperations::AddComDllList.
+ void AddComDllList(std::vector<FilePath>* com_dll_list) const;
+
+ // See ProductOperations::AppendProductFlags.
+ void AppendProductFlags(CommandLine* command_line) const;
+
+ // See Productoperations::SetChannelFlags.
+ bool SetChannelFlags(bool set, ChannelInfo* channel_info) const;
+
protected:
enum CacheStateFlags {
MSI_STATE = 0x01
};
BrowserDistribution* distribution_;
- scoped_refptr<Package> package_;
- mutable bool msi_;
- mutable uint8 cache_state_;
+ scoped_ptr<ProductOperations> operations_;
+ std::set<std::wstring> options_;
private:
- friend class base::RefCounted<Product>;
- ~Product() {
- }
DISALLOW_COPY_AND_ASSIGN(Product);
};
-// A collection of Product objects and related physical installation
-// packages. Each Product is associated with a single installation
-// package object, and each package object is associated with one or more
-// Product objects.
-class ProductPackageMapping {
- public:
- explicit ProductPackageMapping(bool multi_install, bool system_level);
-
- bool multi_install() const {
- return multi_install_;
- }
-
- bool system_level() const {
- return system_level_;
- }
-
- const Packages& packages() const;
-
- const Products& products() const;
-
- bool AddDistribution(BrowserDistribution::Type type,
- const installer::MasterPreferences& prefs);
- bool AddDistribution(BrowserDistribution* distribution);
-
- protected:
- bool multi_install_;
- bool system_level_;
- Packages packages_;
- Products products_;
- scoped_ptr<PackageProperties> package_properties_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProductPackageMapping);
-};
-
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_PRODUCT_H_
diff --git a/chrome/installer/util/product_operations.h b/chrome/installer/util/product_operations.h
new file mode 100644
index 0000000..0874d3d
--- /dev/null
+++ b/chrome/installer/util/product_operations.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 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_PRODUCT_OPERATIONS_H_
+#define CHROME_INSTALLER_UTIL_PRODUCT_OPERATIONS_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/file_path.h"
+
+class CommandLine;
+
+namespace installer {
+
+class ChannelInfo;
+class MasterPreferences;
+
+// An interface to product-specific operations that depend on product
+// configuration. Implementations are expected to be stateless. Configuration
+// can be read from a MasterPreferences instance or from a product's uninstall
+// command.
+class ProductOperations {
+ public:
+ virtual ~ProductOperations() {}
+
+ // Reads product-specific options from |prefs|, adding them to |options|.
+ virtual void ReadOptions(const MasterPreferences& prefs,
+ std::set<std::wstring>* options) const = 0;
+
+ // Reads product-specific options from |command|, adding them to |options|.
+ virtual void ReadOptions(const CommandLine& command,
+ std::set<std::wstring>* options) const = 0;
+
+ // A key-file is a file such as a DLL on Windows that is expected to be in use
+ // when the product is being used. For example "chrome.dll" for Chrome.
+ // Before attempting to delete an installation directory during an
+ // uninstallation, the uninstaller will check if any one of a potential set of
+ // key files is in use and if they are, abort the delete operation. Only if
+ // none of the key files are in use, can the folder be deleted. Note that
+ // this function does not return a full path to the key file(s), only (a) file
+ // name(s).
+ virtual void AddKeyFiles(const std::set<std::wstring>& options,
+ std::vector<FilePath>* key_files) const = 0;
+
+ // Adds to |com_dll_list| the list of COM DLLs that are to be registered
+ // and/or unregistered. The list may be empty.
+ virtual void AddComDllList(const std::set<std::wstring>& options,
+ std::vector<FilePath>* com_dll_list) const = 0;
+
+ // Given a command line, appends the set of uninstall flags the uninstaller
+ // for this product will require.
+ virtual void AppendProductFlags(const std::set<std::wstring>& options,
+ CommandLine* uninstall_command) const = 0;
+
+ // Adds or removes product-specific flags in |channel_info|. Returns true if
+ // |channel_info| is modified.
+ virtual bool SetChannelFlags(const std::set<std::wstring>& options,
+ bool set,
+ ChannelInfo* channel_info) const = 0;
+
+ // Returns true if setup should create an entry in the Add/Remove list
+ // of installed applications for this product. This does not test for use of
+ // MSI; see InstallerState::is_msi.
+ virtual bool ShouldCreateUninstallEntry(
+ const std::set<std::wstring>& options) const = 0;
+};
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_UTIL_PRODUCT_OPERATIONS_H_
diff --git a/chrome/installer/util/product_state_unittest.cc b/chrome/installer/util/product_state_unittest.cc
new file mode 100644
index 0000000..c6031359
--- /dev/null
+++ b/chrome/installer/util/product_state_unittest.cc
@@ -0,0 +1,416 @@
+// Copyright (c) 2011 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 <windows.h>
+
+#include "base/utf_string_conversions.h"
+#include "base/version.h"
+#include "base/win/registry.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/installation_state.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::ProductState;
+
+class ProductStateTest : public testing::Test {
+ protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ virtual void SetUp();
+ virtual void TearDown();
+
+ void ApplyUninstallCommand(const wchar_t* exe_path, const wchar_t* args);
+ void MinimallyInstallProduct(const wchar_t* version);
+
+ static BrowserDistribution* dist_;
+ static std::wstring temp_key_path_;
+ bool system_install_;
+ HKEY overridden_;
+ RegKey clients_;
+ RegKey client_state_;
+};
+
+BrowserDistribution* ProductStateTest::dist_;
+std::wstring ProductStateTest::temp_key_path_;
+
+// static
+void ProductStateTest::SetUpTestCase() {
+ testing::Test::SetUpTestCase();
+
+ // We'll use Chrome as our test subject.
+ dist_ = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_BROWSER);
+
+ // And we'll play in HKCU here:
+ temp_key_path_.assign(TempRegKeyOverride::kTempTestKeyPath)
+ .append(1, L'\\')
+ .append(L"ProductStateTest");
+}
+
+// static
+void ProductStateTest::TearDownTestCase() {
+ temp_key_path_.clear();
+ dist_ = NULL;
+
+ testing::Test::TearDownTestCase();
+}
+
+void ProductStateTest::SetUp() {
+ testing::Test::SetUp();
+
+ // Create/open the keys for the product we'll test.
+ system_install_ = true;
+ overridden_ = (system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER);
+
+ // Override for test purposes. We don't use TempRegKeyOverride
+ // directly because it doesn't suit itself to our use here.
+ RegKey temp_key;
+ EXPECT_EQ(ERROR_SUCCESS,
+ temp_key.Create(HKEY_CURRENT_USER, temp_key_path_.c_str(),
+ KEY_ALL_ACCESS));
+ EXPECT_EQ(ERROR_SUCCESS,
+ ::RegOverridePredefKey(overridden_, temp_key.Handle()));
+
+ EXPECT_EQ(ERROR_SUCCESS,
+ clients_.Create(overridden_, dist_->GetVersionKey().c_str(),
+ KEY_ALL_ACCESS));
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.Create(overridden_, dist_->GetStateKey().c_str(),
+ KEY_ALL_ACCESS));
+}
+
+void ProductStateTest::TearDown() {
+ // Done with the keys.
+ client_state_.Close();
+ clients_.Close();
+ EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(overridden_, NULL));
+ overridden_ = NULL;
+ system_install_ = false;
+
+ // Shotgun approach to clearing out data we may have written.
+ TempRegKeyOverride::DeleteAllTempKeys();
+
+ testing::Test::TearDown();
+}
+
+void ProductStateTest::MinimallyInstallProduct(const wchar_t* version) {
+ EXPECT_EQ(ERROR_SUCCESS,
+ clients_.WriteValue(google_update::kRegVersionField, version));
+}
+
+void ProductStateTest::ApplyUninstallCommand(const wchar_t* exe_path,
+ const wchar_t* args) {
+ if (exe_path == NULL) {
+ LONG result = client_state_.DeleteValue(installer::kUninstallStringField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ } else {
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(installer::kUninstallStringField,
+ exe_path));
+ }
+
+ if (args == NULL) {
+ LONG result =
+ client_state_.DeleteValue(installer::kUninstallArgumentsField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ } else {
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(installer::kUninstallArgumentsField,
+ args));
+ }
+}
+
+TEST_F(ProductStateTest, InitializeInstalled) {
+ // Not installed.
+ {
+ ProductState state;
+ LONG result = clients_.DeleteValue(google_update::kRegVersionField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_FALSE(state.Initialize(system_install_, dist_));
+ }
+
+ // Empty version.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegVersionField, L"");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_FALSE(state.Initialize(system_install_, dist_));
+ }
+
+ // Bogus version.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegVersionField,
+ L"goofy");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_FALSE(state.Initialize(system_install_, dist_));
+ }
+
+ // Valid "pv" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegVersionField,
+ L"10.0.47.0");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ("10.0.47.0", state.version().GetString());
+ }
+}
+
+// Test extraction of the "opv" value from the Clients key.
+TEST_F(ProductStateTest, InitializeOldVersion) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No "opv" value.
+ {
+ ProductState state;
+ LONG result = clients_.DeleteValue(google_update::kRegOldVersionField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.old_version() == NULL);
+ }
+
+ // Empty "opv" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegOldVersionField, L"");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.old_version() == NULL);
+ }
+
+ // Bogus "opv" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegOldVersionField,
+ L"coming home");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.old_version() == NULL);
+ }
+
+ // Valid "opv" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegOldVersionField,
+ L"10.0.47.0");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.old_version() != NULL);
+ EXPECT_EQ("10.0.47.0", state.old_version()->GetString());
+ }
+}
+
+// Test extraction of the "cmd" value from the Clients key.
+TEST_F(ProductStateTest, InitializeRenameCmd) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No "cmd" value.
+ {
+ ProductState state;
+ LONG result = clients_.DeleteValue(google_update::kRegRenameCmdField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.rename_cmd().empty());
+ }
+
+ // Empty "cmd" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegRenameCmdField, L"");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.rename_cmd().empty());
+ }
+
+ // Valid "cmd" value.
+ {
+ ProductState state;
+ LONG result = clients_.WriteValue(google_update::kRegRenameCmdField,
+ L"spam.exe --spamalot");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ(L"spam.exe --spamalot", state.rename_cmd());
+ }
+}
+
+// Test extraction of the "ap" value from the ClientState key.
+TEST_F(ProductStateTest, InitializeChannelInfo) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No "ap" value.
+ {
+ ProductState state;
+ LONG result = client_state_.DeleteValue(google_update::kRegApField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.channel().value().empty());
+ }
+
+ // Empty "ap" value.
+ {
+ ProductState state;
+ LONG result = client_state_.WriteValue(google_update::kRegApField, L"");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.channel().value().empty());
+ }
+
+ // Valid "ap" value.
+ {
+ ProductState state;
+ LONG result = client_state_.WriteValue(google_update::kRegApField, L"spam");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ(L"spam", state.channel().value());
+ }
+}
+
+// Test extraction of the uninstall command and arguments from the ClientState
+// key.
+TEST_F(ProductStateTest, InitializeUninstallCommand) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No uninstall command.
+ {
+ ProductState state;
+ ApplyUninstallCommand(NULL, NULL);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.GetSetupPath().empty());
+ EXPECT_TRUE(state.uninstall_command().command_line_string().empty());
+ EXPECT_EQ(0U, state.uninstall_command().GetSwitchCount());
+ }
+
+ // Empty values.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"", L"");
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.GetSetupPath().empty());
+ EXPECT_TRUE(state.uninstall_command().command_line_string().empty());
+ EXPECT_EQ(0U, state.uninstall_command().GetSwitchCount());
+ }
+
+ // Uninstall command without exe.
+ {
+ ProductState state;
+ ApplyUninstallCommand(NULL, L"--uninstall");
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.GetSetupPath().empty());
+ EXPECT_EQ(L"\"\" --uninstall",
+ state.uninstall_command().command_line_string());
+ EXPECT_EQ(1U, state.uninstall_command().GetSwitchCount());
+ }
+
+ // Uninstall command without args.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"setup.exe", NULL);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
+ EXPECT_EQ(L"\"setup.exe\"",
+ state.uninstall_command().command_line_string());
+ EXPECT_EQ(0U, state.uninstall_command().GetSwitchCount());
+ }
+
+ // Uninstall command with both exe and args.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"setup.exe", L"--uninstall");
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_EQ(L"setup.exe", state.GetSetupPath().value());
+ EXPECT_EQ(L"\"setup.exe\" --uninstall",
+ state.uninstall_command().command_line_string());
+ EXPECT_EQ(1U, state.uninstall_command().GetSwitchCount());
+ }
+}
+
+// Test extraction of the msi marker from the ClientState key.
+TEST_F(ProductStateTest, InitializeMsi) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No msi marker.
+ {
+ ProductState state;
+ LONG result = client_state_.DeleteValue(google_update::kRegMSIField);
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_FALSE(state.is_msi());
+ }
+
+ // Msi marker set to zero.
+ {
+ ProductState state;
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(google_update::kRegMSIField,
+ static_cast<DWORD>(0)));
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_FALSE(state.is_msi());
+ }
+
+ // Msi marker set to one.
+ {
+ ProductState state;
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(google_update::kRegMSIField,
+ static_cast<DWORD>(1)));
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.is_msi());
+ }
+
+ // Msi marker set to a bogus DWORD.
+ {
+ ProductState state;
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(google_update::kRegMSIField,
+ static_cast<DWORD>(47)));
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.is_msi());
+ }
+
+ // Msi marker set to a bogus string.
+ {
+ ProductState state;
+ EXPECT_EQ(ERROR_SUCCESS,
+ client_state_.WriteValue(google_update::kRegMSIField,
+ L"bogus!"));
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_FALSE(state.is_msi());
+ }
+}
+
+// Test detection of multi-install.
+TEST_F(ProductStateTest, InitializeMultiInstall) {
+ MinimallyInstallProduct(L"10.0.1.1");
+
+ // No uninstall command means single install.
+ {
+ ProductState state;
+ ApplyUninstallCommand(NULL, NULL);
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_FALSE(state.is_multi_install());
+ }
+
+ // Uninstall command without --multi-install is single install.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"setup.exe", L"--uninstall");
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_FALSE(state.is_multi_install());
+ }
+
+ // Uninstall command with --multi-install is multi install.
+ {
+ ProductState state;
+ ApplyUninstallCommand(L"setup.exe",
+ L"--uninstall --chrome --multi-install");
+ EXPECT_TRUE(state.Initialize(system_install_, dist_));
+ EXPECT_TRUE(state.is_multi_install());
+ }
+}
diff --git a/chrome/installer/util/product_unittest.cc b/chrome/installer/util/product_unittest.cc
index c072dc5..913a6ff 100644
--- a/chrome/installer/util/product_unittest.cc
+++ b/chrome/installer/util/product_unittest.cc
@@ -9,17 +9,12 @@
#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/installer_state.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/product.h"
using base::win::RegKey;
-using installer::ChromePackageProperties;
-using installer::ChromiumPackageProperties;
-using installer::Package;
using installer::Product;
-using installer::ProductPackageMapping;
using installer::MasterPreferences;
void TestWithTempDir::SetUp() {
@@ -82,15 +77,19 @@ TEST_F(ProductTest, ProductInstallBasic) {
// TODO(tommi): We should mock this and use our mocked distribution.
const bool multi_install = false;
const bool system_level = true;
- const installer::MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
- BrowserDistribution* distribution =
- BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs);
- ChromePackageProperties properties;
- scoped_refptr<Package> package(new Package(multi_install, system_level,
- test_dir_.path(), &properties));
- scoped_refptr<Product> product(new Product(distribution, package.get()));
+ CommandLine cmd_line = CommandLine::FromString(
+ std::wstring(L"setup.exe") +
+ (multi_install ? L" --multi-install --chrome" : L"") +
+ (system_level ? L" --system-level" : L""));
+ installer::MasterPreferences prefs(cmd_line);
+ installer::InstallationState machine_state;
+ machine_state.Initialize();
+ installer::InstallerState installer_state;
+ installer_state.Initialize(cmd_line, prefs, machine_state);
+
+ const Product* product = installer_state.products()[0];
+ BrowserDistribution* distribution = product->distribution();
+ EXPECT_EQ(BrowserDistribution::CHROME_BROWSER, distribution->GetType());
FilePath user_data(product->GetUserDataPath());
EXPECT_FALSE(user_data.empty());
@@ -104,35 +103,15 @@ TEST_F(ProductTest, ProductInstallBasic) {
EXPECT_EQ(std::wstring::npos,
user_data.value().find(program_files.value()));
- // We started out with a non-msi product.
- EXPECT_FALSE(product->IsMsi());
+ // There should be no installed version in the registry.
+ machine_state.Initialize();
+ EXPECT_TRUE(machine_state.GetProductState(
+ system_level, distribution->GetType()) == NULL);
- HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ HKEY root = installer_state.root_key();
{
TempRegKeyOverride override(root, L"root_pit");
- // Create a make-believe client state key.
- RegKey key;
- std::wstring state_key_path(distribution->GetStateKey());
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(root, state_key_path.c_str(), KEY_ALL_ACCESS));
-
- // 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(multi_install, system_level, test_dir_.path(),
- &properties);
- product = new Product(distribution, package.get());
- EXPECT_TRUE(product->IsMsi());
-
- // There should be no installed version in the registry.
- {
- 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(),
KEY_ALL_ACCESS);
@@ -144,16 +123,30 @@ TEST_F(ProductTest, ProductInstallBasic) {
version_key.WriteValue(google_update::kRegVersionField,
UTF8ToWide(current_version->GetString()).c_str());
- {
- 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()));
- }
+ // We started out with a non-msi product.
+ machine_state.Initialize();
+ const installer::ProductState* chrome_state =
+ machine_state.GetProductState(system_level, distribution->GetType());
+ EXPECT_TRUE(chrome_state != NULL);
+ if (chrome_state != NULL) {
+ EXPECT_TRUE(chrome_state->version().Equals(*current_version.get()));
+ EXPECT_FALSE(chrome_state->is_msi());
}
+
+ // Create a make-believe client state key.
+ RegKey key;
+ std::wstring state_key_path(distribution->GetStateKey());
+ ASSERT_EQ(ERROR_SUCCESS,
+ key.Create(root, state_key_path.c_str(), KEY_ALL_ACCESS));
+
+ // Set the MSI marker, refresh, and verify that we now see the MSI marker.
+ EXPECT_TRUE(product->SetMsiMarker(system_level, true));
+ machine_state.Initialize();
+ chrome_state =
+ machine_state.GetProductState(system_level, distribution->GetType());
+ EXPECT_TRUE(chrome_state != NULL);
+ if (chrome_state != NULL)
+ EXPECT_TRUE(chrome_state->is_msi());
}
}
@@ -162,41 +155,3 @@ TEST_F(ProductTest, LaunchChrome) {
// Product::LaunchChromeAndWait.
LOG(ERROR) << "Test not implemented.";
}
-
-// Overrides ChromeFrameDistribution for the sole purpose of returning
-// the Chrome (not Chrome Frame) installation path.
-class FakeChromeFrameDistribution : public ChromeFrameDistribution {
- public:
- explicit FakeChromeFrameDistribution(
- const installer::MasterPreferences& prefs)
- : ChromeFrameDistribution(prefs) {}
- virtual std::wstring GetInstallSubDir() {
- const MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
- return BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_BROWSER, prefs)->GetInstallSubDir();
- }
-};
-
-TEST_F(ProductTest, ProductInstallsBasic) {
- const bool multi_install = true;
- const bool system_level = true;
- ProductPackageMapping installs(multi_install, system_level);
- EXPECT_EQ(multi_install, installs.multi_install());
- EXPECT_EQ(system_level, installs.system_level());
- EXPECT_EQ(0U, installs.packages().size());
- EXPECT_EQ(0U, installs.products().size());
-
- // TODO(robertshield): Include test that use mock master preferences.
- const MasterPreferences& prefs =
- installer::MasterPreferences::ForCurrentProcess();
-
- installs.AddDistribution(BrowserDistribution::CHROME_BROWSER, prefs);
- FakeChromeFrameDistribution fake_chrome_frame(prefs);
- installs.AddDistribution(&fake_chrome_frame);
- EXPECT_EQ(2U, installs.products().size());
- // Since our fake Chrome Frame distribution class is reporting the same
- // installation directory as Chrome, we should have only one package object.
- EXPECT_EQ(1U, installs.packages().size());
- EXPECT_EQ(multi_install, installs.packages()[0]->multi_install());
-}
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index f59d6a4..39e47e9 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -177,4 +177,8 @@ const wchar_t kInstallerResultUIString[] = L"InstallerResultUIString";
const wchar_t kInstallerSuccessLaunchCmdLine[] =
L"InstallerSuccessLaunchCmdLine";
+const wchar_t kOptionCeee[] = L"ceee";
+const wchar_t kOptionMultiInstall[] = L"multi-install";
+const wchar_t kOptionReadyMode[] = L"ready-mode";
+
} // namespace installer
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 5b2f230..9ca8900 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -66,6 +66,9 @@ enum InstallStatus {
// Chrome Frame.
READY_MODE_END_TEMP_OPT_OUT_FAILED, // 38. Failed to end temporary opt-out
// of Chrome Frame.
+ CONFLICTING_CHANNEL_EXISTS, // 39. A multi-install product on a different
+ // update channel exists.
+ READY_MODE_REQUIRES_CHROME, // 40. Chrome Frame in ready-mode requires Chrome
};
namespace switches {
@@ -141,6 +144,11 @@ extern const wchar_t kInstallerError[];
extern const wchar_t kInstallerResultUIString[];
extern const wchar_t kInstallerSuccessLaunchCmdLine[];
+// Product options.
+extern const wchar_t kOptionCeee[];
+extern const wchar_t kOptionMultiInstall[];
+extern const wchar_t kOptionReadyMode[];
+
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_