Chromium Code Reviews| Index: chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| index 6e73c5138ace73ce56853fbd8d6b9f1ce825553f..0a8436c397cabbb535b2b8c753ace20af3b4fd6d 100644 |
| --- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| +++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| @@ -40,11 +40,19 @@ |
| #include "chromeos/chromeos_switches.h" |
| #endif |
| +#if defined(OS_WIN) |
| +#include "base/test/test_reg_util_win.h" |
| +#endif |
| + |
| namespace { |
| // Extension ID of chrome/test/data/extensions/good.crx |
| const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; |
| +// Prefix for the registry path. |
| +constexpr base::char16 kRegistryTestPathPrefix[] = |
| + L"SOFTWARE\\Chromium\\PrefHashBrowserTest\\"; |
| + |
| // Explicit expectations from the caller of GetTrackedPrefHistogramCount(). This |
| // enables detailed reporting of the culprit on failure. |
| enum AllowedBuckets { |
| @@ -58,14 +66,24 @@ enum AllowedBuckets { |
| ALLOW_ANY |
| }; |
| +base::string16 GetRegistryPathForTestProfile() { |
| + base::FilePath profile_dir; |
| + EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &profile_dir)); |
| + return kRegistryTestPathPrefix + profile_dir.BaseName().value(); |
| +} |
| + |
| // Returns the number of times |histogram_name| was reported so far; adding the |
| // results of the first 100 buckets (there are only ~19 reporting IDs as of this |
| // writing; varies depending on the platform). |allowed_buckets| hints at extra |
| // requirements verified in this method (see AllowedBuckets for details). |
| int GetTrackedPrefHistogramCount(const char* histogram_name, |
| + const char* histogram_suffix, |
| int allowed_buckets) { |
| + std::string full_histogram_name(histogram_name); |
| + if (*histogram_suffix != 0) |
| + full_histogram_name.append(".").append(histogram_suffix); |
| const base::HistogramBase* histogram = |
| - base::StatisticsRecorder::FindHistogram(histogram_name); |
| + base::StatisticsRecorder::FindHistogram(full_histogram_name); |
| if (!histogram) |
| return 0; |
| @@ -84,6 +102,13 @@ int GetTrackedPrefHistogramCount(const char* histogram_name, |
| return sum; |
| } |
| +// Helper function to call GetTrackedPrefHistogramCount with no external |
| +// validation suffix. |
| +int GetTrackedPrefHistogramCount(const char* histogram_name, |
| + int allowed_buckets) { |
| + return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets); |
| +} |
| + |
| std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary( |
| const base::FilePath& pref_file) { |
| JSONFileValueDeserializer deserializer(pref_file); |
| @@ -103,6 +128,16 @@ std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary( |
| static_cast<base::DictionaryValue*>(prefs.release())); |
| } |
| +// Returns whether external validation is supported on the platform through |
| +// storing MACs in the registry. |
| +bool SupportsRegistryValidation() { |
| +#if defined(OS_WIN) |
| + return true; |
| +#else |
| + return false; |
| +#endif |
| +} |
| + |
| #define PREF_HASH_BROWSER_TEST(fixture, test_name) \ |
| IN_PROC_BROWSER_TEST_P(fixture, PRE_##test_name) { \ |
| SetupPreferences(); \ |
| @@ -235,6 +270,42 @@ class PrefHashBrowserTestBase |
| // Bots are on a domain, turn off the domain check for settings hardening in |
| // order to be able to test all SettingsEnforcement groups. |
| chrome_prefs::DisableDomainCheckForTesting(); |
| + |
| + // Avoid polluting prefs for the user and the bots by writing to a specific |
| + // testing registry path. |
| + base::string16 registry_key = GetRegistryPathForTestProfile(); |
| + chrome_prefs::SetPreferenceValidationRegistryPathForTesting(registry_key); |
|
proberge
2016/08/06 00:05:08
Getting the registry to work during the browser te
|
| + |
| +#if defined(OS_WIN) |
| + // For PRE tests, delete the Registry key to avoid collisions. |
| + if (IsPRETest()) { |
| + base::win::RegKey key; |
| + if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { |
| + LONG result = key.DeleteKey(L""); |
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); |
| + } |
| + } |
| +#endif |
| + } |
| + |
| + void TearDown() override { |
| +#if defined(OS_WIN) |
| + // For non-PRE tests, delete the Registry key to avoid polluting the |
| + // registry. |
| + // TODO(proberge): it would be nice to delete keys from interrupted tests |
| + // as well. |
| + base::string16 registry_key = GetRegistryPathForTestProfile(); |
| + if (!IsPRETest()) { |
| + base::win::RegKey key; |
| + if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { |
| + LONG result = key.DeleteKey(L""); |
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); |
| + } |
| + } |
| +#endif |
| + ExtensionBrowserTest::TearDown(); |
| } |
| // In the PRE_ test, find the number of tracked preferences that were |
| @@ -268,6 +339,23 @@ class PrefHashBrowserTestBase |
| EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| num_split_tracked_prefs); |
| + if (SupportsRegistryValidation()) { |
| + // Same checks as above, but for the registry. |
| + num_tracked_prefs_ = GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramNullInitialized, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY); |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM, |
| + num_tracked_prefs_ > 0); |
| + |
| + int num_split_tracked_prefs = GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 5); |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + num_split_tracked_prefs); |
| + } |
| + |
| num_tracked_prefs_ += num_split_tracked_prefs; |
| std::string num_tracked_prefs_str = base::IntToString(num_tracked_prefs_); |
| @@ -409,6 +497,17 @@ class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect all prefs to be reported as Unchanged with no resets. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY)); |
| + } |
| } |
| }; |
| @@ -499,6 +598,15 @@ class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect homepage to have been cleared. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramCleared, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| } |
| }; |
| @@ -621,6 +729,18 @@ class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // The MACs have been cleared but the preferences have not been tampered. |
| + // The registry should report all prefs as unchanged. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY)); |
| + } |
| } |
| }; |
| @@ -711,6 +831,15 @@ class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect a single Changed event for tracked pref #4 (startup URLs). |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 4)); |
| + } |
| } |
| }; |
| @@ -808,6 +937,16 @@ class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect a single split pref changed report with a count of 2 for tracked |
| + // pref #5 (extensions). |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 5)); |
| + } |
| } |
| }; |
| @@ -881,6 +1020,17 @@ class PrefHashBrowserTestUntrustedAdditionToPrefs |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM && |
| + protection_level_ < PROTECTION_ENABLED_BASIC) |
| + ? changed_expected |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 3)); |
| + } |
| } |
| }; |
| @@ -955,8 +1105,72 @@ class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + EXPECT_EQ(changed_expected, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + EXPECT_EQ(cleared_expected, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramCleared, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| } |
| }; |
| PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe, |
| UntrustedAdditionToPrefsAfterWipe); |
| +#include "base/strings/utf_string_conversions.h" |
| +class PrefHashBrowserTestRegistryValidationFailure |
| + : public PrefHashBrowserTestBase { |
| + public: |
| + void SetupPreferences() override { |
| + profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com"); |
| + } |
| + |
| + void AttackPreferencesOnDisk( |
| + base::DictionaryValue* unprotected_preferences, |
| + base::DictionaryValue* protected_preferences) override { |
| + // See TearDown |
| + } |
| + |
| + void TearDown() override { |
| +// Modifying prefs in the registry while in AttackPreferencesOnDisk does not |
| +// seem to work (despite returning ERROR_SUCCESS). Do it earlier, during the |
| +// PRE test TearDown instead. |
| +#if defined(OS_WIN) |
| + base::string16 registry_key = |
| + GetRegistryPathForTestProfile() + L"\\PreferenceMACs\\Default"; |
| + base::win::RegKey key; |
| + ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, registry_key.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY)); |
| + // An incorrect hash should still have the correct size. |
| + ASSERT_EQ(ERROR_SUCCESS, |
| + key.WriteValue(L"homepage", base::string16(64, 'A').c_str())); |
| +#endif |
| + PrefHashBrowserTestBase::TearDown(); |
| + } |
| + |
| + void VerifyReactionToPrefAttack() override { |
| + EXPECT_EQ( |
| + protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| + } |
| +}; |
| + |
| +PREF_HASH_BROWSER_TEST(PrefHashBrowserTestRegistryValidationFailure, |
| + RegistryValidationFailure); |