1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/test/integration/preferences_helper.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
13 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
14 #include "chrome/browser/sync/test/integration/sync_test.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "components/prefs/persistent_pref_store.h"
18 #include "components/prefs/pref_change_registrar.h"
19 #include "components/prefs/pref_service.h"
20 #include "components/prefs/scoped_user_pref_update.h"
21
22 using sync_datatype_helper::test;
23
24 namespace preferences_helper {
25
GetPrefs(int index)26 PrefService* GetPrefs(int index) {
27 return test()->GetProfile(index)->GetPrefs();
28 }
29
GetRegistry(Profile * profile)30 user_prefs::PrefRegistrySyncable* GetRegistry(Profile* profile) {
31 // TODO(tschumann): Not sure what's the cleanest way to avoid this deprecated
32 // call is. Ideally we could use a servicification integration test.
33 // Another option would be to have a ForTest-only variant of
34 // KeyedServiceBaseFactory::GetAssociatedPrefRegistry().
35 return static_cast<user_prefs::PrefRegistrySyncable*>(
36 profile->GetPrefs()->DeprecatedGetPrefRegistry());
37 }
38
ChangeBooleanPref(int index,const char * pref_name)39 void ChangeBooleanPref(int index, const char* pref_name) {
40 bool new_value = !GetPrefs(index)->GetBoolean(pref_name);
41 GetPrefs(index)->SetBoolean(pref_name, new_value);
42 }
43
ChangeIntegerPref(int index,const char * pref_name,int new_value)44 void ChangeIntegerPref(int index, const char* pref_name, int new_value) {
45 GetPrefs(index)->SetInteger(pref_name, new_value);
46 }
47
ChangeStringPref(int index,const char * pref_name,const std::string & new_value)48 void ChangeStringPref(int index,
49 const char* pref_name,
50 const std::string& new_value) {
51 GetPrefs(index)->SetString(pref_name, new_value);
52 }
53
ClearPref(int index,const char * pref_name)54 void ClearPref(int index, const char* pref_name) {
55 GetPrefs(index)->ClearPref(pref_name);
56 }
57
ChangeListPref(int index,const char * pref_name,const base::ListValue & new_value)58 void ChangeListPref(int index,
59 const char* pref_name,
60 const base::ListValue& new_value) {
61 ListPrefUpdate update(GetPrefs(index), pref_name);
62 base::ListValue* list = update.Get();
63 for (const auto& it : new_value) {
64 list->Append(it.CreateDeepCopy());
65 }
66 }
67
BuildPrefStoreFromPrefsFile(Profile * profile)68 scoped_refptr<PrefStore> BuildPrefStoreFromPrefsFile(Profile* profile) {
69 base::RunLoop run_loop;
70 profile->GetPrefs()->CommitPendingWrite(run_loop.QuitClosure());
71 run_loop.Run();
72
73 auto pref_store = base::MakeRefCounted<JsonPrefStore>(
74 profile->GetPath().Append(chrome::kPreferencesFilename));
75 base::ScopedAllowBlockingForTesting allow_blocking;
76 if (pref_store->ReadPrefs() != PersistentPrefStore::PREF_READ_ERROR_NONE) {
77 ADD_FAILURE() << " Failed reading the prefs file into the store.";
78 }
79
80 return pref_store;
81 }
82
BooleanPrefMatches(const char * pref_name)83 bool BooleanPrefMatches(const char* pref_name) {
84 bool reference_value = GetPrefs(0)->GetBoolean(pref_name);
85 for (int i = 1; i < test()->num_clients(); ++i) {
86 if (reference_value != GetPrefs(i)->GetBoolean(pref_name)) {
87 DVLOG(1) << "Boolean preference " << pref_name << " mismatched in"
88 << " profile " << i << ".";
89 return false;
90 }
91 }
92 return true;
93 }
94
IntegerPrefMatches(const char * pref_name)95 bool IntegerPrefMatches(const char* pref_name) {
96 int reference_value = GetPrefs(0)->GetInteger(pref_name);
97 for (int i = 1; i < test()->num_clients(); ++i) {
98 if (reference_value != GetPrefs(i)->GetInteger(pref_name)) {
99 DVLOG(1) << "Integer preference " << pref_name << " mismatched in"
100 << " profile " << i << ".";
101 return false;
102 }
103 }
104 return true;
105 }
106
StringPrefMatches(const char * pref_name)107 bool StringPrefMatches(const char* pref_name) {
108 std::string reference_value = GetPrefs(0)->GetString(pref_name);
109 for (int i = 1; i < test()->num_clients(); ++i) {
110 if (reference_value != GetPrefs(i)->GetString(pref_name)) {
111 DVLOG(1) << "String preference " << pref_name << " mismatched in"
112 << " profile " << i << ".";
113 return false;
114 }
115 }
116 return true;
117 }
118
ClearedPrefMatches(const char * pref_name)119 bool ClearedPrefMatches(const char* pref_name) {
120 for (int i = 0; i < test()->num_clients(); ++i) {
121 if (GetPrefs(i)->GetUserPrefValue(pref_name)) {
122 DVLOG(1) << "Preference " << pref_name << " isn't cleared in"
123 << " profile " << i << ".";
124 return false;
125 }
126 }
127 return true;
128 }
129
ListPrefMatches(const char * pref_name)130 bool ListPrefMatches(const char* pref_name) {
131 const base::ListValue* reference_value = GetPrefs(0)->GetList(pref_name);
132 for (int i = 1; i < test()->num_clients(); ++i) {
133 if (!reference_value->Equals(GetPrefs(i)->GetList(pref_name))) {
134 DVLOG(1) << "List preference " << pref_name << " mismatched in"
135 << " profile " << i << ".";
136 return false;
137 }
138 }
139 return true;
140 }
141
142 } // namespace preferences_helper
143
PrefMatchChecker(const char * path)144 PrefMatchChecker::PrefMatchChecker(const char* path) : path_(path) {
145 for (int i = 0; i < test()->num_clients(); ++i) {
146 RegisterPrefListener(preferences_helper::GetPrefs(i));
147 }
148 }
149
150 PrefMatchChecker::~PrefMatchChecker() = default;
151
GetPath() const152 const char* PrefMatchChecker::GetPath() const {
153 return path_;
154 }
155
RegisterPrefListener(PrefService * pref_service)156 void PrefMatchChecker::RegisterPrefListener(PrefService* pref_service) {
157 std::unique_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar());
158 registrar->Init(pref_service);
159 registrar->Add(path_,
160 base::BindRepeating(&PrefMatchChecker::CheckExitCondition,
161 base::Unretained(this)));
162 pref_change_registrars_.push_back(std::move(registrar));
163 }
164
ListPrefMatchChecker(const char * path)165 ListPrefMatchChecker::ListPrefMatchChecker(const char* path)
166 : PrefMatchChecker(path) {}
167
IsExitConditionSatisfied(std::ostream * os)168 bool ListPrefMatchChecker::IsExitConditionSatisfied(std::ostream* os) {
169 *os << "Waiting for pref '" << GetPath() << "' to match";
170 return preferences_helper::ListPrefMatches(GetPath());
171 }
172
BooleanPrefMatchChecker(const char * path)173 BooleanPrefMatchChecker::BooleanPrefMatchChecker(const char* path)
174 : PrefMatchChecker(path) {}
175
IsExitConditionSatisfied(std::ostream * os)176 bool BooleanPrefMatchChecker::IsExitConditionSatisfied(std::ostream* os) {
177 *os << "Waiting for pref '" << GetPath() << "' to match";
178 return preferences_helper::BooleanPrefMatches(GetPath());
179 }
180
IntegerPrefMatchChecker(const char * path)181 IntegerPrefMatchChecker::IntegerPrefMatchChecker(const char* path)
182 : PrefMatchChecker(path) {}
183
IsExitConditionSatisfied(std::ostream * os)184 bool IntegerPrefMatchChecker::IsExitConditionSatisfied(std::ostream* os) {
185 *os << "Waiting for pref '" << GetPath() << "' to match";
186 return preferences_helper::IntegerPrefMatches(GetPath());
187 }
188
StringPrefMatchChecker(const char * path)189 StringPrefMatchChecker::StringPrefMatchChecker(const char* path)
190 : PrefMatchChecker(path) {}
191
IsExitConditionSatisfied(std::ostream * os)192 bool StringPrefMatchChecker::IsExitConditionSatisfied(std::ostream* os) {
193 *os << "Waiting for pref '" << GetPath() << "' to match";
194 return preferences_helper::StringPrefMatches(GetPath());
195 }
196
ClearedPrefMatchChecker(const char * path)197 ClearedPrefMatchChecker::ClearedPrefMatchChecker(const char* path)
198 : PrefMatchChecker(path) {}
199
IsExitConditionSatisfied(std::ostream * os)200 bool ClearedPrefMatchChecker::IsExitConditionSatisfied(std::ostream* os) {
201 *os << "Waiting for pref '" << GetPath() << "' to match";
202 return preferences_helper::ClearedPrefMatches(GetPath());
203 }
204