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 "base/prefs/pref_change_registrar.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/prefs/scoped_user_pref_update.h" 10 #include "base/strings/stringprintf.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" 13 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" 14 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h" 15 #include "chrome/browser/sync/test/integration/sync_test.h" 16 17 using sync_datatype_helper::test; 18 19 namespace preferences_helper { 20 21 PrefService* GetPrefs(int index) { 22 return test()->GetProfile(index)->GetPrefs(); 23 } 24 25 PrefService* GetVerifierPrefs() { 26 return test()->verifier()->GetPrefs(); 27 } 28 29 void ChangeBooleanPref(int index, const char* pref_name) { 30 bool new_value = !GetPrefs(index)->GetBoolean(pref_name); 31 GetPrefs(index)->SetBoolean(pref_name, new_value); 32 if (test()->use_verifier()) 33 GetVerifierPrefs()->SetBoolean(pref_name, new_value); 34 } 35 36 void ChangeIntegerPref(int index, const char* pref_name, int new_value) { 37 GetPrefs(index)->SetInteger(pref_name, new_value); 38 if (test()->use_verifier()) 39 GetVerifierPrefs()->SetInteger(pref_name, new_value); 40 } 41 42 void ChangeInt64Pref(int index, const char* pref_name, int64 new_value) { 43 GetPrefs(index)->SetInt64(pref_name, new_value); 44 if (test()->use_verifier()) 45 GetVerifierPrefs()->SetInt64(pref_name, new_value); 46 } 47 48 void ChangeDoublePref(int index, const char* pref_name, double new_value) { 49 GetPrefs(index)->SetDouble(pref_name, new_value); 50 if (test()->use_verifier()) 51 GetVerifierPrefs()->SetDouble(pref_name, new_value); 52 } 53 54 void ChangeStringPref(int index, 55 const char* pref_name, 56 const std::string& new_value) { 57 GetPrefs(index)->SetString(pref_name, new_value); 58 if (test()->use_verifier()) 59 GetVerifierPrefs()->SetString(pref_name, new_value); 60 } 61 62 void ChangeFilePathPref(int index, 63 const char* pref_name, 64 const base::FilePath& new_value) { 65 GetPrefs(index)->SetFilePath(pref_name, new_value); 66 if (test()->use_verifier()) 67 GetVerifierPrefs()->SetFilePath(pref_name, new_value); 68 } 69 70 void ChangeListPref(int index, 71 const char* pref_name, 72 const base::ListValue& new_value) { 73 { 74 ListPrefUpdate update(GetPrefs(index), pref_name); 75 base::ListValue* list = update.Get(); 76 for (base::ListValue::const_iterator it = new_value.begin(); 77 it != new_value.end(); 78 ++it) { 79 list->Append((*it)->DeepCopy()); 80 } 81 } 82 83 if (test()->use_verifier()) { 84 ListPrefUpdate update_verifier(GetVerifierPrefs(), pref_name); 85 base::ListValue* list_verifier = update_verifier.Get(); 86 for (base::ListValue::const_iterator it = new_value.begin(); 87 it != new_value.end(); 88 ++it) { 89 list_verifier->Append((*it)->DeepCopy()); 90 } 91 } 92 } 93 94 bool BooleanPrefMatches(const char* pref_name) { 95 bool reference_value; 96 if (test()->use_verifier()) { 97 reference_value = GetVerifierPrefs()->GetBoolean(pref_name); 98 } else { 99 reference_value = GetPrefs(0)->GetBoolean(pref_name); 100 } 101 for (int i = 0; i < test()->num_clients(); ++i) { 102 if (reference_value != GetPrefs(i)->GetBoolean(pref_name)) { 103 DVLOG(1) << "Boolean preference " << pref_name << " mismatched in" 104 << " profile " << i << "."; 105 return false; 106 } 107 } 108 return true; 109 } 110 111 bool IntegerPrefMatches(const char* pref_name) { 112 int reference_value; 113 if (test()->use_verifier()) { 114 reference_value = GetVerifierPrefs()->GetInteger(pref_name); 115 } else { 116 reference_value = GetPrefs(0)->GetInteger(pref_name); 117 } 118 for (int i = 0; i < test()->num_clients(); ++i) { 119 if (reference_value != GetPrefs(i)->GetInteger(pref_name)) { 120 DVLOG(1) << "Integer preference " << pref_name << " mismatched in" 121 << " profile " << i << "."; 122 return false; 123 } 124 } 125 return true; 126 } 127 128 bool Int64PrefMatches(const char* pref_name) { 129 int64 reference_value; 130 if (test()->use_verifier()) { 131 reference_value = GetVerifierPrefs()->GetInt64(pref_name); 132 } else { 133 reference_value = GetPrefs(0)->GetInt64(pref_name); 134 } 135 for (int i = 0; i < test()->num_clients(); ++i) { 136 if (reference_value != GetPrefs(i)->GetInt64(pref_name)) { 137 DVLOG(1) << "Integer preference " << pref_name << " mismatched in" 138 << " profile " << i << "."; 139 return false; 140 } 141 } 142 return true; 143 } 144 145 bool DoublePrefMatches(const char* pref_name) { 146 double reference_value; 147 if (test()->use_verifier()) { 148 reference_value = GetVerifierPrefs()->GetDouble(pref_name); 149 } else { 150 reference_value = GetPrefs(0)->GetDouble(pref_name); 151 } 152 for (int i = 0; i < test()->num_clients(); ++i) { 153 if (reference_value != GetPrefs(i)->GetDouble(pref_name)) { 154 DVLOG(1) << "Double preference " << pref_name << " mismatched in" 155 << " profile " << i << "."; 156 return false; 157 } 158 } 159 return true; 160 } 161 162 bool StringPrefMatches(const char* pref_name) { 163 std::string reference_value; 164 if (test()->use_verifier()) { 165 reference_value = GetVerifierPrefs()->GetString(pref_name); 166 } else { 167 reference_value = GetPrefs(0)->GetString(pref_name); 168 } 169 for (int i = 0; i < test()->num_clients(); ++i) { 170 if (reference_value != GetPrefs(i)->GetString(pref_name)) { 171 DVLOG(1) << "String preference " << pref_name << " mismatched in" 172 << " profile " << i << "."; 173 return false; 174 } 175 } 176 return true; 177 } 178 179 bool FilePathPrefMatches(const char* pref_name) { 180 base::FilePath reference_value; 181 if (test()->use_verifier()) { 182 reference_value = GetVerifierPrefs()->GetFilePath(pref_name); 183 } else { 184 reference_value = GetPrefs(0)->GetFilePath(pref_name); 185 } 186 for (int i = 0; i < test()->num_clients(); ++i) { 187 if (reference_value != GetPrefs(i)->GetFilePath(pref_name)) { 188 DVLOG(1) << "base::FilePath preference " << pref_name << " mismatched in" 189 << " profile " << i << "."; 190 return false; 191 } 192 } 193 return true; 194 } 195 196 bool ListPrefMatches(const char* pref_name) { 197 const base::ListValue* reference_value; 198 if (test()->use_verifier()) { 199 reference_value = GetVerifierPrefs()->GetList(pref_name); 200 } else { 201 reference_value = GetPrefs(0)->GetList(pref_name); 202 } 203 for (int i = 0; i < test()->num_clients(); ++i) { 204 if (!reference_value->Equals(GetPrefs(i)->GetList(pref_name))) { 205 DVLOG(1) << "List preference " << pref_name << " mismatched in" 206 << " profile " << i << "."; 207 return false; 208 } 209 } 210 return true; 211 } 212 213 214 namespace { 215 216 class PrefMatchChecker : public StatusChangeChecker { 217 public: 218 explicit PrefMatchChecker(const char* path); 219 virtual ~PrefMatchChecker(); 220 221 // StatusChangeChecker implementation. 222 virtual bool IsExitConditionSatisfied() = 0; 223 virtual std::string GetDebugMessage() const OVERRIDE; 224 225 // Wait for condition to become true. 226 void Wait(); 227 228 protected: 229 const char* GetPath() const; 230 231 private: 232 void RegisterPrefListener(PrefService* pref_service); 233 234 ScopedVector<PrefChangeRegistrar> pref_change_registrars_; 235 const char* path_; 236 }; 237 238 PrefMatchChecker::PrefMatchChecker(const char* path) : path_(path) { 239 } 240 241 PrefMatchChecker::~PrefMatchChecker() { 242 } 243 244 std::string PrefMatchChecker::GetDebugMessage() const { 245 return base::StringPrintf("Waiting for pref '%s' to match", GetPath()); 246 } 247 248 void PrefMatchChecker::Wait() { 249 if (test()->use_verifier()) { 250 RegisterPrefListener(GetVerifierPrefs()); 251 } 252 253 for (int i = 0; i < test()->num_clients(); ++i) { 254 RegisterPrefListener(GetPrefs(i)); 255 } 256 257 if (IsExitConditionSatisfied()) { 258 return; 259 } 260 261 StartBlockingWait(); 262 } 263 264 const char* PrefMatchChecker::GetPath() const { 265 return path_; 266 } 267 268 void PrefMatchChecker::RegisterPrefListener(PrefService* pref_service) { 269 scoped_ptr<PrefChangeRegistrar> registrar(new PrefChangeRegistrar()); 270 registrar->Init(pref_service); 271 registrar->Add(path_, 272 base::Bind(&PrefMatchChecker::CheckExitCondition, 273 base::Unretained(this))); 274 pref_change_registrars_.push_back(registrar.release()); 275 } 276 277 // Helper class used in the implementation of AwaitListPrefMatches. 278 class ListPrefMatchChecker : public PrefMatchChecker { 279 public: 280 explicit ListPrefMatchChecker(const char* path); 281 virtual ~ListPrefMatchChecker(); 282 283 // Implementation of PrefMatchChecker. 284 virtual bool IsExitConditionSatisfied() OVERRIDE; 285 }; 286 287 ListPrefMatchChecker::ListPrefMatchChecker(const char* path) 288 : PrefMatchChecker(path) { 289 } 290 291 ListPrefMatchChecker::~ListPrefMatchChecker() { 292 } 293 294 bool ListPrefMatchChecker::IsExitConditionSatisfied() { 295 return ListPrefMatches(GetPath()); 296 } 297 298 // Helper class used in the implementation of AwaitBooleanPrefMatches. 299 class BooleanPrefMatchChecker : public PrefMatchChecker { 300 public: 301 explicit BooleanPrefMatchChecker(const char* path); 302 virtual ~BooleanPrefMatchChecker(); 303 304 // Implementation of PrefMatchChecker. 305 virtual bool IsExitConditionSatisfied() OVERRIDE; 306 }; 307 308 BooleanPrefMatchChecker::BooleanPrefMatchChecker(const char* path) 309 : PrefMatchChecker(path) { 310 } 311 312 BooleanPrefMatchChecker::~BooleanPrefMatchChecker() { 313 } 314 315 bool BooleanPrefMatchChecker::IsExitConditionSatisfied() { 316 return BooleanPrefMatches(GetPath()); 317 } 318 319 // Helper class used in the implementation of AwaitIntegerPrefMatches. 320 class IntegerPrefMatchChecker : public PrefMatchChecker { 321 public: 322 explicit IntegerPrefMatchChecker(const char* path); 323 virtual ~IntegerPrefMatchChecker(); 324 325 // Implementation of PrefMatchChecker. 326 virtual bool IsExitConditionSatisfied() OVERRIDE; 327 }; 328 329 IntegerPrefMatchChecker::IntegerPrefMatchChecker(const char* path) 330 : PrefMatchChecker(path) { 331 } 332 333 IntegerPrefMatchChecker::~IntegerPrefMatchChecker() { 334 } 335 336 bool IntegerPrefMatchChecker::IsExitConditionSatisfied() { 337 return IntegerPrefMatches(GetPath()); 338 } 339 340 // Helper class used in the implementation of AwaitStringPrefMatches. 341 class StringPrefMatchChecker : public PrefMatchChecker { 342 public: 343 explicit StringPrefMatchChecker(const char* path); 344 virtual ~StringPrefMatchChecker(); 345 346 // Implementation of PrefMatchChecker. 347 virtual bool IsExitConditionSatisfied() OVERRIDE; 348 }; 349 350 StringPrefMatchChecker::StringPrefMatchChecker(const char* path) 351 : PrefMatchChecker(path) { 352 } 353 354 StringPrefMatchChecker::~StringPrefMatchChecker() { 355 } 356 357 bool StringPrefMatchChecker::IsExitConditionSatisfied() { 358 return StringPrefMatches(GetPath()); 359 } 360 361 } // namespace 362 363 bool AwaitListPrefMatches(const char* pref_name) { 364 ListPrefMatchChecker checker(pref_name); 365 checker.Wait(); 366 return !checker.TimedOut(); 367 } 368 369 bool AwaitBooleanPrefMatches(const char* pref_name) { 370 BooleanPrefMatchChecker checker(pref_name); 371 checker.Wait(); 372 return !checker.TimedOut(); 373 } 374 375 bool AwaitIntegerPrefMatches(const char* pref_name) { 376 IntegerPrefMatchChecker checker(pref_name); 377 checker.Wait(); 378 return !checker.TimedOut(); 379 } 380 381 bool AwaitStringPrefMatches(const char* pref_name) { 382 StringPrefMatchChecker checker(pref_name); 383 checker.Wait(); 384 return !checker.TimedOut(); 385 } 386 387 } // namespace preferences_helper 388