1 // Copyright 2014 The Chromium Authors
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/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/json/json_reader.h"
14 #include "base/json/json_string_value_serializer.h"
15 #include "base/json/json_writer.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "build/chromeos_buildflags.h"
20 #include "components/pref_registry/pref_registry_syncable.h"
21 #include "components/prefs/pref_notifier_impl.h"
22 #include "components/prefs/scoped_user_pref_update.h"
23 #include "components/prefs/testing_pref_store.h"
24 #include "components/sync/base/client_tag_hash.h"
25 #include "components/sync/base/model_type.h"
26 #include "components/sync/model/sync_change.h"
27 #include "components/sync/model/sync_change_processor.h"
28 #include "components/sync/model/sync_data.h"
29 #include "components/sync/model/syncable_service.h"
30 #include "components/sync/protocol/entity_specifics.pb.h"
31 #include "components/sync/protocol/preference_specifics.pb.h"
32 #include "components/sync/test/sync_error_factory_mock.h"
33 #include "components/sync_preferences/pref_model_associator.h"
34 #include "components/sync_preferences/pref_model_associator_client.h"
35 #include "components/sync_preferences/pref_service_syncable_observer.h"
36 #include "components/sync_preferences/synced_pref_observer.h"
37 #include "components/sync_preferences/testing_pref_service_syncable.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 #if BUILDFLAG(IS_CHROMEOS_ASH)
41 #include "testing/gmock/include/gmock/gmock-matchers.h"
44 using syncer::ModelType;
45 using syncer::ModelTypeSet;
46 using syncer::SyncChange;
47 using syncer::SyncData;
49 using testing::IsEmpty;
50 using testing::Matches;
51 using testing::NotNull;
52 using testing::UnorderedElementsAre;
53 using user_prefs::PrefRegistrySyncable;
55 namespace sync_preferences {
59 const char kExampleUrl0[] = "http://example.com/0";
60 const char kExampleUrl1[] = "http://example.com/1";
61 const char kExampleUrl2[] = "http://example.com/2";
62 const char kStringPrefName[] = "string_pref_name";
63 const char kListPrefName[] = "list_pref_name";
64 const char kDictPrefName[] = "dict_pref_name";
65 const char kUnsyncedPreferenceName[] = "nonsense_pref_name";
66 const char kUnsyncedPreferenceDefaultValue[] = "default";
67 const char kDefaultCharsetPrefName[] = "default_charset";
68 const char kNonDefaultCharsetValue[] = "foo";
69 const char kDefaultCharsetValue[] = "utf-8";
71 #if BUILDFLAG(IS_CHROMEOS_ASH)
72 constexpr ModelTypeSet kAllPreferenceModelTypes(
74 syncer::PRIORITY_PREFERENCES,
75 syncer::OS_PREFERENCES,
76 syncer::OS_PRIORITY_PREFERENCES);
78 MATCHER_P(MatchesModelType, model_type, "") {
79 const syncer::SyncChange& sync_change = arg;
80 return Matches(model_type)(sync_change.sync_data().GetDataType());
82 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
84 class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
86 explicit TestSyncProcessorStub(syncer::SyncChangeList* output)
89 absl::optional<syncer::ModelError> ProcessSyncChanges(
90 const base::Location& from_here,
91 const syncer::SyncChangeList& change_list) override {
93 output_->insert(output_->end(), change_list.begin(), change_list.end());
97 return syncer::ModelError(FROM_HERE, "Error");
102 void FailNextProcessSyncChanges() { fail_next_ = true; }
105 raw_ptr<syncer::SyncChangeList> output_;
106 bool fail_next_ = false;
109 class TestSyncedPrefObserver : public SyncedPrefObserver {
111 TestSyncedPrefObserver() = default;
112 ~TestSyncedPrefObserver() = default;
114 void OnSyncedPrefChanged(const std::string& path, bool from_sync) override {
119 void OnStartedSyncing(const std::string& path) override {
121 sync_started_count_++;
124 std::string last_pref_;
125 int changed_count_ = 0;
127 std::string synced_pref_;
128 int sync_started_count_ = 0;
131 class TestPrefServiceSyncableObserver : public PrefServiceSyncableObserver {
133 TestPrefServiceSyncableObserver() = default;
134 ~TestPrefServiceSyncableObserver() override = default;
136 void OnIsSyncingChanged() override {
137 if (sync_pref_observer_ && sync_pref_observer_->sync_started_count_ > 0) {
138 is_syncing_changed_ = true;
142 void SetSyncedPrefObserver(const TestSyncedPrefObserver* sync_pref_observer) {
143 sync_pref_observer_ = sync_pref_observer;
146 bool is_syncing_changed() { return is_syncing_changed_; }
149 bool is_syncing_changed_ = false;
150 raw_ptr<const TestSyncedPrefObserver> sync_pref_observer_ = nullptr;
153 syncer::SyncChange MakeRemoteChange(const std::string& name,
154 const base::Value& value,
155 SyncChange::SyncChangeType change_type,
156 syncer::ModelType model_type) {
157 std::string serialized;
158 JSONStringValueSerializer json(&serialized);
159 bool success = json.Serialize(value);
161 sync_pb::EntitySpecifics entity;
162 sync_pb::PreferenceSpecifics* pref =
163 PrefModelAssociator::GetMutableSpecifics(model_type, &entity);
164 pref->set_name(name);
165 pref->set_value(serialized);
166 return syncer::SyncChange(
167 FROM_HERE, change_type,
168 syncer::SyncData::CreateRemoteData(
169 entity, syncer::ClientTagHash::FromUnhashed(model_type, name)));
172 // Creates a SyncChange for model type |PREFERENCES|.
173 syncer::SyncChange MakeRemoteChange(const std::string& name,
174 const base::Value& value,
175 SyncChange::SyncChangeType type) {
176 return MakeRemoteChange(name, value, type, syncer::ModelType::PREFERENCES);
179 // Creates SyncData for a remote pref change.
180 SyncData CreateRemoteSyncData(const std::string& name,
181 const base::Value& value) {
182 std::string serialized;
183 JSONStringValueSerializer json(&serialized);
184 EXPECT_TRUE(json.Serialize(value));
185 sync_pb::EntitySpecifics one;
186 sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
187 pref_one->set_name(name);
188 pref_one->set_value(serialized);
189 return SyncData::CreateRemoteData(
190 one, syncer::ClientTagHash::FromUnhashed(syncer::ModelType::PREFERENCES,
194 class PrefServiceSyncableTest : public testing::Test {
196 PrefServiceSyncableTest() = default;
198 void SetUp() override {
199 prefs_.registry()->RegisterStringPref(kUnsyncedPreferenceName,
200 kUnsyncedPreferenceDefaultValue);
201 prefs_.registry()->RegisterStringPref(
202 kStringPrefName, std::string(),
203 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
204 prefs_.registry()->RegisterListPref(
205 kListPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
206 prefs_.registry()->RegisterStringPref(
207 kDefaultCharsetPrefName, kDefaultCharsetValue,
208 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
210 pref_sync_service_ = static_cast<PrefModelAssociator*>(
211 prefs_.GetSyncableService(syncer::PREFERENCES));
212 ASSERT_TRUE(pref_sync_service_);
215 void AddToRemoteDataList(const std::string& name,
216 const base::Value& value,
217 syncer::SyncDataList* out) {
218 out->push_back(CreateRemoteSyncData(name, value));
221 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
222 syncer::SyncChangeList* output) {
223 absl::optional<syncer::ModelError> error =
224 pref_sync_service_->MergeDataAndStartSyncing(
225 syncer::PREFERENCES, initial_data,
226 std::make_unique<TestSyncProcessorStub>(output),
227 std::make_unique<syncer::SyncErrorFactoryMock>());
228 EXPECT_FALSE(error.has_value());
231 void InitWithNoSyncData() {
232 InitWithSyncDataTakeOutput(syncer::SyncDataList(), nullptr);
235 const base::Value& GetPreferenceValue(const std::string& name) {
236 const PrefService::Preference* preference =
237 prefs_.FindPreference(name.c_str());
238 return *preference->GetValue();
241 std::unique_ptr<base::Value> FindValue(const std::string& name,
242 const syncer::SyncChangeList& list) {
243 auto it = list.begin();
244 for (; it != list.end(); ++it) {
245 if (it->sync_data().GetClientTagHash() ==
246 syncer::ClientTagHash::FromUnhashed(syncer::PREFERENCES, name)) {
247 return base::JSONReader::ReadDeprecated(
248 it->sync_data().GetSpecifics().preference().value());
254 bool IsRegistered(const std::string& pref_name) {
255 return pref_sync_service_->IsPrefRegistered(pref_name.c_str());
258 PrefService* GetPrefs() { return &prefs_; }
259 TestingPrefServiceSyncable* GetTestingPrefService() { return &prefs_; }
262 TestingPrefServiceSyncable prefs_;
264 raw_ptr<PrefModelAssociator> pref_sync_service_ = nullptr;
267 TEST_F(PrefServiceSyncableTest, CreatePrefSyncData) {
268 prefs_.SetString(kStringPrefName, kExampleUrl0);
270 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
271 syncer::SyncData sync_data;
272 EXPECT_TRUE(pref_sync_service_->CreatePrefSyncData(
273 pref->name(), *pref->GetValue(), &sync_data));
275 syncer::ClientTagHash::FromUnhashed(syncer::PREFERENCES, kStringPrefName),
276 sync_data.GetClientTagHash());
277 const sync_pb::PreferenceSpecifics& specifics(
278 sync_data.GetSpecifics().preference());
279 EXPECT_EQ(std::string(kStringPrefName), specifics.name());
281 std::unique_ptr<base::Value> value =
282 base::JSONReader::ReadDeprecated(specifics.value());
283 EXPECT_EQ(*pref->GetValue(), *value);
286 TEST_F(PrefServiceSyncableTest, ModelAssociationDoNotSyncDefaults) {
287 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
288 EXPECT_TRUE(pref->IsDefaultValue());
289 syncer::SyncChangeList out;
290 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
292 EXPECT_TRUE(IsRegistered(kStringPrefName));
293 EXPECT_TRUE(pref->IsDefaultValue());
294 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
297 TEST_F(PrefServiceSyncableTest, ModelAssociationEmptyCloud) {
298 prefs_.SetString(kStringPrefName, kExampleUrl0);
300 ScopedListPrefUpdate update(GetPrefs(), kListPrefName);
301 update->Append(kExampleUrl0);
302 update->Append(kExampleUrl1);
304 syncer::SyncChangeList out;
305 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
307 std::unique_ptr<base::Value> value(FindValue(kStringPrefName, out));
308 ASSERT_TRUE(value.get());
309 EXPECT_EQ(GetPreferenceValue(kStringPrefName), *value);
310 value = FindValue(kListPrefName, out);
311 ASSERT_TRUE(value.get());
312 EXPECT_EQ(GetPreferenceValue(kListPrefName), *value);
315 TEST_F(PrefServiceSyncableTest, ModelAssociationCloudHasData) {
316 prefs_.SetString(kStringPrefName, kExampleUrl0);
318 ScopedListPrefUpdate update(GetPrefs(), kListPrefName);
319 update->Append(kExampleUrl0);
322 syncer::SyncDataList in;
323 syncer::SyncChangeList out;
324 AddToRemoteDataList(kStringPrefName, base::Value(kExampleUrl1), &in);
325 base::ListValue urls_to_restore;
326 urls_to_restore.Append(kExampleUrl1);
327 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
328 AddToRemoteDataList(kDefaultCharsetPrefName,
329 base::Value(kNonDefaultCharsetValue), &in);
330 InitWithSyncDataTakeOutput(in, &out);
332 ASSERT_FALSE(FindValue(kStringPrefName, out).get());
333 ASSERT_FALSE(FindValue(kDefaultCharsetPrefName, out).get());
335 EXPECT_EQ(kExampleUrl1, prefs_.GetString(kStringPrefName));
337 // No associator client is registered, so lists and dictionaries should not
338 // get merged (remote write wins).
339 auto expected_urls = std::make_unique<base::ListValue>();
340 expected_urls->Append(kExampleUrl1);
341 EXPECT_FALSE(FindValue(kListPrefName, out));
342 EXPECT_EQ(GetPreferenceValue(kListPrefName), *expected_urls);
343 EXPECT_EQ(kNonDefaultCharsetValue, prefs_.GetString(kDefaultCharsetPrefName));
346 // Verifies that the implementation gracefully handles an initial remote sync
347 // data of wrong type. The local version should not get modified in these cases.
348 TEST_F(PrefServiceSyncableTest, ModelAssociationWithDataTypeMismatch) {
349 prefs_.SetString(kStringPrefName, kExampleUrl0);
351 syncer::SyncDataList in;
352 base::Value remote_int_value(123);
353 AddToRemoteDataList(kStringPrefName, remote_int_value, &in);
354 syncer::SyncChangeList out;
355 InitWithSyncDataTakeOutput(in, &out);
356 EXPECT_THAT(out, IsEmpty());
357 EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0));
360 class TestPrefModelAssociatorClient : public PrefModelAssociatorClient {
362 TestPrefModelAssociatorClient() = default;
364 TestPrefModelAssociatorClient(const TestPrefModelAssociatorClient&) = delete;
365 TestPrefModelAssociatorClient& operator=(
366 const TestPrefModelAssociatorClient&) = delete;
368 ~TestPrefModelAssociatorClient() override = default;
370 // PrefModelAssociatorClient implementation.
371 bool IsMergeableListPreference(const std::string& pref_name) const override {
372 return pref_name == kListPrefName;
375 bool IsMergeableDictionaryPreference(
376 const std::string& pref_name) const override {
377 return is_dict_pref_;
380 base::Value MaybeMergePreferenceValues(
381 const std::string& pref_name,
382 const base::Value& local_value,
383 const base::Value& server_value) const override {
384 return base::Value();
387 void SetIsDictPref(bool is_dict_pref) { is_dict_pref_ = is_dict_pref; }
390 bool is_dict_pref_ = true;
393 class PrefServiceSyncableMergeTest : public testing::Test {
395 PrefServiceSyncableMergeTest()
397 std::unique_ptr<PrefNotifierImpl>(pref_notifier_),
398 std::make_unique<PrefValueStore>(managed_prefs_.get(),
399 new TestingPrefStore,
400 new TestingPrefStore,
401 new TestingPrefStore,
402 new TestingPrefStore,
404 standalone_browser_prefs_.get(),
405 pref_registry_->defaults().get(),
408 standalone_browser_prefs_,
411 /*read_error_callback=*/base::DoNothing(),
414 void SetUp() override {
415 pref_registry_->RegisterStringPref(kUnsyncedPreferenceName,
416 kUnsyncedPreferenceDefaultValue);
417 pref_registry_->RegisterStringPref(
418 kStringPrefName, std::string(),
419 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
420 pref_registry_->RegisterListPref(
421 kListPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
422 pref_registry_->RegisterDictionaryPref(
423 kDictPrefName, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
424 pref_registry_->RegisterStringPref(
425 kDefaultCharsetPrefName, kDefaultCharsetValue,
426 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
428 pref_sync_service_ = static_cast<PrefModelAssociator*>(
429 prefs_.GetSyncableService(syncer::PREFERENCES));
430 ASSERT_THAT(pref_sync_service_, NotNull());
433 syncer::SyncChange MakeRemoteChange(const std::string& name,
434 const base::Value& value,
435 SyncChange::SyncChangeType type) {
436 std::string serialized;
437 JSONStringValueSerializer json(&serialized);
438 CHECK(json.Serialize(value));
439 sync_pb::EntitySpecifics entity;
440 sync_pb::PreferenceSpecifics* pref_one = entity.mutable_preference();
441 pref_one->set_name(name);
442 pref_one->set_value(serialized);
443 return syncer::SyncChange(FROM_HERE, type,
444 syncer::SyncData::CreateRemoteData(
445 entity, syncer::ClientTagHash::FromUnhashed(
446 syncer::PREFERENCES, name)));
449 void AddToRemoteDataList(const std::string& name,
450 const base::Value& value,
451 syncer::SyncDataList* out) {
452 std::string serialized;
453 JSONStringValueSerializer json(&serialized);
454 ASSERT_TRUE(json.Serialize(value));
455 sync_pb::EntitySpecifics one;
456 sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
457 pref_one->set_name(name);
458 pref_one->set_value(serialized);
459 out->push_back(SyncData::CreateRemoteData(
460 one, syncer::ClientTagHash::FromUnhashed(syncer::PREFERENCES, name)));
463 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
464 syncer::SyncChangeList* output) {
465 absl::optional<syncer::ModelError> error =
466 pref_sync_service_->MergeDataAndStartSyncing(
467 syncer::PREFERENCES, initial_data,
468 std::make_unique<TestSyncProcessorStub>(output),
469 std::make_unique<syncer::SyncErrorFactoryMock>());
470 EXPECT_FALSE(error.has_value());
473 const base::Value& GetPreferenceValue(const std::string& name) {
474 const PrefService::Preference* preference =
475 prefs_.FindPreference(name.c_str());
476 return *preference->GetValue();
479 std::unique_ptr<base::Value> FindValue(const std::string& name,
480 const syncer::SyncChangeList& list) {
481 auto it = list.begin();
482 for (; it != list.end(); ++it) {
483 if (it->sync_data().GetClientTagHash() ==
484 syncer::ClientTagHash::FromUnhashed(syncer::PREFERENCES, name)) {
485 return base::JSONReader::ReadDeprecated(
486 it->sync_data().GetSpecifics().preference().value());
493 scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_ =
494 base::MakeRefCounted<user_prefs::PrefRegistrySyncable>();
496 const raw_ptr<PrefNotifierImpl> pref_notifier_ = new PrefNotifierImpl;
497 scoped_refptr<TestingPrefStore> managed_prefs_ =
498 base::MakeRefCounted<TestingPrefStore>();
499 scoped_refptr<TestingPrefStore> user_prefs_ =
500 base::MakeRefCounted<TestingPrefStore>();
501 scoped_refptr<TestingPrefStore> standalone_browser_prefs_ =
502 base::MakeRefCounted<TestingPrefStore>();
503 TestPrefModelAssociatorClient client_;
504 PrefServiceSyncable prefs_;
505 raw_ptr<PrefModelAssociator> pref_sync_service_ = nullptr;
508 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedListValues) {
510 ScopedListPrefUpdate update(&prefs_, kListPrefName);
511 update->Append(kExampleUrl0);
512 update->Append(kExampleUrl1);
515 base::ListValue urls_to_restore;
516 urls_to_restore.Append(kExampleUrl1);
517 urls_to_restore.Append(kExampleUrl2);
518 syncer::SyncDataList in;
519 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
521 syncer::SyncChangeList out;
522 InitWithSyncDataTakeOutput(in, &out);
524 std::unique_ptr<base::ListValue> expected_urls(new base::ListValue);
525 expected_urls->Append(kExampleUrl1);
526 expected_urls->Append(kExampleUrl2);
527 expected_urls->Append(kExampleUrl0);
528 std::unique_ptr<base::Value> value(FindValue(kListPrefName, out));
529 ASSERT_TRUE(value.get());
530 EXPECT_EQ(*value, *expected_urls) << *value;
531 EXPECT_EQ(GetPreferenceValue(kListPrefName), *expected_urls);
534 // List preferences have special handling at association time due to our ability
535 // to merge the local and sync value. Make sure the merge logic doesn't merge
536 // managed preferences.
537 TEST_F(PrefServiceSyncableMergeTest, ManagedListPreferences) {
538 // Make the list of urls to restore on startup managed.
539 base::Value managed_value(base::Value::Type::LIST);
540 managed_value.Append(kExampleUrl0);
541 managed_value.Append(kExampleUrl1);
542 managed_prefs_->SetValue(kListPrefName, managed_value.Clone(),
543 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
545 // Set a cloud version.
546 syncer::SyncDataList in;
547 base::ListValue urls_to_restore;
548 urls_to_restore.Append(kExampleUrl1);
549 urls_to_restore.Append(kExampleUrl2);
550 AddToRemoteDataList(kListPrefName, urls_to_restore, &in);
552 // Start sync and verify the synced value didn't get merged.
554 syncer::SyncChangeList out;
555 InitWithSyncDataTakeOutput(in, &out);
556 EXPECT_FALSE(FindValue(kListPrefName, out).get());
559 // Changing the user's urls to restore on startup pref should not sync
562 syncer::SyncChangeList out;
563 base::ListValue user_value;
564 user_value.Append("http://chromium.org");
565 prefs_.Set(kListPrefName, user_value);
566 EXPECT_FALSE(FindValue(kListPrefName, out).get());
569 // An incoming sync transaction should change the user value, not the managed
571 base::ListValue sync_value;
572 sync_value.Append("http://crbug.com");
573 syncer::SyncChangeList list;
575 MakeRemoteChange(kListPrefName, sync_value, SyncChange::ACTION_UPDATE));
576 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
578 const base::Value* managed_prefs_result;
579 ASSERT_TRUE(managed_prefs_->GetValue(kListPrefName, &managed_prefs_result));
580 EXPECT_EQ(managed_value, *managed_prefs_result);
581 // Get should return the managed value, too.
582 EXPECT_EQ(managed_value, prefs_.GetValue(kListPrefName));
583 // Verify the user pref value has the change.
584 EXPECT_EQ(sync_value, *prefs_.GetUserPrefValue(kListPrefName));
587 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedDictionaryValues) {
589 ScopedDictPrefUpdate update(&prefs_, kDictPrefName);
590 update->Set("my_key1", "my_value1");
591 update->Set("my_key3", "my_value3");
594 base::DictionaryValue remote_update;
595 remote_update.Set("my_key2", std::make_unique<base::Value>("my_value2"));
596 syncer::SyncDataList in;
597 AddToRemoteDataList(kDictPrefName, remote_update, &in);
599 syncer::SyncChangeList out;
600 InitWithSyncDataTakeOutput(in, &out);
602 base::DictionaryValue expected_dict;
603 expected_dict.Set("my_key1", std::make_unique<base::Value>("my_value1"));
604 expected_dict.Set("my_key2", std::make_unique<base::Value>("my_value2"));
605 expected_dict.Set("my_key3", std::make_unique<base::Value>("my_value3"));
606 std::unique_ptr<base::Value> value(FindValue(kDictPrefName, out));
607 ASSERT_TRUE(value.get());
608 EXPECT_EQ(*value, expected_dict);
609 EXPECT_EQ(GetPreferenceValue(kDictPrefName), expected_dict);
612 // TODO(jamescook): In production all prefs are registered before the
613 // PrefServiceSyncable is created. This test should do the same.
614 TEST_F(PrefServiceSyncableMergeTest, KeepPriorityPreferencesSeparately) {
615 const std::string pref_name = "testing.priority_pref";
616 pref_registry_->RegisterStringPref(
617 pref_name, "priority-default",
618 user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
620 syncer::SyncDataList in;
621 // AddToRemoteDataList() produces sync data for non-priority prefs.
622 AddToRemoteDataList(pref_name, base::Value("non-priority-value"), &in);
623 syncer::SyncChangeList out;
624 InitWithSyncDataTakeOutput(in, &out);
625 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(),
626 Eq("priority-default"));
629 class ShouldNotBeNotifedObserver : public SyncedPrefObserver {
631 ShouldNotBeNotifedObserver() = default;
632 ~ShouldNotBeNotifedObserver() = default;
634 void OnSyncedPrefChanged(const std::string& path, bool from_sync) override {
635 ADD_FAILURE() << "Unexpected notification about a pref change with path: '"
636 << path << "' and from_sync: " << from_sync;
640 TEST_F(PrefServiceSyncableMergeTest, RegisterShouldClearTypeMismatchingData) {
641 const std::string pref_name = "testing.pref";
642 user_prefs_->SetString(pref_name, "string_value");
643 ASSERT_TRUE(user_prefs_->GetValue(pref_name, nullptr));
645 // Make sure no changes will be communicated to any synced pref listeners
646 // (those listeners are typically only used for metrics but we still don't
647 // want to inform them).
648 ShouldNotBeNotifedObserver observer;
649 prefs_.AddSyncedPrefObserver(pref_name, &observer);
651 pref_registry_->RegisterListPref(
652 pref_name, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
653 EXPECT_TRUE(GetPreferenceValue(pref_name).GetList().empty());
654 EXPECT_FALSE(user_prefs_->GetValue(pref_name, nullptr));
656 prefs_.RemoveSyncedPrefObserver(pref_name, &observer);
659 TEST_F(PrefServiceSyncableMergeTest, ShouldIgnoreUpdatesToNotSyncablePrefs) {
660 const std::string pref_name = "testing.not_syncable_pref";
661 pref_registry_->RegisterStringPref(pref_name, "default_value",
662 PrefRegistry::NO_REGISTRATION_FLAGS);
663 syncer::SyncDataList in;
664 AddToRemoteDataList(pref_name, base::Value("remote_value"), &in);
665 syncer::SyncChangeList out;
666 InitWithSyncDataTakeOutput(in, &out);
667 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("default_value"));
669 syncer::SyncChangeList remote_changes;
670 remote_changes.push_back(MakeRemoteChange(
671 pref_name, base::Value("remote_value2"), SyncChange::ACTION_UPDATE));
672 pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes);
673 // The pref isn't synced.
674 EXPECT_THAT(pref_sync_service_->GetAllSyncDataForTesting(syncer::PREFERENCES),
676 EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("default_value"));
679 TEST_F(PrefServiceSyncableTest, FailModelAssociation) {
680 syncer::SyncChangeList output;
681 TestSyncProcessorStub* stub = new TestSyncProcessorStub(&output);
682 stub->FailNextProcessSyncChanges();
683 absl::optional<syncer::ModelError> error =
684 pref_sync_service_->MergeDataAndStartSyncing(
685 syncer::PREFERENCES, syncer::SyncDataList(), base::WrapUnique(stub),
686 std::make_unique<syncer::SyncErrorFactoryMock>());
687 EXPECT_TRUE(error.has_value());
690 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithDefaultValue) {
691 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
692 EXPECT_TRUE(pref->IsDefaultValue());
694 syncer::SyncChangeList out;
695 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
698 base::Value expected(kExampleUrl0);
699 GetPrefs()->Set(kStringPrefName, expected);
701 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
702 ASSERT_TRUE(actual.get());
703 EXPECT_EQ(expected, *actual);
706 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithValue) {
707 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
708 syncer::SyncChangeList out;
709 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
712 base::Value expected(kExampleUrl1);
713 GetPrefs()->Set(kStringPrefName, expected);
715 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
716 ASSERT_TRUE(actual.get());
717 EXPECT_EQ(expected, *actual);
720 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdate) {
721 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
722 InitWithNoSyncData();
724 base::Value expected(kExampleUrl1);
725 syncer::SyncChangeList list;
727 MakeRemoteChange(kStringPrefName, expected, SyncChange::ACTION_UPDATE));
728 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
730 const base::Value& actual = GetPreferenceValue(kStringPrefName);
731 EXPECT_EQ(expected, actual);
734 // Verifies that the implementation gracefully handles a remote update with the
735 // wrong type. The local version should not get modified in these cases.
736 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdateTypeMismatch) {
737 GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
738 InitWithNoSyncData();
740 base::Value remote_int_value(123);
741 syncer::SyncChangeList remote_changes;
742 remote_changes.push_back(MakeRemoteChange(kStringPrefName, remote_int_value,
743 SyncChange::ACTION_UPDATE));
744 pref_sync_service_->ProcessSyncChanges(FROM_HERE, remote_changes);
746 EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0));
749 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionAdd) {
750 InitWithNoSyncData();
752 base::Value expected(kExampleUrl0);
753 syncer::SyncChangeList list;
755 MakeRemoteChange(kStringPrefName, expected, SyncChange::ACTION_ADD));
756 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
758 const base::Value& actual = GetPreferenceValue(kStringPrefName);
759 EXPECT_EQ(expected, actual);
760 EXPECT_TRUE(pref_sync_service_->IsPrefSyncedForTesting(kStringPrefName));
763 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeUnknownPreference) {
764 InitWithNoSyncData();
765 syncer::SyncChangeList list;
766 base::Value expected(kExampleUrl0);
767 list.push_back(MakeRemoteChange("unknown preference", expected,
768 SyncChange::ACTION_UPDATE));
769 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
770 // Nothing interesting happens on the client when it gets an update
771 // of an unknown preference. We just should not crash.
774 TEST_F(PrefServiceSyncableTest, ManagedPreferences) {
775 // Make the homepage preference managed.
776 base::Value managed_value("http://example.com");
777 prefs_.SetManagedPref(kStringPrefName, managed_value.Clone());
779 syncer::SyncChangeList out;
780 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
783 // Changing the homepage preference should not sync anything.
784 base::Value user_value("http://chromium..com");
785 prefs_.SetUserPref(kStringPrefName, user_value.Clone());
786 EXPECT_TRUE(out.empty());
788 // An incoming sync transaction should change the user value, not the managed
790 base::Value sync_value("http://crbug.com");
791 syncer::SyncChangeList list;
793 MakeRemoteChange(kStringPrefName, sync_value, SyncChange::ACTION_UPDATE));
794 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
796 EXPECT_EQ(managed_value, *prefs_.GetManagedPref(kStringPrefName));
797 EXPECT_EQ(sync_value, *prefs_.GetUserPref(kStringPrefName));
800 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferences) {
801 syncer::SyncChangeList out;
802 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
804 base::Value initial_value("http://example.com/initial");
805 GetPrefs()->Set(kStringPrefName, initial_value);
806 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
807 ASSERT_TRUE(actual.get());
808 EXPECT_EQ(initial_value, *actual);
810 // Switch kHomePage to managed and set a different value.
811 base::Value managed_value("http://example.com/managed");
812 GetTestingPrefService()->SetManagedPref(kStringPrefName,
813 managed_value.Clone());
815 // The pref value should be the one dictated by policy.
816 EXPECT_EQ(managed_value, GetPreferenceValue(kStringPrefName));
818 // Switch kHomePage back to unmanaged.
819 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
821 // The original value should be picked up.
822 EXPECT_EQ(initial_value, GetPreferenceValue(kStringPrefName));
825 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferencesWithSyncChange) {
826 syncer::SyncChangeList out;
827 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
830 base::Value initial_value("http://example.com/initial");
831 GetPrefs()->Set(kStringPrefName, initial_value);
832 std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
833 EXPECT_EQ(initial_value, *actual);
835 // Switch kHomePage to managed and set a different value.
836 base::Value managed_value("http://example.com/managed");
837 GetTestingPrefService()->SetManagedPref(kStringPrefName,
838 managed_value.Clone());
840 // Change the sync value.
841 base::Value sync_value("http://example.com/sync");
842 syncer::SyncChangeList list;
844 MakeRemoteChange(kStringPrefName, sync_value, SyncChange::ACTION_UPDATE));
845 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
847 // The pref value should still be the one dictated by policy.
848 EXPECT_EQ(managed_value, GetPreferenceValue(kStringPrefName));
850 // Switch kHomePage back to unmanaged.
851 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
853 // Sync value should be picked up.
854 EXPECT_EQ(sync_value, GetPreferenceValue(kStringPrefName));
857 TEST_F(PrefServiceSyncableTest, DynamicManagedDefaultPreferences) {
858 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
859 EXPECT_TRUE(pref->IsDefaultValue());
860 syncer::SyncChangeList out;
861 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
863 EXPECT_TRUE(IsRegistered(kStringPrefName));
864 EXPECT_TRUE(pref->IsDefaultValue());
865 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
868 // Switch kHomePage to managed and set a different value.
869 base::Value managed_value("http://example.com/managed");
870 GetTestingPrefService()->SetManagedPref(kStringPrefName,
871 managed_value.Clone());
872 // The pref value should be the one dictated by policy.
873 EXPECT_EQ(managed_value, GetPreferenceValue(kStringPrefName));
874 EXPECT_FALSE(pref->IsDefaultValue());
875 // There should be no synced value.
876 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
877 // Switch kHomePage back to unmanaged.
878 GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
879 // The original value should be picked up.
880 EXPECT_TRUE(pref->IsDefaultValue());
881 // There should still be no synced value.
882 EXPECT_FALSE(FindValue(kStringPrefName, out).get());
885 TEST_F(PrefServiceSyncableTest, DeletePreference) {
886 prefs_.SetString(kStringPrefName, kExampleUrl0);
887 const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
888 EXPECT_FALSE(pref->IsDefaultValue());
890 InitWithNoSyncData();
892 auto null_value = std::make_unique<base::Value>();
893 syncer::SyncChangeList list;
894 list.push_back(MakeRemoteChange(kStringPrefName, *null_value,
895 SyncChange::ACTION_DELETE));
896 pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
897 EXPECT_TRUE(pref->IsDefaultValue());
900 #if BUILDFLAG(IS_CHROMEOS_ASH)
901 // The Chrome OS tests exercise pref model association that happens in the
902 // constructor of PrefServiceSyncable. The tests must register prefs first,
903 // then create the PrefServiceSyncable object. The tests live in this file
904 // because they share utility code with the cross-platform tests.
905 class PrefServiceSyncableChromeOsTest : public testing::Test {
907 PrefServiceSyncableChromeOsTest()
908 : pref_registry_(base::MakeRefCounted<PrefRegistrySyncable>()),
909 pref_notifier_(new PrefNotifierImpl),
910 user_prefs_(base::MakeRefCounted<TestingPrefStore>()),
911 standalone_browser_prefs_(base::MakeRefCounted<TestingPrefStore>()) {}
913 void CreatePrefService() {
914 // Register prefs of various types.
915 pref_registry_->RegisterStringPref("unsynced_pref", std::string());
916 pref_registry_->RegisterStringPref("browser_pref", std::string(),
917 PrefRegistrySyncable::SYNCABLE_PREF);
918 pref_registry_->RegisterStringPref(
919 "browser_priority_pref", std::string(),
920 PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
921 pref_registry_->RegisterStringPref("os_pref", std::string(),
922 PrefRegistrySyncable::SYNCABLE_OS_PREF);
923 pref_registry_->RegisterStringPref(
924 "os_priority_pref", std::string(),
925 PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);
926 client_.SetIsDictPref(false);
928 // Create the PrefServiceSyncable after prefs are registered, which is the
929 // order used in production.
930 prefs_ = std::make_unique<PrefServiceSyncable>(
931 std::unique_ptr<PrefNotifierImpl>(pref_notifier_),
932 std::make_unique<PrefValueStore>(
933 new TestingPrefStore, new TestingPrefStore, new TestingPrefStore,
934 new TestingPrefStore, new TestingPrefStore, user_prefs_.get(),
935 standalone_browser_prefs_.get(), pref_registry_->defaults().get(),
937 user_prefs_, standalone_browser_prefs_, pref_registry_, &client_,
938 /*read_error_callback=*/base::DoNothing(),
942 void InitSyncForType(ModelType type,
943 syncer::SyncChangeList* output = nullptr) {
944 syncer::SyncDataList empty_data;
945 absl::optional<syncer::ModelError> error =
946 prefs_->GetSyncableService(type)->MergeDataAndStartSyncing(
947 type, empty_data, std::make_unique<TestSyncProcessorStub>(output),
948 std::make_unique<syncer::SyncErrorFactoryMock>());
949 EXPECT_FALSE(error.has_value());
952 void InitSyncForAllTypes(syncer::SyncChangeList* output = nullptr) {
953 for (ModelType type : kAllPreferenceModelTypes) {
954 InitSyncForType(type, output);
958 ModelTypeSet GetRegisteredModelTypes(const std::string& pref_name) {
959 ModelTypeSet registered_types;
960 for (ModelType type : kAllPreferenceModelTypes) {
961 if (static_cast<PrefModelAssociator*>(prefs_->GetSyncableService(type))
962 ->IsPrefRegistered(pref_name)) {
963 registered_types.Put(type);
966 return registered_types;
969 SyncData MakeRemoteSyncData(const std::string& name,
970 const base::Value& value,
971 syncer::ModelType model_type) {
972 std::string serialized;
973 JSONStringValueSerializer json(&serialized);
974 EXPECT_TRUE(json.Serialize(value));
975 sync_pb::EntitySpecifics entity;
976 sync_pb::PreferenceSpecifics* pref =
977 PrefModelAssociator::GetMutableSpecifics(model_type, &entity);
978 pref->set_name(name);
979 pref->set_value(serialized);
980 return SyncData::CreateRemoteData(
981 entity, syncer::ClientTagHash::FromUnhashed(model_type, name));
985 scoped_refptr<PrefRegistrySyncable> pref_registry_;
986 PrefNotifierImpl* pref_notifier_; // Owned by |prefs_|.
987 scoped_refptr<TestingPrefStore> user_prefs_;
988 scoped_refptr<TestingPrefStore> standalone_browser_prefs_;
989 TestPrefModelAssociatorClient client_;
990 std::unique_ptr<PrefServiceSyncable> prefs_;
993 TEST_F(PrefServiceSyncableChromeOsTest, IsPrefRegistered) {
995 EXPECT_TRUE(GetRegisteredModelTypes("unsynced_pref").Empty());
996 EXPECT_EQ(ModelTypeSet(syncer::PREFERENCES),
997 GetRegisteredModelTypes("browser_pref"));
998 EXPECT_EQ(ModelTypeSet(syncer::PRIORITY_PREFERENCES),
999 GetRegisteredModelTypes("browser_priority_pref"));
1000 EXPECT_EQ(ModelTypeSet(syncer::OS_PREFERENCES),
1001 GetRegisteredModelTypes("os_pref"));
1002 EXPECT_EQ(ModelTypeSet(syncer::OS_PRIORITY_PREFERENCES),
1003 GetRegisteredModelTypes("os_priority_pref"));
1005 // The associator for PREFERENCES knows about OS prefs so that local updates
1006 // are synced back to old clients.
1007 auto* pref_associator = static_cast<PrefModelAssociator*>(
1008 prefs_->GetSyncableService(syncer::PREFERENCES));
1009 EXPECT_TRUE(pref_associator->IsLegacyModelTypePref("os_pref"));
1011 // The associator for PRIORITY_PREFERENCES knows about OS priority prefs so
1012 // that local updates are synced back to old clients.
1013 auto* priority_associator = static_cast<PrefModelAssociator*>(
1014 prefs_->GetSyncableService(syncer::PRIORITY_PREFERENCES));
1015 EXPECT_TRUE(priority_associator->IsLegacyModelTypePref("os_priority_pref"));
1018 TEST_F(PrefServiceSyncableChromeOsTest, IsSyncing) {
1019 CreatePrefService();
1020 InitSyncForType(syncer::PREFERENCES);
1021 EXPECT_TRUE(prefs_->IsSyncing());
1022 EXPECT_FALSE(prefs_->IsPrioritySyncing());
1023 EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
1024 EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
1027 TEST_F(PrefServiceSyncableChromeOsTest, IsPrioritySyncing) {
1028 CreatePrefService();
1029 InitSyncForType(syncer::PRIORITY_PREFERENCES);
1030 EXPECT_FALSE(prefs_->IsSyncing());
1031 EXPECT_TRUE(prefs_->IsPrioritySyncing());
1032 EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
1033 EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
1036 TEST_F(PrefServiceSyncableChromeOsTest, AreOsPrefsSyncing) {
1037 CreatePrefService();
1038 InitSyncForType(syncer::OS_PREFERENCES);
1039 EXPECT_FALSE(prefs_->IsSyncing());
1040 EXPECT_FALSE(prefs_->IsPrioritySyncing());
1041 EXPECT_TRUE(prefs_->AreOsPrefsSyncing());
1042 EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
1045 TEST_F(PrefServiceSyncableChromeOsTest, AreOsPriorityPrefsSyncing) {
1046 CreatePrefService();
1047 InitSyncForType(syncer::OS_PRIORITY_PREFERENCES);
1048 EXPECT_FALSE(prefs_->IsSyncing());
1049 EXPECT_FALSE(prefs_->IsPrioritySyncing());
1050 EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
1051 EXPECT_TRUE(prefs_->AreOsPriorityPrefsSyncing());
1054 TEST_F(PrefServiceSyncableChromeOsTest, IsPrefSynced_OsPref) {
1055 CreatePrefService();
1056 InitSyncForAllTypes();
1057 auto* associator = static_cast<PrefModelAssociator*>(
1058 prefs_->GetSyncableService(syncer::OS_PREFERENCES));
1059 EXPECT_FALSE(associator->IsPrefSyncedForTesting("os_pref"));
1061 syncer::SyncChangeList list;
1062 list.push_back(MakeRemoteChange("os_pref", base::Value("value"),
1063 SyncChange::ACTION_ADD,
1064 syncer::OS_PREFERENCES));
1065 associator->ProcessSyncChanges(FROM_HERE, list);
1066 EXPECT_TRUE(associator->IsPrefSyncedForTesting("os_pref"));
1069 TEST_F(PrefServiceSyncableChromeOsTest, IsPrefSynced_OsPriorityPref) {
1070 CreatePrefService();
1071 InitSyncForAllTypes();
1072 auto* associator = static_cast<PrefModelAssociator*>(
1073 prefs_->GetSyncableService(syncer::OS_PRIORITY_PREFERENCES));
1074 EXPECT_FALSE(associator->IsPrefSyncedForTesting("os_priority_pref"));
1076 syncer::SyncChangeList list;
1077 list.push_back(MakeRemoteChange("os_priority_pref", base::Value("value"),
1078 SyncChange::ACTION_ADD,
1079 syncer::OS_PRIORITY_PREFERENCES));
1080 associator->ProcessSyncChanges(FROM_HERE, list);
1081 EXPECT_TRUE(associator->IsPrefSyncedForTesting("os_priority_pref"));
1084 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPref) {
1085 CreatePrefService();
1086 InitSyncForAllTypes();
1088 TestSyncedPrefObserver observer;
1089 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1091 prefs_->SetString("os_pref", "value");
1092 EXPECT_EQ("os_pref", observer.last_pref_);
1093 EXPECT_EQ(1, observer.changed_count_);
1095 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1098 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPriorityPref) {
1099 CreatePrefService();
1100 InitSyncForAllTypes();
1102 TestSyncedPrefObserver observer;
1103 prefs_->AddSyncedPrefObserver("os_priority_pref", &observer);
1105 prefs_->SetString("os_priority_pref", "value");
1106 EXPECT_EQ("os_priority_pref", observer.last_pref_);
1107 EXPECT_EQ(1, observer.changed_count_);
1109 prefs_->RemoveSyncedPrefObserver("os_priority_pref", &observer);
1112 TEST_F(PrefServiceSyncableChromeOsTest, OsPrefChangeSyncedAsOsPrefChange) {
1113 CreatePrefService();
1114 // Set a non-default value.
1115 prefs_->SetString("os_pref", "new_value");
1117 syncer::SyncChangeList output;
1118 InitSyncForAllTypes(&output);
1119 ASSERT_EQ(1u, output.size());
1120 // The OS pref is treated like an OS pref.
1121 EXPECT_EQ(syncer::OS_PREFERENCES, output[0].sync_data().GetDataType());
1123 // Future changes will be synced back to browser preferences as well.
1124 auto* associator = static_cast<PrefModelAssociator*>(
1125 prefs_->GetSyncableService(syncer::PREFERENCES));
1126 EXPECT_TRUE(associator->IsPrefSyncedForTesting("os_pref"));
1129 TEST_F(PrefServiceSyncableChromeOsTest,
1130 OsPrefChangeMakesSyncChangeForOldClients_Update) {
1131 CreatePrefService();
1132 syncer::SyncChangeList changes;
1133 InitSyncForAllTypes(&changes);
1134 EXPECT_THAT(changes, IsEmpty());
1136 // Make a local change.
1137 prefs_->SetString("os_pref", "new_value");
1139 // Sync changes are made for the legacy ModelType::PREFERENCES (so old clients
1140 // will get updates) and for the current ModelType::OS_PREFERENCES (so new
1141 // clients will get updates).
1142 EXPECT_THAT(changes,
1143 UnorderedElementsAre(MatchesModelType(syncer::PREFERENCES),
1144 MatchesModelType(syncer::OS_PREFERENCES)));
1146 // Future changes will be synced back to browser preferences as well.
1147 auto* associator = static_cast<PrefModelAssociator*>(
1148 prefs_->GetSyncableService(syncer::PREFERENCES));
1149 EXPECT_TRUE(associator->IsPrefSyncedForTesting("os_pref"));
1152 TEST_F(PrefServiceSyncableChromeOsTest,
1153 UpdatesFromOldClientsAreIgnored_Startup) {
1154 CreatePrefService();
1155 TestSyncedPrefObserver observer;
1156 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1158 // Simulate an old client that has "os_pref" registered as SYNCABLE_PREF
1159 // instead of SYNCABLE_OS_PREF.
1160 syncer::SyncDataList list;
1161 list.push_back(CreateRemoteSyncData("os_pref", base::Value("new_value")));
1163 // Simulate the first sync at startup of the legacy browser prefs ModelType.
1164 auto* browser_associator = static_cast<PrefModelAssociator*>(
1165 prefs_->GetSyncableService(syncer::PREFERENCES));
1166 syncer::SyncChangeList outgoing_changes;
1167 browser_associator->MergeDataAndStartSyncing(
1168 syncer::PREFERENCES, list,
1169 std::make_unique<TestSyncProcessorStub>(&outgoing_changes),
1170 std::make_unique<syncer::SyncErrorFactoryMock>());
1172 // No outgoing changes were triggered.
1173 EXPECT_TRUE(outgoing_changes.empty());
1175 // The value from the old client was not applied.
1176 EXPECT_NE("new_value", prefs_->GetString("os_pref"));
1178 // The pref is not considered to be syncing, because it still has its default
1180 EXPECT_FALSE(browser_associator->IsPrefSyncedForTesting("os_pref"));
1182 // Observers were not notified of changes.
1183 EXPECT_EQ(0, observer.changed_count_);
1185 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1188 TEST_F(PrefServiceSyncableChromeOsTest,
1189 UpdatesFromOldClientsAreIgnored_Update) {
1190 CreatePrefService();
1191 InitSyncForAllTypes();
1192 TestSyncedPrefObserver observer;
1193 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1195 syncer::SyncChangeList list;
1196 // Simulate an old client that has "os_pref" registered as SYNCABLE_PREF
1197 // instead of SYNCABLE_OS_PREF.
1198 list.push_back(MakeRemoteChange("os_pref", base::Value("new_value"),
1199 SyncChange::ACTION_ADD, syncer::PREFERENCES));
1201 // Simulate a sync update after startup.
1202 prefs_->GetSyncableService(syncer::PREFERENCES)
1203 ->ProcessSyncChanges(FROM_HERE, list);
1205 // Update was not applied.
1206 EXPECT_NE("new_value", prefs_->GetString("os_pref"));
1208 // Observers were not notified of changes.
1209 EXPECT_EQ(0, observer.changed_count_);
1211 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1214 TEST_F(PrefServiceSyncableChromeOsTest,
1215 SyncedPrefObserver_OsPrefIsChangedFromSync) {
1216 CreatePrefService();
1217 prefs_->SetString("os_pref", "default_value");
1219 TestSyncedPrefObserver observer;
1220 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1222 TestPrefServiceSyncableObserver pref_service_sync_observer;
1223 pref_service_sync_observer.SetSyncedPrefObserver(&observer);
1224 prefs_->AddObserver(&pref_service_sync_observer);
1226 // Simulate that "os_pref" is registered as SYNCABLE_PREF
1227 syncer::SyncDataList list;
1228 list.push_back(MakeRemoteSyncData("os_pref", base::Value("new_value"),
1229 syncer::OS_PREFERENCES));
1231 // Simulate the first sync at startup.
1232 syncer::SyncChangeList outgoing_changes;
1233 prefs_->GetSyncableService(syncer::OS_PREFERENCES)
1234 ->MergeDataAndStartSyncing(
1235 syncer::OS_PREFERENCES, list,
1236 std::make_unique<TestSyncProcessorStub>(&outgoing_changes),
1237 std::make_unique<syncer::SyncErrorFactoryMock>());
1239 EXPECT_EQ("os_pref", observer.synced_pref_);
1240 EXPECT_EQ(1, observer.sync_started_count_);
1241 EXPECT_TRUE(pref_service_sync_observer.is_syncing_changed());
1243 prefs_->RemoveObserver(&pref_service_sync_observer);
1244 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1247 TEST_F(PrefServiceSyncableChromeOsTest,
1248 SyncedPrefObserver_OsPrefIsNotChangedFromSync) {
1249 CreatePrefService();
1250 prefs_->SetString("os_pref", "default_value");
1252 TestSyncedPrefObserver observer;
1253 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1255 TestPrefServiceSyncableObserver pref_service_sync_observer;
1256 pref_service_sync_observer.SetSyncedPrefObserver(&observer);
1257 prefs_->AddObserver(&pref_service_sync_observer);
1259 // Simulate that "os_pref" is registered as SYNCABLE_PREF
1260 syncer::SyncDataList list;
1261 list.push_back(MakeRemoteSyncData("os_pref", base::Value("new_value"),
1262 syncer::OS_PREFERENCES));
1264 // Simulate the first sync at startup.
1265 syncer::SyncChangeList outgoing_changes;
1266 prefs_->GetSyncableService(syncer::OS_PREFERENCES)
1267 ->MergeDataAndStartSyncing(
1268 syncer::OS_PREFERENCES, list,
1269 std::make_unique<TestSyncProcessorStub>(&outgoing_changes),
1270 std::make_unique<syncer::SyncErrorFactoryMock>());
1272 EXPECT_EQ("os_pref", observer.synced_pref_);
1273 EXPECT_EQ(1, observer.sync_started_count_);
1274 EXPECT_TRUE(pref_service_sync_observer.is_syncing_changed());
1276 prefs_->RemoveObserver(&pref_service_sync_observer);
1277 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1280 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_EmptyCloud) {
1281 CreatePrefService();
1282 prefs_->SetString("os_pref", "new_value");
1284 TestSyncedPrefObserver observer;
1285 prefs_->AddSyncedPrefObserver("os_pref", &observer);
1287 // Simulate the first sync at startup.
1288 syncer::SyncChangeList outgoing_changes;
1289 prefs_->GetSyncableService(syncer::OS_PREFERENCES)
1290 ->MergeDataAndStartSyncing(
1291 syncer::OS_PREFERENCES, syncer::SyncDataList(),
1292 std::make_unique<TestSyncProcessorStub>(&outgoing_changes),
1293 std::make_unique<syncer::SyncErrorFactoryMock>());
1295 EXPECT_EQ("", observer.synced_pref_);
1296 EXPECT_EQ(0, observer.sync_started_count_);
1298 prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1301 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
1305 } // namespace sync_preferences