diff options
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/setup/install_worker.cc | 56 | ||||
-rw-r--r-- | chrome/installer/setup/setup_main.cc | 15 | ||||
-rw-r--r-- | chrome/installer/util/google_update_constants.cc | 2 | ||||
-rw-r--r-- | chrome/installer/util/google_update_constants.h | 2 | ||||
-rw-r--r-- | chrome/installer/util/install_util.cc | 2 | ||||
-rw-r--r-- | chrome/installer/util/installer_state.cc | 19 | ||||
-rw-r--r-- | chrome/installer/util/installer_state.h | 10 | ||||
-rw-r--r-- | chrome/installer/util/installer_state_unittest.cc | 158 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.cc | 4 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.h | 1 |
10 files changed, 239 insertions, 30 deletions
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index b771ac3..1200219 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc @@ -199,11 +199,11 @@ void AddUninstallShortcutWorkItems(const InstallerState& installer_state, true); install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, L"Version", - UTF8ToWide(new_version.GetString()), + ASCIIToWide(new_version.GetString()), true); install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, L"DisplayVersion", - UTF8ToWide(new_version.GetString()), + ASCIIToWide(new_version.GetString()), true); install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, L"InstallDate", @@ -254,7 +254,7 @@ void AddVersionKeyWorkItems(HKEY root, false); // set during first install list->AddSetRegValueWorkItem(root, version_key, google_update::kRegVersionField, - UTF8ToWide(new_version.GetString()), + ASCIIToWide(new_version.GetString()), true); // overwrite version } @@ -547,14 +547,19 @@ bool AppendPostInstallTasks(const InstallerState& installer_state, const Products& products = installer_state.products(); // Append work items that will only be executed if this was an update. - // We update the 'opv' key with the current version that is active and 'cmd' - // key with the rename command to run. + // We update the 'opv' value with the current version that is active, + // the 'cpv' value with the critical update version (if present), and the + // 'cmd' value with the rename command to run. { scoped_ptr<WorkItemList> in_use_update_work_items( WorkItem::CreateConditionalWorkItemList( new ConditionRunIfFileExists(new_chrome_exe))); in_use_update_work_items->set_log_message("InUseUpdateWorkItemList"); + // |critical_version| will be valid only if this in-use update includes a + // version considered critical relative to the version being updated. + Version critical_version(installer_state.DetermineCriticalVersion( + current_version, new_version)); FilePath installer_path(installer_state.GetInstallerDirectory(new_version) .Append(setup_path.BaseName())); @@ -574,7 +579,15 @@ bool AppendPostInstallTasks(const InstallerState& installer_state, if (current_version != NULL) { in_use_update_work_items->AddSetRegValueWorkItem(root, version_key, google_update::kRegOldVersionField, - UTF8ToWide(current_version->GetString()), true); + ASCIIToWide(current_version->GetString()), true); + } + if (critical_version.IsValid()) { + in_use_update_work_items->AddSetRegValueWorkItem(root, version_key, + google_update::kRegCriticalVersionField, + ASCIIToWide(critical_version.GetString()), true); + } else { + in_use_update_work_items->AddDeleteRegValueWorkItem(root, version_key, + google_update::kRegCriticalVersionField); } // Adding this registry entry for all products is overkill. @@ -585,22 +598,25 @@ bool AppendPostInstallTasks(const InstallerState& installer_state, CommandLine product_rename_cmd(rename); products[i]->AppendRenameFlags(&product_rename_cmd); in_use_update_work_items->AddSetRegValueWorkItem( - root, - version_key, - google_update::kRegRenameCmdField, - product_rename_cmd.GetCommandLineString(), - true); + root, version_key, google_update::kRegRenameCmdField, + product_rename_cmd.GetCommandLineString(), true); } if (current_version != NULL && installer_state.is_multi_install()) { BrowserDistribution* dist = installer_state.multi_package_binaries_distribution(); + version_key = dist->GetVersionKey(); in_use_update_work_items->AddSetRegValueWorkItem( - root, - dist->GetVersionKey(), - google_update::kRegOldVersionField, - UTF8ToWide(current_version->GetString()), - true); + root, version_key, google_update::kRegOldVersionField, + ASCIIToWide(current_version->GetString()), true); + if (critical_version.IsValid()) { + in_use_update_work_items->AddSetRegValueWorkItem( + root, version_key, google_update::kRegCriticalVersionField, + ASCIIToWide(critical_version.GetString()), true); + } else { + in_use_update_work_items->AddDeleteRegValueWorkItem( + root, version_key, google_update::kRegCriticalVersionField); + } // TODO(tommi): We should move the rename command here. We also need to // update upgrade_utils::SwapNewChromeExeIfPresent. } @@ -620,14 +636,16 @@ bool AppendPostInstallTasks(const InstallerState& installer_state, new Not(new ConditionRunIfFileExists(new_chrome_exe)))); regular_update_work_items->set_log_message("RegularUpdateWorkItemList"); - // Since this was not an in-use-update, delete 'opv' and 'cmd' keys. + // Since this was not an in-use-update, delete 'opv', 'cpv', and 'cmd' keys. for (size_t i = 0; i < products.size(); ++i) { BrowserDistribution* dist = products[i]->distribution(); std::wstring version_key(dist->GetVersionKey()); regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, - google_update::kRegOldVersionField); + google_update::kRegOldVersionField); + regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, + google_update::kRegCriticalVersionField); regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, - google_update::kRegRenameCmdField); + google_update::kRegRenameCmdField); } if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index be33736..fa7103f 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc @@ -230,17 +230,18 @@ installer::InstallStatus RenameChromeExecutables( dists[num_dists++] = products[i]->distribution(); } - // Add work items to delete the "opv" and "cmd" values from all distributions. + // Add work items to delete the "opv", "cpv", and "cmd" values from all + // distributions. HKEY reg_root = installer_state->root_key(); std::wstring version_key; for (int i = 0; i < num_dists; ++i) { version_key = dists[i]->GetVersionKey(); - install_list->AddDeleteRegValueWorkItem(reg_root, - version_key, - google_update::kRegOldVersionField); - install_list->AddDeleteRegValueWorkItem(reg_root, - version_key, - google_update::kRegRenameCmdField); + install_list->AddDeleteRegValueWorkItem( + reg_root, version_key, google_update::kRegOldVersionField); + install_list->AddDeleteRegValueWorkItem( + reg_root, version_key, google_update::kRegCriticalVersionField); + install_list->AddDeleteRegValueWorkItem( + reg_root, version_key, google_update::kRegRenameCmdField); } installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; if (!install_list->Do()) { 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[]; |