bd3bd7c6c9a60124fcefeacac807c69c9768099e
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / profile_sync_service_preference_unittest.cc
1 // Copyright (c) 2012 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 <map>
6 #include <string>
7
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/json/json_reader.h"
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/json/json_writer.h"
14 #include "base/location.h"
15 #include "base/prefs/scoped_user_pref_update.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_piece.h"
18 #include "chrome/browser/invalidation/invalidation_service_factory.h"
19 #include "chrome/browser/prefs/pref_model_associator.h"
20 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
21 #include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
22 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
23 #include "chrome/browser/signin/signin_manager.h"
24 #include "chrome/browser/signin/signin_manager_factory.h"
25 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
26 #include "chrome/browser/sync/glue/generic_change_processor.h"
27 #include "chrome/browser/sync/glue/sync_backend_host.h"
28 #include "chrome/browser/sync/glue/ui_data_type_controller.h"
29 #include "chrome/browser/sync/profile_sync_service_factory.h"
30 #include "chrome/browser/sync/profile_sync_test_util.h"
31 #include "chrome/browser/sync/test_profile_sync_service.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/test/base/testing_pref_service_syncable.h"
34 #include "chrome/test/base/testing_profile.h"
35 #include "components/user_prefs/pref_registry_syncable.h"
36 #include "google_apis/gaia/gaia_constants.h"
37 #include "sync/api/sync_data.h"
38 #include "sync/internal_api/public/base/model_type.h"
39 #include "sync/internal_api/public/change_record.h"
40 #include "sync/internal_api/public/data_type_debug_info_listener.h"
41 #include "sync/internal_api/public/read_node.h"
42 #include "sync/internal_api/public/read_transaction.h"
43 #include "sync/internal_api/public/write_node.h"
44 #include "sync/internal_api/public/write_transaction.h"
45 #include "sync/protocol/preference_specifics.pb.h"
46 #include "testing/gmock/include/gmock/gmock.h"
47 #include "testing/gtest/include/gtest/gtest.h"
48
49 using base::JSONReader;
50 using browser_sync::GenericChangeProcessor;
51 using browser_sync::SharedChangeProcessor;
52 using browser_sync::UIDataTypeController;
53 using syncer::ChangeRecord;
54 using testing::_;
55 using testing::Invoke;
56 using testing::Return;
57
58 typedef std::map<const std::string, const base::Value*> PreferenceValues;
59
60 ACTION_P(CreateAndSaveChangeProcessor, change_processor) {
61   syncer::UserShare* user_share = arg0->GetUserShare();
62   *change_processor = new GenericChangeProcessor(arg1,
63                                                  arg2,
64                                                  arg3,
65                                                  user_share);
66   return *change_processor;
67 }
68
69 ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) {
70   return new browser_sync::DataTypeManagerImpl(
71       debug_listener,
72       arg1,
73       arg2,
74       arg3,
75       arg4,
76       arg5);
77 }
78
79 // TODO(zea): Refactor to remove the ProfileSyncService usage.
80 class ProfileSyncServicePreferenceTest
81     : public AbstractProfileSyncServiceTest,
82       public syncer::DataTypeDebugInfoListener {
83  public:
84   int64 SetSyncedValue(const std::string& name, const base::Value& value) {
85     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
86     syncer::ReadNode root(&trans);
87     if (root.InitByTagLookup(syncer::ModelTypeToRootTag(
88             syncer::PREFERENCES)) != syncer::BaseNode::INIT_OK) {
89       return syncer::kInvalidId;
90     }
91
92     syncer::WriteNode tag_node(&trans);
93     syncer::WriteNode node(&trans);
94
95     if (tag_node.InitByClientTagLookup(syncer::PREFERENCES, name) ==
96             syncer::BaseNode::INIT_OK) {
97       return WriteSyncedValue(name, value, &tag_node);
98     }
99
100     syncer::WriteNode::InitUniqueByCreationResult result =
101         node.InitUniqueByCreation(syncer::PREFERENCES, root, name);
102     if (result == syncer::WriteNode::INIT_SUCCESS)
103       return WriteSyncedValue(name, value, &node);
104
105     return syncer::kInvalidId;
106   }
107
108   // DataTypeDebugInfoListener implementation.
109   virtual void OnDataTypeConfigureComplete(
110       const std::vector<syncer::DataTypeConfigurationStats>&
111           configuration_stats) OVERRIDE {
112     ASSERT_EQ(1u, configuration_stats.size());
113     association_stats_ = configuration_stats[0].association_stats;
114   }
115
116  protected:
117   ProfileSyncServicePreferenceTest()
118       : debug_ptr_factory_(this),
119         example_url0_("http://example.com/0"),
120         example_url1_("http://example.com/1"),
121         example_url2_("http://example.com/2"),
122         not_synced_preference_name_("nonsense_pref_name"),
123         not_synced_preference_default_value_("default"),
124         non_default_charset_value_("foo") {}
125
126   virtual void SetUp() {
127     AbstractProfileSyncServiceTest::SetUp();
128     TestingProfile::Builder builder;
129     builder.AddTestingFactory(
130         ProfileOAuth2TokenServiceFactory::GetInstance(),
131         FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
132     profile_ = builder.Build().Pass();
133     invalidation::InvalidationServiceFactory::GetInstance()->
134         SetBuildOnlyFakeInvalidatorsForTest(true);
135     prefs_ = profile_->GetTestingPrefService();
136
137     prefs_->registry()->RegisterStringPref(
138         not_synced_preference_name_.c_str(),
139         not_synced_preference_default_value_,
140         user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
141   }
142
143   virtual void TearDown() {
144     profile_.reset();
145     AbstractProfileSyncServiceTest::TearDown();
146   }
147
148   int GetSyncPreferenceCount() {
149     syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
150     syncer::ReadNode node(&trans);
151     if (node.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::PREFERENCES)) !=
152         syncer::BaseNode::INIT_OK)
153       return 0;
154     return node.GetTotalNodeCount() - 1;
155   }
156
157   bool StartSyncService(const base::Closure& callback,
158                         bool will_fail_association) {
159     if (sync_service_)
160       return false;
161
162     SigninManagerBase* signin =
163          SigninManagerFactory::GetForProfile(profile_.get());
164     signin->SetAuthenticatedUsername("test");
165     sync_service_ = TestProfileSyncService::BuildAutoStartAsyncInit(
166         profile_.get(), callback);
167     pref_sync_service_ = reinterpret_cast<PrefModelAssociator*>(
168         prefs_->GetSyncableService(syncer::PREFERENCES));
169     if (!pref_sync_service_)
170       return false;
171     ProfileSyncComponentsFactoryMock* components =
172         sync_service_->components_factory_mock();
173     EXPECT_CALL(*components, GetSyncableServiceForType(syncer::PREFERENCES)).
174         WillOnce(Return(pref_sync_service_->AsWeakPtr()));
175
176     EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)).
177         WillOnce(ReturnNewDataTypeManagerWithDebugListener(
178                      syncer::MakeWeakHandle(debug_ptr_factory_.GetWeakPtr())));
179     dtc_ = new UIDataTypeController(base::MessageLoopProxy::current(),
180                                     base::Closure(),
181                                     syncer::PREFERENCES,
182                                     components,
183                                     profile_.get(),
184                                     sync_service_);
185     EXPECT_CALL(*components, CreateSharedChangeProcessor()).
186         WillOnce(Return(new SharedChangeProcessor()));
187     EXPECT_CALL(*components, CreateGenericChangeProcessor(_, _, _, _)).
188         WillOnce(CreateAndSaveChangeProcessor(
189                      &change_processor_));
190     sync_service_->RegisterDataTypeController(dtc_);
191     ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
192         ->UpdateCredentials("test", "oauth2_login_token");
193
194     sync_service_->Initialize();
195     base::MessageLoop::current()->Run();
196
197     // It's possible this test triggered an unrecoverable error, in which case
198     // we can't get the preference count.
199     if (sync_service_->ShouldPushChanges()) {
200         EXPECT_EQ(GetSyncPreferenceCount(),
201                   association_stats_.num_sync_items_after_association);
202     }
203     EXPECT_EQ(association_stats_.num_sync_items_after_association,
204               association_stats_.num_sync_items_before_association +
205               association_stats_.num_sync_items_added -
206               association_stats_.num_sync_items_deleted);
207
208     return true;
209   }
210
211   const base::Value& GetPreferenceValue(const std::string& name) {
212     const PrefService::Preference* preference =
213         prefs_->FindPreference(name.c_str());
214     return *preference->GetValue();
215   }
216
217   // Caller gets ownership of the returned value.
218   const base::Value* GetSyncedValue(const std::string& name) {
219     syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
220     syncer::ReadNode node(&trans);
221
222     if (node.InitByClientTagLookup(syncer::PREFERENCES, name) !=
223             syncer::BaseNode::INIT_OK) {
224       return NULL;
225     }
226
227     const sync_pb::PreferenceSpecifics& specifics(
228         node.GetEntitySpecifics().preference());
229
230     return base::JSONReader::Read(specifics.value());
231   }
232
233   int64 WriteSyncedValue(const std::string& name,
234                          const base::Value& value,
235                          syncer::WriteNode* node) {
236     syncer::SyncData sync_data;
237     if (!pref_sync_service_->CreatePrefSyncData(name,
238                                                 value,
239                                                 &sync_data)) {
240       return syncer::kInvalidId;
241     }
242     node->SetEntitySpecifics(sync_data.GetSpecifics());
243     return node->GetId();
244   }
245
246   bool IsSynced(const std::string& pref_name) {
247     return pref_sync_service_->registered_preferences().count(pref_name) > 0;
248   }
249
250   bool HasSyncData(const std::string& pref_name) {
251     return pref_sync_service_->IsPrefSynced(pref_name);
252   }
253
254   std::string ValueString(const base::Value& value) {
255     std::string serialized;
256     JSONStringValueSerializer json(&serialized);
257     json.Serialize(value);
258     return serialized;
259   }
260
261   // Returns whether a given preference name is a new name of a migrated
262   // preference. Exposed here for testing.
263   static bool IsMigratedPreference(const char* preference_name) {
264     return PrefModelAssociator::IsMigratedPreference(preference_name);
265   }
266   static bool IsOldMigratedPreference(const char* old_preference_name) {
267     return PrefModelAssociator::IsOldMigratedPreference(old_preference_name);
268   }
269
270   scoped_ptr<TestingProfile> profile_;
271   TestingPrefServiceSyncable* prefs_;
272
273   UIDataTypeController* dtc_;
274   PrefModelAssociator* pref_sync_service_;
275   GenericChangeProcessor* change_processor_;
276   syncer::DataTypeAssociationStats association_stats_;
277   base::WeakPtrFactory<DataTypeDebugInfoListener> debug_ptr_factory_;
278
279   std::string example_url0_;
280   std::string example_url1_;
281   std::string example_url2_;
282   std::string not_synced_preference_name_;
283   std::string not_synced_preference_default_value_;
284   std::string non_default_charset_value_;
285 };
286
287 class AddPreferenceEntriesHelper {
288  public:
289   AddPreferenceEntriesHelper(ProfileSyncServicePreferenceTest* test,
290                              const PreferenceValues& entries)
291       : callback_(base::Bind(
292             &AddPreferenceEntriesHelper::AddPreferenceEntriesCallback,
293             base::Unretained(this), test, entries)),
294         success_(false) {
295   }
296
297   const base::Closure& callback() const { return callback_; }
298   bool success() { return success_; }
299
300  private:
301   void AddPreferenceEntriesCallback(ProfileSyncServicePreferenceTest* test,
302                                     const PreferenceValues& entries) {
303     if (!test->CreateRoot(syncer::PREFERENCES))
304       return;
305
306     for (PreferenceValues::const_iterator i = entries.begin();
307          i != entries.end(); ++i) {
308       if (test->SetSyncedValue(i->first, *i->second) == syncer::kInvalidId)
309         return;
310     }
311     success_ = true;
312   }
313
314   base::Closure callback_;
315   bool success_;
316 };
317
318 TEST_F(ProfileSyncServicePreferenceTest, CreatePrefSyncData) {
319   prefs_->SetString(prefs::kHomePage, example_url0_);
320   CreateRootHelper create_root(this, syncer::PREFERENCES);
321   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
322   ASSERT_TRUE(create_root.success());
323
324   const PrefService::Preference* pref =
325       prefs_->FindPreference(prefs::kHomePage);
326   syncer::SyncData sync_data;
327   EXPECT_TRUE(pref_sync_service_->CreatePrefSyncData(pref->name(),
328       *pref->GetValue(), &sync_data));
329   EXPECT_EQ(std::string(prefs::kHomePage), sync_data.GetTag());
330   const sync_pb::PreferenceSpecifics& specifics(sync_data.GetSpecifics().
331       preference());
332   EXPECT_EQ(std::string(prefs::kHomePage), specifics.name());
333
334   scoped_ptr<base::Value> value(base::JSONReader::Read(specifics.value()));
335   EXPECT_TRUE(pref->GetValue()->Equals(value.get()));
336 }
337
338 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationDoNotSyncDefaults) {
339   const PrefService::Preference* pref =
340       prefs_->FindPreference(prefs::kHomePage);
341   EXPECT_TRUE(pref->IsDefaultValue());
342   CreateRootHelper create_root(this, syncer::PREFERENCES);
343   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
344   ASSERT_TRUE(create_root.success());
345   EXPECT_TRUE(IsSynced(prefs::kHomePage));
346   EXPECT_TRUE(pref->IsDefaultValue());
347   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
348   EXPECT_TRUE(GetSyncedValue(not_synced_preference_name_) == NULL);
349 }
350
351 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationEmptyCloud) {
352   prefs_->SetString(prefs::kHomePage, example_url0_);
353   {
354     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
355     base::ListValue* url_list = update.Get();
356     url_list->Append(base::Value::CreateStringValue(example_url0_));
357     url_list->Append(base::Value::CreateStringValue(example_url1_));
358   }
359   CreateRootHelper create_root(this, syncer::PREFERENCES);
360   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
361   ASSERT_TRUE(create_root.success());
362
363   scoped_ptr<const base::Value> value(GetSyncedValue(prefs::kHomePage));
364   ASSERT_TRUE(value.get());
365   EXPECT_TRUE(GetPreferenceValue(prefs::kHomePage).Equals(value.get()));
366   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
367   ASSERT_TRUE(value.get());
368   EXPECT_TRUE(
369       GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get()));
370 }
371
372 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationCloudHasData) {
373   prefs_->SetString(prefs::kHomePage, example_url0_);
374   {
375     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
376     base::ListValue* url_list = update.Get();
377     url_list->Append(base::Value::CreateStringValue(example_url0_));
378     url_list->Append(base::Value::CreateStringValue(example_url1_));
379   }
380
381   PreferenceValues cloud_data;
382   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
383   cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
384   base::ListValue* urls_to_restore = new base::ListValue;
385   urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
386   urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
387   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
388   cloud_data[prefs::kDefaultCharset] =
389       base::Value::CreateStringValue(non_default_charset_value_);
390
391   AddPreferenceEntriesHelper helper(this, cloud_data);
392   ASSERT_TRUE(StartSyncService(helper.callback(), false));
393   ASSERT_TRUE(helper.success());
394
395   scoped_ptr<const base::Value> value(GetSyncedValue(prefs::kHomePage));
396   ASSERT_TRUE(value.get());
397   std::string string_value;
398   EXPECT_TRUE(value->GetAsString(&string_value));
399   EXPECT_EQ(example_url1_, string_value);
400   EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
401
402   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
403   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
404   expected_urls->Append(base::Value::CreateStringValue(example_url2_));
405   expected_urls->Append(base::Value::CreateStringValue(example_url0_));
406   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
407   ASSERT_TRUE(value.get());
408   EXPECT_TRUE(value->Equals(expected_urls.get()));
409   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
410               Equals(expected_urls.get()));
411
412   value.reset(GetSyncedValue(prefs::kDefaultCharset));
413   ASSERT_TRUE(value.get());
414   EXPECT_TRUE(value->GetAsString(&string_value));
415   EXPECT_EQ(non_default_charset_value_, string_value);
416   EXPECT_EQ(non_default_charset_value_,
417             prefs_->GetString(prefs::kDefaultCharset));
418 }
419
420 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationMigrateOldData) {
421   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
422   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
423
424   PreferenceValues cloud_data;
425   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
426   base::ListValue* urls_to_restore = new base::ListValue;
427   urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
428   urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
429   cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore;
430
431   AddPreferenceEntriesHelper helper(this, cloud_data);
432   ASSERT_TRUE(StartSyncService(helper.callback(), false));
433   ASSERT_TRUE(helper.success());
434
435   // Expect that the new preference data contains the old pref's values.
436   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
437   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
438   expected_urls->Append(base::Value::CreateStringValue(example_url2_));
439
440   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
441   scoped_ptr<const base::Value> value(
442       GetSyncedValue(prefs::kURLsToRestoreOnStartup));
443   ASSERT_TRUE(value.get());
444   EXPECT_TRUE(value->Equals(expected_urls.get()));
445   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
446               Equals(expected_urls.get()));
447
448   // The old preference value should be the same.
449   expected_urls.reset(new base::ListValue);
450   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
451   ASSERT_TRUE(value.get());
452   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
453               Equals(expected_urls.get()));
454 }
455
456 TEST_F(ProfileSyncServicePreferenceTest,
457        ModelAssociationCloudHasOldMigratedData) {
458   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
459   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
460   prefs_->SetString(prefs::kHomePage, example_url0_);
461   {
462     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
463     base::ListValue* url_list = update.Get();
464     url_list->Append(base::Value::CreateStringValue(example_url0_));
465     url_list->Append(base::Value::CreateStringValue(example_url1_));
466   }
467
468   PreferenceValues cloud_data;
469   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
470   cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
471   base::ListValue* urls_to_restore = new base::ListValue;
472   urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
473   urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
474   cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore;
475
476   AddPreferenceEntriesHelper helper(this, cloud_data);
477   ASSERT_TRUE(StartSyncService(helper.callback(), false));
478   ASSERT_TRUE(helper.success());
479
480   scoped_ptr<const base::Value> value(GetSyncedValue(prefs::kHomePage));
481   ASSERT_TRUE(value.get());
482   std::string string_value;
483   EXPECT_TRUE(value->GetAsString(&string_value));
484   EXPECT_EQ(example_url1_, string_value);
485   EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
486
487   // Expect that the new preference data contains the merged old prefs values.
488   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
489   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
490   expected_urls->Append(base::Value::CreateStringValue(example_url2_));
491   expected_urls->Append(base::Value::CreateStringValue(example_url0_));
492
493   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
494   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
495   ASSERT_TRUE(value.get());
496   EXPECT_TRUE(value->Equals(expected_urls.get()));
497   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
498               Equals(expected_urls.get()));
499
500   // The old preference name should also contain the merged sync data.
501   expected_urls.reset(new base::ListValue);
502   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
503   ASSERT_TRUE(value.get());
504   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
505               Equals(expected_urls.get()));
506 }
507
508 TEST_F(ProfileSyncServicePreferenceTest,
509        ModelAssociationCloudHasNewMigratedData) {
510   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
511   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
512   prefs_->SetString(prefs::kHomePage, example_url0_);
513   {
514     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartupOld);
515     base::ListValue* url_list = update.Get();
516     url_list->Append(base::Value::CreateStringValue(example_url0_));
517     url_list->Append(base::Value::CreateStringValue(example_url1_));
518   }
519
520   PreferenceValues cloud_data;
521   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
522   cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
523   base::ListValue* urls_to_restore = new base::ListValue;
524   urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
525   urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
526   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
527
528   AddPreferenceEntriesHelper helper(this, cloud_data);
529   ASSERT_TRUE(StartSyncService(helper.callback(), false));
530   ASSERT_TRUE(helper.success());
531
532   scoped_ptr<const base::Value> value(GetSyncedValue(prefs::kHomePage));
533   ASSERT_TRUE(value.get());
534   std::string string_value;
535   EXPECT_TRUE(value->GetAsString(&string_value));
536   EXPECT_EQ(example_url1_, string_value);
537   EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
538
539   // Expect that the cloud data under the new migrated preference name sticks.
540   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
541   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
542   expected_urls->Append(base::Value::CreateStringValue(example_url2_));
543
544   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
545   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
546   ASSERT_TRUE(value.get());
547   EXPECT_TRUE(value->Equals(expected_urls.get()));
548   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
549               Equals(expected_urls.get()));
550
551   // The old preference data should still be here, though not synced.
552   expected_urls.reset(new base::ListValue);
553   expected_urls->Append(base::Value::CreateStringValue(example_url0_));
554   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
555
556   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
557   ASSERT_FALSE(value.get());
558   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
559               Equals(expected_urls.get()));
560 }
561
562 TEST_F(ProfileSyncServicePreferenceTest,
563        ModelAssociationCloudAddsOldAndNewMigratedData) {
564   ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
565   ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
566   prefs_->SetString(prefs::kHomePage, example_url0_);
567   {
568     ListPrefUpdate update_old(prefs_, prefs::kURLsToRestoreOnStartupOld);
569     base::ListValue* url_list_old = update_old.Get();
570     url_list_old->Append(base::Value::CreateStringValue(example_url0_));
571     url_list_old->Append(base::Value::CreateStringValue(example_url1_));
572     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
573     base::ListValue* url_list = update.Get();
574     url_list->Append(base::Value::CreateStringValue(example_url1_));
575     url_list->Append(base::Value::CreateStringValue(example_url2_));
576   }
577
578   PreferenceValues cloud_data;
579   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
580   cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
581
582   AddPreferenceEntriesHelper helper(this, cloud_data);
583   ASSERT_TRUE(StartSyncService(helper.callback(), false));
584   ASSERT_TRUE(helper.success());
585
586   scoped_ptr<const base::Value> value(GetSyncedValue(prefs::kHomePage));
587   ASSERT_TRUE(value.get());
588   std::string string_value;
589   EXPECT_TRUE(value->GetAsString(&string_value));
590   EXPECT_EQ(example_url1_, string_value);
591   EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
592
593   // Expect that the cloud data under the new migrated preference name sticks.
594   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
595   expected_urls->Append(base::Value::CreateStringValue(example_url1_));
596   expected_urls->Append(base::Value::CreateStringValue(example_url2_));
597
598   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
599   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
600   ASSERT_TRUE(value.get());
601   EXPECT_TRUE(value->Equals(expected_urls.get()));
602   EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
603               Equals(expected_urls.get()));
604
605   // Should not have synced in the old startup url values.
606   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
607   ASSERT_FALSE(value.get());
608   EXPECT_FALSE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
609                Equals(expected_urls.get()));
610 }
611
612 TEST_F(ProfileSyncServicePreferenceTest, FailModelAssociation) {
613   ASSERT_TRUE(StartSyncService(base::Closure(), true));
614   EXPECT_TRUE(sync_service_->HasUnrecoverableError());
615 }
616
617 TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithDefaultValue) {
618   const PrefService::Preference* pref =
619       prefs_->FindPreference(prefs::kHomePage);
620   EXPECT_TRUE(pref->IsDefaultValue());
621
622   CreateRootHelper create_root(this, syncer::PREFERENCES);
623   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
624   ASSERT_TRUE(create_root.success());
625
626   scoped_ptr<base::Value> expected(
627       base::Value::CreateStringValue(example_url0_));
628   profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
629
630   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
631   ASSERT_TRUE(actual.get());
632   EXPECT_TRUE(expected->Equals(actual.get()));
633 }
634
635 TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithValue) {
636   profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_);
637   CreateRootHelper create_root(this, syncer::PREFERENCES);
638   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
639   ASSERT_TRUE(create_root.success());
640
641   scoped_ptr<base::Value> expected(
642       base::Value::CreateStringValue(example_url1_));
643   profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
644
645   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
646   ASSERT_TRUE(actual.get());
647   EXPECT_TRUE(expected->Equals(actual.get()));
648 }
649
650 TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionUpdate) {
651   profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_);
652   CreateRootHelper create_root(this, syncer::PREFERENCES);
653   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
654   ASSERT_TRUE(create_root.success());
655
656   scoped_ptr<base::Value> expected(
657       base::Value::CreateStringValue(example_url1_));
658   int64 node_id = SetSyncedValue(prefs::kHomePage, *expected);
659   ASSERT_NE(node_id, syncer::kInvalidId);
660   {
661     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
662     change_processor_->ApplyChangesFromSyncModel(
663         &trans, 0,
664         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
665             node_id, ChangeRecord::ACTION_UPDATE));
666   }
667   change_processor_->CommitChangesFromSyncModel();
668
669   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
670   EXPECT_TRUE(expected->Equals(&actual));
671 }
672
673 TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionAdd) {
674   CreateRootHelper create_root(this, syncer::PREFERENCES);
675   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
676   ASSERT_TRUE(create_root.success());
677
678   scoped_ptr<base::Value> expected(
679       base::Value::CreateStringValue(example_url0_));
680   int64 node_id = SetSyncedValue(prefs::kHomePage, *expected);
681   ASSERT_NE(node_id, syncer::kInvalidId);
682   {
683     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
684     change_processor_->ApplyChangesFromSyncModel(
685         &trans, 0,
686         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
687             node_id, ChangeRecord::ACTION_ADD));
688   }
689   change_processor_->CommitChangesFromSyncModel();
690
691   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
692   EXPECT_TRUE(expected->Equals(&actual));
693   EXPECT_EQ(1U,
694       pref_sync_service_->registered_preferences().count(prefs::kHomePage));
695 }
696
697 TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeUnknownPreference) {
698   CreateRootHelper create_root(this, syncer::PREFERENCES);
699   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
700   ASSERT_TRUE(create_root.success());
701
702   scoped_ptr<base::Value> expected(
703       base::Value::CreateStringValue(example_url0_));
704   int64 node_id = SetSyncedValue("unknown preference", *expected);
705   ASSERT_NE(node_id, syncer::kInvalidId);
706   {
707     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
708     change_processor_->ApplyChangesFromSyncModel(
709         &trans, 0,
710         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
711             node_id, ChangeRecord::ACTION_UPDATE));
712   }
713   change_processor_->CommitChangesFromSyncModel();
714
715   // Nothing interesting happens on the client when it gets an update
716   // of an unknown preference.  We just should not crash.
717 }
718
719 TEST_F(ProfileSyncServicePreferenceTest, ManagedPreferences) {
720   // Make the homepage preference managed.
721   scoped_ptr<base::Value> managed_value(
722       base::Value::CreateStringValue("http://example.com"));
723   prefs_->SetManagedPref(prefs::kHomePage, managed_value->DeepCopy());
724
725   CreateRootHelper create_root(this, syncer::PREFERENCES);
726   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
727   ASSERT_TRUE(create_root.success());
728
729   // Changing the homepage preference should not sync anything.
730   scoped_ptr<base::Value> user_value(
731       base::Value::CreateStringValue("http://chromium..com"));
732   prefs_->SetUserPref(prefs::kHomePage, user_value->DeepCopy());
733   EXPECT_EQ(NULL, GetSyncedValue(prefs::kHomePage));
734
735   // An incoming sync transaction should change the user value, not the managed
736   // value.
737   scoped_ptr<base::Value> sync_value(
738       base::Value::CreateStringValue("http://crbug.com"));
739   int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value);
740   ASSERT_NE(node_id, syncer::kInvalidId);
741   {
742     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
743     change_processor_->ApplyChangesFromSyncModel(
744         &trans, 0,
745         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
746             node_id, ChangeRecord::ACTION_UPDATE));
747   }
748   change_processor_->CommitChangesFromSyncModel();
749
750   EXPECT_TRUE(managed_value->Equals(prefs_->GetManagedPref(prefs::kHomePage)));
751   EXPECT_TRUE(sync_value->Equals(prefs_->GetUserPref(prefs::kHomePage)));
752 }
753
754 // List preferences have special handling at association time due to our ability
755 // to merge the local and sync value. Make sure the merge logic doesn't merge
756 // managed preferences.
757 TEST_F(ProfileSyncServicePreferenceTest, ManagedListPreferences) {
758   // Make the list of urls to restore on startup managed.
759   base::ListValue managed_value;
760   managed_value.Append(base::Value::CreateStringValue(example_url0_));
761   managed_value.Append(base::Value::CreateStringValue(example_url1_));
762   prefs_->SetManagedPref(prefs::kURLsToRestoreOnStartup,
763                          managed_value.DeepCopy());
764
765   // Set a cloud version.
766   PreferenceValues cloud_data;
767   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
768   base::ListValue* urls_to_restore = new base::ListValue;
769   urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
770   urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
771   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
772
773   // Start sync and verify the synced value didn't get merged.
774   AddPreferenceEntriesHelper helper(this, cloud_data);
775   ASSERT_TRUE(StartSyncService(helper.callback(), false));
776   ASSERT_TRUE(helper.success());
777   scoped_ptr<const base::Value> actual(
778       GetSyncedValue(prefs::kURLsToRestoreOnStartup));
779   EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get()));
780
781   // Changing the user's urls to restore on startup pref should not sync
782   // anything.
783   base::ListValue user_value;
784   user_value.Append(base::Value::CreateStringValue("http://chromium.org"));
785   prefs_->SetUserPref(prefs::kURLsToRestoreOnStartup, user_value.DeepCopy());
786   actual.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
787   EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get()));
788
789   // An incoming sync transaction should change the user value, not the managed
790   // value.
791   base::ListValue sync_value;
792   sync_value.Append(base::Value::CreateStringValue("http://crbug.com"));
793   int64 node_id = SetSyncedValue(prefs::kURLsToRestoreOnStartup, sync_value);
794   ASSERT_NE(node_id, syncer::kInvalidId);
795   {
796     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
797     change_processor_->ApplyChangesFromSyncModel(
798         &trans, 0,
799         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
800             node_id, ChangeRecord::ACTION_UPDATE));
801   }
802   change_processor_->CommitChangesFromSyncModel();
803
804   EXPECT_TRUE(managed_value.Equals(
805           prefs_->GetManagedPref(prefs::kURLsToRestoreOnStartup)));
806   EXPECT_TRUE(sync_value.Equals(
807           prefs_->GetUserPref(prefs::kURLsToRestoreOnStartup)));
808 }
809
810 TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedPreferences) {
811   CreateRootHelper create_root(this, syncer::PREFERENCES);
812   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
813   ASSERT_TRUE(create_root.success());
814
815   scoped_ptr<base::Value> initial_value(
816       base::Value::CreateStringValue("http://example.com/initial"));
817   profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value);
818   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
819   ASSERT_TRUE(actual.get());
820   EXPECT_TRUE(initial_value->Equals(actual.get()));
821
822   // Switch kHomePage to managed and set a different value.
823   scoped_ptr<base::Value> managed_value(
824       base::Value::CreateStringValue("http://example.com/managed"));
825   profile_->GetTestingPrefService()->SetManagedPref(
826       prefs::kHomePage, managed_value->DeepCopy());
827
828   // The pref value should be the one dictated by policy.
829   EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
830
831   // Switch kHomePage back to unmanaged.
832   profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
833
834   // The original value should be picked up.
835   EXPECT_TRUE(initial_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
836 }
837
838 TEST_F(ProfileSyncServicePreferenceTest,
839        DynamicManagedPreferencesWithSyncChange) {
840   CreateRootHelper create_root(this, syncer::PREFERENCES);
841   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
842   ASSERT_TRUE(create_root.success());
843
844   scoped_ptr<base::Value> initial_value(
845       base::Value::CreateStringValue("http://example.com/initial"));
846   profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value);
847   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
848   EXPECT_TRUE(initial_value->Equals(actual.get()));
849
850   // Switch kHomePage to managed and set a different value.
851   scoped_ptr<base::Value> managed_value(
852       base::Value::CreateStringValue("http://example.com/managed"));
853   profile_->GetTestingPrefService()->SetManagedPref(
854       prefs::kHomePage, managed_value->DeepCopy());
855
856   // Change the sync value.
857   scoped_ptr<base::Value> sync_value(
858       base::Value::CreateStringValue("http://example.com/sync"));
859   int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value);
860   ASSERT_NE(node_id, syncer::kInvalidId);
861   {
862     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
863     change_processor_->ApplyChangesFromSyncModel(
864         &trans, 0,
865         ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
866             node_id, ChangeRecord::ACTION_ADD));
867   }
868   change_processor_->CommitChangesFromSyncModel();
869
870   // The pref value should still be the one dictated by policy.
871   EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
872
873   // Switch kHomePage back to unmanaged.
874   profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
875
876   // Sync value should be picked up.
877   EXPECT_TRUE(sync_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
878 }
879
880 TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedDefaultPreferences) {
881   const PrefService::Preference* pref =
882       prefs_->FindPreference(prefs::kHomePage);
883   EXPECT_TRUE(pref->IsDefaultValue());
884   CreateRootHelper create_root(this, syncer::PREFERENCES);
885   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
886   ASSERT_TRUE(create_root.success());
887   EXPECT_TRUE(IsSynced(prefs::kHomePage));
888   EXPECT_TRUE(pref->IsDefaultValue());
889   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
890   // Switch kHomePage to managed and set a different value.
891   scoped_ptr<base::Value> managed_value(
892       base::Value::CreateStringValue("http://example.com/managed"));
893   profile_->GetTestingPrefService()->SetManagedPref(
894       prefs::kHomePage, managed_value->DeepCopy());
895   // The pref value should be the one dictated by policy.
896   EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
897   EXPECT_FALSE(pref->IsDefaultValue());
898   // There should be no synced value.
899   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
900   // Switch kHomePage back to unmanaged.
901   profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
902   // The original value should be picked up.
903   EXPECT_TRUE(pref->IsDefaultValue());
904   // There should still be no synced value.
905   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
906 }