#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/prefs/chrome_pref_service_factory.h"
#include "chrome/browser/prefs/profile_pref_store_manager.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engine_choice/search_engine_choice_service_factory.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/search_engines/default_search_manager.h"
#include "components/search_engines/template_url_data.h"
#include "components/sync/base/features.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_launcher.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extension.h"
#include "services/preferences/public/cpp/tracked/tracked_preference_histogram_names.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_switches.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/registry.h"
#include "chrome/install_static/install_util.h"
#endif
namespace {
const char kGoodCrxId[] = …;
enum AllowedBuckets { … };
#if BUILDFLAG(IS_WIN)
std::wstring GetRegistryPathForTestProfile() {
base::win::RegKey key;
if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Chromium\\PrefHashBrowserTest",
KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
LONG result = key.DeleteKey(L"");
EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
}
base::FilePath profile_dir;
EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
if (profile_dir.BaseName().value() == L"user_data") {
profile_dir = profile_dir.DirName();
}
DCHECK(profile_dir.BaseName().value().find_first_of(L"0123456789") !=
std::string::npos);
return install_static::GetRegistryPath() +
L"\\PreferenceMACs\\PrefHashBrowserTest\\" +
profile_dir.BaseName().value();
}
#endif
int GetTrackedPrefHistogramCount(const char* histogram_name,
const char* histogram_suffix,
int allowed_buckets) { … }
int GetTrackedPrefHistogramCount(const char* histogram_name,
int allowed_buckets) { … }
#if !BUILDFLAG(IS_CHROMEOS_ASH)
std::optional<base::Value::Dict> ReadPrefsDictionary(
const base::FilePath& pref_file) { … }
#endif
bool SupportsRegistryValidation() { … }
#define PREF_HASH_BROWSER_TEST(fixture, test_name) …
class PrefHashBrowserTestBase : public extensions::ExtensionBrowserTest { … };
}
class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedDefault, UnchangedDefault);
class PrefHashBrowserTestUnchangedCustom
: public PrefHashBrowserTestUnchangedDefault { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedCustom, UnchangedCustom);
class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestClearedAtomic, ClearedAtomic);
class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedInitialized,
UntrustedInitialized);
class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedAtomic, ChangedAtomic);
class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedSplitPref, ChangedSplitPref);
class PrefHashBrowserTestUntrustedAdditionToPrefs
: public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefs,
UntrustedAdditionToPrefs);
class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe
: public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe,
UntrustedAdditionToPrefsAfterWipe);
#if BUILDFLAG(IS_WIN)
class PrefHashBrowserTestRegistryValidationFailure
: public PrefHashBrowserTestBase {
public:
void SetupPreferences() override {
profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
}
void AttackPreferencesOnDisk(
base::Value::Dict* unprotected_preferences,
base::Value::Dict* protected_preferences) override {
std::wstring 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));
ASSERT_EQ(ERROR_SUCCESS,
key.WriteValue(L"homepage", std::wstring(64, 'A').c_str()));
}
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);
#endif
class PrefHashBrowserTestDefaultSearch : public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestDefaultSearch, SearchProtected);
class PrefHashBrowserTestExtensionDictTypeChanged
: public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestExtensionDictTypeChanged,
ExtensionDictTypeChanged);
class PrefHashBrowserTestAccountValueUntrustedAddition
: public PrefHashBrowserTestBase { … };
PREF_HASH_BROWSER_TEST(PrefHashBrowserTestAccountValueUntrustedAddition,
AccountValueUntrustedAddition);