summaryrefslogtreecommitdiffstats
path: root/chrome/installer/util
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-11 13:28:34 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-11 13:28:34 +0000
commit2589396510cb9ec9a4e3520dcef3524e65fecd58 (patch)
tree54824cb5227354c24f04c7f34b5c104c78a14943 /chrome/installer/util
parentc7959c98c6625ad4e0758bd8e95e35be3442219a (diff)
downloadchromium_src-2589396510cb9ec9a4e3520dcef3524e65fecd58.zip
chromium_src-2589396510cb9ec9a4e3520dcef3524e65fecd58.tar.gz
chromium_src-2589396510cb9ec9a4e3520dcef3524e65fecd58.tar.bz2
Add support for --critical-update-version to installer.
The installer may now be given a --critical-update-version=W.X.Y.Z option on the command line. If this is present for an in-use update and the indicated version is newer than the in-use Chrome, a new "cpv" value is dropped in the registry alongside "opv" and "cmd" (the other state associated with an in-use update). Thanks to Finnur, Chrome will eventually notice that there's a pending critical update and do magical things to keep our users safe and secure. Go users! Other things I did while I was at it: - switched version string conversions from UTF8ToWide to ASCIIToWide since version numbers are always ASCII dotted numbers. - renamed the reg value from "CriticalUpdate" to "cpv" so it fits in nicely with the other cryptic values in the product's Clients key (a.k.a. Version key). BUG=103526,97665 TEST=Install version N, launch it with --check-for-update-interval=5, then install verison M>N with --critical-update-version=M. After a few seconds, Chrome should do something fantastic. Note that the alternate_version_generator can be used to create a newer versioned mini_installer from an existing one (just build it and run it). Review URL: http://codereview.chromium.org/8517012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109620 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer/util')
-rw-r--r--chrome/installer/util/google_update_constants.cc2
-rw-r--r--chrome/installer/util/google_update_constants.h2
-rw-r--r--chrome/installer/util/install_util.cc2
-rw-r--r--chrome/installer/util/installer_state.cc19
-rw-r--r--chrome/installer/util/installer_state.h10
-rw-r--r--chrome/installer/util/installer_state_unittest.cc158
-rw-r--r--chrome/installer/util/util_constants.cc4
-rw-r--r--chrome/installer/util/util_constants.h1
8 files changed, 194 insertions, 4 deletions
diff --git a/chrome/installer/util/google_update_constants.cc b/chrome/installer/util/google_update_constants.cc
index bcc9e80..4e4126d 100644
--- a/chrome/installer/util/google_update_constants.cc
+++ b/chrome/installer/util/google_update_constants.cc
@@ -24,7 +24,7 @@ const wchar_t kRegCFOptOutCmdField[] = L"CFOptOutCmd";
const wchar_t kRegCFTempOptOutCmdField[] = L"CFTempOptOutCmd";
const wchar_t kRegClientField[] = L"client";
const wchar_t kRegCommandLineField[] = L"CommandLine";
-const wchar_t kRegCriticalUpdateField[] = L"CriticalUpdate";
+const wchar_t kRegCriticalVersionField[] = L"cpv";
const wchar_t kRegDidRunField[] = L"dr";
const wchar_t kRegEULAAceptedField[] = L"eulaaccepted";
const wchar_t kRegLangField[] = L"lang";
diff --git a/chrome/installer/util/google_update_constants.h b/chrome/installer/util/google_update_constants.h
index 27a7c0e..eb27910 100644
--- a/chrome/installer/util/google_update_constants.h
+++ b/chrome/installer/util/google_update_constants.h
@@ -34,7 +34,7 @@ extern const wchar_t kRegCFOptOutCmdField[];
extern const wchar_t kRegCFTempOptOutCmdField[];
extern const wchar_t kRegClientField[];
extern const wchar_t kRegCommandLineField[];
-extern const wchar_t kRegCriticalUpdateField[];
+extern const wchar_t kRegCriticalVersionField[];
extern const wchar_t kRegDidRunField[];
extern const wchar_t kRegEULAAceptedField[];
extern const wchar_t kRegLangField[];
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 2d6d1d9..f14f372 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -203,7 +203,7 @@ Version* InstallUtil::GetCriticalUpdateVersion(BrowserDistribution* dist,
string16 version_str;
if (result == ERROR_SUCCESS)
- result = key.ReadValue(google_update::kRegCriticalUpdateField,
+ result = key.ReadValue(google_update::kRegCriticalVersionField,
&version_str);
Version* ret = NULL;
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
index bc365de..5e88ad5 100644
--- a/chrome/installer/util/installer_state.cc
+++ b/chrome/installer/util/installer_state.cc
@@ -156,6 +156,11 @@ void InstallerState::Initialize(const CommandLine& command_line,
state_key_ = operand->GetStateKey();
state_type_ = operand->GetType();
+
+ // Parse --critical-update-version=W.X.Y.Z
+ std::string critical_version_value(
+ command_line.GetSwitchValueASCII(switches::kCriticalUpdateVersion));
+ critical_update_version_ = Version(critical_version_value);
}
void InstallerState::set_level(Level level) {
@@ -413,6 +418,20 @@ Version* InstallerState::GetCurrentVersion(
return current_version.release();
}
+Version InstallerState::DetermineCriticalVersion(
+ const Version* current_version,
+ const Version& new_version) const {
+ DCHECK(current_version == NULL || current_version->IsValid());
+ DCHECK(new_version.IsValid());
+ if (critical_update_version_.IsValid() &&
+ (current_version == NULL ||
+ (current_version->CompareTo(critical_update_version_) < 0)) &&
+ new_version.CompareTo(critical_update_version_) >= 0) {
+ return critical_update_version_;
+ }
+ return Version();
+}
+
bool InstallerState::IsChromeFrameRunning(
const InstallationState& machine_state) const {
// We check only for the current version (e.g. the version we are upgrading
diff --git a/chrome/installer/util/installer_state.h b/chrome/installer/util/installer_state.h
index 04417be..987bf1b 100644
--- a/chrome/installer/util/installer_state.h
+++ b/chrome/installer/util/installer_state.h
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/version.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/product.h"
#include "chrome/installer/util/util_constants.h"
@@ -144,6 +145,14 @@ class InstallerState {
// products are installed. Ownership is passed to the caller.
Version* GetCurrentVersion(const InstallationState& machine_state) const;
+ // Returns the critical update version if all of the following are true:
+ // * --critical-update-version=CUV was specified on the command-line.
+ // * current_version == NULL or current_version < CUV.
+ // * new_version >= CUV.
+ // Otherwise, returns an invalid version.
+ Version DetermineCriticalVersion(const Version* current_version,
+ const Version& new_version) const;
+
// Returns whether or not there is currently a Chrome Frame instance running.
// Note that there isn't a mechanism to lock Chrome Frame in place, so Chrome
// Frame may either exit or start up after this is called.
@@ -211,6 +220,7 @@ class InstallerState {
BrowserDistribution::Type state_type_;
ScopedVector<Product> products_;
BrowserDistribution* multi_package_distribution_;
+ Version critical_update_version_;
Level level_;
PackageType package_type_;
#if defined(OS_WIN)
diff --git a/chrome/installer/util/installer_state_unittest.cc b/chrome/installer/util/installer_state_unittest.cc
index 14dec6d..5029699 100644
--- a/chrome/installer/util/installer_state_unittest.cc
+++ b/chrome/installer/util/installer_state_unittest.cc
@@ -42,7 +42,7 @@ class InstallerStateTest : public TestWithTempDirAndDeleteTempOverrideKeys {
protected:
};
-// An installer state on which we can tweak the target path.
+// An installer state on which we can access otherwise protected members.
class MockInstallerState : public InstallerState {
public:
MockInstallerState() : InstallerState() { }
@@ -52,6 +52,9 @@ class MockInstallerState : public InstallerState {
static bool IsFileInUse(const FilePath& file) {
return InstallerState::IsFileInUse(file);
}
+ const Version& critical_update_version() const {
+ return critical_update_version_;
+ }
};
// Simple function to dump some text into a new file.
@@ -491,3 +494,156 @@ TEST_F(InstallerStateTest, IsFileInUse) {
// And once the handle is gone, it should no longer be in use.
EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file));
}
+
+// A fixture for testing InstallerState::DetermineCriticalVersion. Individual
+// tests must invoke Initialize() with a critical version.
+class InstallerStateCriticalVersionTest : public ::testing::Test {
+ protected:
+ InstallerStateCriticalVersionTest() : cmd_line_(CommandLine::NO_PROGRAM) {}
+
+ // Creates a set of versions for use by all test runs.
+ static void SetUpTestCase() {
+ low_version_ = new Version("15.0.874.106");
+ opv_version_ = new Version("15.0.874.255");
+ middle_version_ = new Version("16.0.912.32");
+ pv_version_ = new Version("16.0.912.255");
+ high_version_ = new Version("17.0.932.0");
+ }
+
+ // Cleans up versions used by all test runs.
+ static void TearDownTestCase() {
+ delete low_version_;
+ delete opv_version_;
+ delete middle_version_;
+ delete pv_version_;
+ delete high_version_;
+ }
+
+ // Initializes the InstallerState to use for a test run. The returned
+ // instance's critical update version is set to |version|. |version| may be
+ // NULL, in which case the critical update version is unset.
+ MockInstallerState& Initialize(const Version* version) {
+ cmd_line_ = version == NULL ?
+ CommandLine::FromString(L"setup.exe") :
+ CommandLine::FromString(
+ L"setup.exe --critical-update-version=" +
+ ASCIIToWide(version->GetString()));
+ prefs_.reset(new MasterPreferences(cmd_line_));
+ machine_state_.Initialize();
+ installer_state_.Initialize(cmd_line_, *prefs_, machine_state_);
+ return installer_state_;
+ }
+
+ static Version* low_version_;
+ static Version* opv_version_;
+ static Version* middle_version_;
+ static Version* pv_version_;
+ static Version* high_version_;
+
+ CommandLine cmd_line_;
+ scoped_ptr<MasterPreferences> prefs_;
+ InstallationState machine_state_;
+ MockInstallerState installer_state_;
+};
+
+Version* InstallerStateCriticalVersionTest::low_version_ = NULL;
+Version* InstallerStateCriticalVersionTest::opv_version_ = NULL;
+Version* InstallerStateCriticalVersionTest::middle_version_ = NULL;
+Version* InstallerStateCriticalVersionTest::pv_version_ = NULL;
+Version* InstallerStateCriticalVersionTest::high_version_ = NULL;
+
+// Test the case where the critical version is less than the currently-running
+// Chrome. The critical version is ignored since it doesn't apply.
+TEST_F(InstallerStateCriticalVersionTest, CriticalBeforeOpv) {
+ MockInstallerState& installer_state(Initialize(low_version_));
+
+ EXPECT_TRUE(installer_state.critical_update_version().Equals(*low_version_));
+ // Unable to determine the installed version, so assume critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid());
+ // Installed version is past the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(opv_version_, *pv_version_)
+ .IsValid());
+ // Installed version is past the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(pv_version_, *pv_version_)
+ .IsValid());
+}
+
+// Test the case where the critical version is equal to the currently-running
+// Chrome. The critical version is ignored since it doesn't apply.
+TEST_F(InstallerStateCriticalVersionTest, CriticalEqualsOpv) {
+ MockInstallerState& installer_state(Initialize(opv_version_));
+
+ EXPECT_TRUE(installer_state.critical_update_version().Equals(*opv_version_));
+ // Unable to determine the installed version, so assume critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid());
+ // Installed version equals the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(opv_version_, *pv_version_)
+ .IsValid());
+ // Installed version equals the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(pv_version_, *pv_version_)
+ .IsValid());
+}
+
+// Test the case where the critical version is between the currently-running
+// Chrome and the to-be-installed Chrome.
+TEST_F(InstallerStateCriticalVersionTest, CriticalBetweenOpvAndPv) {
+ MockInstallerState& installer_state(Initialize(middle_version_));
+
+ EXPECT_TRUE(installer_state.critical_update_version().Equals(
+ *middle_version_));
+ // Unable to determine the installed version, so assume critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid());
+ // Installed version before the critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(opv_version_, *pv_version_)
+ .IsValid());
+ // Installed version is past the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(pv_version_, *pv_version_)
+ .IsValid());
+}
+
+// Test the case where the critical version is the same as the to-be-installed
+// Chrome.
+TEST_F(InstallerStateCriticalVersionTest, CriticalEqualsPv) {
+ MockInstallerState& installer_state(Initialize(pv_version_));
+
+ EXPECT_TRUE(installer_state.critical_update_version().Equals(
+ *pv_version_));
+ // Unable to determine the installed version, so assume critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid());
+ // Installed version before the critical update.
+ EXPECT_TRUE(
+ installer_state.DetermineCriticalVersion(opv_version_, *pv_version_)
+ .IsValid());
+ // Installed version equals the critical update.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(pv_version_, *pv_version_)
+ .IsValid());
+}
+
+// Test the case where the critical version is greater than the to-be-installed
+// Chrome.
+TEST_F(InstallerStateCriticalVersionTest, CriticalAfterPv) {
+ MockInstallerState& installer_state(Initialize(high_version_));
+
+ EXPECT_TRUE(installer_state.critical_update_version().Equals(
+ *high_version_));
+ // Critical update newer than the new version.
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid());
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(opv_version_, *pv_version_)
+ .IsValid());
+ EXPECT_FALSE(
+ installer_state.DetermineCriticalVersion(pv_version_, *pv_version_)
+ .IsValid());
+}
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index c470faf..72943a8 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -42,6 +42,10 @@ const char kChromeSxS[] = "chrome-sxs";
// Create Desktop and QuickLaunch shortcuts
const char kCreateAllShortcuts[] = "create-all-shortcuts";
+// The version number of an update containing critical fixes, for which an
+// in-use Chrome should be restarted ASAP.
+const char kCriticalUpdateVersion[] = "critical-update-version";
+
// Delete user profile data. This param is useful only when specified with
// kUninstall, otherwise it is silently ignored.
const char kDeleteProfile[] = "delete-profile";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 95d79df..5911701 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -128,6 +128,7 @@ extern const char kChromeFrameReadyModeTempOptOut[];
extern const char kChromeFrameReadyModeEndTempOptOut[];
extern const char kChromeSxS[];
extern const char kCreateAllShortcuts[];
+extern const char kCriticalUpdateVersion[];
extern const char kDeleteProfile[];
extern const char kDisableLogging[];
extern const char kDoNotCreateShortcuts[];