blob: e12dc93193e6570ef18626bd69c176a867729fcc [file] [log] [blame]
// 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.
#include "chrome/browser/sync/test/integration/preferences_helper.h"
#include <utility>
#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/common/chrome_constants.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/persistent_pref_store.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
using sync_datatype_helper::test;
namespace preferences_helper {
PrefService* GetPrefs(int index) {
return test()->GetProfile(index)->GetPrefs();
}
PrefService* GetVerifierPrefs() {
return test()->verifier()->GetPrefs();
}
user_prefs::PrefRegistrySyncable* GetRegistry(Profile* profile) {
// TODO(tschumann): Not sure what's the cleanest way to avoid this deprecated
// call is. Ideally we could use a servicification integration test.
// Another option would be to have a ForTest-only variant of
// KeyedServiceBaseFactory::GetAssociatedPrefRegistry().
return static_cast<user_prefs::PrefRegistrySyncable*>(
profile->GetPrefs()->DeprecatedGetPrefRegistry());
}
void ChangeBooleanPref(int index, const char* pref_name) {
bool new_value = !GetPrefs(index)->GetBoolean(pref_name);
GetPrefs(index)->SetBoolean(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetBoolean(pref_name, new_value);
}
void ChangeIntegerPref(int index, const char* pref_name, int new_value) {
GetPrefs(index)->SetInteger(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetInteger(pref_name, new_value);
}
void ChangeInt64Pref(int index, const char* pref_name, int64_t new_value) {
GetPrefs(index)->SetInt64(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetInt64(pref_name, new_value);
}
void ChangeDoublePref(int index, const char* pref_name, double new_value) {
GetPrefs(index)->SetDouble(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetDouble(pref_name, new_value);
}
void ChangeStringPref(int index,
const char* pref_name,
const std::string& new_value) {
GetPrefs(index)->SetString(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetString(pref_name, new_value);
}
void ClearPref(int index, const char* pref_name) {
GetPrefs(index)->ClearPref(pref_name);
if (test()->use_verifier())
GetVerifierPrefs()->ClearPref(pref_name);
}
void ChangeFilePathPref(int index,
const char* pref_name,
const base::FilePath& new_value) {
GetPrefs(index)->SetFilePath(pref_name, new_value);
if (test()->use_verifier())
GetVerifierPrefs()->SetFilePath(pref_name, new_value);
}
void ChangeListPref(int index,
const char* pref_name,
const base::ListValue& new_value) {
{
ListPrefUpdate update(GetPrefs(index), pref_name);
base::ListValue* list = update.Get();
for (auto it = new_value.begin(); it != new_value.end(); ++it) {
list->Append(it->CreateDeepCopy());
}
}
if (test()->use_verifier()) {
ListPrefUpdate update_verifier(GetVerifierPrefs(), pref_name);
base::ListValue* list_verifier = update_verifier.Get();
for (auto it = new_value.begin(); it != new_value.end(); ++it) {
list_verifier->Append(it->CreateDeepCopy());
}
}
}
scoped_refptr<PrefStore> BuildPrefStoreFromPrefsFile(Profile* profile) {
profile->GetPrefs()->CommitPendingWrite();
// Writes are scheduled on the IO thread. The JsonPrefStore requires all
// access (construction, Get, Set, ReadPrefs) to be made from the same thread.
// So instead of reading the file from the IO thread, we simply schedule a
// dummy task to avoid races with writing the file and reading it.
base::RunLoop run_loop;
profile->GetIOTaskRunner()->PostTask(FROM_HERE,
base::BindOnce(run_loop.QuitClosure()));
run_loop.Run();
auto pref_store = base::MakeRefCounted<JsonPrefStore>(
profile->GetPath().Append(chrome::kPreferencesFilename));
base::ScopedAllowBlockingForTesting allow_blocking;
if (pref_store->ReadPrefs() != PersistentPrefStore::PREF_READ_ERROR_NONE) {
ADD_FAILURE() << " Failed reading the prefs file into the store.";
}
return pref_store;
}
bool BooleanPrefMatches(const char* pref_name) {
bool reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetBoolean(pref_name);
} else {
reference_value = GetPrefs(0)->GetBoolean(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetBoolean(pref_name)) {
DVLOG(1) << "Boolean preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool IntegerPrefMatches(const char* pref_name) {
int reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetInteger(pref_name);
} else {
reference_value = GetPrefs(0)->GetInteger(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetInteger(pref_name)) {
DVLOG(1) << "Integer preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool Int64PrefMatches(const char* pref_name) {
int64_t reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetInt64(pref_name);
} else {
reference_value = GetPrefs(0)->GetInt64(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetInt64(pref_name)) {
DVLOG(1) << "Integer preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool DoublePrefMatches(const char* pref_name) {
double reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetDouble(pref_name);
} else {
reference_value = GetPrefs(0)->GetDouble(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetDouble(pref_name)) {
DVLOG(1) << "Double preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool StringPrefMatches(const char* pref_name) {
std::string reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetString(pref_name);
} else {
reference_value = GetPrefs(0)->GetString(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetString(pref_name)) {
DVLOG(1) << "String preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool ClearedPrefMatches(const char* pref_name) {
if (test()->use_verifier()) {
if (GetVerifierPrefs()->GetUserPrefValue(pref_name)) {
return false;
}
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (GetPrefs(i)->GetUserPrefValue(pref_name)) {
DVLOG(1) << "Preference " << pref_name << " isn't cleared in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool FilePathPrefMatches(const char* pref_name) {
base::FilePath reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetFilePath(pref_name);
} else {
reference_value = GetPrefs(0)->GetFilePath(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (reference_value != GetPrefs(i)->GetFilePath(pref_name)) {
DVLOG(1) << "base::FilePath preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
bool ListPrefMatches(const char* pref_name) {
const base::ListValue* reference_value;
if (test()->use_verifier()) {
reference_value = GetVerifierPrefs()->GetList(pref_name);
} else {
reference_value = GetPrefs(0)->GetList(pref_name);
}
for (int i = 0; i < test()->num_clients(); ++i) {
if (!reference_value->Equals(GetPrefs(i)->GetList(pref_name))) {
DVLOG(1) << "List preference " << pref_name << " mismatched in"
<< " profile " << i << ".";
return false;
}
}
return true;
}
} // namespace preferences_helper
PrefMatchChecker::PrefMatchChecker(const char* path) : path_(path) {
if (test()->use_verifier()) {
RegisterPrefListener(preferences_helper::GetVerifierPrefs());
}
for (int i = 0; i < test()->num_clients(); ++i) {
RegisterPrefListener(preferences_helper::GetPrefs(i));
}
}
PrefMatchChecker::~PrefMatchChecker() {}
std::string PrefMatchChecker::GetDebugMessage() const {
return base::StringPrintf("Waiting for pref '%s' to match", GetPath());
}
const char* PrefMatchChecker::GetPath() const {
return path_;
}
void PrefMatchChecker::RegisterPrefListener(PrefService* pref_service) {
std::unique_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar());
registrar->Init(pref_service);
registrar->Add(path_,
base::Bind(&PrefMatchChecker::CheckExitCondition,
base::Unretained(this)));
pref_change_registrars_.push_back(std::move(registrar));
}
ListPrefMatchChecker::ListPrefMatchChecker(const char* path)
: PrefMatchChecker(path) {}
bool ListPrefMatchChecker::IsExitConditionSatisfied() {
return preferences_helper::ListPrefMatches(GetPath());
}
BooleanPrefMatchChecker::BooleanPrefMatchChecker(const char* path)
: PrefMatchChecker(path) {}
bool BooleanPrefMatchChecker::IsExitConditionSatisfied() {
return preferences_helper::BooleanPrefMatches(GetPath());
}
IntegerPrefMatchChecker::IntegerPrefMatchChecker(const char* path)
: PrefMatchChecker(path) {}
bool IntegerPrefMatchChecker::IsExitConditionSatisfied() {
return preferences_helper::IntegerPrefMatches(GetPath());
}
StringPrefMatchChecker::StringPrefMatchChecker(const char* path)
: PrefMatchChecker(path) {}
bool StringPrefMatchChecker::IsExitConditionSatisfied() {
return preferences_helper::StringPrefMatches(GetPath());
}
ClearedPrefMatchChecker::ClearedPrefMatchChecker(const char* path)
: PrefMatchChecker(path) {}
bool ClearedPrefMatchChecker::IsExitConditionSatisfied() {
return preferences_helper::ClearedPrefMatches(GetPath());
}