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/profile_oauth2_token_service_factory.h"
21 #include "chrome/browser/signin/signin_manager.h"
22 #include "chrome/browser/signin/signin_manager_factory.h"
23 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
24 #include "chrome/browser/sync/fake_oauth2_token_service_for_sync.h"
25 #include "chrome/browser/sync/glue/generic_change_processor.h"
26 #include "chrome/browser/sync/glue/sync_backend_host.h"
27 #include "chrome/browser/sync/glue/ui_data_type_controller.h"
28 #include "chrome/browser/sync/profile_sync_service_factory.h"
29 #include "chrome/browser/sync/profile_sync_test_util.h"
30 #include "chrome/browser/sync/test_profile_sync_service.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/test/base/testing_pref_service_syncable.h"
33 #include "chrome/test/base/testing_profile.h"
34 #include "components/user_prefs/pref_registry_syncable.h"
35 #include "google_apis/gaia/gaia_constants.h"
36 #include "sync/api/sync_data.h"
37 #include "sync/internal_api/public/base/model_type.h"
38 #include "sync/internal_api/public/change_record.h"
39 #include "sync/internal_api/public/data_type_debug_info_listener.h"
40 #include "sync/internal_api/public/read_node.h"
41 #include "sync/internal_api/public/read_transaction.h"
42 #include "sync/internal_api/public/write_node.h"
43 #include "sync/internal_api/public/write_transaction.h"
44 #include "sync/protocol/preference_specifics.pb.h"
45 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h"
48 using base::JSONReader
;
49 using browser_sync::GenericChangeProcessor
;
50 using browser_sync::SharedChangeProcessor
;
51 using browser_sync::UIDataTypeController
;
52 using syncer::ChangeRecord
;
54 using testing::Invoke
;
55 using testing::Return
;
57 typedef std::map
<const std::string
, const base::Value
*> PreferenceValues
;
59 ACTION_P(CreateAndSaveChangeProcessor
, change_processor
) {
60 syncer::UserShare
* user_share
= arg0
->GetUserShare();
61 *change_processor
= new GenericChangeProcessor(arg1
,
65 return *change_processor
;
68 ACTION_P(ReturnNewDataTypeManagerWithDebugListener
, debug_listener
) {
69 return new browser_sync::DataTypeManagerImpl(
78 // TODO(zea): Refactor to remove the ProfileSyncService usage.
79 class ProfileSyncServicePreferenceTest
80 : public AbstractProfileSyncServiceTest
,
81 public syncer::DataTypeDebugInfoListener
{
83 int64
SetSyncedValue(const std::string
& name
, const base::Value
& value
) {
84 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
85 syncer::ReadNode
root(&trans
);
86 if (root
.InitByTagLookup(syncer::ModelTypeToRootTag(
87 syncer::PREFERENCES
)) != syncer::BaseNode::INIT_OK
) {
88 return syncer::kInvalidId
;
91 syncer::WriteNode
tag_node(&trans
);
92 syncer::WriteNode
node(&trans
);
94 if (tag_node
.InitByClientTagLookup(syncer::PREFERENCES
, name
) ==
95 syncer::BaseNode::INIT_OK
) {
96 return WriteSyncedValue(name
, value
, &tag_node
);
99 syncer::WriteNode::InitUniqueByCreationResult result
=
100 node
.InitUniqueByCreation(syncer::PREFERENCES
, root
, name
);
101 if (result
== syncer::WriteNode::INIT_SUCCESS
)
102 return WriteSyncedValue(name
, value
, &node
);
104 return syncer::kInvalidId
;
107 // DataTypeDebugInfoListener implementation.
108 virtual void OnDataTypeConfigureComplete(
109 const std::vector
<syncer::DataTypeConfigurationStats
>&
110 configuration_stats
) OVERRIDE
{
111 ASSERT_EQ(1u, configuration_stats
.size());
112 association_stats_
= configuration_stats
[0].association_stats
;
116 ProfileSyncServicePreferenceTest()
117 : debug_ptr_factory_(this),
118 example_url0_("http://example.com/0"),
119 example_url1_("http://example.com/1"),
120 example_url2_("http://example.com/2"),
121 not_synced_preference_name_("nonsense_pref_name"),
122 not_synced_preference_default_value_("default"),
123 non_default_charset_value_("foo") {}
125 virtual void SetUp() {
126 AbstractProfileSyncServiceTest::SetUp();
127 TestingProfile::Builder builder
;
128 builder
.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
129 FakeOAuth2TokenServiceForSync::BuildTokenService
);
130 profile_
= builder
.Build().Pass();
131 invalidation::InvalidationServiceFactory::GetInstance()->
132 SetBuildOnlyFakeInvalidatorsForTest(true);
133 prefs_
= profile_
->GetTestingPrefService();
135 prefs_
->registry()->RegisterStringPref(
136 not_synced_preference_name_
.c_str(),
137 not_synced_preference_default_value_
,
138 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
141 virtual void TearDown() {
143 AbstractProfileSyncServiceTest::TearDown();
146 int GetSyncPreferenceCount() {
147 syncer::ReadTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
148 syncer::ReadNode
node(&trans
);
149 if (node
.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::PREFERENCES
)) !=
150 syncer::BaseNode::INIT_OK
)
152 return node
.GetTotalNodeCount() - 1;
155 bool StartSyncService(const base::Closure
& callback
,
156 bool will_fail_association
) {
160 SigninManagerBase
* signin
=
161 SigninManagerFactory::GetForProfile(profile_
.get());
162 signin
->SetAuthenticatedUsername("test");
163 sync_service_
= static_cast<TestProfileSyncService
*>(
164 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
165 profile_
.get(), &TestProfileSyncService::BuildAutoStartAsyncInit
));
166 sync_service_
->set_backend_init_callback(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(syncer::PREFERENCES
,
183 EXPECT_CALL(*components
, CreateSharedChangeProcessor()).
184 WillOnce(Return(new SharedChangeProcessor()));
185 EXPECT_CALL(*components
, CreateGenericChangeProcessor(_
, _
, _
, _
)).
186 WillOnce(CreateAndSaveChangeProcessor(
187 &change_processor_
));
188 sync_service_
->RegisterDataTypeController(dtc_
);
189 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_
.get())
190 ->UpdateCredentials("test", "oauth2_login_token");
192 sync_service_
->Initialize();
193 base::MessageLoop::current()->Run();
195 // It's possible this test triggered an unrecoverable error, in which case
196 // we can't get the preference count.
197 if (sync_service_
->ShouldPushChanges()) {
198 EXPECT_EQ(GetSyncPreferenceCount(),
199 association_stats_
.num_sync_items_after_association
);
201 EXPECT_EQ(association_stats_
.num_sync_items_after_association
,
202 association_stats_
.num_sync_items_before_association
+
203 association_stats_
.num_sync_items_added
-
204 association_stats_
.num_sync_items_deleted
);
209 const base::Value
& GetPreferenceValue(const std::string
& name
) {
210 const PrefService::Preference
* preference
=
211 prefs_
->FindPreference(name
.c_str());
212 return *preference
->GetValue();
215 // Caller gets ownership of the returned value.
216 const base::Value
* GetSyncedValue(const std::string
& name
) {
217 syncer::ReadTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
218 syncer::ReadNode
node(&trans
);
220 if (node
.InitByClientTagLookup(syncer::PREFERENCES
, name
) !=
221 syncer::BaseNode::INIT_OK
) {
225 const sync_pb::PreferenceSpecifics
& specifics(
226 node
.GetEntitySpecifics().preference());
228 return base::JSONReader::Read(specifics
.value());
231 int64
WriteSyncedValue(const std::string
& name
,
232 const base::Value
& value
,
233 syncer::WriteNode
* node
) {
234 syncer::SyncData sync_data
;
235 if (!pref_sync_service_
->CreatePrefSyncData(name
,
238 return syncer::kInvalidId
;
240 node
->SetEntitySpecifics(sync_data
.GetSpecifics());
241 return node
->GetId();
244 bool IsSynced(const std::string
& pref_name
) {
245 return pref_sync_service_
->registered_preferences().count(pref_name
) > 0;
248 bool HasSyncData(const std::string
& pref_name
) {
249 return pref_sync_service_
->IsPrefSynced(pref_name
);
252 std::string
ValueString(const base::Value
& value
) {
253 std::string serialized
;
254 JSONStringValueSerializer
json(&serialized
);
255 json
.Serialize(value
);
259 // Returns whether a given preference name is a new name of a migrated
260 // preference. Exposed here for testing.
261 static bool IsMigratedPreference(const char* preference_name
) {
262 return PrefModelAssociator::IsMigratedPreference(preference_name
);
264 static bool IsOldMigratedPreference(const char* old_preference_name
) {
265 return PrefModelAssociator::IsOldMigratedPreference(old_preference_name
);
268 scoped_ptr
<TestingProfile
> profile_
;
269 TestingPrefServiceSyncable
* prefs_
;
271 UIDataTypeController
* dtc_
;
272 PrefModelAssociator
* pref_sync_service_
;
273 GenericChangeProcessor
* change_processor_
;
274 syncer::DataTypeAssociationStats association_stats_
;
275 base::WeakPtrFactory
<DataTypeDebugInfoListener
> debug_ptr_factory_
;
277 std::string example_url0_
;
278 std::string example_url1_
;
279 std::string example_url2_
;
280 std::string not_synced_preference_name_
;
281 std::string not_synced_preference_default_value_
;
282 std::string non_default_charset_value_
;
285 class AddPreferenceEntriesHelper
{
287 AddPreferenceEntriesHelper(ProfileSyncServicePreferenceTest
* test
,
288 const PreferenceValues
& entries
)
289 : callback_(base::Bind(
290 &AddPreferenceEntriesHelper::AddPreferenceEntriesCallback
,
291 base::Unretained(this), test
, entries
)),
295 const base::Closure
& callback() const { return callback_
; }
296 bool success() { return success_
; }
299 void AddPreferenceEntriesCallback(ProfileSyncServicePreferenceTest
* test
,
300 const PreferenceValues
& entries
) {
301 if (!test
->CreateRoot(syncer::PREFERENCES
))
304 for (PreferenceValues::const_iterator i
= entries
.begin();
305 i
!= entries
.end(); ++i
) {
306 if (test
->SetSyncedValue(i
->first
, *i
->second
) == syncer::kInvalidId
)
312 base::Closure callback_
;
316 TEST_F(ProfileSyncServicePreferenceTest
, CreatePrefSyncData
) {
317 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
318 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
319 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
320 ASSERT_TRUE(create_root
.success());
322 const PrefService::Preference
* pref
=
323 prefs_
->FindPreference(prefs::kHomePage
);
324 syncer::SyncData sync_data
;
325 EXPECT_TRUE(pref_sync_service_
->CreatePrefSyncData(pref
->name(),
326 *pref
->GetValue(), &sync_data
));
327 EXPECT_EQ(std::string(prefs::kHomePage
), sync_data
.GetTag());
328 const sync_pb::PreferenceSpecifics
& specifics(sync_data
.GetSpecifics().
330 EXPECT_EQ(std::string(prefs::kHomePage
), specifics
.name());
332 scoped_ptr
<base::Value
> value(base::JSONReader::Read(specifics
.value()));
333 EXPECT_TRUE(pref
->GetValue()->Equals(value
.get()));
336 TEST_F(ProfileSyncServicePreferenceTest
, ModelAssociationDoNotSyncDefaults
) {
337 const PrefService::Preference
* pref
=
338 prefs_
->FindPreference(prefs::kHomePage
);
339 EXPECT_TRUE(pref
->IsDefaultValue());
340 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
341 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
342 ASSERT_TRUE(create_root
.success());
343 EXPECT_TRUE(IsSynced(prefs::kHomePage
));
344 EXPECT_TRUE(pref
->IsDefaultValue());
345 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage
) == NULL
);
346 EXPECT_TRUE(GetSyncedValue(not_synced_preference_name_
) == NULL
);
349 TEST_F(ProfileSyncServicePreferenceTest
, ModelAssociationEmptyCloud
) {
350 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
352 ListPrefUpdate
update(prefs_
, prefs::kURLsToRestoreOnStartup
);
353 base::ListValue
* url_list
= update
.Get();
354 url_list
->Append(base::Value::CreateStringValue(example_url0_
));
355 url_list
->Append(base::Value::CreateStringValue(example_url1_
));
357 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
358 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
359 ASSERT_TRUE(create_root
.success());
361 scoped_ptr
<const base::Value
> value(GetSyncedValue(prefs::kHomePage
));
362 ASSERT_TRUE(value
.get());
363 EXPECT_TRUE(GetPreferenceValue(prefs::kHomePage
).Equals(value
.get()));
364 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
365 ASSERT_TRUE(value
.get());
367 GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).Equals(value
.get()));
370 TEST_F(ProfileSyncServicePreferenceTest
, ModelAssociationCloudHasData
) {
371 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
373 ListPrefUpdate
update(prefs_
, prefs::kURLsToRestoreOnStartup
);
374 base::ListValue
* url_list
= update
.Get();
375 url_list
->Append(base::Value::CreateStringValue(example_url0_
));
376 url_list
->Append(base::Value::CreateStringValue(example_url1_
));
379 PreferenceValues cloud_data
;
380 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
381 cloud_data
[prefs::kHomePage
] = base::Value::CreateStringValue(example_url1_
);
382 base::ListValue
* urls_to_restore
= new base::ListValue
;
383 urls_to_restore
->Append(base::Value::CreateStringValue(example_url1_
));
384 urls_to_restore
->Append(base::Value::CreateStringValue(example_url2_
));
385 cloud_data
[prefs::kURLsToRestoreOnStartup
] = urls_to_restore
;
386 cloud_data
[prefs::kDefaultCharset
] =
387 base::Value::CreateStringValue(non_default_charset_value_
);
389 AddPreferenceEntriesHelper
helper(this, cloud_data
);
390 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
391 ASSERT_TRUE(helper
.success());
393 scoped_ptr
<const base::Value
> value(GetSyncedValue(prefs::kHomePage
));
394 ASSERT_TRUE(value
.get());
395 std::string string_value
;
396 EXPECT_TRUE(value
->GetAsString(&string_value
));
397 EXPECT_EQ(example_url1_
, string_value
);
398 EXPECT_EQ(example_url1_
, prefs_
->GetString(prefs::kHomePage
));
400 scoped_ptr
<base::ListValue
> expected_urls(new base::ListValue
);
401 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
402 expected_urls
->Append(base::Value::CreateStringValue(example_url2_
));
403 expected_urls
->Append(base::Value::CreateStringValue(example_url0_
));
404 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
405 ASSERT_TRUE(value
.get());
406 EXPECT_TRUE(value
->Equals(expected_urls
.get()));
407 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).
408 Equals(expected_urls
.get()));
410 value
.reset(GetSyncedValue(prefs::kDefaultCharset
));
411 ASSERT_TRUE(value
.get());
412 EXPECT_TRUE(value
->GetAsString(&string_value
));
413 EXPECT_EQ(non_default_charset_value_
, string_value
);
414 EXPECT_EQ(non_default_charset_value_
,
415 prefs_
->GetString(prefs::kDefaultCharset
));
418 TEST_F(ProfileSyncServicePreferenceTest
, ModelAssociationMigrateOldData
) {
419 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup
));
420 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld
));
422 PreferenceValues cloud_data
;
423 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
424 base::ListValue
* urls_to_restore
= new base::ListValue
;
425 urls_to_restore
->Append(base::Value::CreateStringValue(example_url1_
));
426 urls_to_restore
->Append(base::Value::CreateStringValue(example_url2_
));
427 cloud_data
[prefs::kURLsToRestoreOnStartupOld
] = urls_to_restore
;
429 AddPreferenceEntriesHelper
helper(this, cloud_data
);
430 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
431 ASSERT_TRUE(helper
.success());
433 // Expect that the new preference data contains the old pref's values.
434 scoped_ptr
<base::ListValue
> expected_urls(new base::ListValue
);
435 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
436 expected_urls
->Append(base::Value::CreateStringValue(example_url2_
));
438 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup
));
439 scoped_ptr
<const base::Value
> value(
440 GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
441 ASSERT_TRUE(value
.get());
442 EXPECT_TRUE(value
->Equals(expected_urls
.get()));
443 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).
444 Equals(expected_urls
.get()));
446 // The old preference value should be the same.
447 expected_urls
.reset(new base::ListValue
);
448 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld
));
449 ASSERT_TRUE(value
.get());
450 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld
).
451 Equals(expected_urls
.get()));
454 TEST_F(ProfileSyncServicePreferenceTest
,
455 ModelAssociationCloudHasOldMigratedData
) {
456 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup
));
457 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld
));
458 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
460 ListPrefUpdate
update(prefs_
, prefs::kURLsToRestoreOnStartup
);
461 base::ListValue
* url_list
= update
.Get();
462 url_list
->Append(base::Value::CreateStringValue(example_url0_
));
463 url_list
->Append(base::Value::CreateStringValue(example_url1_
));
466 PreferenceValues cloud_data
;
467 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
468 cloud_data
[prefs::kHomePage
] = base::Value::CreateStringValue(example_url1_
);
469 base::ListValue
* urls_to_restore
= new base::ListValue
;
470 urls_to_restore
->Append(base::Value::CreateStringValue(example_url1_
));
471 urls_to_restore
->Append(base::Value::CreateStringValue(example_url2_
));
472 cloud_data
[prefs::kURLsToRestoreOnStartupOld
] = urls_to_restore
;
474 AddPreferenceEntriesHelper
helper(this, cloud_data
);
475 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
476 ASSERT_TRUE(helper
.success());
478 scoped_ptr
<const base::Value
> value(GetSyncedValue(prefs::kHomePage
));
479 ASSERT_TRUE(value
.get());
480 std::string string_value
;
481 EXPECT_TRUE(value
->GetAsString(&string_value
));
482 EXPECT_EQ(example_url1_
, string_value
);
483 EXPECT_EQ(example_url1_
, prefs_
->GetString(prefs::kHomePage
));
485 // Expect that the new preference data contains the merged old prefs values.
486 scoped_ptr
<base::ListValue
> expected_urls(new base::ListValue
);
487 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
488 expected_urls
->Append(base::Value::CreateStringValue(example_url2_
));
489 expected_urls
->Append(base::Value::CreateStringValue(example_url0_
));
491 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup
));
492 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
493 ASSERT_TRUE(value
.get());
494 EXPECT_TRUE(value
->Equals(expected_urls
.get()));
495 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).
496 Equals(expected_urls
.get()));
498 // The old preference name should also contain the merged sync data.
499 expected_urls
.reset(new base::ListValue
);
500 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld
));
501 ASSERT_TRUE(value
.get());
502 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld
).
503 Equals(expected_urls
.get()));
506 TEST_F(ProfileSyncServicePreferenceTest
,
507 ModelAssociationCloudHasNewMigratedData
) {
508 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup
));
509 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld
));
510 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
512 ListPrefUpdate
update(prefs_
, prefs::kURLsToRestoreOnStartupOld
);
513 base::ListValue
* url_list
= update
.Get();
514 url_list
->Append(base::Value::CreateStringValue(example_url0_
));
515 url_list
->Append(base::Value::CreateStringValue(example_url1_
));
518 PreferenceValues cloud_data
;
519 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
520 cloud_data
[prefs::kHomePage
] = base::Value::CreateStringValue(example_url1_
);
521 base::ListValue
* urls_to_restore
= new base::ListValue
;
522 urls_to_restore
->Append(base::Value::CreateStringValue(example_url1_
));
523 urls_to_restore
->Append(base::Value::CreateStringValue(example_url2_
));
524 cloud_data
[prefs::kURLsToRestoreOnStartup
] = urls_to_restore
;
526 AddPreferenceEntriesHelper
helper(this, cloud_data
);
527 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
528 ASSERT_TRUE(helper
.success());
530 scoped_ptr
<const base::Value
> value(GetSyncedValue(prefs::kHomePage
));
531 ASSERT_TRUE(value
.get());
532 std::string string_value
;
533 EXPECT_TRUE(value
->GetAsString(&string_value
));
534 EXPECT_EQ(example_url1_
, string_value
);
535 EXPECT_EQ(example_url1_
, prefs_
->GetString(prefs::kHomePage
));
537 // Expect that the cloud data under the new migrated preference name sticks.
538 scoped_ptr
<base::ListValue
> expected_urls(new base::ListValue
);
539 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
540 expected_urls
->Append(base::Value::CreateStringValue(example_url2_
));
542 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup
));
543 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
544 ASSERT_TRUE(value
.get());
545 EXPECT_TRUE(value
->Equals(expected_urls
.get()));
546 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).
547 Equals(expected_urls
.get()));
549 // The old preference data should still be here, though not synced.
550 expected_urls
.reset(new base::ListValue
);
551 expected_urls
->Append(base::Value::CreateStringValue(example_url0_
));
552 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
554 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld
));
555 ASSERT_FALSE(value
.get());
556 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld
).
557 Equals(expected_urls
.get()));
560 TEST_F(ProfileSyncServicePreferenceTest
,
561 ModelAssociationCloudAddsOldAndNewMigratedData
) {
562 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup
));
563 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld
));
564 prefs_
->SetString(prefs::kHomePage
, example_url0_
);
566 ListPrefUpdate
update_old(prefs_
, prefs::kURLsToRestoreOnStartupOld
);
567 base::ListValue
* url_list_old
= update_old
.Get();
568 url_list_old
->Append(base::Value::CreateStringValue(example_url0_
));
569 url_list_old
->Append(base::Value::CreateStringValue(example_url1_
));
570 ListPrefUpdate
update(prefs_
, prefs::kURLsToRestoreOnStartup
);
571 base::ListValue
* url_list
= update
.Get();
572 url_list
->Append(base::Value::CreateStringValue(example_url1_
));
573 url_list
->Append(base::Value::CreateStringValue(example_url2_
));
576 PreferenceValues cloud_data
;
577 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
578 cloud_data
[prefs::kHomePage
] = base::Value::CreateStringValue(example_url1_
);
580 AddPreferenceEntriesHelper
helper(this, cloud_data
);
581 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
582 ASSERT_TRUE(helper
.success());
584 scoped_ptr
<const base::Value
> value(GetSyncedValue(prefs::kHomePage
));
585 ASSERT_TRUE(value
.get());
586 std::string string_value
;
587 EXPECT_TRUE(value
->GetAsString(&string_value
));
588 EXPECT_EQ(example_url1_
, string_value
);
589 EXPECT_EQ(example_url1_
, prefs_
->GetString(prefs::kHomePage
));
591 // Expect that the cloud data under the new migrated preference name sticks.
592 scoped_ptr
<base::ListValue
> expected_urls(new base::ListValue
);
593 expected_urls
->Append(base::Value::CreateStringValue(example_url1_
));
594 expected_urls
->Append(base::Value::CreateStringValue(example_url2_
));
596 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup
));
597 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
598 ASSERT_TRUE(value
.get());
599 EXPECT_TRUE(value
->Equals(expected_urls
.get()));
600 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup
).
601 Equals(expected_urls
.get()));
603 // Should not have synced in the old startup url values.
604 value
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld
));
605 ASSERT_FALSE(value
.get());
606 EXPECT_FALSE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld
).
607 Equals(expected_urls
.get()));
610 TEST_F(ProfileSyncServicePreferenceTest
, FailModelAssociation
) {
611 ASSERT_TRUE(StartSyncService(base::Closure(), true));
612 EXPECT_TRUE(sync_service_
->HasUnrecoverableError());
615 TEST_F(ProfileSyncServicePreferenceTest
, UpdatedPreferenceWithDefaultValue
) {
616 const PrefService::Preference
* pref
=
617 prefs_
->FindPreference(prefs::kHomePage
);
618 EXPECT_TRUE(pref
->IsDefaultValue());
620 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
621 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
622 ASSERT_TRUE(create_root
.success());
624 scoped_ptr
<base::Value
> expected(
625 base::Value::CreateStringValue(example_url0_
));
626 profile_
->GetPrefs()->Set(prefs::kHomePage
, *expected
);
628 scoped_ptr
<const base::Value
> actual(GetSyncedValue(prefs::kHomePage
));
629 ASSERT_TRUE(actual
.get());
630 EXPECT_TRUE(expected
->Equals(actual
.get()));
633 TEST_F(ProfileSyncServicePreferenceTest
, UpdatedPreferenceWithValue
) {
634 profile_
->GetPrefs()->SetString(prefs::kHomePage
, example_url0_
);
635 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
636 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
637 ASSERT_TRUE(create_root
.success());
639 scoped_ptr
<base::Value
> expected(
640 base::Value::CreateStringValue(example_url1_
));
641 profile_
->GetPrefs()->Set(prefs::kHomePage
, *expected
);
643 scoped_ptr
<const base::Value
> actual(GetSyncedValue(prefs::kHomePage
));
644 ASSERT_TRUE(actual
.get());
645 EXPECT_TRUE(expected
->Equals(actual
.get()));
648 TEST_F(ProfileSyncServicePreferenceTest
, UpdatedSyncNodeActionUpdate
) {
649 profile_
->GetPrefs()->SetString(prefs::kHomePage
, example_url0_
);
650 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
651 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
652 ASSERT_TRUE(create_root
.success());
654 scoped_ptr
<base::Value
> expected(
655 base::Value::CreateStringValue(example_url1_
));
656 int64 node_id
= SetSyncedValue(prefs::kHomePage
, *expected
);
657 ASSERT_NE(node_id
, syncer::kInvalidId
);
659 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
660 change_processor_
->ApplyChangesFromSyncModel(
662 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
663 node_id
, ChangeRecord::ACTION_UPDATE
));
665 change_processor_
->CommitChangesFromSyncModel();
667 const base::Value
& actual
= GetPreferenceValue(prefs::kHomePage
);
668 EXPECT_TRUE(expected
->Equals(&actual
));
671 TEST_F(ProfileSyncServicePreferenceTest
, UpdatedSyncNodeActionAdd
) {
672 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
673 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
674 ASSERT_TRUE(create_root
.success());
676 scoped_ptr
<base::Value
> expected(
677 base::Value::CreateStringValue(example_url0_
));
678 int64 node_id
= SetSyncedValue(prefs::kHomePage
, *expected
);
679 ASSERT_NE(node_id
, syncer::kInvalidId
);
681 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
682 change_processor_
->ApplyChangesFromSyncModel(
684 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
685 node_id
, ChangeRecord::ACTION_ADD
));
687 change_processor_
->CommitChangesFromSyncModel();
689 const base::Value
& actual
= GetPreferenceValue(prefs::kHomePage
);
690 EXPECT_TRUE(expected
->Equals(&actual
));
692 pref_sync_service_
->registered_preferences().count(prefs::kHomePage
));
695 TEST_F(ProfileSyncServicePreferenceTest
, UpdatedSyncNodeUnknownPreference
) {
696 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
697 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
698 ASSERT_TRUE(create_root
.success());
700 scoped_ptr
<base::Value
> expected(
701 base::Value::CreateStringValue(example_url0_
));
702 int64 node_id
= SetSyncedValue("unknown preference", *expected
);
703 ASSERT_NE(node_id
, syncer::kInvalidId
);
705 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
706 change_processor_
->ApplyChangesFromSyncModel(
708 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
709 node_id
, ChangeRecord::ACTION_UPDATE
));
711 change_processor_
->CommitChangesFromSyncModel();
713 // Nothing interesting happens on the client when it gets an update
714 // of an unknown preference. We just should not crash.
717 TEST_F(ProfileSyncServicePreferenceTest
, ManagedPreferences
) {
718 // Make the homepage preference managed.
719 scoped_ptr
<base::Value
> managed_value(
720 base::Value::CreateStringValue("http://example.com"));
721 prefs_
->SetManagedPref(prefs::kHomePage
, managed_value
->DeepCopy());
723 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
724 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
725 ASSERT_TRUE(create_root
.success());
727 // Changing the homepage preference should not sync anything.
728 scoped_ptr
<base::Value
> user_value(
729 base::Value::CreateStringValue("http://chromium..com"));
730 prefs_
->SetUserPref(prefs::kHomePage
, user_value
->DeepCopy());
731 EXPECT_EQ(NULL
, GetSyncedValue(prefs::kHomePage
));
733 // An incoming sync transaction should change the user value, not the managed
735 scoped_ptr
<base::Value
> sync_value(
736 base::Value::CreateStringValue("http://crbug.com"));
737 int64 node_id
= SetSyncedValue(prefs::kHomePage
, *sync_value
);
738 ASSERT_NE(node_id
, syncer::kInvalidId
);
740 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
741 change_processor_
->ApplyChangesFromSyncModel(
743 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
744 node_id
, ChangeRecord::ACTION_UPDATE
));
746 change_processor_
->CommitChangesFromSyncModel();
748 EXPECT_TRUE(managed_value
->Equals(prefs_
->GetManagedPref(prefs::kHomePage
)));
749 EXPECT_TRUE(sync_value
->Equals(prefs_
->GetUserPref(prefs::kHomePage
)));
752 // List preferences have special handling at association time due to our ability
753 // to merge the local and sync value. Make sure the merge logic doesn't merge
754 // managed preferences.
755 TEST_F(ProfileSyncServicePreferenceTest
, ManagedListPreferences
) {
756 // Make the list of urls to restore on startup managed.
757 base::ListValue managed_value
;
758 managed_value
.Append(base::Value::CreateStringValue(example_url0_
));
759 managed_value
.Append(base::Value::CreateStringValue(example_url1_
));
760 prefs_
->SetManagedPref(prefs::kURLsToRestoreOnStartup
,
761 managed_value
.DeepCopy());
763 // Set a cloud version.
764 PreferenceValues cloud_data
;
765 STLValueDeleter
<PreferenceValues
> cloud_data_deleter(&cloud_data
);
766 base::ListValue
* urls_to_restore
= new base::ListValue
;
767 urls_to_restore
->Append(base::Value::CreateStringValue(example_url1_
));
768 urls_to_restore
->Append(base::Value::CreateStringValue(example_url2_
));
769 cloud_data
[prefs::kURLsToRestoreOnStartup
] = urls_to_restore
;
771 // Start sync and verify the synced value didn't get merged.
772 AddPreferenceEntriesHelper
helper(this, cloud_data
);
773 ASSERT_TRUE(StartSyncService(helper
.callback(), false));
774 ASSERT_TRUE(helper
.success());
775 scoped_ptr
<const base::Value
> actual(
776 GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
777 EXPECT_TRUE(cloud_data
[prefs::kURLsToRestoreOnStartup
]->Equals(actual
.get()));
779 // Changing the user's urls to restore on startup pref should not sync
781 base::ListValue user_value
;
782 user_value
.Append(base::Value::CreateStringValue("http://chromium.org"));
783 prefs_
->SetUserPref(prefs::kURLsToRestoreOnStartup
, user_value
.DeepCopy());
784 actual
.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup
));
785 EXPECT_TRUE(cloud_data
[prefs::kURLsToRestoreOnStartup
]->Equals(actual
.get()));
787 // An incoming sync transaction should change the user value, not the managed
789 base::ListValue sync_value
;
790 sync_value
.Append(base::Value::CreateStringValue("http://crbug.com"));
791 int64 node_id
= SetSyncedValue(prefs::kURLsToRestoreOnStartup
, sync_value
);
792 ASSERT_NE(node_id
, syncer::kInvalidId
);
794 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
795 change_processor_
->ApplyChangesFromSyncModel(
797 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
798 node_id
, ChangeRecord::ACTION_UPDATE
));
800 change_processor_
->CommitChangesFromSyncModel();
802 EXPECT_TRUE(managed_value
.Equals(
803 prefs_
->GetManagedPref(prefs::kURLsToRestoreOnStartup
)));
804 EXPECT_TRUE(sync_value
.Equals(
805 prefs_
->GetUserPref(prefs::kURLsToRestoreOnStartup
)));
808 TEST_F(ProfileSyncServicePreferenceTest
, DynamicManagedPreferences
) {
809 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
810 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
811 ASSERT_TRUE(create_root
.success());
813 scoped_ptr
<base::Value
> initial_value(
814 base::Value::CreateStringValue("http://example.com/initial"));
815 profile_
->GetPrefs()->Set(prefs::kHomePage
, *initial_value
);
816 scoped_ptr
<const base::Value
> actual(GetSyncedValue(prefs::kHomePage
));
817 ASSERT_TRUE(actual
.get());
818 EXPECT_TRUE(initial_value
->Equals(actual
.get()));
820 // Switch kHomePage to managed and set a different value.
821 scoped_ptr
<base::Value
> managed_value(
822 base::Value::CreateStringValue("http://example.com/managed"));
823 profile_
->GetTestingPrefService()->SetManagedPref(
824 prefs::kHomePage
, managed_value
->DeepCopy());
826 // The pref value should be the one dictated by policy.
827 EXPECT_TRUE(managed_value
->Equals(&GetPreferenceValue(prefs::kHomePage
)));
829 // Switch kHomePage back to unmanaged.
830 profile_
->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage
);
832 // The original value should be picked up.
833 EXPECT_TRUE(initial_value
->Equals(&GetPreferenceValue(prefs::kHomePage
)));
836 TEST_F(ProfileSyncServicePreferenceTest
,
837 DynamicManagedPreferencesWithSyncChange
) {
838 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
839 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
840 ASSERT_TRUE(create_root
.success());
842 scoped_ptr
<base::Value
> initial_value(
843 base::Value::CreateStringValue("http://example.com/initial"));
844 profile_
->GetPrefs()->Set(prefs::kHomePage
, *initial_value
);
845 scoped_ptr
<const base::Value
> actual(GetSyncedValue(prefs::kHomePage
));
846 EXPECT_TRUE(initial_value
->Equals(actual
.get()));
848 // Switch kHomePage to managed and set a different value.
849 scoped_ptr
<base::Value
> managed_value(
850 base::Value::CreateStringValue("http://example.com/managed"));
851 profile_
->GetTestingPrefService()->SetManagedPref(
852 prefs::kHomePage
, managed_value
->DeepCopy());
854 // Change the sync value.
855 scoped_ptr
<base::Value
> sync_value(
856 base::Value::CreateStringValue("http://example.com/sync"));
857 int64 node_id
= SetSyncedValue(prefs::kHomePage
, *sync_value
);
858 ASSERT_NE(node_id
, syncer::kInvalidId
);
860 syncer::WriteTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
861 change_processor_
->ApplyChangesFromSyncModel(
863 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
864 node_id
, ChangeRecord::ACTION_ADD
));
866 change_processor_
->CommitChangesFromSyncModel();
868 // The pref value should still be the one dictated by policy.
869 EXPECT_TRUE(managed_value
->Equals(&GetPreferenceValue(prefs::kHomePage
)));
871 // Switch kHomePage back to unmanaged.
872 profile_
->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage
);
874 // Sync value should be picked up.
875 EXPECT_TRUE(sync_value
->Equals(&GetPreferenceValue(prefs::kHomePage
)));
878 TEST_F(ProfileSyncServicePreferenceTest
, DynamicManagedDefaultPreferences
) {
879 const PrefService::Preference
* pref
=
880 prefs_
->FindPreference(prefs::kHomePage
);
881 EXPECT_TRUE(pref
->IsDefaultValue());
882 CreateRootHelper
create_root(this, syncer::PREFERENCES
);
883 ASSERT_TRUE(StartSyncService(create_root
.callback(), false));
884 ASSERT_TRUE(create_root
.success());
885 EXPECT_TRUE(IsSynced(prefs::kHomePage
));
886 EXPECT_TRUE(pref
->IsDefaultValue());
887 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage
) == NULL
);
888 // Switch kHomePage to managed and set a different value.
889 scoped_ptr
<base::Value
> managed_value(
890 base::Value::CreateStringValue("http://example.com/managed"));
891 profile_
->GetTestingPrefService()->SetManagedPref(
892 prefs::kHomePage
, managed_value
->DeepCopy());
893 // The pref value should be the one dictated by policy.
894 EXPECT_TRUE(managed_value
->Equals(&GetPreferenceValue(prefs::kHomePage
)));
895 EXPECT_FALSE(pref
->IsDefaultValue());
896 // There should be no synced value.
897 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage
) == NULL
);
898 // Switch kHomePage back to unmanaged.
899 profile_
->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage
);
900 // The original value should be picked up.
901 EXPECT_TRUE(pref
->IsDefaultValue());
902 // There should still be no synced value.
903 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage
) == NULL
);