Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / components / sync_preferences / pref_service_syncable_unittest.cc
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.
4
5 #include "components/sync_preferences/pref_service_syncable.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10
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"
39
40 #if BUILDFLAG(IS_CHROMEOS_ASH)
41 #include "testing/gmock/include/gmock/gmock-matchers.h"
42 #endif
43
44 using syncer::ModelType;
45 using syncer::ModelTypeSet;
46 using syncer::SyncChange;
47 using syncer::SyncData;
48 using testing::Eq;
49 using testing::IsEmpty;
50 using testing::Matches;
51 using testing::NotNull;
52 using testing::UnorderedElementsAre;
53 using user_prefs::PrefRegistrySyncable;
54
55 namespace sync_preferences {
56
57 namespace {
58
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";
70
71 #if BUILDFLAG(IS_CHROMEOS_ASH)
72 constexpr ModelTypeSet kAllPreferenceModelTypes(
73     syncer::PREFERENCES,
74     syncer::PRIORITY_PREFERENCES,
75     syncer::OS_PREFERENCES,
76     syncer::OS_PRIORITY_PREFERENCES);
77
78 MATCHER_P(MatchesModelType, model_type, "") {
79   const syncer::SyncChange& sync_change = arg;
80   return Matches(model_type)(sync_change.sync_data().GetDataType());
81 }
82 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
83
84 class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
85  public:
86   explicit TestSyncProcessorStub(syncer::SyncChangeList* output)
87       : output_(output) {}
88
89   absl::optional<syncer::ModelError> ProcessSyncChanges(
90       const base::Location& from_here,
91       const syncer::SyncChangeList& change_list) override {
92     if (output_) {
93       output_->insert(output_->end(), change_list.begin(), change_list.end());
94     }
95     if (fail_next_) {
96       fail_next_ = false;
97       return syncer::ModelError(FROM_HERE, "Error");
98     }
99     return absl::nullopt;
100   }
101
102   void FailNextProcessSyncChanges() { fail_next_ = true; }
103
104  private:
105   raw_ptr<syncer::SyncChangeList> output_;
106   bool fail_next_ = false;
107 };
108
109 class TestSyncedPrefObserver : public SyncedPrefObserver {
110  public:
111   TestSyncedPrefObserver() = default;
112   ~TestSyncedPrefObserver() = default;
113
114   void OnSyncedPrefChanged(const std::string& path, bool from_sync) override {
115     last_pref_ = path;
116     changed_count_++;
117   }
118
119   void OnStartedSyncing(const std::string& path) override {
120     synced_pref_ = path;
121     sync_started_count_++;
122   }
123
124   std::string last_pref_;
125   int changed_count_ = 0;
126
127   std::string synced_pref_;
128   int sync_started_count_ = 0;
129 };
130
131 class TestPrefServiceSyncableObserver : public PrefServiceSyncableObserver {
132  public:
133   TestPrefServiceSyncableObserver() = default;
134   ~TestPrefServiceSyncableObserver() override = default;
135
136   void OnIsSyncingChanged() override {
137     if (sync_pref_observer_ && sync_pref_observer_->sync_started_count_ > 0) {
138       is_syncing_changed_ = true;
139     }
140   }
141
142   void SetSyncedPrefObserver(const TestSyncedPrefObserver* sync_pref_observer) {
143     sync_pref_observer_ = sync_pref_observer;
144   }
145
146   bool is_syncing_changed() { return is_syncing_changed_; }
147
148  private:
149   bool is_syncing_changed_ = false;
150   raw_ptr<const TestSyncedPrefObserver> sync_pref_observer_ = nullptr;
151 };
152
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);
160   DCHECK(success);
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)));
170 }
171
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);
177 }
178
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,
191                                                name));
192 }
193
194 class PrefServiceSyncableTest : public testing::Test {
195  public:
196   PrefServiceSyncableTest() = default;
197
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);
209
210     pref_sync_service_ = static_cast<PrefModelAssociator*>(
211         prefs_.GetSyncableService(syncer::PREFERENCES));
212     ASSERT_TRUE(pref_sync_service_);
213   }
214
215   void AddToRemoteDataList(const std::string& name,
216                            const base::Value& value,
217                            syncer::SyncDataList* out) {
218     out->push_back(CreateRemoteSyncData(name, value));
219   }
220
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());
229   }
230
231   void InitWithNoSyncData() {
232     InitWithSyncDataTakeOutput(syncer::SyncDataList(), nullptr);
233   }
234
235   const base::Value& GetPreferenceValue(const std::string& name) {
236     const PrefService::Preference* preference =
237         prefs_.FindPreference(name.c_str());
238     return *preference->GetValue();
239   }
240
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());
249       }
250     }
251     return nullptr;
252   }
253
254   bool IsRegistered(const std::string& pref_name) {
255     return pref_sync_service_->IsPrefRegistered(pref_name.c_str());
256   }
257
258   PrefService* GetPrefs() { return &prefs_; }
259   TestingPrefServiceSyncable* GetTestingPrefService() { return &prefs_; }
260
261  protected:
262   TestingPrefServiceSyncable prefs_;
263
264   raw_ptr<PrefModelAssociator> pref_sync_service_ = nullptr;
265 };
266
267 TEST_F(PrefServiceSyncableTest, CreatePrefSyncData) {
268   prefs_.SetString(kStringPrefName, kExampleUrl0);
269
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));
274   EXPECT_EQ(
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());
280
281   std::unique_ptr<base::Value> value =
282       base::JSONReader::ReadDeprecated(specifics.value());
283   EXPECT_EQ(*pref->GetValue(), *value);
284 }
285
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);
291
292   EXPECT_TRUE(IsRegistered(kStringPrefName));
293   EXPECT_TRUE(pref->IsDefaultValue());
294   EXPECT_FALSE(FindValue(kStringPrefName, out).get());
295 }
296
297 TEST_F(PrefServiceSyncableTest, ModelAssociationEmptyCloud) {
298   prefs_.SetString(kStringPrefName, kExampleUrl0);
299   {
300     ScopedListPrefUpdate update(GetPrefs(), kListPrefName);
301     update->Append(kExampleUrl0);
302     update->Append(kExampleUrl1);
303   }
304   syncer::SyncChangeList out;
305   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
306
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);
313 }
314
315 TEST_F(PrefServiceSyncableTest, ModelAssociationCloudHasData) {
316   prefs_.SetString(kStringPrefName, kExampleUrl0);
317   {
318     ScopedListPrefUpdate update(GetPrefs(), kListPrefName);
319     update->Append(kExampleUrl0);
320   }
321
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);
331
332   ASSERT_FALSE(FindValue(kStringPrefName, out).get());
333   ASSERT_FALSE(FindValue(kDefaultCharsetPrefName, out).get());
334
335   EXPECT_EQ(kExampleUrl1, prefs_.GetString(kStringPrefName));
336
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));
344 }
345
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);
350
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));
358 }
359
360 class TestPrefModelAssociatorClient : public PrefModelAssociatorClient {
361  public:
362   TestPrefModelAssociatorClient() = default;
363
364   TestPrefModelAssociatorClient(const TestPrefModelAssociatorClient&) = delete;
365   TestPrefModelAssociatorClient& operator=(
366       const TestPrefModelAssociatorClient&) = delete;
367
368   ~TestPrefModelAssociatorClient() override = default;
369
370   // PrefModelAssociatorClient implementation.
371   bool IsMergeableListPreference(const std::string& pref_name) const override {
372     return pref_name == kListPrefName;
373   }
374
375   bool IsMergeableDictionaryPreference(
376       const std::string& pref_name) const override {
377     return is_dict_pref_;
378   }
379
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();
385   }
386
387   void SetIsDictPref(bool is_dict_pref) { is_dict_pref_ = is_dict_pref; }
388
389  private:
390   bool is_dict_pref_ = true;
391 };
392
393 class PrefServiceSyncableMergeTest : public testing::Test {
394  public:
395   PrefServiceSyncableMergeTest()
396       : prefs_(
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,
403                                              user_prefs_.get(),
404                                              standalone_browser_prefs_.get(),
405                                              pref_registry_->defaults().get(),
406                                              pref_notifier_),
407             user_prefs_,
408             standalone_browser_prefs_,
409             pref_registry_,
410             &client_,
411             /*read_error_callback=*/base::DoNothing(),
412             /*async=*/false) {}
413
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);
427
428     pref_sync_service_ = static_cast<PrefModelAssociator*>(
429         prefs_.GetSyncableService(syncer::PREFERENCES));
430     ASSERT_THAT(pref_sync_service_, NotNull());
431   }
432
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)));
447   }
448
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)));
461   }
462
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());
471   }
472
473   const base::Value& GetPreferenceValue(const std::string& name) {
474     const PrefService::Preference* preference =
475         prefs_.FindPreference(name.c_str());
476     return *preference->GetValue();
477   }
478
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());
487       }
488     }
489     return nullptr;
490   }
491
492  protected:
493   scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_ =
494       base::MakeRefCounted<user_prefs::PrefRegistrySyncable>();
495   // Owned by prefs_;
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;
506 };
507
508 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedListValues) {
509   {
510     ScopedListPrefUpdate update(&prefs_, kListPrefName);
511     update->Append(kExampleUrl0);
512     update->Append(kExampleUrl1);
513   }
514
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);
520
521   syncer::SyncChangeList out;
522   InitWithSyncDataTakeOutput(in, &out);
523
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);
532 }
533
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);
544
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);
551
552   // Start sync and verify the synced value didn't get merged.
553   {
554     syncer::SyncChangeList out;
555     InitWithSyncDataTakeOutput(in, &out);
556     EXPECT_FALSE(FindValue(kListPrefName, out).get());
557   }
558
559   // Changing the user's urls to restore on startup pref should not sync
560   // anything.
561   {
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());
567   }
568
569   // An incoming sync transaction should change the user value, not the managed
570   // value.
571   base::ListValue sync_value;
572   sync_value.Append("http://crbug.com");
573   syncer::SyncChangeList list;
574   list.push_back(
575       MakeRemoteChange(kListPrefName, sync_value, SyncChange::ACTION_UPDATE));
576   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
577
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));
585 }
586
587 TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedDictionaryValues) {
588   {
589     ScopedDictPrefUpdate update(&prefs_, kDictPrefName);
590     update->Set("my_key1", "my_value1");
591     update->Set("my_key3", "my_value3");
592   }
593
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);
598
599   syncer::SyncChangeList out;
600   InitWithSyncDataTakeOutput(in, &out);
601
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);
610 }
611
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);
619
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"));
627 }
628
629 class ShouldNotBeNotifedObserver : public SyncedPrefObserver {
630  public:
631   ShouldNotBeNotifedObserver() = default;
632   ~ShouldNotBeNotifedObserver() = default;
633
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;
637   }
638 };
639
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));
644
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);
650
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));
655
656   prefs_.RemoveSyncedPrefObserver(pref_name, &observer);
657 }
658
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"));
668
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),
675               IsEmpty());
676   EXPECT_THAT(GetPreferenceValue(pref_name).GetString(), Eq("default_value"));
677 }
678
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());
688 }
689
690 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithDefaultValue) {
691   const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
692   EXPECT_TRUE(pref->IsDefaultValue());
693
694   syncer::SyncChangeList out;
695   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
696   out.clear();
697
698   base::Value expected(kExampleUrl0);
699   GetPrefs()->Set(kStringPrefName, expected);
700
701   std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
702   ASSERT_TRUE(actual.get());
703   EXPECT_EQ(expected, *actual);
704 }
705
706 TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithValue) {
707   GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
708   syncer::SyncChangeList out;
709   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
710   out.clear();
711
712   base::Value expected(kExampleUrl1);
713   GetPrefs()->Set(kStringPrefName, expected);
714
715   std::unique_ptr<base::Value> actual(FindValue(kStringPrefName, out));
716   ASSERT_TRUE(actual.get());
717   EXPECT_EQ(expected, *actual);
718 }
719
720 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdate) {
721   GetPrefs()->SetString(kStringPrefName, kExampleUrl0);
722   InitWithNoSyncData();
723
724   base::Value expected(kExampleUrl1);
725   syncer::SyncChangeList list;
726   list.push_back(
727       MakeRemoteChange(kStringPrefName, expected, SyncChange::ACTION_UPDATE));
728   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
729
730   const base::Value& actual = GetPreferenceValue(kStringPrefName);
731   EXPECT_EQ(expected, actual);
732 }
733
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();
739
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);
745
746   EXPECT_THAT(prefs_.GetString(kStringPrefName), Eq(kExampleUrl0));
747 }
748
749 TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionAdd) {
750   InitWithNoSyncData();
751
752   base::Value expected(kExampleUrl0);
753   syncer::SyncChangeList list;
754   list.push_back(
755       MakeRemoteChange(kStringPrefName, expected, SyncChange::ACTION_ADD));
756   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
757
758   const base::Value& actual = GetPreferenceValue(kStringPrefName);
759   EXPECT_EQ(expected, actual);
760   EXPECT_TRUE(pref_sync_service_->IsPrefSyncedForTesting(kStringPrefName));
761 }
762
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.
772 }
773
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());
778
779   syncer::SyncChangeList out;
780   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
781   out.clear();
782
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());
787
788   // An incoming sync transaction should change the user value, not the managed
789   // value.
790   base::Value sync_value("http://crbug.com");
791   syncer::SyncChangeList list;
792   list.push_back(
793       MakeRemoteChange(kStringPrefName, sync_value, SyncChange::ACTION_UPDATE));
794   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
795
796   EXPECT_EQ(managed_value, *prefs_.GetManagedPref(kStringPrefName));
797   EXPECT_EQ(sync_value, *prefs_.GetUserPref(kStringPrefName));
798 }
799
800 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferences) {
801   syncer::SyncChangeList out;
802   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
803   out.clear();
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);
809
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());
814
815   // The pref value should be the one dictated by policy.
816   EXPECT_EQ(managed_value, GetPreferenceValue(kStringPrefName));
817
818   // Switch kHomePage back to unmanaged.
819   GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
820
821   // The original value should be picked up.
822   EXPECT_EQ(initial_value, GetPreferenceValue(kStringPrefName));
823 }
824
825 TEST_F(PrefServiceSyncableTest, DynamicManagedPreferencesWithSyncChange) {
826   syncer::SyncChangeList out;
827   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
828   out.clear();
829
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);
834
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());
839
840   // Change the sync value.
841   base::Value sync_value("http://example.com/sync");
842   syncer::SyncChangeList list;
843   list.push_back(
844       MakeRemoteChange(kStringPrefName, sync_value, SyncChange::ACTION_UPDATE));
845   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
846
847   // The pref value should still be the one dictated by policy.
848   EXPECT_EQ(managed_value, GetPreferenceValue(kStringPrefName));
849
850   // Switch kHomePage back to unmanaged.
851   GetTestingPrefService()->RemoveManagedPref(kStringPrefName);
852
853   // Sync value should be picked up.
854   EXPECT_EQ(sync_value, GetPreferenceValue(kStringPrefName));
855 }
856
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);
862
863   EXPECT_TRUE(IsRegistered(kStringPrefName));
864   EXPECT_TRUE(pref->IsDefaultValue());
865   EXPECT_FALSE(FindValue(kStringPrefName, out).get());
866   out.clear();
867
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());
883 }
884
885 TEST_F(PrefServiceSyncableTest, DeletePreference) {
886   prefs_.SetString(kStringPrefName, kExampleUrl0);
887   const PrefService::Preference* pref = prefs_.FindPreference(kStringPrefName);
888   EXPECT_FALSE(pref->IsDefaultValue());
889
890   InitWithNoSyncData();
891
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());
898 }
899
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 {
906  public:
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>()) {}
912
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);
927
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(),
936             pref_notifier_),
937         user_prefs_, standalone_browser_prefs_, pref_registry_, &client_,
938         /*read_error_callback=*/base::DoNothing(),
939         /*async=*/false);
940   }
941
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());
950   }
951
952   void InitSyncForAllTypes(syncer::SyncChangeList* output = nullptr) {
953     for (ModelType type : kAllPreferenceModelTypes) {
954       InitSyncForType(type, output);
955     }
956   }
957
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);
964       }
965     }
966     return registered_types;
967   }
968
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));
982   }
983
984  protected:
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_;
991 };
992
993 TEST_F(PrefServiceSyncableChromeOsTest, IsPrefRegistered) {
994   CreatePrefService();
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"));
1004
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"));
1010
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"));
1016 }
1017
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());
1025 }
1026
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());
1034 }
1035
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());
1043 }
1044
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());
1052 }
1053
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"));
1060
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"));
1067 }
1068
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"));
1075
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"));
1082 }
1083
1084 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPref) {
1085   CreatePrefService();
1086   InitSyncForAllTypes();
1087
1088   TestSyncedPrefObserver observer;
1089   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1090
1091   prefs_->SetString("os_pref", "value");
1092   EXPECT_EQ("os_pref", observer.last_pref_);
1093   EXPECT_EQ(1, observer.changed_count_);
1094
1095   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1096 }
1097
1098 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPriorityPref) {
1099   CreatePrefService();
1100   InitSyncForAllTypes();
1101
1102   TestSyncedPrefObserver observer;
1103   prefs_->AddSyncedPrefObserver("os_priority_pref", &observer);
1104
1105   prefs_->SetString("os_priority_pref", "value");
1106   EXPECT_EQ("os_priority_pref", observer.last_pref_);
1107   EXPECT_EQ(1, observer.changed_count_);
1108
1109   prefs_->RemoveSyncedPrefObserver("os_priority_pref", &observer);
1110 }
1111
1112 TEST_F(PrefServiceSyncableChromeOsTest, OsPrefChangeSyncedAsOsPrefChange) {
1113   CreatePrefService();
1114   // Set a non-default value.
1115   prefs_->SetString("os_pref", "new_value");
1116   // Start syncing.
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());
1122
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"));
1127 }
1128
1129 TEST_F(PrefServiceSyncableChromeOsTest,
1130        OsPrefChangeMakesSyncChangeForOldClients_Update) {
1131   CreatePrefService();
1132   syncer::SyncChangeList changes;
1133   InitSyncForAllTypes(&changes);
1134   EXPECT_THAT(changes, IsEmpty());
1135
1136   // Make a local change.
1137   prefs_->SetString("os_pref", "new_value");
1138
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)));
1145
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"));
1150 }
1151
1152 TEST_F(PrefServiceSyncableChromeOsTest,
1153        UpdatesFromOldClientsAreIgnored_Startup) {
1154   CreatePrefService();
1155   TestSyncedPrefObserver observer;
1156   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1157
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")));
1162
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>());
1171
1172   // No outgoing changes were triggered.
1173   EXPECT_TRUE(outgoing_changes.empty());
1174
1175   // The value from the old client was not applied.
1176   EXPECT_NE("new_value", prefs_->GetString("os_pref"));
1177
1178   // The pref is not considered to be syncing, because it still has its default
1179   // value.
1180   EXPECT_FALSE(browser_associator->IsPrefSyncedForTesting("os_pref"));
1181
1182   // Observers were not notified of changes.
1183   EXPECT_EQ(0, observer.changed_count_);
1184
1185   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1186 }
1187
1188 TEST_F(PrefServiceSyncableChromeOsTest,
1189        UpdatesFromOldClientsAreIgnored_Update) {
1190   CreatePrefService();
1191   InitSyncForAllTypes();
1192   TestSyncedPrefObserver observer;
1193   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1194
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));
1200
1201   // Simulate a sync update after startup.
1202   prefs_->GetSyncableService(syncer::PREFERENCES)
1203       ->ProcessSyncChanges(FROM_HERE, list);
1204
1205   // Update was not applied.
1206   EXPECT_NE("new_value", prefs_->GetString("os_pref"));
1207
1208   // Observers were not notified of changes.
1209   EXPECT_EQ(0, observer.changed_count_);
1210
1211   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1212 }
1213
1214 TEST_F(PrefServiceSyncableChromeOsTest,
1215        SyncedPrefObserver_OsPrefIsChangedFromSync) {
1216   CreatePrefService();
1217   prefs_->SetString("os_pref", "default_value");
1218
1219   TestSyncedPrefObserver observer;
1220   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1221
1222   TestPrefServiceSyncableObserver pref_service_sync_observer;
1223   pref_service_sync_observer.SetSyncedPrefObserver(&observer);
1224   prefs_->AddObserver(&pref_service_sync_observer);
1225
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));
1230
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>());
1238
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());
1242
1243   prefs_->RemoveObserver(&pref_service_sync_observer);
1244   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1245 }
1246
1247 TEST_F(PrefServiceSyncableChromeOsTest,
1248        SyncedPrefObserver_OsPrefIsNotChangedFromSync) {
1249   CreatePrefService();
1250   prefs_->SetString("os_pref", "default_value");
1251
1252   TestSyncedPrefObserver observer;
1253   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1254
1255   TestPrefServiceSyncableObserver pref_service_sync_observer;
1256   pref_service_sync_observer.SetSyncedPrefObserver(&observer);
1257   prefs_->AddObserver(&pref_service_sync_observer);
1258
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));
1263
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>());
1271
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());
1275
1276   prefs_->RemoveObserver(&pref_service_sync_observer);
1277   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1278 }
1279
1280 TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_EmptyCloud) {
1281   CreatePrefService();
1282   prefs_->SetString("os_pref", "new_value");
1283
1284   TestSyncedPrefObserver observer;
1285   prefs_->AddSyncedPrefObserver("os_pref", &observer);
1286
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>());
1294
1295   EXPECT_EQ("", observer.synced_pref_);
1296   EXPECT_EQ(0, observer.sync_started_count_);
1297
1298   prefs_->RemoveSyncedPrefObserver("os_pref", &observer);
1299 }
1300
1301 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1302
1303 }  // namespace
1304
1305 }  // namespace sync_preferences