Home | History | Annotate | Download | only in prefs
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/json/json_reader.h"
      6 #include "base/json/json_string_value_serializer.h"
      7 #include "base/json/json_writer.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/prefs/scoped_user_pref_update.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/prefs/pref_model_associator.h"
     12 #include "chrome/browser/prefs/pref_service_syncable.h"
     13 #include "chrome/common/pref_names.h"
     14 #include "chrome/grit/locale_settings.h"
     15 #include "chrome/test/base/testing_pref_service_syncable.h"
     16 #include "components/pref_registry/pref_registry_syncable.h"
     17 #include "sync/api/attachments/attachment_id.h"
     18 #include "sync/api/sync_change.h"
     19 #include "sync/api/sync_data.h"
     20 #include "sync/api/sync_error_factory_mock.h"
     21 #include "sync/api/syncable_service.h"
     22 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
     23 #include "sync/protocol/preference_specifics.pb.h"
     24 #include "sync/protocol/sync.pb.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 
     27 using syncer::SyncChange;
     28 using syncer::SyncData;
     29 
     30 namespace {
     31 const char kExampleUrl0[] = "http://example.com/0";
     32 const char kExampleUrl1[] = "http://example.com/1";
     33 const char kExampleUrl2[] = "http://example.com/2";
     34 const char kUnsyncedPreferenceName[] = "nonsense_pref_name";
     35 const char kUnsyncedPreferenceDefaultValue[] = "default";
     36 const char kNonDefaultCharsetValue[] = "foo";
     37 }  // namespace
     38 
     39 class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
     40  public:
     41   explicit TestSyncProcessorStub(syncer::SyncChangeList* output)
     42       : output_(output), fail_next_(false) {}
     43   virtual syncer::SyncError ProcessSyncChanges(
     44       const tracked_objects::Location& from_here,
     45       const syncer::SyncChangeList& change_list) OVERRIDE {
     46     if (output_)
     47       output_->insert(output_->end(), change_list.begin(), change_list.end());
     48     if (fail_next_) {
     49       fail_next_ = false;
     50       return syncer::SyncError(
     51           FROM_HERE, syncer::SyncError::DATATYPE_ERROR, "Error",
     52           syncer::PREFERENCES);
     53     }
     54     return syncer::SyncError();
     55   }
     56 
     57   void FailNextProcessSyncChanges() {
     58     fail_next_ = true;
     59   }
     60 
     61   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type)
     62       const OVERRIDE {
     63     return syncer::SyncDataList();
     64   }
     65  private:
     66   syncer::SyncChangeList* output_;
     67   bool fail_next_;
     68 };
     69 
     70 class PrefsSyncableServiceTest : public testing::Test {
     71  public:
     72   PrefsSyncableServiceTest() :
     73       pref_sync_service_(NULL),
     74       test_processor_(NULL),
     75       next_pref_remote_sync_node_id_(0) {}
     76 
     77   virtual void SetUp() {
     78     prefs_.registry()->RegisterStringPref(
     79         kUnsyncedPreferenceName,
     80         kUnsyncedPreferenceDefaultValue,
     81         user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
     82     prefs_.registry()->RegisterStringPref(
     83         prefs::kHomePage,
     84         std::string(),
     85         user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     86     prefs_.registry()->RegisterListPref(
     87         prefs::kURLsToRestoreOnStartup,
     88         user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     89     prefs_.registry()->RegisterListPref(
     90         prefs::kURLsToRestoreOnStartupOld,
     91         user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
     92     prefs_.registry()->RegisterLocalizedStringPref(
     93         prefs::kDefaultCharset,
     94         IDS_DEFAULT_ENCODING,
     95         user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     96 
     97     pref_sync_service_ = reinterpret_cast<PrefModelAssociator*>(
     98         prefs_.GetSyncableService(syncer::PREFERENCES));
     99     ASSERT_TRUE(pref_sync_service_);
    100     next_pref_remote_sync_node_id_ = 0;
    101   }
    102 
    103   syncer::SyncChange MakeRemoteChange(
    104       int64 id,
    105       const std::string& name,
    106       const base::Value& value,
    107       SyncChange::SyncChangeType type) {
    108     std::string serialized;
    109     JSONStringValueSerializer json(&serialized);
    110     if (!json.Serialize(value))
    111       return syncer::SyncChange();
    112     sync_pb::EntitySpecifics entity;
    113     sync_pb::PreferenceSpecifics* pref_one = entity.mutable_preference();
    114     pref_one->set_name(name);
    115     pref_one->set_value(serialized);
    116     return syncer::SyncChange(
    117         FROM_HERE,
    118         type,
    119         syncer::SyncData::CreateRemoteData(
    120             id,
    121             entity,
    122             base::Time(),
    123             syncer::AttachmentIdList(),
    124             syncer::AttachmentServiceProxyForTest::Create()));
    125   }
    126 
    127   void AddToRemoteDataList(const std::string& name,
    128                            const base::Value& value,
    129                            syncer::SyncDataList* out) {
    130     std::string serialized;
    131     JSONStringValueSerializer json(&serialized);
    132     ASSERT_TRUE(json.Serialize(value));
    133     sync_pb::EntitySpecifics one;
    134     sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
    135     pref_one->set_name(name);
    136     pref_one->set_value(serialized);
    137     out->push_back(SyncData::CreateRemoteData(
    138         ++next_pref_remote_sync_node_id_,
    139         one,
    140         base::Time(),
    141         syncer::AttachmentIdList(),
    142         syncer::AttachmentServiceProxyForTest::Create()));
    143   }
    144 
    145   void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
    146                                   syncer::SyncChangeList* output) {
    147     test_processor_ = new TestSyncProcessorStub(output);
    148     syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
    149         syncer::PREFERENCES, initial_data,
    150         scoped_ptr<syncer::SyncChangeProcessor>(test_processor_),
    151         scoped_ptr<syncer::SyncErrorFactory>(
    152             new syncer::SyncErrorFactoryMock()));
    153     EXPECT_FALSE(r.error().IsSet());
    154   }
    155 
    156   void InitWithNoSyncData() {
    157     InitWithSyncDataTakeOutput(syncer::SyncDataList(), NULL);
    158   }
    159 
    160   const base::Value& GetPreferenceValue(const std::string& name) {
    161     const PrefService::Preference* preference =
    162         prefs_.FindPreference(name.c_str());
    163     return *preference->GetValue();
    164   }
    165 
    166   scoped_ptr<base::Value> FindValue(const std::string& name,
    167       const syncer::SyncChangeList& list) {
    168     syncer::SyncChangeList::const_iterator it = list.begin();
    169     for (; it != list.end(); ++it) {
    170       if (syncer::SyncDataLocal(it->sync_data()).GetTag() == name) {
    171         return make_scoped_ptr(base::JSONReader::Read(
    172             it->sync_data().GetSpecifics().preference().value()));
    173       }
    174     }
    175     return scoped_ptr<base::Value>();
    176   }
    177 
    178   bool IsSynced(const std::string& pref_name) {
    179     return pref_sync_service_->registered_preferences().count(pref_name) > 0;
    180   }
    181 
    182   bool HasSyncData(const std::string& pref_name) {
    183     return pref_sync_service_->IsPrefSynced(pref_name);
    184   }
    185 
    186   // Returns whether a given preference name is a new name of a migrated
    187   // preference. Exposed here for testing.
    188   static bool IsMigratedPreference(const char* preference_name) {
    189     return PrefModelAssociator::IsMigratedPreference(preference_name);
    190   }
    191   static bool IsOldMigratedPreference(const char* old_preference_name) {
    192     return PrefModelAssociator::IsOldMigratedPreference(old_preference_name);
    193   }
    194 
    195   PrefService* GetPrefs() { return &prefs_; }
    196   TestingPrefServiceSyncable* GetTestingPrefService() { return &prefs_; }
    197 
    198  protected:
    199   TestingPrefServiceSyncable prefs_;
    200 
    201   PrefModelAssociator* pref_sync_service_;
    202   TestSyncProcessorStub* test_processor_;
    203 
    204   // TODO(tim): Remove this by fixing AttachmentServiceProxyForTest.
    205   base::MessageLoop loop_;
    206 
    207   int next_pref_remote_sync_node_id_;
    208 };
    209 
    210 TEST_F(PrefsSyncableServiceTest, CreatePrefSyncData) {
    211   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    212 
    213   const PrefService::Preference* pref =
    214       prefs_.FindPreference(prefs::kHomePage);
    215   syncer::SyncData sync_data;
    216   EXPECT_TRUE(pref_sync_service_->CreatePrefSyncData(pref->name(),
    217       *pref->GetValue(), &sync_data));
    218   EXPECT_EQ(std::string(prefs::kHomePage),
    219             syncer::SyncDataLocal(sync_data).GetTag());
    220   const sync_pb::PreferenceSpecifics& specifics(sync_data.GetSpecifics().
    221       preference());
    222   EXPECT_EQ(std::string(prefs::kHomePage), specifics.name());
    223 
    224   scoped_ptr<base::Value> value(base::JSONReader::Read(specifics.value()));
    225   EXPECT_TRUE(pref->GetValue()->Equals(value.get()));
    226 }
    227 
    228 TEST_F(PrefsSyncableServiceTest, ModelAssociationDoNotSyncDefaults) {
    229   const PrefService::Preference* pref =
    230       prefs_.FindPreference(prefs::kHomePage);
    231   EXPECT_TRUE(pref->IsDefaultValue());
    232   syncer::SyncChangeList out;
    233   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    234 
    235   EXPECT_TRUE(IsSynced(prefs::kHomePage));
    236   EXPECT_TRUE(pref->IsDefaultValue());
    237   EXPECT_FALSE(FindValue(prefs::kHomePage, out).get());
    238 }
    239 
    240 TEST_F(PrefsSyncableServiceTest, ModelAssociationEmptyCloud) {
    241   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    242   {
    243     ListPrefUpdate update(GetPrefs(), prefs::kURLsToRestoreOnStartup);
    244     base::ListValue* url_list = update.Get();
    245     url_list->Append(new base::StringValue(kExampleUrl0));
    246     url_list->Append(new base::StringValue(kExampleUrl1));
    247   }
    248   syncer::SyncChangeList out;
    249   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    250 
    251   scoped_ptr<base::Value> value(FindValue(prefs::kHomePage, out));
    252   ASSERT_TRUE(value.get());
    253   EXPECT_TRUE(GetPreferenceValue(prefs::kHomePage).Equals(value.get()));
    254   value = FindValue(prefs::kURLsToRestoreOnStartup, out).Pass();
    255   ASSERT_TRUE(value.get());
    256   EXPECT_TRUE(
    257       GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get()));
    258 }
    259 
    260 TEST_F(PrefsSyncableServiceTest, ModelAssociationCloudHasData) {
    261   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    262   {
    263     ListPrefUpdate update(GetPrefs(), prefs::kURLsToRestoreOnStartup);
    264     base::ListValue* url_list = update.Get();
    265     url_list->Append(new base::StringValue(kExampleUrl0));
    266     url_list->Append(new base::StringValue(kExampleUrl1));
    267   }
    268 
    269   syncer::SyncDataList in;
    270   syncer::SyncChangeList out;
    271   AddToRemoteDataList(prefs::kHomePage, base::StringValue(kExampleUrl1), &in);
    272   base::ListValue urls_to_restore;
    273   urls_to_restore.Append(new base::StringValue(kExampleUrl1));
    274   urls_to_restore.Append(new base::StringValue(kExampleUrl2));
    275   AddToRemoteDataList(prefs::kURLsToRestoreOnStartup, urls_to_restore, &in);
    276   AddToRemoteDataList(prefs::kDefaultCharset,
    277                       base::StringValue(kNonDefaultCharsetValue),
    278                       &in);
    279   InitWithSyncDataTakeOutput(in, &out);
    280 
    281   ASSERT_FALSE(FindValue(prefs::kHomePage, out).get());
    282   ASSERT_FALSE(FindValue(prefs::kDefaultCharset, out).get());
    283 
    284   EXPECT_EQ(kExampleUrl1, prefs_.GetString(prefs::kHomePage));
    285 
    286   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
    287   expected_urls->Append(new base::StringValue(kExampleUrl1));
    288   expected_urls->Append(new base::StringValue(kExampleUrl2));
    289   expected_urls->Append(new base::StringValue(kExampleUrl0));
    290   scoped_ptr<base::Value> value(
    291       FindValue(prefs::kURLsToRestoreOnStartup, out));
    292   ASSERT_TRUE(value.get());
    293   EXPECT_TRUE(value->Equals(expected_urls.get()));
    294   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
    295               Equals(expected_urls.get()));
    296   EXPECT_EQ(kNonDefaultCharsetValue,
    297             prefs_.GetString(prefs::kDefaultCharset));
    298 }
    299 
    300 TEST_F(PrefsSyncableServiceTest, ModelAssociationMigrateOldData) {
    301   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
    302   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
    303 
    304   syncer::SyncDataList in;
    305   syncer::SyncChangeList out;
    306   base::ListValue urls_to_restore;
    307   urls_to_restore.Append(new base::StringValue(kExampleUrl1));
    308   urls_to_restore.Append(new base::StringValue(kExampleUrl2));
    309   AddToRemoteDataList(prefs::kURLsToRestoreOnStartupOld, urls_to_restore,
    310                       &in);
    311   InitWithSyncDataTakeOutput(in, &out);
    312 
    313   // Expect that the new preference data contains the old pref's values.
    314   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
    315   expected_urls->Append(new base::StringValue(kExampleUrl1));
    316   expected_urls->Append(new base::StringValue(kExampleUrl2));
    317 
    318   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
    319   scoped_ptr<base::Value> value(
    320       FindValue(prefs::kURLsToRestoreOnStartup, out));
    321   ASSERT_TRUE(value.get());
    322   EXPECT_TRUE(value->Equals(expected_urls.get()));
    323   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
    324               Equals(expected_urls.get()));
    325 
    326   // The old preference value should be the same.
    327   expected_urls.reset(new base::ListValue);
    328   ASSERT_FALSE(FindValue(prefs::kURLsToRestoreOnStartupOld, out).get());
    329   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
    330               Equals(expected_urls.get()));
    331 }
    332 
    333 TEST_F(PrefsSyncableServiceTest,
    334        ModelAssociationCloudHasOldMigratedData) {
    335   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
    336   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
    337   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    338   {
    339     ListPrefUpdate update(GetPrefs(), prefs::kURLsToRestoreOnStartup);
    340     base::ListValue* url_list = update.Get();
    341     url_list->Append(new base::StringValue(kExampleUrl0));
    342     url_list->Append(new base::StringValue(kExampleUrl1));
    343   }
    344 
    345   syncer::SyncDataList in;
    346   syncer::SyncChangeList out;
    347   base::ListValue urls_to_restore;
    348   urls_to_restore.Append(new base::StringValue(kExampleUrl1));
    349   urls_to_restore.Append(new base::StringValue(kExampleUrl2));
    350   AddToRemoteDataList(prefs::kURLsToRestoreOnStartupOld, urls_to_restore, &in);
    351   AddToRemoteDataList(prefs::kHomePage, base::StringValue(kExampleUrl1), &in);
    352   InitWithSyncDataTakeOutput(in, &out);
    353 
    354   ASSERT_FALSE(FindValue(prefs::kHomePage, out).get());
    355 
    356   // Expect that the new preference data contains the merged old prefs values.
    357   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
    358   expected_urls->Append(new base::StringValue(kExampleUrl1));
    359   expected_urls->Append(new base::StringValue(kExampleUrl2));
    360   expected_urls->Append(new base::StringValue(kExampleUrl0));
    361 
    362   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
    363   scoped_ptr<base::Value> value(
    364       FindValue(prefs::kURLsToRestoreOnStartup, out));
    365   ASSERT_TRUE(value.get());
    366   EXPECT_TRUE(value->Equals(expected_urls.get()));
    367   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
    368               Equals(expected_urls.get()));
    369 
    370   expected_urls.reset(new base::ListValue);
    371   value = FindValue(prefs::kURLsToRestoreOnStartupOld, out).Pass();
    372   ASSERT_TRUE(value.get());
    373   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
    374               Equals(expected_urls.get()));
    375 }
    376 
    377 TEST_F(PrefsSyncableServiceTest,
    378        ModelAssociationCloudHasNewMigratedData) {
    379   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
    380   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
    381   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    382   {
    383     ListPrefUpdate update(GetPrefs(), prefs::kURLsToRestoreOnStartupOld);
    384     base::ListValue* url_list = update.Get();
    385     url_list->Append(new base::StringValue(kExampleUrl0));
    386     url_list->Append(new base::StringValue(kExampleUrl1));
    387   }
    388 
    389   syncer::SyncDataList in;
    390   syncer::SyncChangeList out;
    391   base::ListValue urls_to_restore;
    392   urls_to_restore.Append(new base::StringValue(kExampleUrl1));
    393   urls_to_restore.Append(new base::StringValue(kExampleUrl2));
    394   AddToRemoteDataList(prefs::kURLsToRestoreOnStartupOld, urls_to_restore, &in);
    395   AddToRemoteDataList(prefs::kHomePage, base::StringValue(kExampleUrl1), &in);
    396   InitWithSyncDataTakeOutput(in, &out);
    397 
    398   scoped_ptr<base::Value> value(FindValue(prefs::kHomePage, out));
    399   ASSERT_FALSE(value.get());
    400 
    401   // Expect that the cloud data under the new migrated preference name sticks.
    402   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
    403   expected_urls->Append(new base::StringValue(kExampleUrl1));
    404   expected_urls->Append(new base::StringValue(kExampleUrl2));
    405 
    406   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
    407   value = FindValue(prefs::kURLsToRestoreOnStartup, out).Pass();
    408   ASSERT_TRUE(value.get());
    409   EXPECT_TRUE(value->Equals(expected_urls.get()));
    410   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
    411               Equals(expected_urls.get()));
    412 
    413   // The old preference data should still be here, though not synced.
    414   expected_urls.reset(new base::ListValue);
    415   expected_urls->Append(new base::StringValue(kExampleUrl0));
    416   expected_urls->Append(new base::StringValue(kExampleUrl1));
    417 
    418   value = FindValue(prefs::kURLsToRestoreOnStartupOld, out).Pass();
    419   ASSERT_FALSE(value.get());
    420   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
    421               Equals(expected_urls.get()));
    422 }
    423 
    424 TEST_F(PrefsSyncableServiceTest,
    425        ModelAssociationCloudAddsOldAndNewMigratedData) {
    426   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
    427   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
    428   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    429   {
    430     ListPrefUpdate update_old(GetPrefs(), prefs::kURLsToRestoreOnStartupOld);
    431     base::ListValue* url_list_old = update_old.Get();
    432     url_list_old->Append(new base::StringValue(kExampleUrl0));
    433     url_list_old->Append(new base::StringValue(kExampleUrl1));
    434     ListPrefUpdate update(GetPrefs(), prefs::kURLsToRestoreOnStartup);
    435     base::ListValue* url_list = update.Get();
    436     url_list->Append(new base::StringValue(kExampleUrl1));
    437     url_list->Append(new base::StringValue(kExampleUrl2));
    438   }
    439 
    440   syncer::SyncDataList in;
    441   syncer::SyncChangeList out;
    442   AddToRemoteDataList(prefs::kHomePage, base::StringValue(kExampleUrl1), &in);
    443   InitWithSyncDataTakeOutput(in, &out);
    444 
    445   scoped_ptr<base::Value> value(FindValue(prefs::kHomePage, out));
    446   ASSERT_FALSE(value.get());
    447 
    448   // Expect that the cloud data under the new migrated preference name sticks.
    449   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
    450   expected_urls->Append(new base::StringValue(kExampleUrl1));
    451   expected_urls->Append(new base::StringValue(kExampleUrl2));
    452 
    453   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
    454   value = FindValue(prefs::kURLsToRestoreOnStartup, out).Pass();
    455   ASSERT_TRUE(value.get());
    456   EXPECT_TRUE(value->Equals(expected_urls.get()));
    457   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
    458               Equals(expected_urls.get()));
    459 
    460   // Should not have synced in the old startup url values.
    461   value = FindValue(prefs::kURLsToRestoreOnStartupOld, out).Pass();
    462   ASSERT_FALSE(value.get());
    463   EXPECT_FALSE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
    464                Equals(expected_urls.get()));
    465 }
    466 
    467 TEST_F(PrefsSyncableServiceTest, FailModelAssociation) {
    468   syncer::SyncChangeList output;
    469   TestSyncProcessorStub* stub = new TestSyncProcessorStub(&output);
    470   stub->FailNextProcessSyncChanges();
    471   syncer::SyncMergeResult r = pref_sync_service_->MergeDataAndStartSyncing(
    472       syncer::PREFERENCES, syncer::SyncDataList(),
    473       scoped_ptr<syncer::SyncChangeProcessor>(stub),
    474       scoped_ptr<syncer::SyncErrorFactory>(
    475           new syncer::SyncErrorFactoryMock()));
    476   EXPECT_TRUE(r.error().IsSet());
    477 }
    478 
    479 TEST_F(PrefsSyncableServiceTest, UpdatedPreferenceWithDefaultValue) {
    480   const PrefService::Preference* pref =
    481       prefs_.FindPreference(prefs::kHomePage);
    482   EXPECT_TRUE(pref->IsDefaultValue());
    483 
    484   syncer::SyncChangeList out;
    485   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    486   out.clear();
    487 
    488   base::StringValue expected(kExampleUrl0);
    489   GetPrefs()->Set(prefs::kHomePage, expected);
    490 
    491   scoped_ptr<base::Value> actual(FindValue(prefs::kHomePage, out));
    492   ASSERT_TRUE(actual.get());
    493   EXPECT_TRUE(expected.Equals(actual.get()));
    494 }
    495 
    496 TEST_F(PrefsSyncableServiceTest, UpdatedPreferenceWithValue) {
    497   GetPrefs()->SetString(prefs::kHomePage, kExampleUrl0);
    498   syncer::SyncChangeList out;
    499   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    500   out.clear();
    501 
    502   base::StringValue expected(kExampleUrl1);
    503   GetPrefs()->Set(prefs::kHomePage, expected);
    504 
    505   scoped_ptr<base::Value> actual(FindValue(prefs::kHomePage, out));
    506   ASSERT_TRUE(actual.get());
    507   EXPECT_TRUE(expected.Equals(actual.get()));
    508 }
    509 
    510 TEST_F(PrefsSyncableServiceTest, UpdatedSyncNodeActionUpdate) {
    511   GetPrefs()->SetString(prefs::kHomePage, kExampleUrl0);
    512   InitWithNoSyncData();
    513 
    514   base::StringValue expected(kExampleUrl1);
    515   syncer::SyncChangeList list;
    516   list.push_back(MakeRemoteChange(
    517       1, prefs::kHomePage, expected, SyncChange::ACTION_UPDATE));
    518   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    519 
    520   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
    521   EXPECT_TRUE(expected.Equals(&actual));
    522 }
    523 
    524 TEST_F(PrefsSyncableServiceTest, UpdatedSyncNodeActionAdd) {
    525   InitWithNoSyncData();
    526 
    527   base::StringValue expected(kExampleUrl0);
    528   syncer::SyncChangeList list;
    529   list.push_back(MakeRemoteChange(
    530       1, prefs::kHomePage, expected, SyncChange::ACTION_ADD));
    531   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    532 
    533   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
    534   EXPECT_TRUE(expected.Equals(&actual));
    535   EXPECT_EQ(1U,
    536       pref_sync_service_->registered_preferences().count(prefs::kHomePage));
    537 }
    538 
    539 TEST_F(PrefsSyncableServiceTest, UpdatedSyncNodeUnknownPreference) {
    540   InitWithNoSyncData();
    541   syncer::SyncChangeList list;
    542   base::StringValue expected(kExampleUrl0);
    543   list.push_back(MakeRemoteChange(
    544       1, "unknown preference", expected, SyncChange::ACTION_UPDATE));
    545   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    546   // Nothing interesting happens on the client when it gets an update
    547   // of an unknown preference.  We just should not crash.
    548 }
    549 
    550 TEST_F(PrefsSyncableServiceTest, ManagedPreferences) {
    551   // Make the homepage preference managed.
    552   base::StringValue managed_value("http://example.com");
    553   prefs_.SetManagedPref(prefs::kHomePage, managed_value.DeepCopy());
    554 
    555   syncer::SyncChangeList out;
    556   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    557   out.clear();
    558 
    559   // Changing the homepage preference should not sync anything.
    560   base::StringValue user_value("http://chromium..com");
    561   prefs_.SetUserPref(prefs::kHomePage, user_value.DeepCopy());
    562   EXPECT_TRUE(out.empty());
    563 
    564   // An incoming sync transaction should change the user value, not the managed
    565   // value.
    566   base::StringValue sync_value("http://crbug.com");
    567   syncer::SyncChangeList list;
    568   list.push_back(MakeRemoteChange(
    569       1, prefs::kHomePage, sync_value, SyncChange::ACTION_UPDATE));
    570   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    571 
    572   EXPECT_TRUE(managed_value.Equals(prefs_.GetManagedPref(prefs::kHomePage)));
    573   EXPECT_TRUE(sync_value.Equals(prefs_.GetUserPref(prefs::kHomePage)));
    574 }
    575 
    576 // List preferences have special handling at association time due to our ability
    577 // to merge the local and sync value. Make sure the merge logic doesn't merge
    578 // managed preferences.
    579 TEST_F(PrefsSyncableServiceTest, ManagedListPreferences) {
    580   // Make the list of urls to restore on startup managed.
    581   base::ListValue managed_value;
    582   managed_value.Append(new base::StringValue(kExampleUrl0));
    583   managed_value.Append(new base::StringValue(kExampleUrl1));
    584   prefs_.SetManagedPref(prefs::kURLsToRestoreOnStartup,
    585                          managed_value.DeepCopy());
    586 
    587   // Set a cloud version.
    588   syncer::SyncDataList in;
    589   syncer::SyncChangeList out;
    590   base::ListValue urls_to_restore;
    591   urls_to_restore.Append(new base::StringValue(kExampleUrl1));
    592   urls_to_restore.Append(new base::StringValue(kExampleUrl2));
    593   AddToRemoteDataList(prefs::kURLsToRestoreOnStartup, urls_to_restore, &in);
    594 
    595   // Start sync and verify the synced value didn't get merged.
    596   InitWithSyncDataTakeOutput(in, &out);
    597   EXPECT_FALSE(FindValue(prefs::kURLsToRestoreOnStartup, out).get());
    598   out.clear();
    599 
    600   // Changing the user's urls to restore on startup pref should not sync
    601   // anything.
    602   base::ListValue user_value;
    603   user_value.Append(new base::StringValue("http://chromium.org"));
    604   prefs_.SetUserPref(prefs::kURLsToRestoreOnStartup, user_value.DeepCopy());
    605   EXPECT_FALSE(FindValue(prefs::kURLsToRestoreOnStartup, out).get());
    606 
    607   // An incoming sync transaction should change the user value, not the managed
    608   // value.
    609   base::ListValue sync_value;
    610   sync_value.Append(new base::StringValue("http://crbug.com"));
    611   syncer::SyncChangeList list;
    612   list.push_back(MakeRemoteChange(
    613       1, prefs::kURLsToRestoreOnStartup, sync_value,
    614       SyncChange::ACTION_UPDATE));
    615   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    616 
    617   EXPECT_TRUE(managed_value.Equals(
    618           prefs_.GetManagedPref(prefs::kURLsToRestoreOnStartup)));
    619   EXPECT_TRUE(sync_value.Equals(
    620           prefs_.GetUserPref(prefs::kURLsToRestoreOnStartup)));
    621 }
    622 
    623 TEST_F(PrefsSyncableServiceTest, DynamicManagedPreferences) {
    624   syncer::SyncChangeList out;
    625   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    626   out.clear();
    627   base::StringValue initial_value("http://example.com/initial");
    628   GetPrefs()->Set(prefs::kHomePage, initial_value);
    629   scoped_ptr<base::Value> actual(FindValue(prefs::kHomePage, out));
    630   ASSERT_TRUE(actual.get());
    631   EXPECT_TRUE(initial_value.Equals(actual.get()));
    632 
    633   // Switch kHomePage to managed and set a different value.
    634   base::StringValue managed_value("http://example.com/managed");
    635   GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
    636                                                     managed_value.DeepCopy());
    637 
    638   // The pref value should be the one dictated by policy.
    639   EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
    640 
    641   // Switch kHomePage back to unmanaged.
    642   GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
    643 
    644   // The original value should be picked up.
    645   EXPECT_TRUE(initial_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
    646 }
    647 
    648 TEST_F(PrefsSyncableServiceTest,
    649        DynamicManagedPreferencesWithSyncChange) {
    650   syncer::SyncChangeList out;
    651   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    652   out.clear();
    653 
    654   base::StringValue initial_value("http://example.com/initial");
    655   GetPrefs()->Set(prefs::kHomePage, initial_value);
    656   scoped_ptr<base::Value> actual(FindValue(prefs::kHomePage, out));
    657   EXPECT_TRUE(initial_value.Equals(actual.get()));
    658 
    659   // Switch kHomePage to managed and set a different value.
    660   base::StringValue managed_value("http://example.com/managed");
    661   GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
    662                                                     managed_value.DeepCopy());
    663 
    664   // Change the sync value.
    665   base::StringValue sync_value("http://example.com/sync");
    666   syncer::SyncChangeList list;
    667   list.push_back(MakeRemoteChange(
    668       1, prefs::kHomePage, sync_value, SyncChange::ACTION_UPDATE));
    669   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    670 
    671   // The pref value should still be the one dictated by policy.
    672   EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
    673 
    674   // Switch kHomePage back to unmanaged.
    675   GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
    676 
    677   // Sync value should be picked up.
    678   EXPECT_TRUE(sync_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
    679 }
    680 
    681 TEST_F(PrefsSyncableServiceTest, DynamicManagedDefaultPreferences) {
    682   const PrefService::Preference* pref =
    683       prefs_.FindPreference(prefs::kHomePage);
    684   EXPECT_TRUE(pref->IsDefaultValue());
    685   syncer::SyncChangeList out;
    686   InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out);
    687 
    688   EXPECT_TRUE(IsSynced(prefs::kHomePage));
    689   EXPECT_TRUE(pref->IsDefaultValue());
    690   EXPECT_FALSE(FindValue(prefs::kHomePage, out).get());
    691   out.clear();
    692 
    693   // Switch kHomePage to managed and set a different value.
    694   base::StringValue managed_value("http://example.com/managed");
    695   GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
    696                                           managed_value.DeepCopy());
    697   // The pref value should be the one dictated by policy.
    698   EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
    699   EXPECT_FALSE(pref->IsDefaultValue());
    700   // There should be no synced value.
    701   EXPECT_FALSE(FindValue(prefs::kHomePage, out).get());
    702   // Switch kHomePage back to unmanaged.
    703   GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
    704   // The original value should be picked up.
    705   EXPECT_TRUE(pref->IsDefaultValue());
    706   // There should still be no synced value.
    707   EXPECT_FALSE(FindValue(prefs::kHomePage, out).get());
    708 }
    709 
    710 TEST_F(PrefsSyncableServiceTest, DeletePreference) {
    711   prefs_.SetString(prefs::kHomePage, kExampleUrl0);
    712   const PrefService::Preference* pref =
    713       prefs_.FindPreference(prefs::kHomePage);
    714   EXPECT_FALSE(pref->IsDefaultValue());
    715 
    716   InitWithNoSyncData();
    717 
    718   scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
    719   syncer::SyncChangeList list;
    720   list.push_back(MakeRemoteChange(
    721       1, prefs::kHomePage, *null_value, SyncChange::ACTION_DELETE));
    722   pref_sync_service_->ProcessSyncChanges(FROM_HERE, list);
    723   EXPECT_TRUE(pref->IsDefaultValue());
    724 }
    725