diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-27 17:51:01 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-27 17:51:01 +0000 |
commit | 1c69c77f2cad3725602a6d7718b5624517857f63 (patch) | |
tree | 0bbb518987b8c59776125b0278af5f91d5be3bd9 /chrome/installer | |
parent | 6c3e649ee7c06f6be0a56d8e9c665c035280e9be (diff) | |
download | chromium_src-1c69c77f2cad3725602a6d7718b5624517857f63.zip chromium_src-1c69c77f2cad3725602a6d7718b5624517857f63.tar.gz chromium_src-1c69c77f2cad3725602a6d7718b5624517857f63.tar.bz2 |
Mike's change to allow the type of reactivation to be specified based on current elevation level.
I added some minor style changes and fixed up the tests.
BUG=NONE
TEST=gcapi_test
Review URL: https://chromiumcodereview.appspot.com/9465013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123755 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/gcapi/gcapi.cc | 49 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi.h | 29 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_omaha_experiment.cc | 14 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_omaha_experiment.h | 2 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_reactivation.cc | 8 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_reactivation.h | 2 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_reactivation_test.cc | 57 | ||||
-rw-r--r-- | chrome/installer/gcapi/gcapi_test.cc | 12 |
8 files changed, 122 insertions, 51 deletions
diff --git a/chrome/installer/gcapi/gcapi.cc b/chrome/installer/gcapi/gcapi.cc index cb746f1..4abe39b 100644 --- a/chrome/installer/gcapi/gcapi.cc +++ b/chrome/installer/gcapi/gcapi.cc @@ -320,7 +320,9 @@ bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) { } } // namespace -BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD* reasons) { +BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, + int shell_mode, + DWORD* reasons) { DWORD local_reasons = 0; WindowsVersion windows_version = GetWindowsVersion(); @@ -334,13 +336,17 @@ BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD* reasons) { if (IsChromeInstalled(HKEY_CURRENT_USER)) local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT; - if (!VerifyHKLMAccess()) { + if (shell_mode == GCAPI_INVOKED_UAC_ELEVATION) { + // Only check that we have HKLM write permissions if we specify that + // GCAPI is being invoked from an elevated shell, or in admin mode + if (!VerifyHKLMAccess()) { local_reasons |= GCCC_ERROR_ACCESSDENIED; - } else if ((windows_version == VERSION_VISTA_OR_HIGHER) && - !VerifyAdminGroup()) { + } else if ((windows_version == VERSION_VISTA_OR_HIGHER) && + !VerifyAdminGroup()) { // For Vista or later check for elevation since even for admin user we could // be running in non-elevated mode. We require integrity level High. local_reasons |= GCCC_ERROR_INTEGRITYLEVEL; + } } // Then only check whether we can re-offer, if everything else is OK. @@ -545,6 +551,7 @@ int __stdcall GoogleChromeDaysSinceLastRun() { BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, int previous_brand_codes_length, const wchar_t** previous_brand_codes, + int shell_mode, DWORD* error_code) { DCHECK(error_code); @@ -574,17 +581,23 @@ BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, // Make sure we haven't previously been reactivated by this brand code // or any of the previous brand codes from this partner. - std::vector<std::wstring> reactivation_brands; - reactivation_brands.push_back(brand_code); - if (previous_brand_codes_length > 0 && previous_brand_codes != NULL) { - std::copy(previous_brand_codes, - previous_brand_codes + previous_brand_codes_length, - std::back_inserter(reactivation_brands)); - } - if (HasBeenReactivatedByBrandCodes(reactivation_brands)) { - if (error_code) - *error_code = REACTIVATE_ERROR_ALREADY_REACTIVATED; - return FALSE; + // Since this function is invoked by ReactivateChrome, and since + // ReactivateChrome is called first in non-elevated shell and + // second in UAC-elevated shell, we only want to execute this block + // of code the first time, in non-elevated mode. + if (shell_mode == GCAPI_INVOKED_STANDARD_SHELL) { + std::vector<std::wstring> reactivation_brands; + reactivation_brands.push_back(brand_code); + if (previous_brand_codes_length > 0 && previous_brand_codes != NULL) { + std::copy(previous_brand_codes, + previous_brand_codes + previous_brand_codes_length, + std::back_inserter(reactivation_brands)); + } + if (HasBeenReactivatedByBrandCodes(reactivation_brands)) { + if (error_code) + *error_code = REACTIVATE_ERROR_ALREADY_REACTIVATED; + return FALSE; + } } return TRUE; @@ -593,16 +606,18 @@ BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, BOOL __stdcall ReactivateChrome(wchar_t* brand_code, int previous_brand_codes_length, const wchar_t** previous_brand_codes, + int shell_mode, DWORD* error_code) { BOOL result = FALSE; if (CanOfferReactivation(brand_code, previous_brand_codes_length, previous_brand_codes, + shell_mode, error_code)) { - if (SetReactivationBrandCode(brand_code)) { + if (SetReactivationBrandCode(brand_code, shell_mode)) { // Currently set this as a best-effort thing. We return TRUE if // reactivation succeeded regardless of the experiment label result. - SetOmahaExperimentLabel(brand_code); + SetOmahaExperimentLabel(brand_code, shell_mode); result = TRUE; } else { diff --git a/chrome/installer/gcapi/gcapi.h b/chrome/installer/gcapi/gcapi.h index 30a5226..8232a1e 100644 --- a/chrome/installer/gcapi/gcapi.h +++ b/chrome/installer/gcapi/gcapi.h @@ -24,18 +24,27 @@ extern "C" { #define REACTIVATE_ERROR_INVALID_INPUT 0x08 #define REACTIVATE_ERROR_REACTIVATION_FAILED 0x10 +// Flags to indicate how GCAPI is invoked +#define GCAPI_INVOKED_STANDARD_SHELL 0x01 +#define GCAPI_INVOKED_UAC_ELEVATION 0x02 + // The minimum number of days an installation can be dormant before reactivation // may be offered. const int kReactivationMinDaysDormant = 50; // This function returns TRUE if Google Chrome should be offered. -// If the return is FALSE, the reasons DWORD explains why. If you don't care -// for the reason, you can pass NULL for reasons. -// set_flag indicates whether a flag should be set indicating that Chrome was +// If the return is FALSE, the |reasons| DWORD explains why. If you don't care +// for the reason, you can pass NULL for |reasons|. +// |set_flag| indicates whether a flag should be set indicating that Chrome was // offered within the last six months; if passed FALSE, this method will not // set the flag even if Chrome can be offered. If passed TRUE, this method // will set the flag only if Chrome can be offered. -BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, DWORD* reasons); +// |shell_mode| should be set to one of GCAPI_INVOKED_STANDARD_SHELL or +// GCAPI_INVOKED_UAC_ELEVATION depending on whether this method is invoked +// from an elevated or non-elevated process. +BOOL __stdcall GoogleChromeCompatibilityCheck(BOOL set_flag, + int shell_mode, + DWORD* reasons); // This function launches Google Chrome after a successful install. Make // sure COM library is NOT initialized before you call this function (so if @@ -71,9 +80,13 @@ int __stdcall GoogleChromeDaysSinceLastRun(); // as |previous_brand_codes|. Returns false if the vendor may not offer // reactivation at this time, and places one of the REACTIVATE_ERROR_XXX values // in |error_code| if |error_code| is non-null. +// |shell_mode| should be set to one of GCAPI_INVOKED_STANDARD_SHELL or +// GCAPI_INVOKED_UAC_ELEVATION depending on whether this method is invoked +// from an elevated or non-elevated process. BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, int previous_brand_codes_length, const wchar_t** previous_brand_codes, + int shell_mode, DWORD* error_code); // Attempts to reactivate Chrome for the specified |brand_code|. If the vendor @@ -81,23 +94,29 @@ BOOL __stdcall CanOfferReactivation(const wchar_t* brand_code, // size |previous_brand_codes_length| as |previous_brand_codes|. Returns false // if reactivation fails, and places one of the REACTIVATE_ERROR_XXX values // in |error_code| if |error_code| is non-null. +// |shell_mode| should be set to one of GCAPI_INVOKED_STANDARD_SHELL or +// GCAPI_INVOKED_UAC_ELEVATION depending on whether this method is invoked +// from an elevated or non-elevated process. BOOL __stdcall ReactivateChrome(wchar_t* brand_code, int previous_brand_codes_length, const wchar_t** previous_brand_codes, + int shell_mode, DWORD* error_code); // Function pointer type declarations to use with GetProcAddress. -typedef BOOL (__stdcall *GCCC_CompatibilityCheck)(BOOL, DWORD *); +typedef BOOL (__stdcall *GCCC_CompatibilityCheck)(BOOL, int, DWORD *); typedef BOOL (__stdcall *GCCC_LaunchGC)(HANDLE *); typedef BOOL (__stdcall *GCCC_LaunchGCWithDimensions)(int, int, int, int); typedef int (__stdcall *GCCC_GoogleChromeDaysSinceLastRun)(); typedef BOOL (__stdcall *GCCC_CanOfferReactivation)(const wchar_t*, int, const wchar_t**, + int, DWORD*); typedef BOOL (__stdcall *GCCC_ReactivateChrome)(const wchar_t*, int, const wchar_t**, + int, DWORD*); } // extern "C" diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.cc b/chrome/installer/gcapi/gcapi_omaha_experiment.cc index 539bd6f..6b4b94e 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment.cc +++ b/chrome/installer/gcapi/gcapi_omaha_experiment.cc @@ -11,6 +11,7 @@ #include "base/win/registry.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" +#include "chrome/installer/gcapi/gcapi.h" using base::Time; using base::TimeDelta; @@ -73,18 +74,25 @@ int GetCurrentRlzWeek() { } // namespace -bool SetOmahaExperimentLabel(const wchar_t* brand_code) { +bool SetOmahaExperimentLabel(const wchar_t* brand_code, int shell_mode) { if (!brand_code) { return false; } + // When this function is invoked in standard, non-elevated shell, we default + // to writing the experiment label to HKCU. When it is invoked in a UAC- + // elevated shell, we write the experiment label to HKLM. + HKEY registry_hive = + shell_mode == GCAPI_INVOKED_UAC_ELEVATION ? HKEY_LOCAL_MACHINE : + HKEY_CURRENT_USER; + int week_number = GetCurrentRlzWeek(); if (week_number < 0 || week_number > 999) week_number = 999; string16 experiment_label; base::SStringPrintf(&experiment_label, - L"%ls_%d|%ls", + L"reacbrand=%ls_%d|%ls", brand_code, week_number, BuildOmahaExperimentDateString().c_str()); @@ -95,7 +103,7 @@ bool SetOmahaExperimentLabel(const wchar_t* brand_code) { experiment_path += L"\\"; experiment_path += kExperimentAppGuids[i]; - RegKey client_state(HKEY_LOCAL_MACHINE, experiment_path.c_str(), + RegKey client_state(registry_hive, experiment_path.c_str(), KEY_SET_VALUE); if (client_state.Valid()) { if (client_state.WriteValue(kExperimentLabels, diff --git a/chrome/installer/gcapi/gcapi_omaha_experiment.h b/chrome/installer/gcapi/gcapi_omaha_experiment.h index 0550305..0f5bdbd 100644 --- a/chrome/installer/gcapi/gcapi_omaha_experiment.h +++ b/chrome/installer/gcapi/gcapi_omaha_experiment.h @@ -6,6 +6,6 @@ #define CHROME_INSTALLER_GCAPI_GCAPI_OMAHA_EXPERIMENT_H_ #pragma once -bool SetOmahaExperimentLabel(const wchar_t* brand_code); +bool SetOmahaExperimentLabel(const wchar_t* brand_code, int shell_mode); #endif // CHROME_INSTALLER_GCAPI_GCAPI_OMAHA_EXPERIMENT_H_ diff --git a/chrome/installer/gcapi/gcapi_reactivation.cc b/chrome/installer/gcapi/gcapi_reactivation.cc index 6755e2f..87abc0e 100644 --- a/chrome/installer/gcapi/gcapi_reactivation.cc +++ b/chrome/installer/gcapi/gcapi_reactivation.cc @@ -7,6 +7,7 @@ #include "base/time.h" #include "base/win/registry.h" #include "chrome/installer/util/google_update_constants.h" +#include "chrome/installer/gcapi/gcapi.h" using base::Time; using base::win::RegKey; @@ -44,9 +45,14 @@ bool HasBeenReactivatedByBrandCodes( return success; } -bool SetReactivationBrandCode(const std::wstring& brand_code) { +bool SetReactivationBrandCode(const std::wstring& brand_code, int shell_mode) { bool success = false; + // This function currently only should be run in a non-elevated shell, + // so we return "true" if it is being invoked from an elevated shell. + if (shell_mode == GCAPI_INVOKED_UAC_ELEVATION) + return true; + std::wstring path(google_update::kRegPathClientState); path += L"\\"; path += google_update::kChromeUpgradeCode; diff --git a/chrome/installer/gcapi/gcapi_reactivation.h b/chrome/installer/gcapi/gcapi_reactivation.h index d9e5db8..69ae105 100644 --- a/chrome/installer/gcapi/gcapi_reactivation.h +++ b/chrome/installer/gcapi/gcapi_reactivation.h @@ -12,6 +12,6 @@ bool HasBeenReactivatedByBrandCodes( const std::vector<std::wstring>& brand_codes); -bool SetReactivationBrandCode(const std::wstring& brand_code); +bool SetReactivationBrandCode(const std::wstring& brand_code, int shell_mode); #endif // CHROME_INSTALLER_GCAPI_GCAPI_REACTIVATION_H_ diff --git a/chrome/installer/gcapi/gcapi_reactivation_test.cc b/chrome/installer/gcapi/gcapi_reactivation_test.cc index 822cb80..66c2882 100644 --- a/chrome/installer/gcapi/gcapi_reactivation_test.cc +++ b/chrome/installer/gcapi/gcapi_reactivation_test.cc @@ -78,14 +78,14 @@ class GCAPIReactivationTest : public ::testing::Test { last_run_time_string.c_str()) == ERROR_SUCCESS); } - bool HasExperimentLabels() { + bool HasExperimentLabels(HKEY hive) { int label_count = 0; for (int i = 0; i < arraysize(kExperimentAppGuids); ++i) { string16 client_state_path(google_update::kRegPathClientState); client_state_path += L"\\"; client_state_path += kExperimentAppGuids[i]; - RegKey client_state_key(HKEY_LOCAL_MACHINE, + RegKey client_state_key(hive, client_state_path.c_str(), KEY_QUERY_VALUE); if (client_state_key.Valid() && @@ -122,7 +122,7 @@ class GCAPIReactivationTest : public ::testing::Test { }; TEST_F(GCAPIReactivationTest, CheckSetReactivationBrandCode) { - EXPECT_TRUE(SetReactivationBrandCode(L"GAGA")); + EXPECT_TRUE(SetReactivationBrandCode(L"GAGA", GCAPI_INVOKED_STANDARD_SHELL)); EXPECT_EQ(L"GAGA", GetReactivationString(HKEY_CURRENT_USER)); std::vector<std::wstring> check_codes; @@ -142,20 +142,26 @@ TEST_F(GCAPIReactivationTest, CanOfferReactivation_Basic) { // We're not installed yet. Make sure CanOfferReactivation fails. EXPECT_FALSE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_NOTINSTALLED, error); // Now pretend to be installed. CanOfferReactivation should pass. EXPECT_TRUE(SetChromeInstallMarker(HKEY_CURRENT_USER)); EXPECT_TRUE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); // Now set a recent last_run value. CanOfferReactivation should fail again. Time hkcu_last_run = Time::NowFromSystemTime() - TimeDelta::FromDays(20); EXPECT_TRUE(SetLastRunTime(HKEY_CURRENT_USER, hkcu_last_run.ToInternalValue())); EXPECT_FALSE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_NOTDORMANT, error); // Now set a last_run value that exceeds the threshold. @@ -164,23 +170,33 @@ TEST_F(GCAPIReactivationTest, CanOfferReactivation_Basic) { EXPECT_TRUE(SetLastRunTime(HKEY_CURRENT_USER, hkcu_last_run.ToInternalValue())); EXPECT_TRUE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); // Test some invalid inputs EXPECT_FALSE(CanOfferReactivation(NULL, arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_INVALID_INPUT, error); EXPECT_FALSE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - NULL, &error)); + NULL, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_INVALID_INPUT, error); // One more valid one - EXPECT_TRUE(CanOfferReactivation(L"GAGA", 0, NULL, &error)); + EXPECT_TRUE(CanOfferReactivation(L"GAGA", 0, NULL, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); // Check that the previous brands check works: - EXPECT_TRUE(SetReactivationBrandCode(L"GOOGOO")); + EXPECT_TRUE(SetReactivationBrandCode(L"GOOGOO", + GCAPI_INVOKED_STANDARD_SHELL)); EXPECT_FALSE(CanOfferReactivation(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, + GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_ALREADY_REACTIVATED, error); } @@ -197,22 +213,26 @@ TEST_F(GCAPIReactivationTest, Reactivation_Flow) { hkcu_last_run.ToInternalValue())); EXPECT_TRUE(ReactivateChrome(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(L"GAGA", GetReactivationString(HKEY_CURRENT_USER)); // Make sure we can't reactivate again: EXPECT_FALSE(ReactivateChrome(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_ALREADY_REACTIVATED, error); // Should still be able to reactivate under other brands: EXPECT_TRUE(ReactivateChrome(L"MAMA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(L"MAMA", GetReactivationString(HKEY_CURRENT_USER)); // Validate that previous_brands are rejected: EXPECT_FALSE(ReactivateChrome(L"PFFT", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(REACTIVATE_ERROR_ALREADY_REACTIVATED, error); EXPECT_EQ(L"MAMA", GetReactivationString(HKEY_CURRENT_USER)); } @@ -230,8 +250,9 @@ TEST_F(GCAPIReactivationTest, ExperimentLabelCheck) { hkcu_last_run.ToInternalValue())); EXPECT_TRUE(ReactivateChrome(L"GAGA", arraysize(previous_brands), - previous_brands, &error)); + previous_brands, GCAPI_INVOKED_STANDARD_SHELL, + &error)); EXPECT_EQ(L"GAGA", GetReactivationString(HKEY_CURRENT_USER)); - EXPECT_TRUE(HasExperimentLabels()); + EXPECT_TRUE(HasExperimentLabels(HKEY_CURRENT_USER)); } diff --git a/chrome/installer/gcapi/gcapi_test.cc b/chrome/installer/gcapi/gcapi_test.cc index b7f08bb..68633e0 100644 --- a/chrome/installer/gcapi/gcapi_test.cc +++ b/chrome/installer/gcapi/gcapi_test.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -16,8 +16,10 @@ void call_statically() { // running this twice verifies that the first call does not set // a flag that would make the second fail. Thus, the results // of the two calls should be the same (no state should have changed) - result_flag_off = GoogleChromeCompatibilityCheck(FALSE, &reason); - result_flag_on = GoogleChromeCompatibilityCheck(TRUE, &reason); + result_flag_off = GoogleChromeCompatibilityCheck( + FALSE, GCAPI_INVOKED_STANDARD_SHELL, &reason); + result_flag_on = GoogleChromeCompatibilityCheck( + TRUE, GCAPI_INVOKED_STANDARD_SHELL, &reason); if (result_flag_off != result_flag_on) printf("Registry key flag is not being set properly."); @@ -41,8 +43,8 @@ void call_dynamically() { // running this twice verifies that the first call does not set // a flag that would make the second fail. Thus, the results // of the two calls should be the same (no state should have changed) - BOOL result_flag_off = gccfn(FALSE, &reason); - BOOL result_flag_on = gccfn(TRUE, &reason); + BOOL result_flag_off = gccfn(FALSE, GCAPI_INVOKED_STANDARD_SHELL, &reason); + BOOL result_flag_on = gccfn(TRUE, GCAPI_INVOKED_STANDARD_SHELL, &reason); if (result_flag_off != result_flag_on) printf("Registry key flag is not being set properly."); |