| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2016 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 "services/preferences/public/cpp/pref_client_store.h" |  | 
| 6 |  | 
| 7 #include "base/macros.h" |  | 
| 8 #include "base/memory/ptr_util.h" |  | 
| 9 #include "base/message_loop/message_loop.h" |  | 
| 10 #include "base/run_loop.h" |  | 
| 11 #include "base/values.h" |  | 
| 12 #include "components/prefs/pref_store_observer_mock.h" |  | 
| 13 #include "services/preferences/public/interfaces/preferences.mojom.h" |  | 
| 14 #include "testing/gtest/include/gtest/gtest.h" |  | 
| 15 |  | 
| 16 namespace { |  | 
| 17 |  | 
| 18 // Test implmentation of prefs::mojom::PreferenceManager which simply tracks |  | 
| 19 // calls. Allows for testing to be done in process, without mojo IPC. |  | 
| 20 class TestPreferenceService : public prefs::mojom::PreferencesService { |  | 
| 21  public: |  | 
| 22   TestPreferenceService( |  | 
| 23       mojo::InterfaceRequest<prefs::mojom::PreferencesService> request) |  | 
| 24       : set_preferences_called_(false), binding_(this, std::move(request)) {} |  | 
| 25   ~TestPreferenceService() override {} |  | 
| 26 |  | 
| 27   const std::set<std::string>& last_preference_set() { |  | 
| 28     return last_preference_set_; |  | 
| 29   } |  | 
| 30   bool set_preferences_called() { return set_preferences_called_; } |  | 
| 31 |  | 
| 32   // prefs::mojom::TestPreferenceService: |  | 
| 33   void SetPreferences( |  | 
| 34       std::unique_ptr<base::DictionaryValue> preferences) override; |  | 
| 35   void Subscribe(const std::vector<std::string>& preferences) override; |  | 
| 36 |  | 
| 37  private: |  | 
| 38   std::set<std::string> last_preference_set_; |  | 
| 39   bool set_preferences_called_; |  | 
| 40   mojo::Binding<prefs::mojom::PreferencesService> binding_; |  | 
| 41 |  | 
| 42   DISALLOW_COPY_AND_ASSIGN(TestPreferenceService); |  | 
| 43 }; |  | 
| 44 |  | 
| 45 void TestPreferenceService::SetPreferences( |  | 
| 46     std::unique_ptr<base::DictionaryValue> preferences) { |  | 
| 47   set_preferences_called_ = true; |  | 
| 48 } |  | 
| 49 |  | 
| 50 void TestPreferenceService::Subscribe( |  | 
| 51     const std::vector<std::string>& preferences) { |  | 
| 52   last_preference_set_.clear(); |  | 
| 53   last_preference_set_.insert(preferences.begin(), preferences.end()); |  | 
| 54 } |  | 
| 55 |  | 
| 56 // Test implementation of prefs::mojom::PreferencesServiceFactory which simply |  | 
| 57 // creates the TestPreferenceService used for testing. |  | 
| 58 class TestPreferenceFactory : public prefs::mojom::PreferencesServiceFactory { |  | 
| 59  public: |  | 
| 60   TestPreferenceFactory( |  | 
| 61       mojo::InterfaceRequest<prefs::mojom::PreferencesServiceFactory> request) |  | 
| 62       : binding_(this, std::move(request)) {} |  | 
| 63   ~TestPreferenceFactory() override {} |  | 
| 64 |  | 
| 65   TestPreferenceService* service() { return service_.get(); } |  | 
| 66 |  | 
| 67   void Create(prefs::mojom::PreferencesServiceClientPtr observer, |  | 
| 68               prefs::mojom::PreferencesServiceRequest service) override; |  | 
| 69 |  | 
| 70  private: |  | 
| 71   mojo::Binding<prefs::mojom::PreferencesServiceFactory> binding_; |  | 
| 72   std::unique_ptr<TestPreferenceService> service_; |  | 
| 73 |  | 
| 74   DISALLOW_COPY_AND_ASSIGN(TestPreferenceFactory); |  | 
| 75 }; |  | 
| 76 |  | 
| 77 void TestPreferenceFactory::Create( |  | 
| 78     prefs::mojom::PreferencesServiceClientPtr observer, |  | 
| 79     prefs::mojom::PreferencesServiceRequest service) { |  | 
| 80   service_.reset(new TestPreferenceService(std::move(service))); |  | 
| 81 } |  | 
| 82 |  | 
| 83 }  // namespace |  | 
| 84 |  | 
| 85 namespace preferences { |  | 
| 86 |  | 
| 87 class PrefClientStoreTest : public testing::Test { |  | 
| 88  public: |  | 
| 89   PrefClientStoreTest() {} |  | 
| 90   ~PrefClientStoreTest() override {} |  | 
| 91 |  | 
| 92   TestPreferenceService* service() { return factory_->service(); } |  | 
| 93   PrefStoreObserverMock* observer() { return &observer_; } |  | 
| 94   PrefClientStore* store() { return store_.get(); } |  | 
| 95 |  | 
| 96   bool Initialized() { return store_->initialized_; } |  | 
| 97   void OnPreferencesChanged(const base::DictionaryValue& preferences) { |  | 
| 98     store_->OnPreferencesChanged(preferences.CreateDeepCopy()); |  | 
| 99   } |  | 
| 100 |  | 
| 101   // testing::Test: |  | 
| 102   void SetUp() override; |  | 
| 103   void TearDown() override; |  | 
| 104 |  | 
| 105  private: |  | 
| 106   scoped_refptr<PrefClientStore> store_; |  | 
| 107   prefs::mojom::PreferencesServiceFactoryPtr factory_proxy_; |  | 
| 108   std::unique_ptr<TestPreferenceFactory> factory_; |  | 
| 109   PrefStoreObserverMock observer_; |  | 
| 110   // Required by mojo binding code within PrefClientStore. |  | 
| 111   base::MessageLoop message_loop_; |  | 
| 112 |  | 
| 113   DISALLOW_COPY_AND_ASSIGN(PrefClientStoreTest); |  | 
| 114 }; |  | 
| 115 |  | 
| 116 void PrefClientStoreTest::SetUp() { |  | 
| 117   factory_.reset(new TestPreferenceFactory(mojo::MakeRequest(&factory_proxy_))); |  | 
| 118   store_ = new PrefClientStore(std::move(factory_proxy_)); |  | 
| 119   base::RunLoop().RunUntilIdle(); |  | 
| 120   store_->AddObserver(&observer_); |  | 
| 121 } |  | 
| 122 |  | 
| 123 void PrefClientStoreTest::TearDown() { |  | 
| 124   store_->RemoveObserver(&observer_); |  | 
| 125 } |  | 
| 126 |  | 
| 127 // Tests that observers are notified upon the completion of initialization, and |  | 
| 128 // that values become available. |  | 
| 129 TEST_F(PrefClientStoreTest, Initialization) { |  | 
| 130   std::set<std::string> keys; |  | 
| 131   const std::string key("hey"); |  | 
| 132   keys.insert(key); |  | 
| 133   store()->Subscribe(keys); |  | 
| 134 |  | 
| 135   EXPECT_FALSE(Initialized()); |  | 
| 136   EXPECT_FALSE(observer()->initialized); |  | 
| 137 |  | 
| 138   const int kValue = 42; |  | 
| 139   base::Value pref(kValue); |  | 
| 140   base::DictionaryValue prefs; |  | 
| 141   prefs.Set(key, pref.CreateDeepCopy()); |  | 
| 142 |  | 
| 143   // PreferenceManager notifies of PreferencesChanged, completing |  | 
| 144   // initialization. |  | 
| 145   OnPreferencesChanged(prefs); |  | 
| 146   EXPECT_TRUE(Initialized()); |  | 
| 147   EXPECT_TRUE(observer()->initialized); |  | 
| 148   EXPECT_TRUE(observer()->initialization_success); |  | 
| 149   observer()->VerifyAndResetChangedKey(key); |  | 
| 150 |  | 
| 151   const base::Value* value = nullptr; |  | 
| 152   int actual_value; |  | 
| 153   EXPECT_TRUE(store()->GetValue(key, &value)); |  | 
| 154   EXPECT_NE(nullptr, value); |  | 
| 155   EXPECT_TRUE(value->GetAsInteger(&actual_value)); |  | 
| 156   EXPECT_EQ(kValue, actual_value); |  | 
| 157   EXPECT_FALSE(service()->set_preferences_called()); |  | 
| 158 } |  | 
| 159 |  | 
| 160 // Tests that values set silently are also set on the preference service, but |  | 
| 161 // that no observers are notified. |  | 
| 162 TEST_F(PrefClientStoreTest, SetValueSilently) { |  | 
| 163   std::set<std::string> keys; |  | 
| 164   const std::string key("hey"); |  | 
| 165   keys.insert(key); |  | 
| 166   store()->Subscribe(keys); |  | 
| 167 |  | 
| 168   const int kValue = 42; |  | 
| 169   base::Value pref(kValue); |  | 
| 170   store()->SetValueSilently(key, pref.CreateDeepCopy(), 0); |  | 
| 171   base::RunLoop().RunUntilIdle(); |  | 
| 172   EXPECT_TRUE(service()->set_preferences_called()); |  | 
| 173   EXPECT_TRUE(observer()->changed_keys.empty()); |  | 
| 174 } |  | 
| 175 |  | 
| 176 // Test that reporting values changed notifies observers, and the preference |  | 
| 177 // service. |  | 
| 178 TEST_F(PrefClientStoreTest, ReportValueChanged) { |  | 
| 179   std::set<std::string> keys; |  | 
| 180   const std::string key("hey"); |  | 
| 181   keys.insert(key); |  | 
| 182   store()->Subscribe(keys); |  | 
| 183 |  | 
| 184   const int kValue = 42; |  | 
| 185   base::Value pref(kValue); |  | 
| 186   base::DictionaryValue prefs; |  | 
| 187   prefs.Set(key, pref.CreateDeepCopy()); |  | 
| 188   OnPreferencesChanged(prefs); |  | 
| 189   observer()->changed_keys.clear(); |  | 
| 190 |  | 
| 191   store()->ReportValueChanged(key, 0); |  | 
| 192   base::RunLoop().RunUntilIdle(); |  | 
| 193   EXPECT_TRUE(service()->set_preferences_called()); |  | 
| 194   observer()->VerifyAndResetChangedKey(key); |  | 
| 195 } |  | 
| 196 |  | 
| 197 // Test that when initialized with multiple keys, that observers receive a |  | 
| 198 // notification for each key. |  | 
| 199 TEST_F(PrefClientStoreTest, MultipleKeyInitialization) { |  | 
| 200   std::set<std::string> keys; |  | 
| 201   const std::string key1("hey"); |  | 
| 202   const std::string key2("listen"); |  | 
| 203   keys.insert(key1); |  | 
| 204   keys.insert(key2); |  | 
| 205   store()->Subscribe(keys); |  | 
| 206 |  | 
| 207   EXPECT_FALSE(Initialized()); |  | 
| 208   EXPECT_FALSE(observer()->initialized); |  | 
| 209 |  | 
| 210   const int kValue = 42; |  | 
| 211   base::Value pref1(kValue); |  | 
| 212   const std::string kStringValue("look"); |  | 
| 213   base::Value pref2(kStringValue); |  | 
| 214 |  | 
| 215   base::DictionaryValue prefs; |  | 
| 216   prefs.Set(key1, pref1.CreateDeepCopy()); |  | 
| 217   prefs.Set(key2, pref2.CreateDeepCopy()); |  | 
| 218 |  | 
| 219   // The observer should be notified of all keys set. |  | 
| 220   OnPreferencesChanged(prefs); |  | 
| 221   EXPECT_TRUE(Initialized()); |  | 
| 222   EXPECT_TRUE(observer()->initialized); |  | 
| 223   EXPECT_EQ(2u, observer()->changed_keys.size()); |  | 
| 224   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 225             std::find(observer()->changed_keys.begin(), |  | 
| 226                       observer()->changed_keys.end(), key1)); |  | 
| 227   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 228             std::find(observer()->changed_keys.begin(), |  | 
| 229                       observer()->changed_keys.end(), key2)); |  | 
| 230 } |  | 
| 231 |  | 
| 232 // Tests that if OnPreferencesChanged is received with invalid keys, that they |  | 
| 233 // are ignored. |  | 
| 234 TEST_F(PrefClientStoreTest, InvalidInitialization) { |  | 
| 235   std::set<std::string> keys; |  | 
| 236   const std::string key("hey"); |  | 
| 237   keys.insert(key); |  | 
| 238   store()->Subscribe(keys); |  | 
| 239 |  | 
| 240   const std::string kInvalidKey("look"); |  | 
| 241   const int kValue = 42; |  | 
| 242   base::Value pref(kValue); |  | 
| 243   base::DictionaryValue prefs; |  | 
| 244   prefs.Set(kInvalidKey, pref.CreateDeepCopy()); |  | 
| 245 |  | 
| 246   OnPreferencesChanged(prefs); |  | 
| 247   EXPECT_TRUE(observer()->changed_keys.empty()); |  | 
| 248 } |  | 
| 249 |  | 
| 250 // Tests that when tracking preferences which nest other DictionaryValues, that |  | 
| 251 // modifications to the nested values properly notify the observer. |  | 
| 252 TEST_F(PrefClientStoreTest, WriteToNestedPrefs) { |  | 
| 253   std::set<std::string> keys; |  | 
| 254   const std::string key1("hey"); |  | 
| 255   const std::string key2("listen"); |  | 
| 256   keys.insert(key1); |  | 
| 257   keys.insert(key2); |  | 
| 258   store()->Subscribe(keys); |  | 
| 259 |  | 
| 260   EXPECT_FALSE(Initialized()); |  | 
| 261   EXPECT_FALSE(observer()->initialized); |  | 
| 262 |  | 
| 263   const std::string sub_key1("look"); |  | 
| 264   const int kValue1 = 42; |  | 
| 265   base::Value pref1(kValue1); |  | 
| 266   base::DictionaryValue sub_dictionary1; |  | 
| 267   sub_dictionary1.Set(sub_key1, pref1.CreateDeepCopy()); |  | 
| 268 |  | 
| 269   const std::string sub_key2("Watch out!\n"); |  | 
| 270   const int kValue2 = 1337; |  | 
| 271   base::Value pref2(kValue2); |  | 
| 272   base::DictionaryValue sub_dictionary2; |  | 
| 273   sub_dictionary2.Set(sub_key2, pref2.CreateDeepCopy()); |  | 
| 274 |  | 
| 275   base::DictionaryValue prefs; |  | 
| 276   prefs.Set(key1, sub_dictionary1.CreateDeepCopy()); |  | 
| 277   prefs.Set(key2, sub_dictionary2.CreateDeepCopy()); |  | 
| 278 |  | 
| 279   // Initialize with the nested dictionaries |  | 
| 280   OnPreferencesChanged(prefs); |  | 
| 281   EXPECT_TRUE(Initialized()); |  | 
| 282   EXPECT_TRUE(observer()->initialized); |  | 
| 283   EXPECT_EQ(2u, observer()->changed_keys.size()); |  | 
| 284   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 285             std::find(observer()->changed_keys.begin(), |  | 
| 286                       observer()->changed_keys.end(), key1)); |  | 
| 287   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 288             std::find(observer()->changed_keys.begin(), |  | 
| 289                       observer()->changed_keys.end(), key2)); |  | 
| 290 |  | 
| 291   // Change an item within the nested dictionary |  | 
| 292   base::Value* result = nullptr; |  | 
| 293   store()->GetMutableValue(key1, &result); |  | 
| 294   EXPECT_EQ(base::Value::Type::DICTIONARY, result->GetType()); |  | 
| 295   EXPECT_TRUE(result->Equals(&sub_dictionary1)); |  | 
| 296 |  | 
| 297   base::DictionaryValue* dictionary_result = nullptr; |  | 
| 298   result->GetAsDictionary(&dictionary_result); |  | 
| 299   EXPECT_NE(nullptr, dictionary_result); |  | 
| 300 |  | 
| 301   const std::string sub_key3("????"); |  | 
| 302   const int kValue3 = 9001; |  | 
| 303   base::Value pref3(kValue3); |  | 
| 304   dictionary_result->Set(sub_key3, pref3.CreateDeepCopy()); |  | 
| 305 |  | 
| 306   observer()->changed_keys.clear(); |  | 
| 307   store()->ReportValueChanged(key1, 0); |  | 
| 308   EXPECT_EQ(1u, observer()->changed_keys.size()); |  | 
| 309 } |  | 
| 310 |  | 
| 311 // Tests that when tracking preferences that nest other DictionaryValues, that |  | 
| 312 // changes to the tracked keys properly notify the service and observer. |  | 
| 313 TEST_F(PrefClientStoreTest, UpdateOuterNestedPrefs) { |  | 
| 314   std::set<std::string> keys; |  | 
| 315   const std::string key1("hey"); |  | 
| 316   const std::string key2("listen"); |  | 
| 317   keys.insert(key1); |  | 
| 318   keys.insert(key2); |  | 
| 319   store()->Subscribe(keys); |  | 
| 320 |  | 
| 321   EXPECT_FALSE(Initialized()); |  | 
| 322   EXPECT_FALSE(observer()->initialized); |  | 
| 323 |  | 
| 324   const std::string sub_key1("look"); |  | 
| 325   const int kValue1 = 42; |  | 
| 326   base::Value pref1(kValue1); |  | 
| 327   base::DictionaryValue sub_dictionary1; |  | 
| 328   sub_dictionary1.Set(sub_key1, pref1.CreateDeepCopy()); |  | 
| 329 |  | 
| 330   const std::string sub_key2("Watch out!\n"); |  | 
| 331   const int kValue2 = 1337; |  | 
| 332   base::Value pref2(kValue2); |  | 
| 333   base::DictionaryValue sub_dictionary2; |  | 
| 334   sub_dictionary2.Set(sub_key2, pref2.CreateDeepCopy()); |  | 
| 335 |  | 
| 336   base::DictionaryValue prefs; |  | 
| 337   prefs.Set(key1, sub_dictionary1.CreateDeepCopy()); |  | 
| 338   prefs.Set(key2, sub_dictionary2.CreateDeepCopy()); |  | 
| 339 |  | 
| 340   // Initialize with the nested dictionaries |  | 
| 341   OnPreferencesChanged(prefs); |  | 
| 342   EXPECT_TRUE(Initialized()); |  | 
| 343   EXPECT_TRUE(observer()->initialized); |  | 
| 344   EXPECT_EQ(2u, observer()->changed_keys.size()); |  | 
| 345   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 346             std::find(observer()->changed_keys.begin(), |  | 
| 347                       observer()->changed_keys.end(), key1)); |  | 
| 348   EXPECT_NE(observer()->changed_keys.end(), |  | 
| 349             std::find(observer()->changed_keys.begin(), |  | 
| 350                       observer()->changed_keys.end(), key2)); |  | 
| 351 |  | 
| 352   observer()->changed_keys.clear(); |  | 
| 353   const int kValue3 = 9001; |  | 
| 354   base::Value pref3(kValue3); |  | 
| 355   store()->SetValue(key1, pref3.CreateDeepCopy(), 0); |  | 
| 356   base::RunLoop().RunUntilIdle(); |  | 
| 357   EXPECT_EQ(1u, observer()->changed_keys.size()); |  | 
| 358   EXPECT_TRUE(service()->set_preferences_called()); |  | 
| 359 } |  | 
| 360 |  | 
| 361 // Tests that a PrefClientStore can subscribe multiple times to different |  | 
| 362 // keys. |  | 
| 363 TEST_F(PrefClientStoreTest, MultipleSubscriptions) { |  | 
| 364   std::set<std::string> keys1; |  | 
| 365   const std::string key1("hey"); |  | 
| 366   keys1.insert(key1); |  | 
| 367   store()->Subscribe(keys1); |  | 
| 368   base::RunLoop().RunUntilIdle(); |  | 
| 369   EXPECT_NE(service()->last_preference_set().end(), |  | 
| 370             service()->last_preference_set().find(key1)); |  | 
| 371 |  | 
| 372   std::set<std::string> keys2; |  | 
| 373   const std::string key2("listen"); |  | 
| 374   keys2.insert(key2); |  | 
| 375   store()->Subscribe(keys2); |  | 
| 376   base::RunLoop().RunUntilIdle(); |  | 
| 377   EXPECT_NE(service()->last_preference_set().end(), |  | 
| 378             service()->last_preference_set().find(key2)); |  | 
| 379 } |  | 
| 380 |  | 
| 381 // Tests that multiple PrefStore::Observers can be added to a PrefClientStore |  | 
| 382 // and that they are each notified of changes. |  | 
| 383 TEST_F(PrefClientStoreTest, MultipleObservers) { |  | 
| 384   PrefStoreObserverMock observer2; |  | 
| 385   store()->AddObserver(&observer2); |  | 
| 386 |  | 
| 387   std::set<std::string> keys; |  | 
| 388   const std::string key("hey"); |  | 
| 389   keys.insert(key); |  | 
| 390   store()->Subscribe(keys); |  | 
| 391 |  | 
| 392   const int kValue = 42; |  | 
| 393   base::Value pref(kValue); |  | 
| 394   base::DictionaryValue prefs; |  | 
| 395   prefs.Set(key, pref.CreateDeepCopy()); |  | 
| 396 |  | 
| 397   // PreferenceManager notifies of PreferencesChanged, completing |  | 
| 398   // initialization. |  | 
| 399   OnPreferencesChanged(prefs); |  | 
| 400   EXPECT_TRUE(observer()->initialized); |  | 
| 401   EXPECT_TRUE(observer2.initialized); |  | 
| 402   EXPECT_TRUE(observer()->initialization_success); |  | 
| 403   EXPECT_TRUE(observer2.initialization_success); |  | 
| 404   observer()->VerifyAndResetChangedKey(key); |  | 
| 405   observer2.VerifyAndResetChangedKey(key); |  | 
| 406 |  | 
| 407   store()->RemoveObserver(&observer2); |  | 
| 408 } |  | 
| 409 |  | 
| 410 }  // namespace preferences |  | 
| OLD | NEW | 
|---|