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/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.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" 47 48using base::JSONReader; 49using browser_sync::GenericChangeProcessor; 50using browser_sync::SharedChangeProcessor; 51using browser_sync::UIDataTypeController; 52using syncer::ChangeRecord; 53using testing::_; 54using testing::Invoke; 55using testing::Return; 56 57typedef std::map<const std::string, const Value*> PreferenceValues; 58 59ACTION_P(CreateAndSaveChangeProcessor, change_processor) { 60 syncer::UserShare* user_share = arg0->GetUserShare(); 61 *change_processor = new GenericChangeProcessor(arg1, 62 arg2, 63 arg3, 64 user_share); 65 return *change_processor; 66} 67 68ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) { 69 return new browser_sync::DataTypeManagerImpl( 70 debug_listener, 71 arg1, 72 arg2, 73 arg3, 74 arg4, 75 arg5); 76} 77 78// TODO(zea): Refactor to remove the ProfileSyncService usage. 79class ProfileSyncServicePreferenceTest 80 : public AbstractProfileSyncServiceTest, 81 public syncer::DataTypeDebugInfoListener { 82 public: 83 int64 SetSyncedValue(const std::string& name, const 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; 89 } 90 91 syncer::WriteNode tag_node(&trans); 92 syncer::WriteNode node(&trans); 93 94 if (tag_node.InitByClientTagLookup(syncer::PREFERENCES, name) == 95 syncer::BaseNode::INIT_OK) { 96 return WriteSyncedValue(name, value, &tag_node); 97 } 98 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); 103 104 return syncer::kInvalidId; 105 } 106 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; 113 } 114 115 protected: 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") {} 124 125 virtual void SetUp() { 126 AbstractProfileSyncServiceTest::SetUp(); 127 TestingProfile::Builder builder; 128 builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), 129 FakeOAuth2TokenService::BuildTokenService); 130 profile_ = builder.Build().Pass(); 131 invalidation::InvalidationServiceFactory::GetInstance()-> 132 SetBuildOnlyFakeInvalidatorsForTest(true); 133 prefs_ = profile_->GetTestingPrefService(); 134 135 prefs_->registry()->RegisterStringPref( 136 not_synced_preference_name_.c_str(), 137 not_synced_preference_default_value_, 138 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 139 } 140 141 virtual void TearDown() { 142 profile_.reset(); 143 AbstractProfileSyncServiceTest::TearDown(); 144 } 145 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) 151 return 0; 152 return node.GetTotalNodeCount() - 1; 153 } 154 155 bool StartSyncService(const base::Closure& callback, 156 bool will_fail_association) { 157 if (sync_service_) 158 return false; 159 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_) 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(syncer::PREFERENCES, 180 components, 181 profile_.get(), 182 sync_service_); 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"); 191 192 sync_service_->Initialize(); 193 base::MessageLoop::current()->Run(); 194 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); 200 } 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); 205 206 return true; 207 } 208 209 const Value& GetPreferenceValue(const std::string& name) { 210 const PrefService::Preference* preference = 211 prefs_->FindPreference(name.c_str()); 212 return *preference->GetValue(); 213 } 214 215 // Caller gets ownership of the returned value. 216 const Value* GetSyncedValue(const std::string& name) { 217 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 218 syncer::ReadNode node(&trans); 219 220 if (node.InitByClientTagLookup(syncer::PREFERENCES, name) != 221 syncer::BaseNode::INIT_OK) { 222 return NULL; 223 } 224 225 const sync_pb::PreferenceSpecifics& specifics( 226 node.GetEntitySpecifics().preference()); 227 228 return base::JSONReader::Read(specifics.value()); 229 } 230 231 int64 WriteSyncedValue(const std::string& name, 232 const Value& value, 233 syncer::WriteNode* node) { 234 syncer::SyncData sync_data; 235 if (!pref_sync_service_->CreatePrefSyncData(name, 236 value, 237 &sync_data)) { 238 return syncer::kInvalidId; 239 } 240 node->SetEntitySpecifics(sync_data.GetSpecifics()); 241 return node->GetId(); 242 } 243 244 bool IsSynced(const std::string& pref_name) { 245 return pref_sync_service_->registered_preferences().count(pref_name) > 0; 246 } 247 248 bool HasSyncData(const std::string& pref_name) { 249 return pref_sync_service_->IsPrefSynced(pref_name); 250 } 251 252 std::string ValueString(const Value& value) { 253 std::string serialized; 254 JSONStringValueSerializer json(&serialized); 255 json.Serialize(value); 256 return serialized; 257 } 258 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); 263 } 264 static bool IsOldMigratedPreference(const char* old_preference_name) { 265 return PrefModelAssociator::IsOldMigratedPreference(old_preference_name); 266 } 267 268 scoped_ptr<TestingProfile> profile_; 269 TestingPrefServiceSyncable* prefs_; 270 271 UIDataTypeController* dtc_; 272 PrefModelAssociator* pref_sync_service_; 273 GenericChangeProcessor* change_processor_; 274 syncer::DataTypeAssociationStats association_stats_; 275 base::WeakPtrFactory<DataTypeDebugInfoListener> debug_ptr_factory_; 276 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_; 283}; 284 285class AddPreferenceEntriesHelper { 286 public: 287 AddPreferenceEntriesHelper(ProfileSyncServicePreferenceTest* test, 288 const PreferenceValues& entries) 289 : callback_(base::Bind( 290 &AddPreferenceEntriesHelper::AddPreferenceEntriesCallback, 291 base::Unretained(this), test, entries)), 292 success_(false) { 293 } 294 295 const base::Closure& callback() const { return callback_; } 296 bool success() { return success_; } 297 298 private: 299 void AddPreferenceEntriesCallback(ProfileSyncServicePreferenceTest* test, 300 const PreferenceValues& entries) { 301 if (!test->CreateRoot(syncer::PREFERENCES)) 302 return; 303 304 for (PreferenceValues::const_iterator i = entries.begin(); 305 i != entries.end(); ++i) { 306 if (test->SetSyncedValue(i->first, *i->second) == syncer::kInvalidId) 307 return; 308 } 309 success_ = true; 310 } 311 312 base::Closure callback_; 313 bool success_; 314}; 315 316TEST_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()); 321 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(). 329 preference()); 330 EXPECT_EQ(std::string(prefs::kHomePage), specifics.name()); 331 332 scoped_ptr<Value> value(base::JSONReader::Read(specifics.value())); 333 EXPECT_TRUE(pref->GetValue()->Equals(value.get())); 334} 335 336TEST_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); 347} 348 349TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationEmptyCloud) { 350 prefs_->SetString(prefs::kHomePage, example_url0_); 351 { 352 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 353 ListValue* url_list = update.Get(); 354 url_list->Append(Value::CreateStringValue(example_url0_)); 355 url_list->Append(Value::CreateStringValue(example_url1_)); 356 } 357 CreateRootHelper create_root(this, syncer::PREFERENCES); 358 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 359 ASSERT_TRUE(create_root.success()); 360 361 scoped_ptr<const 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()); 366 EXPECT_TRUE( 367 GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get())); 368} 369 370TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationCloudHasData) { 371 prefs_->SetString(prefs::kHomePage, example_url0_); 372 { 373 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 374 ListValue* url_list = update.Get(); 375 url_list->Append(Value::CreateStringValue(example_url0_)); 376 url_list->Append(Value::CreateStringValue(example_url1_)); 377 } 378 379 PreferenceValues cloud_data; 380 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 381 cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_); 382 ListValue* urls_to_restore = new ListValue; 383 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 384 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 385 cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore; 386 cloud_data[prefs::kDefaultCharset] = 387 Value::CreateStringValue(non_default_charset_value_); 388 389 AddPreferenceEntriesHelper helper(this, cloud_data); 390 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 391 ASSERT_TRUE(helper.success()); 392 393 scoped_ptr<const 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)); 399 400 scoped_ptr<ListValue> expected_urls(new ListValue); 401 expected_urls->Append(Value::CreateStringValue(example_url1_)); 402 expected_urls->Append(Value::CreateStringValue(example_url2_)); 403 expected_urls->Append(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())); 409 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)); 416} 417 418TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationMigrateOldData) { 419 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup)); 420 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld)); 421 422 PreferenceValues cloud_data; 423 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 424 ListValue* urls_to_restore = new ListValue; 425 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 426 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 427 cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore; 428 429 AddPreferenceEntriesHelper helper(this, cloud_data); 430 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 431 ASSERT_TRUE(helper.success()); 432 433 // Expect that the new preference data contains the old pref's values. 434 scoped_ptr<ListValue> expected_urls(new ListValue); 435 expected_urls->Append(Value::CreateStringValue(example_url1_)); 436 expected_urls->Append(Value::CreateStringValue(example_url2_)); 437 438 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup)); 439 scoped_ptr<const Value> value(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 440 ASSERT_TRUE(value.get()); 441 EXPECT_TRUE(value->Equals(expected_urls.get())); 442 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup). 443 Equals(expected_urls.get())); 444 445 // The old preference value should be the same. 446 expected_urls.reset(new ListValue); 447 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld)); 448 ASSERT_TRUE(value.get()); 449 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld). 450 Equals(expected_urls.get())); 451} 452 453TEST_F(ProfileSyncServicePreferenceTest, 454 ModelAssociationCloudHasOldMigratedData) { 455 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup)); 456 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld)); 457 prefs_->SetString(prefs::kHomePage, example_url0_); 458 { 459 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 460 ListValue* url_list = update.Get(); 461 url_list->Append(Value::CreateStringValue(example_url0_)); 462 url_list->Append(Value::CreateStringValue(example_url1_)); 463 } 464 465 PreferenceValues cloud_data; 466 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 467 cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_); 468 ListValue* urls_to_restore = new ListValue; 469 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 470 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 471 cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore; 472 473 AddPreferenceEntriesHelper helper(this, cloud_data); 474 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 475 ASSERT_TRUE(helper.success()); 476 477 scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage)); 478 ASSERT_TRUE(value.get()); 479 std::string string_value; 480 EXPECT_TRUE(value->GetAsString(&string_value)); 481 EXPECT_EQ(example_url1_, string_value); 482 EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage)); 483 484 // Expect that the new preference data contains the merged old prefs values. 485 scoped_ptr<ListValue> expected_urls(new ListValue); 486 expected_urls->Append(Value::CreateStringValue(example_url1_)); 487 expected_urls->Append(Value::CreateStringValue(example_url2_)); 488 expected_urls->Append(Value::CreateStringValue(example_url0_)); 489 490 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup)); 491 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 492 ASSERT_TRUE(value.get()); 493 EXPECT_TRUE(value->Equals(expected_urls.get())); 494 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup). 495 Equals(expected_urls.get())); 496 497 // The old preference name should also contain the merged sync data. 498 expected_urls.reset(new ListValue); 499 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld)); 500 ASSERT_TRUE(value.get()); 501 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld). 502 Equals(expected_urls.get())); 503} 504 505TEST_F(ProfileSyncServicePreferenceTest, 506 ModelAssociationCloudHasNewMigratedData) { 507 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup)); 508 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld)); 509 prefs_->SetString(prefs::kHomePage, example_url0_); 510 { 511 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartupOld); 512 ListValue* url_list = update.Get(); 513 url_list->Append(Value::CreateStringValue(example_url0_)); 514 url_list->Append(Value::CreateStringValue(example_url1_)); 515 } 516 517 PreferenceValues cloud_data; 518 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 519 cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_); 520 ListValue* urls_to_restore = new ListValue; 521 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 522 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 523 cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore; 524 525 AddPreferenceEntriesHelper helper(this, cloud_data); 526 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 527 ASSERT_TRUE(helper.success()); 528 529 scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage)); 530 ASSERT_TRUE(value.get()); 531 std::string string_value; 532 EXPECT_TRUE(value->GetAsString(&string_value)); 533 EXPECT_EQ(example_url1_, string_value); 534 EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage)); 535 536 // Expect that the cloud data under the new migrated preference name sticks. 537 scoped_ptr<ListValue> expected_urls(new ListValue); 538 expected_urls->Append(Value::CreateStringValue(example_url1_)); 539 expected_urls->Append(Value::CreateStringValue(example_url2_)); 540 541 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup)); 542 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 543 ASSERT_TRUE(value.get()); 544 EXPECT_TRUE(value->Equals(expected_urls.get())); 545 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup). 546 Equals(expected_urls.get())); 547 548 // The old preference data should still be here, though not synced. 549 expected_urls.reset(new ListValue); 550 expected_urls->Append(Value::CreateStringValue(example_url0_)); 551 expected_urls->Append(Value::CreateStringValue(example_url1_)); 552 553 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld)); 554 ASSERT_FALSE(value.get()); 555 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld). 556 Equals(expected_urls.get())); 557} 558 559TEST_F(ProfileSyncServicePreferenceTest, 560 ModelAssociationCloudAddsOldAndNewMigratedData) { 561 ASSERT_TRUE(IsMigratedPreference(prefs::kURLsToRestoreOnStartup)); 562 ASSERT_TRUE(IsOldMigratedPreference(prefs::kURLsToRestoreOnStartupOld)); 563 prefs_->SetString(prefs::kHomePage, example_url0_); 564 { 565 ListPrefUpdate update_old(prefs_, prefs::kURLsToRestoreOnStartupOld); 566 ListValue* url_list_old = update_old.Get(); 567 url_list_old->Append(Value::CreateStringValue(example_url0_)); 568 url_list_old->Append(Value::CreateStringValue(example_url1_)); 569 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 570 ListValue* url_list = update.Get(); 571 url_list->Append(Value::CreateStringValue(example_url1_)); 572 url_list->Append(Value::CreateStringValue(example_url2_)); 573 } 574 575 PreferenceValues cloud_data; 576 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 577 cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_); 578 579 AddPreferenceEntriesHelper helper(this, cloud_data); 580 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 581 ASSERT_TRUE(helper.success()); 582 583 scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage)); 584 ASSERT_TRUE(value.get()); 585 std::string string_value; 586 EXPECT_TRUE(value->GetAsString(&string_value)); 587 EXPECT_EQ(example_url1_, string_value); 588 EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage)); 589 590 // Expect that the cloud data under the new migrated preference name sticks. 591 scoped_ptr<ListValue> expected_urls(new ListValue); 592 expected_urls->Append(Value::CreateStringValue(example_url1_)); 593 expected_urls->Append(Value::CreateStringValue(example_url2_)); 594 595 ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup)); 596 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 597 ASSERT_TRUE(value.get()); 598 EXPECT_TRUE(value->Equals(expected_urls.get())); 599 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup). 600 Equals(expected_urls.get())); 601 602 // Should not have synced in the old startup url values. 603 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld)); 604 ASSERT_FALSE(value.get()); 605 EXPECT_FALSE(GetPreferenceValue(prefs::kURLsToRestoreOnStartupOld). 606 Equals(expected_urls.get())); 607} 608 609TEST_F(ProfileSyncServicePreferenceTest, FailModelAssociation) { 610 ASSERT_TRUE(StartSyncService(base::Closure(), true)); 611 EXPECT_TRUE(sync_service_->HasUnrecoverableError()); 612} 613 614TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithDefaultValue) { 615 const PrefService::Preference* pref = 616 prefs_->FindPreference(prefs::kHomePage); 617 EXPECT_TRUE(pref->IsDefaultValue()); 618 619 CreateRootHelper create_root(this, syncer::PREFERENCES); 620 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 621 ASSERT_TRUE(create_root.success()); 622 623 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 624 profile_->GetPrefs()->Set(prefs::kHomePage, *expected); 625 626 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 627 ASSERT_TRUE(actual.get()); 628 EXPECT_TRUE(expected->Equals(actual.get())); 629} 630 631TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithValue) { 632 profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_); 633 CreateRootHelper create_root(this, syncer::PREFERENCES); 634 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 635 ASSERT_TRUE(create_root.success()); 636 637 scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_)); 638 profile_->GetPrefs()->Set(prefs::kHomePage, *expected); 639 640 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 641 ASSERT_TRUE(actual.get()); 642 EXPECT_TRUE(expected->Equals(actual.get())); 643} 644 645TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionUpdate) { 646 profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_); 647 CreateRootHelper create_root(this, syncer::PREFERENCES); 648 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 649 ASSERT_TRUE(create_root.success()); 650 651 scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_)); 652 int64 node_id = SetSyncedValue(prefs::kHomePage, *expected); 653 ASSERT_NE(node_id, syncer::kInvalidId); 654 { 655 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 656 change_processor_->ApplyChangesFromSyncModel( 657 &trans, 0, 658 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 659 node_id, ChangeRecord::ACTION_UPDATE)); 660 } 661 change_processor_->CommitChangesFromSyncModel(); 662 663 const Value& actual = GetPreferenceValue(prefs::kHomePage); 664 EXPECT_TRUE(expected->Equals(&actual)); 665} 666 667TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionAdd) { 668 CreateRootHelper create_root(this, syncer::PREFERENCES); 669 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 670 ASSERT_TRUE(create_root.success()); 671 672 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 673 int64 node_id = SetSyncedValue(prefs::kHomePage, *expected); 674 ASSERT_NE(node_id, syncer::kInvalidId); 675 { 676 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 677 change_processor_->ApplyChangesFromSyncModel( 678 &trans, 0, 679 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 680 node_id, ChangeRecord::ACTION_ADD)); 681 } 682 change_processor_->CommitChangesFromSyncModel(); 683 684 const Value& actual = GetPreferenceValue(prefs::kHomePage); 685 EXPECT_TRUE(expected->Equals(&actual)); 686 EXPECT_EQ(1U, 687 pref_sync_service_->registered_preferences().count(prefs::kHomePage)); 688} 689 690TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeUnknownPreference) { 691 CreateRootHelper create_root(this, syncer::PREFERENCES); 692 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 693 ASSERT_TRUE(create_root.success()); 694 695 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 696 int64 node_id = SetSyncedValue("unknown preference", *expected); 697 ASSERT_NE(node_id, syncer::kInvalidId); 698 { 699 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 700 change_processor_->ApplyChangesFromSyncModel( 701 &trans, 0, 702 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 703 node_id, ChangeRecord::ACTION_UPDATE)); 704 } 705 change_processor_->CommitChangesFromSyncModel(); 706 707 // Nothing interesting happens on the client when it gets an update 708 // of an unknown preference. We just should not crash. 709} 710 711TEST_F(ProfileSyncServicePreferenceTest, ManagedPreferences) { 712 // Make the homepage preference managed. 713 scoped_ptr<Value> managed_value( 714 Value::CreateStringValue("http://example.com")); 715 prefs_->SetManagedPref(prefs::kHomePage, managed_value->DeepCopy()); 716 717 CreateRootHelper create_root(this, syncer::PREFERENCES); 718 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 719 ASSERT_TRUE(create_root.success()); 720 721 // Changing the homepage preference should not sync anything. 722 scoped_ptr<Value> user_value( 723 Value::CreateStringValue("http://chromium..com")); 724 prefs_->SetUserPref(prefs::kHomePage, user_value->DeepCopy()); 725 EXPECT_EQ(NULL, GetSyncedValue(prefs::kHomePage)); 726 727 // An incoming sync transaction should change the user value, not the managed 728 // value. 729 scoped_ptr<Value> sync_value( 730 Value::CreateStringValue("http://crbug.com")); 731 int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value); 732 ASSERT_NE(node_id, syncer::kInvalidId); 733 { 734 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 735 change_processor_->ApplyChangesFromSyncModel( 736 &trans, 0, 737 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 738 node_id, ChangeRecord::ACTION_UPDATE)); 739 } 740 change_processor_->CommitChangesFromSyncModel(); 741 742 EXPECT_TRUE(managed_value->Equals(prefs_->GetManagedPref(prefs::kHomePage))); 743 EXPECT_TRUE(sync_value->Equals(prefs_->GetUserPref(prefs::kHomePage))); 744} 745 746// List preferences have special handling at association time due to our ability 747// to merge the local and sync value. Make sure the merge logic doesn't merge 748// managed preferences. 749TEST_F(ProfileSyncServicePreferenceTest, ManagedListPreferences) { 750 // Make the list of urls to restore on startup managed. 751 ListValue managed_value; 752 managed_value.Append(Value::CreateStringValue(example_url0_)); 753 managed_value.Append(Value::CreateStringValue(example_url1_)); 754 prefs_->SetManagedPref(prefs::kURLsToRestoreOnStartup, 755 managed_value.DeepCopy()); 756 757 // Set a cloud version. 758 PreferenceValues cloud_data; 759 STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data); 760 ListValue* urls_to_restore = new ListValue; 761 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 762 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 763 cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore; 764 765 // Start sync and verify the synced value didn't get merged. 766 AddPreferenceEntriesHelper helper(this, cloud_data); 767 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 768 ASSERT_TRUE(helper.success()); 769 scoped_ptr<const Value> actual( 770 GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 771 EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get())); 772 773 // Changing the user's urls to restore on startup pref should not sync 774 // anything. 775 ListValue user_value; 776 user_value.Append(Value::CreateStringValue("http://chromium.org")); 777 prefs_->SetUserPref(prefs::kURLsToRestoreOnStartup, user_value.DeepCopy()); 778 actual.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 779 EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get())); 780 781 // An incoming sync transaction should change the user value, not the managed 782 // value. 783 ListValue sync_value; 784 sync_value.Append(Value::CreateStringValue("http://crbug.com")); 785 int64 node_id = SetSyncedValue(prefs::kURLsToRestoreOnStartup, sync_value); 786 ASSERT_NE(node_id, syncer::kInvalidId); 787 { 788 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 789 change_processor_->ApplyChangesFromSyncModel( 790 &trans, 0, 791 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 792 node_id, ChangeRecord::ACTION_UPDATE)); 793 } 794 change_processor_->CommitChangesFromSyncModel(); 795 796 EXPECT_TRUE(managed_value.Equals( 797 prefs_->GetManagedPref(prefs::kURLsToRestoreOnStartup))); 798 EXPECT_TRUE(sync_value.Equals( 799 prefs_->GetUserPref(prefs::kURLsToRestoreOnStartup))); 800} 801 802TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedPreferences) { 803 CreateRootHelper create_root(this, syncer::PREFERENCES); 804 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 805 ASSERT_TRUE(create_root.success()); 806 807 scoped_ptr<Value> initial_value( 808 Value::CreateStringValue("http://example.com/initial")); 809 profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value); 810 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 811 ASSERT_TRUE(actual.get()); 812 EXPECT_TRUE(initial_value->Equals(actual.get())); 813 814 // Switch kHomePage to managed and set a different value. 815 scoped_ptr<Value> managed_value( 816 Value::CreateStringValue("http://example.com/managed")); 817 profile_->GetTestingPrefService()->SetManagedPref( 818 prefs::kHomePage, managed_value->DeepCopy()); 819 820 // The pref value should be the one dictated by policy. 821 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 822 823 // Switch kHomePage back to unmanaged. 824 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 825 826 // The original value should be picked up. 827 EXPECT_TRUE(initial_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 828} 829 830TEST_F(ProfileSyncServicePreferenceTest, 831 DynamicManagedPreferencesWithSyncChange) { 832 CreateRootHelper create_root(this, syncer::PREFERENCES); 833 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 834 ASSERT_TRUE(create_root.success()); 835 836 scoped_ptr<Value> initial_value( 837 Value::CreateStringValue("http://example.com/initial")); 838 profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value); 839 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 840 EXPECT_TRUE(initial_value->Equals(actual.get())); 841 842 // Switch kHomePage to managed and set a different value. 843 scoped_ptr<Value> managed_value( 844 Value::CreateStringValue("http://example.com/managed")); 845 profile_->GetTestingPrefService()->SetManagedPref( 846 prefs::kHomePage, managed_value->DeepCopy()); 847 848 // Change the sync value. 849 scoped_ptr<Value> sync_value( 850 Value::CreateStringValue("http://example.com/sync")); 851 int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value); 852 ASSERT_NE(node_id, syncer::kInvalidId); 853 { 854 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 855 change_processor_->ApplyChangesFromSyncModel( 856 &trans, 0, 857 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 858 node_id, ChangeRecord::ACTION_ADD)); 859 } 860 change_processor_->CommitChangesFromSyncModel(); 861 862 // The pref value should still be the one dictated by policy. 863 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 864 865 // Switch kHomePage back to unmanaged. 866 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 867 868 // Sync value should be picked up. 869 EXPECT_TRUE(sync_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 870} 871 872TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedDefaultPreferences) { 873 const PrefService::Preference* pref = 874 prefs_->FindPreference(prefs::kHomePage); 875 EXPECT_TRUE(pref->IsDefaultValue()); 876 CreateRootHelper create_root(this, syncer::PREFERENCES); 877 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 878 ASSERT_TRUE(create_root.success()); 879 EXPECT_TRUE(IsSynced(prefs::kHomePage)); 880 EXPECT_TRUE(pref->IsDefaultValue()); 881 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 882 // Switch kHomePage to managed and set a different value. 883 scoped_ptr<Value> managed_value( 884 Value::CreateStringValue("http://example.com/managed")); 885 profile_->GetTestingPrefService()->SetManagedPref( 886 prefs::kHomePage, managed_value->DeepCopy()); 887 // The pref value should be the one dictated by policy. 888 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 889 EXPECT_FALSE(pref->IsDefaultValue()); 890 // There should be no synced value. 891 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 892 // Switch kHomePage back to unmanaged. 893 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 894 // The original value should be picked up. 895 EXPECT_TRUE(pref->IsDefaultValue()); 896 // There should still be no synced value. 897 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 898} 899