1 // Copyright 2014 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.
5 #include "components/sync_preferences/pref_service_syncable.h"
11 #include "base/json/json_reader.h"
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/json/json_writer.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/test/metrics/histogram_tester.h"
18 #include "components/pref_registry/pref_registry_syncable.h"
19 #include "components/prefs/pref_notifier_impl.h"
20 #include "components/prefs/scoped_user_pref_update.h"
21 #include "components/prefs/testing_pref_store.h"
22 #include "components/sync/model/sync_change.h"
23 #include "components/sync/model/sync_change_processor.h"
24 #include "components/sync/model/sync_data.h"
25 #include "components/sync/model/sync_error_factory_mock.h"
26 #include "components/sync/model/syncable_service.h"
27 #include "components/sync/protocol/preference_specifics.pb.h"
28 #include "components/sync/protocol/sync.pb.h"
29 #include "components/sync_preferences/pref_model_associator.h"
30 #include "components/sync_preferences/pref_model_associator_client.h"
31 #include "components/sync_preferences/synced_pref_observer.h"
32 #include "components/sync_preferences/testing_pref_service_syncable.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 using syncer::SyncChange;
36 using syncer::SyncData;
38 using testing::IsEmpty;
40 using testing::NotNull;
41 using testing::SizeIs;
43 namespace sync_preferences {
47 const char kExampleUrl0[] = "http://example.com/0";
48 const char kExampleUrl1[] = "http://example.com/1";
49 const char kExampleUrl2[] = "http://example.com/2";
50 const char kStringPrefName[] = "string_pref_name";
51 const char kListPrefName[] = "list_pref_name";
52 const char kDictPrefName[] = "dict_pref_name";
53 const char kUnsyncedPreferenceName[] = "nonsense_pref_name";
54 const char kUnsyncedPreferenceDefaultValue[] = "default";
55 const char kDefaultCharsetPrefName[] = "default_charset";
56 const char kNonDefaultCharsetValue[] = "foo";
57 const char kDefaultCharsetValue[] = "utf-8";
59 void Increment(int* num) {
63 class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
65 explicit TestSyncProcessorStub(syncer::SyncChangeList* output)
66 : output_(output), fail_next_(false) {}
68 syncer::SyncError ProcessSyncChanges(
69 const base::Location& from_here,
70 const syncer::SyncChangeList& change_list) override {
72 output_->insert(output_->end(), change_list.begin(), change_list.end());
75 return syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
76 "Error", syncer::PREFERENCES);
78 return syncer::SyncError();
81 void FailNextProcessSyncChanges() { fail_next_ = true; }
83 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
84 return syncer::SyncDataList();
88 syncer::SyncChangeList* output_;
92 class PrefServiceSyncableTest : public testing::Test {
94 PrefServiceSyncableTest()
95 : pref_sync_service_(nullptr),
96 next_pref_remote_sync_node_id_(0) {}
98 void SetUp() override {
99 prefs_.registry()->RegisterStringPref(kUnsyncedPreferenceName,
100 kUnsyncedPreferenceDefaultValue);
101 prefs_.registry()->RegisterStringPref(
102 kStringPrefName, std::string(),
103 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
104 prefs_.registry()->RegisterListPref(
105 kListPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
106 prefs_.registry()->RegisterStringPref(
107 kDefaultCharsetPrefName, kDefaultCharsetValue,
108 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
110 pref_sync_service_ = static_cast<PrefModelAssociator*>(
111 prefs_.GetSyncableService(syncer::PREFERENCES));
112 ASSERT_TRUE(pref_sync_service_);
115 syncer::SyncChange MakeRemoteChange(int64_t id,
116 const std::string& name,
117 const base::Value& value,
118 SyncChange::SyncChangeType type) {
119 std::string serialized;
120 JSONStringValueSerializer json(&serialized);
121 if (!json.Serialize(value))
122 return syncer::SyncChange();
123 sync_pb::EntitySpecifics entity;
124 sync_pb::PreferenceSpecifics* pref_one = entity.mutable_preference();
125 pref_one->set_name(name);
126 pref_one->set_value(serialized);
127 return syncer::SyncChange(FROM_HERE, type,
128 syncer::SyncData::CreateRemoteData(id, entity));
131 void AddToRemoteDataList(const std::string& name,
132 const base::Value& value,
133 syncer::SyncDataList* out) {
134 std::string serialized;
135 JSONStringValueSerializer json(&serialized);
136 ASSERT_TRUE(json.Serialize(value));
137 sync_pb::EntitySpecifics one;
138 sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
139 pref_one->set_name(name);
140 pref_one->set_value(serialized);
142 SyncData::CreateRemoteData(++next_pref_remote_sync_node_id_, one));
145 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
146 syncer::SyncChangeList* output) {
147 syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
148 syncer::PREFERENCES, initial_data,
149 std::make_unique<TestSyncProcessorStub>(output),
150 std::make_unique<syncer::SyncErrorFactoryMock>());
151 EXPECT_FALSE(r.error().IsSet());
154 void InitWithNoSyncData() {
155 InitWithSyncDataTakeOutput(syncer::SyncDataList(), nullptr);
158 const base::Value& GetPreferenceValue(const std::string& name) {
159 const PrefService::Preference* preference =
160 prefs_.FindPreference(name.c_str());
161 return *preference->GetValue();
164 std::unique_ptr<base::Value> FindValue(const std::string& name,
165 const syncer::SyncChangeList& list) {
166 auto it = list.begin();
167 for (; it != list.end(); ++it) {
168 if (syncer::SyncDataLocal(it->sync_data()).GetTag() == name) {
169 return base::JSONReader::Read(
170 it->sync_data().GetSpecifics().preference().value());
176 bool IsSynced(const std::string& pref_name) {
177 return pref_sync_service_->IsPrefSynced(pref_name);
180 bool IsRegistered(const std::string& pref_name) {
181 return pref_sync_service_->IsPrefRegistered(pref_name.c_str());
184 PrefService* GetPrefs() { return &prefs_; }
185 TestingPrefServiceSyncable* GetTestingPrefService() { return &prefs_; }
188 TestingPrefServiceSyncable prefs_;
190 PrefModelAssociator* pref_sync_service_;
192 int next_pref_remote_sync_node_id_;
195 TEST_F(PrefServiceSyncableTest, CreatePrefSyncData) {
196 prefs_.SetString(kStringPrefName, kExampleUrl0);
198 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
199 syncer::SyncData sync_data;
200 EXPECT_TRUE(pref_sync_service_->CreatePrefSyncData(
201 pref->name(), *pref->GetValue(), &sync_data));
202 EXPECT_EQ(std::string(kStringPrefName),
203 syncer::SyncDataLocal(sync_data).GetTag());
204 const sync_pb::PreferenceSpecifics& specifics(
205 sync_data.GetSpecifics().preference());
206 EXPECT_EQ(std::string(kStringPrefName), specifics.name());
208 std::unique_ptr<base::Value> value =
209 base::JSONReader::Read(specifics.value());
210 EXPECT_TRUE(pref->GetValue()->Equals(value.get()));
213 TEST_F(PrefServiceSyncableTest, ModelAssociationDoNotSyncDefaults) {
214 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
215 EXPECT_TRUE(pref->IsDefaultValue());
216 syncer::SyncChangeList out;
217 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
219 EXPECT_TRUE(IsRegistered(kStringPrefName));
220 EXPECT_TRUE(pref->IsDefaultValue());
221 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
224 TEST_F(PrefServiceSyncableTest, ModelAssociationEmptyCloud) {
225 prefs_.SetString(kStringPrefName, kExampleUrl0);
227 ListPrefUpdate update(GetPrefs(), kListPrefName);
228 base::ListValue* url_list = update.Get();
229 url_list->AppendString(kExampleUrl0);
230 url_list->AppendString(kExampleUrl1);
232 syncer::SyncChangeList out;
233 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
235 std::unique_ptr<base::Value> value(FindValue(kStringPrefName, out));
236 ASSERT_TRUE(value.get());
237 EXPECT_TRUE(GetPreferenceValue(kStringPrefName).Equals(value.get()));
238 value = FindValue(kListPrefName, out);
239 ASSERT_TRUE(value.get());
240 EXPECT_TRUE(GetPreferenceValue(kListPrefName).Equals(value.get()));
243 TEST_F(PrefServiceSyncableTest, ModelAssociationCloudHasData) {
244 prefs_.SetString(kStringPrefName, kExampleUrl0);
246 ListPrefUpdate update(GetPrefs(), kListPrefName);
247 base::ListValue* url_list = update.Get();
248 url_list->AppendString(kExampleUrl0);
251 syncer::SyncDataList in;
252 syncer::SyncChangeList out;
253 AddToRemoteDataList(kStringPrefName, base::Value(kExampleUrl1), &in);
254 base::ListValue urls_to_restore;
255 urls_to_restore.AppendString(kExampleUrl1);
256 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
257 AddToRemoteDataList(kDefaultCharsetPrefName,
258 base::Value(kNonDefaultCharsetValue), &in);
259 InitWithSyncDataTakeOutput(in, &out);
261 ASSERT_FALSE(FindValue(kStringPrefName, out).get());
262 ASSERT_FALSE(FindValue(kDefaultCharsetPrefName, out).get());
264 EXPECT_EQ(kExampleUrl1, prefs_.GetString(kStringPrefName));
266 // No associator client is registered, so lists and dictionaries should not
267 // get merged (remote write wins).
268 auto expected_urls = std::make_unique<base::ListValue>();
269 expected_urls->AppendString(kExampleUrl1);
270 EXPECT_FALSE(FindValue(kListPrefName, out));
271 EXPECT_TRUE(GetPreferenceValue(kListPrefName).Equals(expected_urls.get()));
272 EXPECT_EQ(kNonDefaultCharsetValue, prefs_.GetString(kDefaultCharsetPrefName));
275 // Verifies that the implementation gracefully handles an initial remote sync
276 // data of wrong type. The local version should not get modified in these cases.
277 TEST_F(PrefServiceSyncableTest, ModelAssociationWithDataTypeMismatch) {
278 base::HistogramTester histogram_tester;
279 prefs_.SetString(kStringPrefName, kExampleUrl0);
281 syncer::SyncDataList in;
282 base::Value remote_int_value(123);
283 AddToRemoteDataList(kStringPrefName, remote_int_value, &in);
284 syncer::SyncChangeList out;
285 InitWithSyncDataTakeOutput(in, &out);
286 EXPECT_THAT(out, IsEmpty());
287 histogram_tester.ExpectBucketCount("Sync.Preferences.RemotePrefTypeMismatch",
289 EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0));
292 class TestPrefModelAssociatorClient : public PrefModelAssociatorClient {
294 TestPrefModelAssociatorClient() {}
295 ~TestPrefModelAssociatorClient() override {}
297 // PrefModelAssociatorClient implementation.
298 bool IsMergeableListPreference(const std::string& pref_name) const override {
299 return pref_name == kListPrefName;
302 bool IsMergeableDictionaryPreference(
303 const std::string& pref_name) const override {
307 std::unique_ptr<base::Value> MaybeMergePreferenceValues(
308 const std::string& pref_name,
309 const base::Value& local_value,
310 const base::Value& server_value) const override {
315 DISALLOW_COPY_AND_ASSIGN(TestPrefModelAssociatorClient);
318 class PrefServiceSyncableMergeTest : public testing::Test {
320 PrefServiceSyncableMergeTest()
322 base::MakeRefCounted<user_prefs::PrefRegistrySyncable>()),
323 pref_notifier_(new PrefNotifierImpl),
324 managed_prefs_(base::MakeRefCounted<TestingPrefStore>()),
325 user_prefs_(base::MakeRefCounted<TestingPrefStore>()),
327 std::unique_ptr<PrefNotifierImpl>(pref_notifier_),
328 std::make_unique<PrefValueStore>(managed_prefs_.get(),
329 new TestingPrefStore,
330 new TestingPrefStore,
331 new TestingPrefStore,
333 new TestingPrefStore,
334 pref_registry_->defaults().get(),
339 base::BindRepeating(&PrefServiceSyncableMergeTest::HandleReadError),
341 pref_sync_service_(nullptr),
342 next_pref_remote_sync_node_id_(0) {}
344 void SetUp() override {
345 pref_registry_->RegisterStringPref(kUnsyncedPreferenceName,
346 kUnsyncedPreferenceDefaultValue);
347 pref_registry_->RegisterStringPref(
348 kStringPrefName, std::string(),
349 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
350 pref_registry_->RegisterListPref(
351 kListPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
352 pref_registry_->RegisterDictionaryPref(
353 kDictPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
354 pref_registry_->RegisterStringPref(
355 kDefaultCharsetPrefName, kDefaultCharsetValue,
356 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
358 // Downcast to PrefModelAssociator so that tests can access its' specific
359 // behavior. This is a smell. The roles between PrefServiceSyncable and
360 // PrefModelAssociator are not clearly separated (and this test should only
361 // test against the SyncableService interface).
362 pref_sync_service_ = // static_cast<PrefModelAssociator*>(
363 prefs_.GetSyncableService(syncer::PREFERENCES); //);
364 ASSERT_THAT(pref_sync_service_, NotNull());
367 /// Empty stub for prefs_ error handling.
368 static void HandleReadError(PersistentPrefStore::PrefReadError error) {}
370 syncer::SyncChange MakeRemoteChange(int64_t id,
371 const std::string& name,
372 const base::Value& value,
373 SyncChange::SyncChangeType type) {
374 std::string serialized;
375 JSONStringValueSerializer json(&serialized);
376 CHECK(json.Serialize(value));
377 sync_pb::EntitySpecifics entity;
378 sync_pb::PreferenceSpecifics* pref_one = entity.mutable_preference();
379 pref_one->set_name(name);
380 pref_one->set_value(serialized);
381 return syncer::SyncChange(FROM_HERE, type,
382 syncer::SyncData::CreateRemoteData(id, entity));
385 void AddToRemoteDataList(const std::string& name,
386 const base::Value& value,
387 syncer::SyncDataList* out) {
388 std::string serialized;
389 JSONStringValueSerializer json(&serialized);
390 ASSERT_TRUE(json.Serialize(value));
391 sync_pb::EntitySpecifics one;
392 sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
393 pref_one->set_name(name);
394 pref_one->set_value(serialized);
396 SyncData::CreateRemoteData(++next_pref_remote_sync_node_id_, one));
399 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
400 syncer::SyncChangeList* output) {
401 syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
402 syncer::PREFERENCES, initial_data,
403 std::make_unique<TestSyncProcessorStub>(output),
404 std::make_unique<syncer::SyncErrorFactoryMock>());
405 EXPECT_FALSE(r.error().IsSet());
408 const base::Value& GetPreferenceValue(const std::string& name) {
409 const PrefService::Preference* preference =
410 prefs_.FindPreference(name.c_str());
411 return *preference->GetValue();
414 std::unique_ptr<base::Value> FindValue(const std::string& name,
415 const syncer::SyncChangeList& list) {
416 auto it = list.begin();
417 for (; it != list.end(); ++it) {
418 if (syncer::SyncDataLocal(it->sync_data()).GetTag() == name) {
419 return base::JSONReader::Read(
420 it->sync_data().GetSpecifics().preference().value());
427 scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_;
429 PrefNotifierImpl* pref_notifier_;
430 scoped_refptr<TestingPrefStore> managed_prefs_;
431 scoped_refptr<TestingPrefStore> user_prefs_;
432 TestPrefModelAssociatorClient client_;
433 PrefServiceSyncable prefs_;
434 syncer::SyncableService* pref_sync_service_;
435 int next_pref_remote_sync_node_id_;
438 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedListValues) {
440 ListPrefUpdate update(&prefs_, kListPrefName);
441 base::ListValue* url_list = update.Get();
442 url_list->AppendString(kExampleUrl0);
443 url_list->AppendString(kExampleUrl1);
446 base::ListValue urls_to_restore;
447 urls_to_restore.AppendString(kExampleUrl1);
448 urls_to_restore.AppendString(kExampleUrl2);
449 syncer::SyncDataList in;
450 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
452 syncer::SyncChangeList out;
453 InitWithSyncDataTakeOutput(in, &out);
455 std::unique_ptr<base::ListValue> expected_urls(new base::ListValue);
456 expected_urls->AppendString(kExampleUrl1);
457 expected_urls->AppendString(kExampleUrl2);
458 expected_urls->AppendString(kExampleUrl0);
459 std::unique_ptr<base::Value> value(FindValue(kListPrefName, out));
460 ASSERT_TRUE(value.get());
461 EXPECT_TRUE(value->Equals(expected_urls.get())) << *value;
462 EXPECT_TRUE(GetPreferenceValue(kListPrefName).Equals(expected_urls.get()));
465 // List preferences have special handling at association time due to our ability
466 // to merge the local and sync value. Make sure the merge logic doesn't merge
467 // managed preferences.
468 TEST_F(PrefServiceSyncableMergeTest, ManagedListPreferences) {
469 // Make the list of urls to restore on startup managed.
470 base::ListValue managed_value;
471 managed_value.AppendString(kExampleUrl0);
472 managed_value.AppendString(kExampleUrl1);
473 managed_prefs_->SetValue(kListPrefName, managed_value.CreateDeepCopy(),
474 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
476 // Set a cloud version.
477 syncer::SyncDataList in;
478 base::ListValue urls_to_restore;
479 urls_to_restore.AppendString(kExampleUrl1);
480 urls_to_restore.AppendString(kExampleUrl2);
481 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
483 // Start sync and verify the synced value didn't get merged.
485 syncer::SyncChangeList out;
486 InitWithSyncDataTakeOutput(in, &out);
487 EXPECT_FALSE(FindValue(kListPrefName, out).get());
490 // Changing the user's urls to restore on startup pref should not sync
493 syncer::SyncChangeList out;
494 base::ListValue user_value;
495 user_value.AppendString("http://chromium.org");
496 prefs_.Set(kListPrefName, user_value);
497 EXPECT_FALSE(FindValue(kListPrefName, out).get());
500 // An incoming sync transaction should change the user value, not the managed
502 base::ListValue sync_value;
503 sync_value.AppendString("http://crbug.com");
504 syncer::SyncChangeList list;
505 list.push_back(MakeRemoteChange(1, kListPrefName, sync_value,
506 SyncChange::ACTION_UPDATE));
507 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
509 const base::Value* managed_prefs_result;
510 ASSERT_TRUE(managed_prefs_->GetValue(kListPrefName, &managed_prefs_result));
511 EXPECT_TRUE(managed_value.Equals(managed_prefs_result));
512 // Get should return the managed value, too.
513 EXPECT_TRUE(managed_value.Equals(prefs_.Get(kListPrefName)));
514 // Verify the user pref value has the change.
515 EXPECT_TRUE(sync_value.Equals(prefs_.GetUserPrefValue(kListPrefName)));
518 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedDictionaryValues) {
520 DictionaryPrefUpdate update(&prefs_, kDictPrefName);
521 base::DictionaryValue* dict_value = update.Get();
522 dict_value->Set("my_key1", std::make_unique<base::Value>("my_value1"));
523 dict_value->Set("my_key3", std::make_unique<base::Value>("my_value3"));
526 base::DictionaryValue remote_update;
527 remote_update.Set("my_key2", std::make_unique<base::Value>("my_value2"));
528 syncer::SyncDataList in;
529 AddToRemoteDataList(kDictPrefName, remote_update, &in);
531 syncer::SyncChangeList out;
532 InitWithSyncDataTakeOutput(in, &out);
534 base::DictionaryValue expected_dict;
535 expected_dict.Set("my_key1", std::make_unique<base::Value>("my_value1"));
536 expected_dict.Set("my_key2", std::make_unique<base::Value>("my_value2"));
537 expected_dict.Set("my_key3", std::make_unique<base::Value>("my_value3"));
538 std::unique_ptr<base::Value> value(FindValue(kDictPrefName, out));
539 ASSERT_TRUE(value.get());
540 EXPECT_TRUE(value->Equals(&expected_dict));
541 EXPECT_TRUE(GetPreferenceValue(kDictPrefName).Equals(&expected_dict));
544 TEST_F(PrefServiceSyncableMergeTest, InitWithUnknownPrefsValue) {
545 base::HistogramTester histogram_tester;
546 const std::string pref_name1 = "testing.whitelisted_pref1";
547 const std::string pref_name2 = "testing.whitelisted_pref2";
548 pref_registry_->WhitelistLateRegistrationPrefForSync(pref_name1);
549 pref_registry_->WhitelistLateRegistrationPrefForSync(pref_name2);
551 syncer::SyncDataList in;
552 AddToRemoteDataList(pref_name1, base::Value("remote_value1"), &in);
553 AddToRemoteDataList(pref_name2, base::Value("remote_value2"), &in);
554 syncer::SyncChangeList out;
555 InitWithSyncDataTakeOutput(in, &out);
556 pref_registry_->RegisterStringPref(
557 pref_name1, "default_value",
558 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
559 EXPECT_THAT(GetPreferenceValue(pref_name1).GetString(), Eq("remote_value1"));
561 histogram_tester.ExpectBucketCount("Sync.Preferences.SyncingUnknownPrefs", 2,
565 TEST_F(PrefServiceSyncableMergeTest, ReceiveUnknownPrefsValue) {
566 base::HistogramTester histogram_tester;
567 const std::string pref_name = "testing.whitelisted_pref";
568 pref_registry_->WhitelistLateRegistrationPrefForSync(pref_name);
570 syncer::SyncChangeList out;
571 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
573 syncer::SyncChangeList remote_changes;
574 remote_changes.push_back(MakeRemoteChange(
575 1, pref_name, base::Value("remote_value"), SyncChange::ACTION_UPDATE));
576 pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes);
577 EXPECT_THAT(prefs_.IsPrefSynced(pref_name), Eq(true));
579 pref_registry_->RegisterStringPref(
580 pref_name, "default_value",
581 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
582 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("remote_value"));
585 TEST_F(PrefServiceSyncableMergeTest, KeepPriorityPreferencesSeparately) {
586 base::HistogramTester histogram_tester;
587 const std::string pref_name = "testing.priority_pref";
588 pref_registry_->RegisterStringPref(
589 pref_name, "priority-default",
590 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
592 syncer::SyncDataList in;
593 // AddToRemoteDataList() produces sync data for non-priority prefs.
594 AddToRemoteDataList(pref_name, base::Value("non-priority-value"), &in);
595 syncer::SyncChangeList out;
596 InitWithSyncDataTakeOutput(in, &out);
597 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(),
598 Eq("priority-default"));
601 class ShouldNotBeNotifedObserver : public SyncedPrefObserver {
603 ShouldNotBeNotifedObserver() {}
604 ~ShouldNotBeNotifedObserver() {}
606 void OnSyncedPrefChanged(const std::string& path, bool from_sync) override {
607 ADD_FAILURE() << "Unexpected notification about a pref change with path: '"
608 << path << "' and from_sync: " << from_sync;
612 TEST_F(PrefServiceSyncableMergeTest, RegisterShouldClearTypeMismatchingData) {
613 base::HistogramTester histogram_tester;
614 const std::string pref_name = "testing.whitelisted_pref";
615 pref_registry_->WhitelistLateRegistrationPrefForSync(pref_name);
616 // Make sure no changes will be communicated to any synced pref listeners
617 // (those listeners are typically only used for metrics but we still don't
618 // want to inform them).
619 ShouldNotBeNotifedObserver observer;
620 prefs_.AddSyncedPrefObserver(pref_name, &observer);
621 syncer::SyncDataList in;
622 AddToRemoteDataList(pref_name, base::Value("remote_value"), &in);
623 syncer::SyncChangeList out;
624 InitWithSyncDataTakeOutput(in, &out);
625 ASSERT_THAT(out, IsEmpty());
627 EXPECT_TRUE(user_prefs_->GetValue(pref_name, nullptr));
629 pref_registry_->RegisterListPref(
630 pref_name, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
631 EXPECT_TRUE(GetPreferenceValue(pref_name).GetList().empty());
632 EXPECT_FALSE(user_prefs_->GetValue(pref_name, nullptr));
633 // Make sure the removal of the value was not communicated to sync via the
635 EXPECT_THAT(out, IsEmpty());
637 histogram_tester.ExpectBucketCount(
638 "Sync.Preferences.ClearedLocalPrefOnTypeMismatch", true, 1);
639 prefs_.RemoveSyncedPrefObserver(pref_name, &observer);
642 TEST_F(PrefServiceSyncableMergeTest, ShouldIgnoreUpdatesToNotSyncablePrefs) {
643 const std::string pref_name = "testing.not_syncable_pref";
644 pref_registry_->RegisterStringPref(pref_name, "default_value",
645 PrefRegistry::NO_REGISTRATION_FLAGS);
646 syncer::SyncDataList in;
647 AddToRemoteDataList(pref_name, base::Value("remote_value"), &in);
648 syncer::SyncChangeList out;
649 InitWithSyncDataTakeOutput(in, &out);
650 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("default_value"));
652 syncer::SyncChangeList remote_changes;
653 remote_changes.push_back(MakeRemoteChange(
654 1, pref_name, base::Value("remote_value2"), SyncChange::ACTION_UPDATE));
655 pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes);
656 EXPECT_THAT(prefs_.IsPrefSynced(pref_name), Eq(false));
658 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("default_value"));
661 TEST_F(PrefServiceSyncableMergeTest, GetAllSyncDataForLateRegisteredPrefs) {
662 const std::string pref_name = "testing.whitelisted_pref";
663 pref_registry_->WhitelistLateRegistrationPrefForSync(pref_name);
665 syncer::SyncDataList in;
666 AddToRemoteDataList(pref_name, base::Value("remote_value"), &in);
667 syncer::SyncChangeList out;
668 InitWithSyncDataTakeOutput(in, &out);
670 syncer::SyncDataList all_data =
671 prefs_.GetSyncableService(syncer::PREFERENCES)
672 ->GetAllSyncData(syncer::PREFERENCES);
673 EXPECT_THAT(all_data, IsEmpty());
675 // Make sure the preference appears in the result once it's registered.
676 pref_registry_->RegisterStringPref(
677 pref_name, "default_value",
678 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
680 all_data = prefs_.GetSyncableService(syncer::PREFERENCES)
681 ->GetAllSyncData(syncer::PREFERENCES);
682 ASSERT_THAT(all_data, SizeIs(1));
683 EXPECT_THAT(all_data[0].GetSpecifics().preference().name(), Eq(pref_name));
684 EXPECT_THAT(all_data[0].GetSpecifics().preference().value(),
685 Eq("\"remote_value\""));
688 TEST_F(PrefServiceSyncableTest, FailModelAssociation) {
689 syncer::SyncChangeList output;
690 TestSyncProcessorStub* stub = new TestSyncProcessorStub(&output);
691 stub->FailNextProcessSyncChanges();
692 syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
693 syncer::PREFERENCES, syncer::SyncDataList(), base::WrapUnique(stub),
694 std::make_unique<syncer::SyncErrorFactoryMock>());
695 EXPECT_TRUE(r.error().IsSet());
698 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithDefaultValue) {
699 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
700 EXPECT_TRUE(pref->IsDefaultValue());
702 syncer::SyncChangeList out;
703 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
706 base::Value expected(kExampleUrl0);
707 GetPrefs()->Set(kStringPrefName, expected);
709 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
710 ASSERT_TRUE(actual.get());
711 EXPECT_TRUE(expected.Equals(actual.get()));
714 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithValue) {
715 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
716 syncer::SyncChangeList out;
717 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
720 base::Value expected(kExampleUrl1);
721 GetPrefs()->Set(kStringPrefName, expected);
723 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
724 ASSERT_TRUE(actual.get());
725 EXPECT_TRUE(expected.Equals(actual.get()));
728 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdate) {
729 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
730 InitWithNoSyncData();
732 base::Value expected(kExampleUrl1);
733 syncer::SyncChangeList list;
734 list.push_back(MakeRemoteChange(1, kStringPrefName, expected,
735 SyncChange::ACTION_UPDATE));
736 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
738 const base::Value& actual = GetPreferenceValue(kStringPrefName);
739 EXPECT_TRUE(expected.Equals(&actual));
742 // Verifies that the implementation gracefully handles a remote update with the
743 // wrong type. The local version should not get modified in these cases.
744 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdateTypeMismatch) {
745 base::HistogramTester histogram_tester;
746 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
747 InitWithNoSyncData();
749 base::Value remote_int_value(123);
750 syncer::SyncChangeList remote_changes;
751 remote_changes.push_back(MakeRemoteChange(
752 1, kStringPrefName, remote_int_value, SyncChange::ACTION_UPDATE));
753 pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes);
755 EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0));
756 histogram_tester.ExpectBucketCount("Sync.Preferences.RemotePrefTypeMismatch",
760 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionAdd) {
761 InitWithNoSyncData();
763 base::Value expected(kExampleUrl0);
764 syncer::SyncChangeList list;
766 MakeRemoteChange(1, kStringPrefName, expected, SyncChange::ACTION_ADD));
767 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
769 const base::Value& actual = GetPreferenceValue(kStringPrefName);
770 EXPECT_TRUE(expected.Equals(&actual));
771 EXPECT_TRUE(pref_sync_service_->IsPrefSynced(kStringPrefName));
774 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeUnknownPreference) {
775 InitWithNoSyncData();
776 syncer::SyncChangeList list;
777 base::Value expected(kExampleUrl0);
778 list.push_back(MakeRemoteChange(1, "unknown preference", expected,
779 SyncChange::ACTION_UPDATE));
780 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
781 // Nothing interesting happens on the client when it gets an update
782 // of an unknown preference. We just should not crash.
785 TEST_F(PrefServiceSyncableTest, ManagedPreferences) {
786 // Make the homepage preference managed.
787 base::Value managed_value("http://example.com");
788 prefs_.SetManagedPref(kStringPrefName, managed_value.CreateDeepCopy());
790 syncer::SyncChangeList out;
791 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
794 // Changing the homepage preference should not sync anything.
795 base::Value user_value("http://chromium..com");
796 prefs_.SetUserPref(kStringPrefName, user_value.CreateDeepCopy());
797 EXPECT_TRUE(out.empty());
799 // An incoming sync transaction should change the user value, not the managed
801 base::Value sync_value("http://crbug.com");
802 syncer::SyncChangeList list;
803 list.push_back(MakeRemoteChange(1, kStringPrefName, sync_value,
804 SyncChange::ACTION_UPDATE));
805 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
807 EXPECT_TRUE(managed_value.Equals(prefs_.GetManagedPref(kStringPrefName)));
808 EXPECT_TRUE(sync_value.Equals(prefs_.GetUserPref(kStringPrefName)));
811 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferences) {
812 syncer::SyncChangeList out;
813 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
815 base::Value initial_value("http://example.com/initial");
816 GetPrefs()->Set(kStringPrefName, initial_value);
817 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
818 ASSERT_TRUE(actual.get());
819 EXPECT_TRUE(initial_value.Equals(actual.get()));
821 // Switch kHomePage to managed and set a different value.
822 base::Value managed_value("http://example.com/managed");
823 GetTestingPrefService()->SetManagedPref(kStringPrefName,
824 managed_value.CreateDeepCopy());
826 // The pref value should be the one dictated by policy.
827 EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(kStringPrefName)));
829 // Switch kHomePage back to unmanaged.
830 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
832 // The original value should be picked up.
833 EXPECT_TRUE(initial_value.Equals(&GetPreferenceValue(kStringPrefName)));
836 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferencesWithSyncChange) {
837 syncer::SyncChangeList out;
838 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
841 base::Value initial_value("http://example.com/initial");
842 GetPrefs()->Set(kStringPrefName, initial_value);
843 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
844 EXPECT_TRUE(initial_value.Equals(actual.get()));
846 // Switch kHomePage to managed and set a different value.
847 base::Value managed_value("http://example.com/managed");
848 GetTestingPrefService()->SetManagedPref(kStringPrefName,
849 managed_value.CreateDeepCopy());
851 // Change the sync value.
852 base::Value sync_value("http://example.com/sync");
853 syncer::SyncChangeList list;
854 list.push_back(MakeRemoteChange(1, kStringPrefName, sync_value,
855 SyncChange::ACTION_UPDATE));
856 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
858 // The pref value should still be the one dictated by policy.
859 EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(kStringPrefName)));
861 // Switch kHomePage back to unmanaged.
862 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
864 // Sync value should be picked up.
865 EXPECT_TRUE(sync_value.Equals(&GetPreferenceValue(kStringPrefName)));
868 TEST_F(PrefServiceSyncableTest, DynamicManagedDefaultPreferences) {
869 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
870 EXPECT_TRUE(pref->IsDefaultValue());
871 syncer::SyncChangeList out;
872 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
874 EXPECT_TRUE(IsRegistered(kStringPrefName));
875 EXPECT_TRUE(pref->IsDefaultValue());
876 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
879 // Switch kHomePage to managed and set a different value.
880 base::Value managed_value("http://example.com/managed");
881 GetTestingPrefService()->SetManagedPref(kStringPrefName,
882 managed_value.CreateDeepCopy());
883 // The pref value should be the one dictated by policy.
884 EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(kStringPrefName)));
885 EXPECT_FALSE(pref->IsDefaultValue());
886 // There should be no synced value.
887 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
888 // Switch kHomePage back to unmanaged.
889 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
890 // The original value should be picked up.
891 EXPECT_TRUE(pref->IsDefaultValue());
892 // There should still be no synced value.
893 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
896 TEST_F(PrefServiceSyncableTest, DeletePreference) {
897 prefs_.SetString(kStringPrefName, kExampleUrl0);
898 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
899 EXPECT_FALSE(pref->IsDefaultValue());
901 InitWithNoSyncData();
903 auto null_value = std::make_unique<base::Value>();
904 syncer::SyncChangeList list;
905 list.push_back(MakeRemoteChange(1, kStringPrefName, *null_value,
906 SyncChange::ACTION_DELETE));
907 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
908 EXPECT_TRUE(pref->IsDefaultValue());
911 TEST_F(PrefServiceSyncableTest, RegisterMergeDataFinishedCallback) {
912 int num_callbacks = 0;
914 prefs_.RegisterMergeDataFinishedCallback(
915 base::Bind(&Increment, &num_callbacks));
916 EXPECT_EQ(0, num_callbacks);
918 InitWithNoSyncData();
919 EXPECT_EQ(1, num_callbacks);
924 } // namespace sync_preferences