OLD | NEW |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "services/preferences/public/cpp/pref_service_factory.h" | 5 #include "services/preferences/public/cpp/pref_service_factory.h" |
6 | 6 |
7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/strings/utf_string_conversions.h" |
10 #include "base/test/sequenced_worker_pool_owner.h" | 11 #include "base/test/sequenced_worker_pool_owner.h" |
11 #include "components/prefs/pref_change_registrar.h" | 12 #include "components/prefs/pref_change_registrar.h" |
12 #include "components/prefs/pref_registry_simple.h" | 13 #include "components/prefs/pref_registry_simple.h" |
13 #include "components/prefs/pref_service.h" | 14 #include "components/prefs/pref_service.h" |
14 #include "components/prefs/value_map_pref_store.h" | 15 #include "components/prefs/value_map_pref_store.h" |
15 #include "components/prefs/writeable_pref_store.h" | 16 #include "components/prefs/writeable_pref_store.h" |
16 #include "mojo/public/cpp/bindings/binding_set.h" | 17 #include "mojo/public/cpp/bindings/binding_set.h" |
17 #include "services/preferences/public/cpp/pref_service_main.h" | 18 #include "services/preferences/public/cpp/pref_service_main.h" |
18 #include "services/preferences/public/cpp/pref_store_impl.h" | 19 #include "services/preferences/public/cpp/pref_store_impl.h" |
| 20 #include "services/preferences/public/cpp/scoped_pref_update.h" |
19 #include "services/preferences/public/interfaces/preferences.mojom.h" | 21 #include "services/preferences/public/interfaces/preferences.mojom.h" |
20 #include "services/service_manager/public/cpp/binder_registry.h" | 22 #include "services/service_manager/public/cpp/binder_registry.h" |
21 #include "services/service_manager/public/cpp/interface_factory.h" | 23 #include "services/service_manager/public/cpp/interface_factory.h" |
22 #include "services/service_manager/public/cpp/service_context.h" | 24 #include "services/service_manager/public/cpp/service_context.h" |
23 #include "services/service_manager/public/cpp/service_test.h" | 25 #include "services/service_manager/public/cpp/service_test.h" |
24 #include "services/service_manager/public/interfaces/service_factory.mojom.h" | 26 #include "services/service_manager/public/interfaces/service_factory.mojom.h" |
25 | 27 |
26 namespace prefs { | 28 namespace prefs { |
27 namespace { | 29 namespace { |
28 | 30 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 service_manager::BinderRegistry registry_; | 71 service_manager::BinderRegistry registry_; |
70 mojo::BindingSet<service_manager::mojom::ServiceFactory> | 72 mojo::BindingSet<service_manager::mojom::ServiceFactory> |
71 service_factory_bindings_; | 73 service_factory_bindings_; |
72 std::unique_ptr<service_manager::ServiceContext> pref_service_context_; | 74 std::unique_ptr<service_manager::ServiceContext> pref_service_context_; |
73 }; | 75 }; |
74 | 76 |
75 constexpr int kInitialValue = 1; | 77 constexpr int kInitialValue = 1; |
76 constexpr int kUpdatedValue = 2; | 78 constexpr int kUpdatedValue = 2; |
77 constexpr char kKey[] = "some_key"; | 79 constexpr char kKey[] = "some_key"; |
78 constexpr char kOtherKey[] = "some_other_key"; | 80 constexpr char kOtherKey[] = "some_other_key"; |
| 81 constexpr char kDictionaryKey[] = "a.dictionary.pref"; |
79 | 82 |
80 class PrefServiceFactoryTest : public base::MessageLoop::DestructionObserver, | 83 class PrefServiceFactoryTest : public base::MessageLoop::DestructionObserver, |
81 public service_manager::test::ServiceTest { | 84 public service_manager::test::ServiceTest { |
82 public: | 85 public: |
83 PrefServiceFactoryTest() : ServiceTest("prefs_unittests", false) {} | 86 PrefServiceFactoryTest() : ServiceTest("prefs_unittests", false) {} |
84 | 87 |
85 protected: | 88 protected: |
86 void SetUp() override { | 89 void SetUp() override { |
87 ServiceTest::SetUp(); | 90 ServiceTest::SetUp(); |
88 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); | 91 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // base::MessageLoop::DestructionObserver | 127 // base::MessageLoop::DestructionObserver |
125 void WillDestroyCurrentMessageLoop() override { worker_pool_owner_.reset(); } | 128 void WillDestroyCurrentMessageLoop() override { worker_pool_owner_.reset(); } |
126 | 129 |
127 // Create a fully initialized PrefService synchronously. | 130 // Create a fully initialized PrefService synchronously. |
128 std::unique_ptr<PrefService> Create() { | 131 std::unique_ptr<PrefService> Create() { |
129 std::unique_ptr<PrefService> pref_service; | 132 std::unique_ptr<PrefService> pref_service; |
130 base::RunLoop run_loop; | 133 base::RunLoop run_loop; |
131 auto pref_registry = make_scoped_refptr(new PrefRegistrySimple()); | 134 auto pref_registry = make_scoped_refptr(new PrefRegistrySimple()); |
132 pref_registry->RegisterIntegerPref(kKey, kInitialValue); | 135 pref_registry->RegisterIntegerPref(kKey, kInitialValue); |
133 pref_registry->RegisterIntegerPref(kOtherKey, kInitialValue); | 136 pref_registry->RegisterIntegerPref(kOtherKey, kInitialValue); |
| 137 pref_registry->RegisterDictionaryPref(kDictionaryKey); |
134 ConnectToPrefService(connector(), pref_registry, | 138 ConnectToPrefService(connector(), pref_registry, |
135 std::vector<PrefValueStore::PrefStoreType>(), | 139 std::vector<PrefValueStore::PrefStoreType>(), |
136 base::Bind(&PrefServiceFactoryTest::OnCreate, | 140 base::Bind(&PrefServiceFactoryTest::OnCreate, |
137 run_loop.QuitClosure(), &pref_service)); | 141 run_loop.QuitClosure(), &pref_service)); |
138 run_loop.Run(); | 142 run_loop.Run(); |
139 return pref_service; | 143 return pref_service; |
140 } | 144 } |
141 | 145 |
142 // Wait until first update of the pref |key| in |pref_service| synchronously. | 146 // Wait until first update of the pref |key| in |pref_service| synchronously. |
143 void WaitForPrefChange(PrefService* pref_service, const std::string& key) { | 147 void WaitForPrefChange(PrefService* pref_service, const std::string& key) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 | 262 |
259 above_user_prefs_pref_store()->SetValue(kKey, | 263 above_user_prefs_pref_store()->SetValue(kKey, |
260 base::MakeUnique<base::Value>(2), 0); | 264 base::MakeUnique<base::Value>(2), 0); |
261 WaitForPrefChange(pref_service.get(), kKey); | 265 WaitForPrefChange(pref_service.get(), kKey); |
262 EXPECT_EQ(2, pref_service->GetInteger(kKey)); | 266 EXPECT_EQ(2, pref_service->GetInteger(kKey)); |
263 | 267 |
264 pref_service->SetInteger(kKey, 3); | 268 pref_service->SetInteger(kKey, 3); |
265 EXPECT_EQ(2, pref_service->GetInteger(kKey)); | 269 EXPECT_EQ(2, pref_service->GetInteger(kKey)); |
266 } | 270 } |
267 | 271 |
| 272 void Fail(PrefService* pref_service) { |
| 273 FAIL() << "Unexpected change notification: " |
| 274 << *pref_service->GetDictionary(kDictionaryKey); |
| 275 } |
| 276 |
| 277 TEST_F(PrefServiceFactoryTest, MultipleClients_SubPrefUpdates_Basic) { |
| 278 auto pref_service = Create(); |
| 279 auto pref_service2 = Create(); |
| 280 |
| 281 void (*updates[])(ScopedDictionaryPrefUpdate*) = { |
| 282 [](ScopedDictionaryPrefUpdate* update) { |
| 283 (*update)->SetInteger("path.to.integer", 1); |
| 284 int out = 0; |
| 285 ASSERT_TRUE((*update)->GetInteger("path.to.integer", &out)); |
| 286 EXPECT_EQ(1, out); |
| 287 }, |
| 288 [](ScopedDictionaryPrefUpdate* update) { |
| 289 (*update)->SetIntegerWithoutPathExpansion("key.for.integer", 2); |
| 290 int out = 0; |
| 291 ASSERT_TRUE( |
| 292 (*update)->GetIntegerWithoutPathExpansion("key.for.integer", &out)); |
| 293 EXPECT_EQ(2, out); |
| 294 }, |
| 295 [](ScopedDictionaryPrefUpdate* update) { |
| 296 (*update)->SetDouble("path.to.double", 3); |
| 297 double out = 0; |
| 298 ASSERT_TRUE((*update)->GetDouble("path.to.double", &out)); |
| 299 EXPECT_EQ(3, out); |
| 300 }, |
| 301 [](ScopedDictionaryPrefUpdate* update) { |
| 302 (*update)->SetDoubleWithoutPathExpansion("key.for.double", 4); |
| 303 double out = 0; |
| 304 ASSERT_TRUE( |
| 305 (*update)->GetDoubleWithoutPathExpansion("key.for.double", &out)); |
| 306 EXPECT_EQ(4, out); |
| 307 }, |
| 308 [](ScopedDictionaryPrefUpdate* update) { |
| 309 (*update)->SetBoolean("path.to.boolean", true); |
| 310 bool out = 0; |
| 311 ASSERT_TRUE((*update)->GetBoolean("path.to.boolean", &out)); |
| 312 EXPECT_TRUE(out); |
| 313 }, |
| 314 [](ScopedDictionaryPrefUpdate* update) { |
| 315 (*update)->SetBooleanWithoutPathExpansion("key.for.boolean", false); |
| 316 bool out = 0; |
| 317 ASSERT_TRUE( |
| 318 (*update)->GetBooleanWithoutPathExpansion("key.for.boolean", &out)); |
| 319 EXPECT_FALSE(out); |
| 320 }, |
| 321 [](ScopedDictionaryPrefUpdate* update) { |
| 322 (*update)->SetString("path.to.string", "hello"); |
| 323 std::string out; |
| 324 ASSERT_TRUE((*update)->GetString("path.to.string", &out)); |
| 325 EXPECT_EQ("hello", out); |
| 326 }, |
| 327 [](ScopedDictionaryPrefUpdate* update) { |
| 328 (*update)->SetStringWithoutPathExpansion("key.for.string", "prefs!"); |
| 329 std::string out; |
| 330 ASSERT_TRUE( |
| 331 (*update)->GetStringWithoutPathExpansion("key.for.string", &out)); |
| 332 EXPECT_EQ("prefs!", out); |
| 333 }, |
| 334 [](ScopedDictionaryPrefUpdate* update) { |
| 335 (*update)->SetString("path.to.string", base::ASCIIToUTF16("hello")); |
| 336 base::string16 out; |
| 337 ASSERT_TRUE((*update)->GetString("path.to.string", &out)); |
| 338 EXPECT_EQ(base::ASCIIToUTF16("hello"), out); |
| 339 }, |
| 340 [](ScopedDictionaryPrefUpdate* update) { |
| 341 (*update)->SetStringWithoutPathExpansion("key.for.string16", |
| 342 base::ASCIIToUTF16("prefs!")); |
| 343 base::string16 out; |
| 344 ASSERT_TRUE( |
| 345 (*update)->GetStringWithoutPathExpansion("key.for.string16", &out)); |
| 346 EXPECT_EQ(base::ASCIIToUTF16("prefs!"), out); |
| 347 }, |
| 348 [](ScopedDictionaryPrefUpdate* update) { |
| 349 base::Value buffer(std::vector<char>{1, 2, 3, 4, 5}); |
| 350 (*update)->Set("path.to.binary", base::MakeUnique<base::Value>(buffer)); |
| 351 const base::Value* out; |
| 352 ASSERT_TRUE((*update)->GetBinary("path.to.binary", &out)); |
| 353 EXPECT_EQ(buffer, *out); |
| 354 }, |
| 355 [](ScopedDictionaryPrefUpdate* update) { |
| 356 base::ListValue list; |
| 357 list.AppendInteger(1); |
| 358 list.AppendDouble(2); |
| 359 list.AppendBoolean(true); |
| 360 list.AppendString("four"); |
| 361 (*update)->Set("path.to.list", list.CreateDeepCopy()); |
| 362 const base::ListValue* out = nullptr; |
| 363 ASSERT_TRUE((*update)->GetList("path.to.list", &out)); |
| 364 EXPECT_EQ(list, *out); |
| 365 }, |
| 366 [](ScopedDictionaryPrefUpdate* update) { |
| 367 base::ListValue list; |
| 368 list.AppendInteger(1); |
| 369 list.AppendDouble(2); |
| 370 list.AppendBoolean(true); |
| 371 list.AppendString("four"); |
| 372 (*update)->SetWithoutPathExpansion("key.for.list", |
| 373 list.CreateDeepCopy()); |
| 374 const base::ListValue* out = nullptr; |
| 375 ASSERT_TRUE( |
| 376 (*update)->GetListWithoutPathExpansion("key.for.list", &out)); |
| 377 EXPECT_EQ(list, *out); |
| 378 }, |
| 379 [](ScopedDictionaryPrefUpdate* update) { |
| 380 base::DictionaryValue dict; |
| 381 dict.SetInteger("int", 1); |
| 382 dict.SetDouble("double", 2); |
| 383 dict.SetBoolean("bool", true); |
| 384 dict.SetString("string", "four"); |
| 385 (*update)->Set("path.to.dict", dict.CreateDeepCopy()); |
| 386 const base::DictionaryValue* out = nullptr; |
| 387 ASSERT_TRUE((*update)->GetDictionary("path.to.dict", &out)); |
| 388 EXPECT_EQ(dict, *out); |
| 389 }, |
| 390 [](ScopedDictionaryPrefUpdate* update) { |
| 391 base::DictionaryValue dict; |
| 392 dict.SetInteger("int", 1); |
| 393 dict.SetDouble("double", 2); |
| 394 dict.SetBoolean("bool", true); |
| 395 dict.SetString("string", "four"); |
| 396 (*update)->SetWithoutPathExpansion("key.for.dict", |
| 397 dict.CreateDeepCopy()); |
| 398 const base::DictionaryValue* out = nullptr; |
| 399 ASSERT_TRUE( |
| 400 (*update)->GetDictionaryWithoutPathExpansion("key.for.dict", &out)); |
| 401 EXPECT_EQ(dict, *out); |
| 402 }, |
| 403 }; |
| 404 int current_value = kInitialValue + 1; |
| 405 for (auto& mutation : updates) { |
| 406 base::DictionaryValue expected_value; |
| 407 { |
| 408 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 409 EXPECT_EQ(update->AsConstDictionary()->empty(), update->empty()); |
| 410 EXPECT_EQ(update->AsConstDictionary()->size(), update->size()); |
| 411 mutation(&update); |
| 412 EXPECT_EQ(update->AsConstDictionary()->empty(), update->empty()); |
| 413 EXPECT_EQ(update->AsConstDictionary()->size(), update->size()); |
| 414 expected_value = *update->AsConstDictionary(); |
| 415 } |
| 416 |
| 417 EXPECT_EQ(expected_value, *pref_service->GetDictionary(kDictionaryKey)); |
| 418 WaitForPrefChange(pref_service2.get(), kDictionaryKey); |
| 419 EXPECT_EQ(expected_value, *pref_service2->GetDictionary(kDictionaryKey)); |
| 420 |
| 421 { |
| 422 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 423 mutation(&update); |
| 424 EXPECT_EQ(expected_value, *update->AsConstDictionary()); |
| 425 } |
| 426 { |
| 427 PrefChangeRegistrar registrar; |
| 428 registrar.Init(pref_service2.get()); |
| 429 registrar.Add(kDictionaryKey, base::Bind(&Fail, pref_service2.get())); |
| 430 pref_service->SetInteger(kKey, ++current_value); |
| 431 WaitForPrefChange(pref_service2.get(), kKey); |
| 432 } |
| 433 if (!pref_service->GetDictionary(kDictionaryKey)->empty()) { |
| 434 { |
| 435 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 436 update->Clear(); |
| 437 } |
| 438 WaitForPrefChange(pref_service2.get(), kDictionaryKey); |
| 439 } |
| 440 } |
| 441 } |
| 442 |
| 443 TEST_F(PrefServiceFactoryTest, MultipleClients_SubPrefUpdates_Erase) { |
| 444 auto pref_service = Create(); |
| 445 auto pref_service2 = Create(); |
| 446 { |
| 447 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 448 update->SetInteger("path.to.integer", 1); |
| 449 } |
| 450 WaitForPrefChange(pref_service2.get(), kDictionaryKey); |
| 451 |
| 452 { |
| 453 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 454 ASSERT_TRUE(update->RemovePath("path.to.integer", nullptr)); |
| 455 } |
| 456 WaitForPrefChange(pref_service2.get(), kDictionaryKey); |
| 457 EXPECT_TRUE(pref_service2->GetDictionary(kDictionaryKey)->empty()); |
| 458 } |
| 459 |
| 460 TEST_F(PrefServiceFactoryTest, MultipleClients_SubPrefUpdates_ClearDictionary) { |
| 461 auto pref_service = Create(); |
| 462 auto pref_service2 = Create(); |
| 463 |
| 464 { ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); } |
| 465 WaitForPrefChange(pref_service2.get(), kDictionaryKey); |
| 466 |
| 467 { |
| 468 ScopedDictionaryPrefUpdate update(pref_service.get(), kDictionaryKey); |
| 469 update->Clear(); |
| 470 } |
| 471 PrefChangeRegistrar registrar; |
| 472 registrar.Init(pref_service2.get()); |
| 473 registrar.Add(kDictionaryKey, base::Bind(&Fail, pref_service2.get())); |
| 474 pref_service->SetInteger(kKey, kUpdatedValue); |
| 475 WaitForPrefChange(pref_service2.get(), kKey); |
| 476 } |
| 477 |
268 } // namespace | 478 } // namespace |
269 } // namespace prefs | 479 } // namespace prefs |
OLD | NEW |