diff options
author | grt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-12 21:21:18 +0000 |
---|---|---|
committer | grt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-12 21:21:18 +0000 |
commit | 5ac8aff8fd32ece193f0eb12f89a90599186ea13 (patch) | |
tree | c25cb22ccb09cea9ba22cc238a9916f5658186ce /chrome/installer | |
parent | 6eac57a601d0f2e88390609b5716c08eb5f19b73 (diff) | |
download | chromium_src-5ac8aff8fd32ece193f0eb12f89a90599186ea13.zip chromium_src-5ac8aff8fd32ece193f0eb12f89a90599186ea13.tar.gz chromium_src-5ac8aff8fd32ece193f0eb12f89a90599186ea13.tar.bz2 |
Handle eulaaccepted and oeminstall mo betta for multi-install. During first install, these values (deposited by Google Update) are now mirrored from the product-specific ClientState key into the binaries' key. When the EULA is accepted, the modification is written to both the product's and binaries' ClientStateMedium key. As a result, multi-install OEM installs will start updating only when the EULA is accepted (as desired) and the EVENT_INSTALL_OEM_FIRST_CHECK ping is sent for both the product and the binaries.
BUG=88584
TEST=see bug
R=robertshield@chromium.org
Review URL: http://codereview.chromium.org/7346011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92234 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/setup/install_worker.cc | 128 | ||||
-rw-r--r-- | chrome/installer/setup/install_worker.h | 12 | ||||
-rw-r--r-- | chrome/installer/setup/install_worker_unittest.cc | 39 | ||||
-rw-r--r-- | chrome/installer/setup/setup_main.cc | 13 | ||||
-rw-r--r-- | chrome/installer/setup/uninstall.cc | 9 | ||||
-rw-r--r-- | chrome/installer/util/browser_distribution.cc | 10 | ||||
-rw-r--r-- | chrome/installer/util/browser_distribution.h | 10 | ||||
-rw-r--r-- | chrome/installer/util/browser_distribution_unittest.cc | 12 | ||||
-rw-r--r-- | chrome/installer/util/google_update_constants.cc | 1 | ||||
-rw-r--r-- | chrome/installer/util/google_update_constants.h | 1 | ||||
-rw-r--r-- | chrome/installer/util/google_update_settings.cc | 75 | ||||
-rw-r--r-- | chrome/installer/util/google_update_settings.h | 4 | ||||
-rw-r--r-- | chrome/installer/util/google_update_settings_unittest.cc | 54 | ||||
-rw-r--r-- | chrome/installer/util/installation_state.cc | 48 | ||||
-rw-r--r-- | chrome/installer/util/installation_state.h | 21 |
15 files changed, 314 insertions, 123 deletions
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 552d39f..94c191c 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc @@ -250,6 +250,106 @@ void AddProductSpecificWorkItems(const InstallationState& original_state, } } +// Mirror oeminstall the first time anything is installed multi. There is no +// need to update the value on future install/update runs since this value never +// changes. Note that the value is removed by Google Update after EULA +// acceptance is processed. +void AddOemInstallWorkItems(const InstallationState& original_state, + const InstallerState& installer_state, + WorkItemList* install_list) { + DCHECK(installer_state.is_multi_install()); + const bool system_install = installer_state.system_install(); + if (!original_state.GetProductState(system_install, + BrowserDistribution::CHROME_BINARIES)) { + const HKEY root_key = installer_state.root_key(); + std::wstring multi_key( + installer_state.multi_package_binaries_distribution()->GetStateKey()); + + // Copy the value from Chrome unless Chrome isn't installed or being + // installed. + BrowserDistribution::Type source_type; + if (installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER)) { + source_type = BrowserDistribution::CHROME_BROWSER; + } else if (!installer_state.products().empty()) { + // Pick a product, any product. + source_type = installer_state.products()[0]->distribution()->GetType(); + } else { + // Nothing is being installed? Entirely unexpected, so do no harm. + LOG(ERROR) << "No products found in AddOemInstallWorkItems"; + return; + } + const ProductState* source_product = + original_state.GetNonVersionedProductState(system_install, source_type); + + std::wstring oem_install; + if (source_product->GetOemInstall(&oem_install)) { + VLOG(1) << "Mirroring oeminstall=\"" << oem_install << "\" from " + << BrowserDistribution::GetSpecificDistribution(source_type) + ->GetAppShortCutName(); + install_list->AddCreateRegKeyWorkItem(root_key, multi_key); + // Always overwrite an old value. + install_list->AddSetRegValueWorkItem(root_key, multi_key, + google_update::kRegOemInstallField, + oem_install, true); + } else { + // Clear any old value. + install_list->AddDeleteRegValueWorkItem( + root_key, multi_key, google_update::kRegOemInstallField); + } + } +} + +// Mirror eulaaccepted the first time anything is installed multi. There is no +// need to update the value on future install/update runs since +// GoogleUpdateSettings::SetEULAConsent will modify the value for both the +// relevant product and for the binaries. +void AddEulaAcceptedWorkItems(const InstallationState& original_state, + const InstallerState& installer_state, + WorkItemList* install_list) { + DCHECK(installer_state.is_multi_install()); + const bool system_install = installer_state.system_install(); + if (!original_state.GetProductState(system_install, + BrowserDistribution::CHROME_BINARIES)) { + const HKEY root_key = installer_state.root_key(); + std::wstring multi_key( + installer_state.multi_package_binaries_distribution()->GetStateKey()); + + // Copy the value from the product with the greatest value. + bool have_eula_accepted = false; + BrowserDistribution::Type product_type; + DWORD eula_accepted; + const Products& products = installer_state.products(); + for (size_t i = 0, count = products.size(); i != count; ++i) { + DWORD dword_value = 0; + BrowserDistribution::Type this_type = + products[i]->distribution()->GetType(); + const ProductState* product_state = + original_state.GetNonVersionedProductState( + system_install, this_type); + if (product_state->GetEulaAccepted(&dword_value) && + (!have_eula_accepted || dword_value > eula_accepted)) { + have_eula_accepted = true; + eula_accepted = dword_value; + product_type = this_type; + } + } + + if (have_eula_accepted) { + VLOG(1) << "Mirroring eulaaccepted=" << eula_accepted << " from " + << BrowserDistribution::GetSpecificDistribution(product_type) + ->GetAppShortCutName(); + install_list->AddCreateRegKeyWorkItem(root_key, multi_key); + install_list->AddSetRegValueWorkItem( + root_key, multi_key, google_update::kRegEULAAceptedField, + eula_accepted, true); + } else { + // Clear any old value. + install_list->AddDeleteRegValueWorkItem( + root_key, multi_key, google_update::kRegEULAAceptedField); + } + } +} + // Adds work items that make registry adjustments for Google Update. void AddGoogleUpdateWorkItems(const InstallationState& original_state, const InstallerState& installer_state, @@ -261,24 +361,34 @@ void AddGoogleUpdateWorkItems(const InstallationState& original_state, return; } + const bool system_install = installer_state.system_install(); + const HKEY root_key = installer_state.root_key(); + std::wstring multi_key( + installer_state.multi_package_binaries_distribution()->GetStateKey()); + + // For system-level installs, make sure the ClientStateMedium key for the + // binaries exists. + if (system_install) { + install_list->AddCreateRegKeyWorkItem( + root_key, + installer_state.multi_package_binaries_distribution()-> + GetStateMediumKey().c_str()); + } + // Creating the ClientState key for binaries, if we're migrating to multi then // copy over Chrome's brand code if it has one. Chrome Frame currently never // has a brand code. if (installer_state.state_type() != BrowserDistribution::CHROME_BINARIES) { - std::wstring multi_key( - installer_state.multi_package_binaries_distribution()->GetStateKey()); const ProductState* chrome_product_state = original_state.GetNonVersionedProductState( - installer_state.system_install(), - BrowserDistribution::CHROME_BROWSER); + system_install, BrowserDistribution::CHROME_BROWSER); const std::wstring& brand(chrome_product_state->brand()); if (!brand.empty()) { - install_list->AddCreateRegKeyWorkItem(installer_state.root_key(), - multi_key); + install_list->AddCreateRegKeyWorkItem(root_key, multi_key); // Write Chrome's brand code to the multi key. Never overwrite the value // if one is already present (although this shouldn't happen). - install_list->AddSetRegValueWorkItem(installer_state.root_key(), + install_list->AddSetRegValueWorkItem(root_key, multi_key, google_update::kRegBrandField, brand, @@ -286,6 +396,10 @@ void AddGoogleUpdateWorkItems(const InstallationState& original_state, } } + AddOemInstallWorkItems(original_state, installer_state, install_list); + + AddEulaAcceptedWorkItems(original_state, installer_state, install_list); + AddUsageStatsWorkItems(original_state, installer_state, install_list); // TODO(grt): check for other keys/values we should put in the package's diff --git a/chrome/installer/setup/install_worker.h b/chrome/installer/setup/install_worker.h index 7e4e19f..82a4901 100644 --- a/chrome/installer/setup/install_worker.h +++ b/chrome/installer/setup/install_worker.h @@ -28,8 +28,18 @@ class InstallerState; class Package; class Product; +// Helper function for AddGoogleUpdateWorkItems that mirrors oeminstall. +void AddOemInstallWorkItems(const InstallationState& original_state, + const InstallerState& installer_state, + WorkItemList* install_list); + +// Helper function for AddGoogleUpdateWorkItems that mirrors eulaaccepted. +void AddEulaAcceptedWorkItems(const InstallationState& original_state, + const InstallerState& installer_state, + WorkItemList* install_list); + // Adds work items that make registry adjustments for Google Update; namely, -// copy a brand value and move a usagestats value. +// copy brand, oeminstall, and eulaaccepted values; and move a usagestats value. void AddGoogleUpdateWorkItems(const InstallationState& original_state, const InstallerState& installer_state, WorkItemList* install_list); diff --git a/chrome/installer/setup/install_worker_unittest.cc b/chrome/installer/setup/install_worker_unittest.cc index 4a99174..67ef806 100644 --- a/chrome/installer/setup/install_worker_unittest.cc +++ b/chrome/installer/setup/install_worker_unittest.cc @@ -93,11 +93,21 @@ class MockProductState : public ProductState { void set_version(Version* version) { version_.reset(version); } void set_multi_install(bool multi) { multi_install_ = multi; } void set_brand(const std::wstring& brand) { brand_ = brand; } + void set_eula_accepted(DWORD eula_accepted) { + has_eula_accepted_ = true; + eula_accepted_ = eula_accepted; + } + void clear_eula_accepted() { has_eula_accepted_ = false; } void set_usagestats(DWORD usagestats) { has_usagestats_ = true; usagestats_ = usagestats; } void clear_usagestats() { has_usagestats_ = false; } + void set_oem_install(const std::wstring& oem_install) { + has_oem_install_ = true; + oem_install_ = oem_install; + } + void clear_oem_install() { has_oem_install_ = false; } void SetUninstallProgram(const FilePath& setup_exe) { uninstall_command_ = CommandLine(setup_exe); } @@ -175,6 +185,7 @@ class InstallWorkerTest : public testing::Test { product_state.set_version(current_version_->Clone()); product_state.set_multi_install(multi_install); product_state.set_brand(L"TEST"); + product_state.set_eula_accepted(1); BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( BrowserDistribution::CHROME_BROWSER); @@ -543,14 +554,22 @@ TEST_F(InstallWorkerTest, GoogleUpdateWorkItemsTest) { BrowserDistribution::GetSpecificDistribution( BrowserDistribution::CHROME_BINARIES); std::wstring multi_app_guid(multi_dist->GetAppGuid()); + std::wstring multi_client_state_suffix(L"ClientState\\" + multi_app_guid); EXPECT_CALL(work_item_list, - AddCreateRegKeyWorkItem(_, HasSubstr(multi_app_guid))).Times(1); + AddCreateRegKeyWorkItem(_, HasSubstr(multi_client_state_suffix))) + .Times(testing::AnyNumber()); + + // Expect ClientStateMedium to be created for system-level installs. + EXPECT_CALL(work_item_list, + AddCreateRegKeyWorkItem(_, HasSubstr(L"ClientStateMedium\\" + + multi_app_guid))) + .Times(system_level ? 1 : 0); // Expect to see a set value for the "TEST" brand code in the multi Client // State key. EXPECT_CALL(work_item_list, AddSetRegStringValueWorkItem(_, - HasSubstr(multi_app_guid), + HasSubstr(multi_client_state_suffix), StrEq(google_update::kRegBrandField), StrEq(L"TEST"), _)).Times(1); @@ -561,6 +580,22 @@ TEST_F(InstallWorkerTest, GoogleUpdateWorkItemsTest) { StrEq(google_update::kRegApField), _, _)).Times(testing::AnyNumber()); + // Expect "oeminstall" to be cleared. + EXPECT_CALL(work_item_list, + AddDeleteRegValueWorkItem( + _, + HasSubstr(multi_client_state_suffix), + StrEq(google_update::kRegOemInstallField))).Times(1); + + // Expect "eulaaccepted" to set. + EXPECT_CALL(work_item_list, + AddSetRegDwordValueWorkItem( + _, + HasSubstr(multi_client_state_suffix), + StrEq(google_update::kRegEULAAceptedField), + Eq(static_cast<DWORD>(1)), + _)).Times(1); + AddGoogleUpdateWorkItems(*installation_state.get(), *installer_state.get(), &work_item_list); diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 7affe54..cbd6e33 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc @@ -147,14 +147,8 @@ DWORD UnPackArchive(const FilePath& archive, void AddExistingMultiInstalls(const InstallationState& original_state, InstallerState* installer_state) { if (installer_state->is_multi_install()) { - // TODO(grt): Find all occurrences of such arrays and generalize/centralize. - static const BrowserDistribution::Type product_checks[] = { - BrowserDistribution::CHROME_BROWSER, - BrowserDistribution::CHROME_FRAME - }; - - for (size_t i = 0; i < arraysize(product_checks); ++i) { - BrowserDistribution::Type type = product_checks[i]; + for (size_t i = 0; i < BrowserDistribution::kNumProductTypes; ++i) { + BrowserDistribution::Type type = BrowserDistribution::kProductTypes[i]; if (!installer_state->FindProduct(type)) { const ProductState* state = original_state.GetProductState(installer_state->system_install(), @@ -347,7 +341,6 @@ bool CheckMultiInstallConditions(const InstallationState& original_state, const Products& products = installer_state->products(); DCHECK(products.size()); - bool is_first_install = true; const bool system_level = installer_state->system_install(); if (installer_state->is_multi_install()) { @@ -899,7 +892,7 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state, cmd_line.GetSwitchValueNative(installer::switches::kShowEula); *exit_code = ShowEULADialog(inner_frame); if (installer::EULA_REJECTED != *exit_code) - GoogleUpdateSettings::SetEULAConsent(*installer_state, true); + GoogleUpdateSettings::SetEULAConsent(original_state, true); } else if (cmd_line.HasSwitch( installer::switches::kRegisterChromeBrowser)) { installer::InstallStatus status = installer::UNKNOWN_STATUS; diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc index c2200ba..56f2bdd 100644 --- a/chrome/installer/setup/uninstall.cc +++ b/chrome/installer/setup/uninstall.cc @@ -801,13 +801,10 @@ InstallStatus UninstallProduct(const InstallationState& original_state, bool can_delete_files = true; if (installer_state.is_multi_install()) { - BrowserDistribution::Type types[] = { - BrowserDistribution::CHROME_BROWSER, - BrowserDistribution::CHROME_FRAME - }; ProductState prod_state; - for (int i = 0; i < arraysize(types); ++i) { - if (prod_state.Initialize(installer_state.system_install(), types[i]) && + for (size_t i = 0; i < BrowserDistribution::kNumProductTypes; ++i) { + if (prod_state.Initialize(installer_state.system_install(), + BrowserDistribution::kProductTypes[i]) && prod_state.is_multi_install()) { can_delete_files = false; break; diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc index ce4d1c6..535797a 100644 --- a/chrome/installer/util/browser_distribution.cc +++ b/chrome/installer/util/browser_distribution.cc @@ -54,6 +54,16 @@ BrowserDistribution::Type GetCurrentDistributionType() { } // end namespace +// CHROME_BINARIES represents the binaries shared by multi-install products and +// is not a product in and of itself, so it is not present in this collection. +const BrowserDistribution::Type BrowserDistribution::kProductTypes[] = { + BrowserDistribution::CHROME_BROWSER, + BrowserDistribution::CHROME_FRAME, +}; + +const size_t BrowserDistribution::kNumProductTypes = + arraysize(BrowserDistribution::kProductTypes); + BrowserDistribution::BrowserDistribution() : type_(CHROME_BROWSER) { } diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h index fa0c9d6..6d92501 100644 --- a/chrome/installer/util/browser_distribution.h +++ b/chrome/installer/util/browser_distribution.h @@ -30,8 +30,6 @@ class Product; class BrowserDistribution { public: - virtual ~BrowserDistribution() {} - enum Type { CHROME_BROWSER, CHROME_FRAME, @@ -52,6 +50,14 @@ class BrowserDistribution { // experiment but does not participate. }; + // An array of the Types representing products; + static const Type kProductTypes[]; + + // The number of elements in the array |kProductTypes|. + static const size_t kNumProductTypes; + + virtual ~BrowserDistribution() {} + static BrowserDistribution* GetDistribution(); static BrowserDistribution* GetSpecificDistribution(Type type); diff --git a/chrome/installer/util/browser_distribution_unittest.cc b/chrome/installer/util/browser_distribution_unittest.cc index 61c9652..942f62c 100644 --- a/chrome/installer/util/browser_distribution_unittest.cc +++ b/chrome/installer/util/browser_distribution_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 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. // @@ -24,14 +24,10 @@ 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) { - BrowserDistribution::Type browser_tests[] = { - BrowserDistribution::CHROME_BROWSER, - BrowserDistribution::CHROME_FRAME, - }; - - for (int i = 0; i < arraysize(browser_tests); ++i) { + for (size_t i = 0; i < BrowserDistribution::kNumProductTypes; ++i) { BrowserDistribution* dist = - BrowserDistribution::GetSpecificDistribution(browser_tests[i]); + BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::kProductTypes[i]); ASSERT_TRUE(dist != NULL); std::wstring name = dist->GetApplicationName(); EXPECT_FALSE(name.empty()); diff --git a/chrome/installer/util/google_update_constants.cc b/chrome/installer/util/google_update_constants.cc index 1380cc5..96204cd 100644 --- a/chrome/installer/util/google_update_constants.cc +++ b/chrome/installer/util/google_update_constants.cc @@ -32,6 +32,7 @@ const wchar_t kRegLastRunTimeField[] = L"lastrun"; const wchar_t kRegMetricsId[] = L"metricsid"; const wchar_t kRegMSIField[] = L"msi"; const wchar_t kRegNameField[] = L"name"; +const wchar_t kRegOemInstallField[] = L"oeminstall"; const wchar_t kRegOldVersionField[] = L"opv"; const wchar_t kRegOopcrashesField[] = L"oopcrashes"; const wchar_t kRegRLZBrandField[] = L"brand"; diff --git a/chrome/installer/util/google_update_constants.h b/chrome/installer/util/google_update_constants.h index 26106e8..5e78b77 100644 --- a/chrome/installer/util/google_update_constants.h +++ b/chrome/installer/util/google_update_constants.h @@ -41,6 +41,7 @@ extern const wchar_t kRegLastCheckedField[]; extern const wchar_t kRegMetricsId[]; extern const wchar_t kRegMSIField[]; extern const wchar_t kRegNameField[]; +extern const wchar_t kRegOemInstallField[]; extern const wchar_t kRegOldVersionField[]; extern const wchar_t kRegOopcrashesField[]; extern const wchar_t kRegRLZBrandField[]; diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc index 4572494..45234c2 100644 --- a/chrome/installer/util/google_update_settings.cc +++ b/chrome/installer/util/google_update_settings.cc @@ -18,11 +18,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/installer_state.h" +#include "chrome/installer/util/installation_state.h" #include "chrome/installer/util/product.h" using base::win::RegKey; -using installer::InstallerState; +using installer::InstallationState; namespace { @@ -268,49 +268,44 @@ bool GoogleUpdateSettings::SetMetricsId(const std::wstring& metrics_id) { return WriteGoogleUpdateStrKey(google_update::kRegMetricsId, metrics_id); } +// EULA consent is only relevant for system-level installs. bool GoogleUpdateSettings::SetEULAConsent( - const InstallerState& installer_state, + const InstallationState& machine_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 = 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); + const DWORD eula_accepted = consented ? 1 : 0; + // This magical method will return the right instance based on such details as + // whether or not --chrome-frame is present on the command-line. + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); + std::wstring reg_path = dist->GetStateMediumKey(); + bool succeeded = true; + RegKey key; + + // Write the consent value into the product's ClientStateMedium key. + if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), + KEY_SET_VALUE) != ERROR_SUCCESS || + key.WriteValue(google_update::kRegEULAAceptedField, + eula_accepted) != ERROR_SUCCESS) { + succeeded = false; } - if (status != FOUND_SAME_SETTING) { - EulaSearchResult new_status = NO_SETTING; - 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) { - 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 = (*scan)->distribution()->GetStateMediumKey(); - } - } - if (status == NO_SETTING) { - LOG(WARNING) - << "eulaaccepted value not found; setting consent in key " - << fallback_reg_path; - reg_path = fallback_reg_path; + + // If this is a multi-install, also write it into the binaries' key. + // --mutli-install is not provided on the command-line, so deduce it from + // the product's state. + const installer::ProductState* product_state = + machine_state.GetProductState(true, dist->GetType()); + if (product_state != NULL && product_state->is_multi_install()) { + dist = BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::CHROME_BINARIES); + reg_path = dist->GetStateMediumKey(); + if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), + KEY_SET_VALUE) != ERROR_SUCCESS || + key.WriteValue(google_update::kRegEULAAceptedField, + eula_accepted) != ERROR_SUCCESS) { + succeeded = false; } } - RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_SET_VALUE); - return (key.WriteValue(google_update::kRegEULAAceptedField, - consented ? 1 : 0) == ERROR_SUCCESS); + + return succeeded; } int GoogleUpdateSettings::GetLastRunTime() { diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h index 888ba73..7e37e79 100644 --- a/chrome/installer/util/google_update_settings.h +++ b/chrome/installer/util/google_update_settings.h @@ -13,7 +13,7 @@ namespace installer { class ChannelInfo; -class InstallerState; +class InstallationState; } // This class provides accessors to the Google Update 'ClientState' information @@ -46,7 +46,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::InstallerState& installer_state, + static bool SetEULAConsent(const installer::InstallationState& machine_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 e27309d..aed09d5 100644 --- a/chrome/installer/util/google_update_settings_unittest.cc +++ b/chrome/installer/util/google_update_settings_unittest.cc @@ -5,20 +5,14 @@ #include <windows.h> #include <shlwapi.h> // For SHDeleteKey. -#include <functional> -#include <map> - -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/win/registry.h" +#include "chrome/common/chrome_constants.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/channel_info.h" +#include "chrome/installer/util/fake_installation_state.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/product.h" #include "chrome/installer/util/work_item_list.h" #include "testing/gtest/include/gtest/gtest.h" @@ -427,50 +421,36 @@ TEST_F(GoogleUpdateSettingsTest, UpdateInstallStatusTest) { } TEST_F(GoogleUpdateSettingsTest, SetEULAConsent) { + using installer::FakeInstallationState; + const bool multi_install = true; 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(); - installer::InstallerState installer_state; - installer_state.Initialize(cmd_line, prefs, machine_state); - HKEY root = installer_state.root_key(); + FakeInstallationState machine_state; + + // Chrome is installed. + machine_state.AddChrome(system_level, multi_install, + Version::GetVersionFromString(chrome::kChromeVersion)); RegKey key; DWORD value; BrowserDistribution* binaries = - installer_state.multi_package_binaries_distribution(); - EXPECT_EQ(BrowserDistribution::CHROME_BINARIES, binaries->GetType()); + BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::CHROME_BINARIES); BrowserDistribution* chrome = - installer_state.products()[0]->distribution(); - EXPECT_EQ(BrowserDistribution::CHROME_BROWSER, chrome->GetType()); + BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::CHROME_BROWSER); - // By default, eulaconsent ends up on the package. - EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(installer_state, true)); + // eulaconsent is set on both the product and the binaries. + EXPECT_TRUE(GoogleUpdateSettings::SetEULAConsent(machine_state, true)); EXPECT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, binaries->GetStateMediumKey().c_str(), - KEY_QUERY_VALUE | KEY_SET_VALUE)); + KEY_QUERY_VALUE)); EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(google_update::kRegEULAAceptedField, &value)); EXPECT_EQ(1U, value); EXPECT_EQ(ERROR_SUCCESS, - key.DeleteValue(google_update::kRegEULAAceptedField)); - - // But it will end up on the product if needed - EXPECT_EQ(ERROR_SUCCESS, - 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(installer_state, true)); - EXPECT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, chrome->GetStateMediumKey().c_str(), - KEY_QUERY_VALUE | KEY_SET_VALUE)); + KEY_QUERY_VALUE)); EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(google_update::kRegEULAAceptedField, &value)); EXPECT_EQ(1U, value); diff --git a/chrome/installer/util/installation_state.cc b/chrome/installer/util/installation_state.cc index ff46253..919db89 100644 --- a/chrome/installer/util/installation_state.cc +++ b/chrome/installer/util/installation_state.cc @@ -18,6 +18,8 @@ ProductState::ProductState() usagestats_(0), msi_(false), multi_install_(false), + has_eula_accepted_(false), + has_oem_install_(false), has_usagestats_(false) { } @@ -97,6 +99,12 @@ bool ProductState::Initialize(bool system_install, // we find. has_usagestats_ = (key.ReadValueDW(google_update::kRegUsageStatsField, &usagestats_) == ERROR_SUCCESS); + // "oeminstall" may be present with any value or absent. + has_oem_install_ = (key.ReadValue(google_update::kRegOemInstallField, + &oem_install_) == ERROR_SUCCESS); + // "eulaaccepted" may be absent, 0 or 1. + has_eula_accepted_ = (key.ReadValueDW(google_update::kRegEULAAceptedField, + &eula_accepted_) == ERROR_SUCCESS); // "msi" may be absent, 0 or 1 DWORD dw_value = 0; msi_ = (key.ReadValueDW(google_update::kRegMSIField, @@ -108,17 +116,23 @@ bool ProductState::Initialize(bool system_install, multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall); } - // Read from the ClientStateMedium key. + // Read from the ClientStateMedium key. Values here override those in + // ClientState. if (system_install && key.Open(root_key, distribution->GetStateMediumKey().c_str(), KEY_QUERY_VALUE) == ERROR_SUCCESS) { - DWORD usagestats = 0; + DWORD dword_value = 0; - // A usagestats value in ClientStateMedium overrides that in ClientState. if (key.ReadValueDW(google_update::kRegUsageStatsField, - &usagestats) == ERROR_SUCCESS) { + &dword_value) == ERROR_SUCCESS) { has_usagestats_ = true; - usagestats_ = usagestats; + usagestats_ = dword_value; + } + + if (key.ReadValueDW(google_update::kRegEULAAceptedField, + &dword_value) == ERROR_SUCCESS) { + has_eula_accepted_ = true; + eula_accepted_ = dword_value; } } @@ -142,10 +156,14 @@ ProductState& ProductState::CopyFrom(const ProductState& other) { brand_ = other.brand_; rename_cmd_ = other.rename_cmd_; uninstall_command_ = other.uninstall_command_; + oem_install_ = other.oem_install_; commands_.CopyFrom(other.commands_); + eula_accepted_ = other.eula_accepted_; usagestats_ = other.usagestats_; msi_ = other.msi_; multi_install_ = other.multi_install_; + has_eula_accepted_ = other.has_eula_accepted_; + has_oem_install_ = other.has_oem_install_; has_usagestats_ = other.has_usagestats_; return *this; @@ -157,14 +175,34 @@ void ProductState::Clear() { old_version_.reset(); brand_.clear(); rename_cmd_.clear(); + oem_install_.clear(); uninstall_command_ = CommandLine(CommandLine::NO_PROGRAM); commands_.Clear(); + eula_accepted_ = 0; usagestats_ = 0; msi_ = false; multi_install_ = false; + has_eula_accepted_ = false; + has_oem_install_ = false; has_usagestats_ = false; } +bool ProductState::GetEulaAccepted(DWORD* eula_accepted) const { + DCHECK(eula_accepted); + if (!has_eula_accepted_) + return false; + *eula_accepted = eula_accepted_; + return true; +} + +bool ProductState::GetOemInstall(std::wstring* oem_install) const { + DCHECK(oem_install); + if (!has_oem_install_) + return false; + *oem_install = oem_install_; + return true; +} + bool ProductState::GetUsageStats(DWORD* usagestats) const { DCHECK(usagestats); if (!has_usagestats_) diff --git a/chrome/installer/util/installation_state.h b/chrome/installer/util/installation_state.h index 1ced729..889e64e 100644 --- a/chrome/installer/util/installation_state.h +++ b/chrome/installer/util/installation_state.h @@ -65,6 +65,17 @@ class ProductState { // awaiting update; may be empty. const std::wstring& rename_cmd() const { return rename_cmd_; } + // Returns true and populates |eula_accepted| if the product has such a value; + // otherwise, returns false and does not modify |eula_accepted|. Expected + // values are 0 (false) and 1 (true), although |eula_accepted| is given + // whatever is found. + bool GetEulaAccepted(DWORD* eula_accepted) const; + + // Returns true and populates |oem_install| if the product has such a value; + // otherwise, returns false and does not modify |oem_install|. Expected + // value is "1", although |oem_install| is given whatever is found. + bool GetOemInstall(std::wstring* oem_install) const; + // Returns true and populates |usagestats| if the product has such a value; // otherwise, returns false and does not modify |usagestats|. Expected values // are 0 (false) and 1 (true), although |usagestats| is given whatever is @@ -98,12 +109,16 @@ class ProductState { scoped_ptr<Version> old_version_; std::wstring brand_; std::wstring rename_cmd_; + std::wstring oem_install_; CommandLine uninstall_command_; AppCommands commands_; + DWORD eula_accepted_; DWORD usagestats_; - bool msi_; - bool multi_install_; - bool has_usagestats_; + bool msi_ : 1; + bool multi_install_ : 1; + bool has_eula_accepted_ : 1; + bool has_oem_install_ : 1; + bool has_usagestats_ : 1; private: friend class InstallationState; |