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.
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"
49 using base::JSONReader;
50 using browser_sync::GenericChangeProcessor;
51 using browser_sync::SharedChangeProcessor;
52 using browser_sync::UIDataTypeController;
53 using syncer::ChangeRecord;
55 using testing::Invoke;
56 using testing::Return;
58 typedef std::map<const std::string, const base::Value*> PreferenceValues;
60 ACTION_P(CreateAndSaveChangeProcessor, change_processor) {
61 syncer::UserShare* user_share = arg0->GetUserShare();
62 *change_processor = new GenericChangeProcessor(arg1,
66 return *change_processor;
69 ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) {
70 return new browser_sync::DataTypeManagerImpl(
79 // TODO(zea): Refactor to remove the ProfileSyncService usage.
80 class ProfileSyncServicePreferenceTest
81 : public AbstractProfileSyncServiceTest,
82 public syncer::DataTypeDebugInfoListener {
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;
92 syncer::WriteNode tag_node(&trans);
93 syncer::WriteNode node(&trans);
95 if (tag_node.InitByClientTagLookup(syncer::PREFERENCES, name) ==
96 syncer::BaseNode::INIT_OK) {
97 return WriteSyncedValue(name, value, &tag_node);
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);
105 return syncer::kInvalidId;
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;
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") {}
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();
137 prefs_->registry()->RegisterStringPref(
138 not_synced_preference_name_.c_str(),
139 not_synced_preference_default_value_,
140 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
143 virtual void TearDown() {
145 AbstractProfileSyncServiceTest::TearDown();
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)
154 return node.GetTotalNodeCount() - 1;
157 bool StartSyncService(const base::Closure& callback,
158 bool will_fail_association) {
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_)
171 ProfileSyncComponentsFactoryMock* components =
172 sync_service_->components_factory_mock();
173 EXPECT_CALL(*components, GetSyncableServiceForType(syncer::PREFERENCES)).
174 WillOnce(Return(pref_sync_service_->AsWeakPtr()));
176 EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)).
177 WillOnce(ReturnNewDataTypeManagerWithDebugListener(
178 syncer::MakeWeakHandle(debug_ptr_factory_.GetWeakPtr())));
179 dtc_ = new UIDataTypeController(base::MessageLoopProxy::current(),
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");
194 sync_service_->Initialize();
195 base::MessageLoop::current()->Run();
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);
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);
211 const base::Value& GetPreferenceValue(const std::string& name) {
212 const PrefService::Preference* preference =
213 prefs_->FindPreference(name.c_str());
214 return *preference->GetValue();
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);
222 if (node.InitByClientTagLookup(syncer::PREFERENCES, name) !=
223 syncer::BaseNode::INIT_OK) {
227 const sync_pb::PreferenceSpecifics& specifics(
228 node.GetEntitySpecifics().preference());
230 return base::JSONReader::Read(specifics.value());
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,
240 return syncer::kInvalidId;
242 node->SetEntitySpecifics(sync_data.GetSpecifics());
243 return node->GetId();
246 bool IsSynced(const std::string& pref_name) {
247 return pref_sync_service_->registered_preferences().count(pref_name) > 0;
250 bool HasSyncData(const std::string& pref_name) {
251 return pref_sync_service_->IsPrefSynced(pref_name);
254 std::string ValueString(const base::Value& value) {
255 std::string serialized;
256 JSONStringValueSerializer json(&serialized);
257 json.Serialize(value);
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);
266 static bool IsOldMigratedPreference(const char* old_preference_name) {
267 return PrefModelAssociator::IsOldMigratedPreference(old_preference_name);
270 scoped_ptr<TestingProfile> profile_;
271 TestingPrefServiceSyncable* prefs_;
273 UIDataTypeController* dtc_;
274 PrefModelAssociator* pref_sync_service_;
275 GenericChangeProcessor* change_processor_;
276 syncer::DataTypeAssociationStats association_stats_;
277 base::WeakPtrFactory<DataTypeDebugInfoListener> debug_ptr_factory_;
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_;
287 class AddPreferenceEntriesHelper {
289 AddPreferenceEntriesHelper(ProfileSyncServicePreferenceTest* test,
290 const PreferenceValues& entries)
291 : callback_(base::Bind(
292 &AddPreferenceEntriesHelper::AddPreferenceEntriesCallback,
293 base::Unretained(this), test, entries)),
297 const base::Closure& callback() const { return callback_; }
298 bool success() { return success_; }
301 void AddPreferenceEntriesCallback(ProfileSyncServicePreferenceTest* test,
302 const PreferenceValues& entries) {
303 if (!test->CreateRoot(syncer::PREFERENCES))
306 for (PreferenceValues::const_iterator i = entries.begin();
307 i != entries.end(); ++i) {
308 if (test->SetSyncedValue(i->first, *i->second) == syncer::kInvalidId)
314 base::Closure callback_;
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());
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().
332 EXPECT_EQ(std::string(prefs::kHomePage), specifics.name());
334 scoped_ptr<base::Value> value(base::JSONReader::Read(specifics.value()));
335 EXPECT_TRUE(pref->GetValue()->Equals(value.get()));
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);
351 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationEmptyCloud) {
352 prefs_->SetString(prefs::kHomePage, example_url0_);
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_));
359 CreateRootHelper create_root(this, syncer::PREFERENCES);
360 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
361 ASSERT_TRUE(create_root.success());
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());
369 GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get()));
372 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationCloudHasData) {
373 prefs_->SetString(prefs::kHomePage, example_url0_);
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_));
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_);
391 AddPreferenceEntriesHelper helper(this, cloud_data);
392 ASSERT_TRUE(StartSyncService(helper.callback(), false));
393 ASSERT_TRUE(helper.success());
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));
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()));
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));
420 TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationMigrateOldData) {
421 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup));
422 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld));
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;
431 AddPreferenceEntriesHelper helper(this, cloud_data);
432 ASSERT_TRUE(StartSyncService(helper.callback(), false));
433 ASSERT_TRUE(helper.success());
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_));
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()));
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()));
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_);
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_));
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;
476 AddPreferenceEntriesHelper helper(this, cloud_data);
477 ASSERT_TRUE(StartSyncService(helper.callback(), false));
478 ASSERT_TRUE(helper.success());
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));
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_));
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()));
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()));
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_);
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_));
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;
528 AddPreferenceEntriesHelper helper(this, cloud_data);
529 ASSERT_TRUE(StartSyncService(helper.callback(), false));
530 ASSERT_TRUE(helper.success());
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));
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_));
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()));
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_));
556 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
557 ASSERT_FALSE(value.get());
558 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld).
559 Equals(expected_urls.get()));
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_);
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_));
578 PreferenceValues cloud_data;
579 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
580 cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
582 AddPreferenceEntriesHelper helper(this, cloud_data);
583 ASSERT_TRUE(StartSyncService(helper.callback(), false));
584 ASSERT_TRUE(helper.success());
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));
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_));
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()));
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()));
612 TEST_F(ProfileSyncServicePreferenceTest, FailModelAssociation) {
613 ASSERT_TRUE(StartSyncService(base::Closure(), true));
614 EXPECT_TRUE(sync_service_->HasUnrecoverableError());
617 TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithDefaultValue) {
618 const PrefService::Preference* pref =
619 prefs_->FindPreference(prefs::kHomePage);
620 EXPECT_TRUE(pref->IsDefaultValue());
622 CreateRootHelper create_root(this, syncer::PREFERENCES);
623 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
624 ASSERT_TRUE(create_root.success());
626 scoped_ptr<base::Value> expected(
627 base::Value::CreateStringValue(example_url0_));
628 profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
630 scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
631 ASSERT_TRUE(actual.get());
632 EXPECT_TRUE(expected->Equals(actual.get()));
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());
641 scoped_ptr<base::Value> expected(
642 base::Value::CreateStringValue(example_url1_));
643 profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
645 scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
646 ASSERT_TRUE(actual.get());
647 EXPECT_TRUE(expected->Equals(actual.get()));
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());
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);
661 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
662 change_processor_->ApplyChangesFromSyncModel(
664 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
665 node_id, ChangeRecord::ACTION_UPDATE));
667 change_processor_->CommitChangesFromSyncModel();
669 const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
670 EXPECT_TRUE(expected->Equals(&actual));
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());
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);
683 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
684 change_processor_->ApplyChangesFromSyncModel(
686 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
687 node_id, ChangeRecord::ACTION_ADD));
689 change_processor_->CommitChangesFromSyncModel();
691 const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
692 EXPECT_TRUE(expected->Equals(&actual));
694 pref_sync_service_->registered_preferences().count(prefs::kHomePage));
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());
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);
707 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
708 change_processor_->ApplyChangesFromSyncModel(
710 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
711 node_id, ChangeRecord::ACTION_UPDATE));
713 change_processor_->CommitChangesFromSyncModel();
715 // Nothing interesting happens on the client when it gets an update
716 // of an unknown preference. We just should not crash.
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());
725 CreateRootHelper create_root(this, syncer::PREFERENCES);
726 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
727 ASSERT_TRUE(create_root.success());
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));
735 // An incoming sync transaction should change the user value, not the managed
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);
742 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
743 change_processor_->ApplyChangesFromSyncModel(
745 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
746 node_id, ChangeRecord::ACTION_UPDATE));
748 change_processor_->CommitChangesFromSyncModel();
750 EXPECT_TRUE(managed_value->Equals(prefs_->GetManagedPref(prefs::kHomePage)));
751 EXPECT_TRUE(sync_value->Equals(prefs_->GetUserPref(prefs::kHomePage)));
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());
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;
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()));
781 // Changing the user's urls to restore on startup pref should not sync
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()));
789 // An incoming sync transaction should change the user value, not the managed
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);
796 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
797 change_processor_->ApplyChangesFromSyncModel(
799 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
800 node_id, ChangeRecord::ACTION_UPDATE));
802 change_processor_->CommitChangesFromSyncModel();
804 EXPECT_TRUE(managed_value.Equals(
805 prefs_->GetManagedPref(prefs::kURLsToRestoreOnStartup)));
806 EXPECT_TRUE(sync_value.Equals(
807 prefs_->GetUserPref(prefs::kURLsToRestoreOnStartup)));
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());
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()));
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());
828 // The pref value should be the one dictated by policy.
829 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
831 // Switch kHomePage back to unmanaged.
832 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
834 // The original value should be picked up.
835 EXPECT_TRUE(initial_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
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());
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()));
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());
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);
862 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
863 change_processor_->ApplyChangesFromSyncModel(
865 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
866 node_id, ChangeRecord::ACTION_ADD));
868 change_processor_->CommitChangesFromSyncModel();
870 // The pref value should still be the one dictated by policy.
871 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
873 // Switch kHomePage back to unmanaged.
874 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
876 // Sync value should be picked up.
877 EXPECT_TRUE(sync_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
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);