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/location.h" 14#include "base/stl_util.h" 15#include "base/strings/string_piece.h" 16#include "chrome/browser/invalidation/invalidation_service_factory.h" 17#include "chrome/browser/prefs/pref_model_associator.h" 18#include "chrome/browser/prefs/scoped_user_pref_update.h" 19#include "chrome/browser/signin/signin_manager.h" 20#include "chrome/browser/signin/signin_manager_factory.h" 21#include "chrome/browser/signin/token_service_factory.h" 22#include "chrome/browser/sync/abstract_profile_sync_service_test.h" 23#include "chrome/browser/sync/glue/generic_change_processor.h" 24#include "chrome/browser/sync/glue/sync_backend_host.h" 25#include "chrome/browser/sync/glue/ui_data_type_controller.h" 26#include "chrome/browser/sync/profile_sync_service_factory.h" 27#include "chrome/browser/sync/profile_sync_test_util.h" 28#include "chrome/browser/sync/test_profile_sync_service.h" 29#include "chrome/common/pref_names.h" 30#include "chrome/test/base/testing_pref_service_syncable.h" 31#include "chrome/test/base/testing_profile.h" 32#include "components/user_prefs/pref_registry_syncable.h" 33#include "google_apis/gaia/gaia_constants.h" 34#include "sync/api/sync_data.h" 35#include "sync/internal_api/public/base/model_type.h" 36#include "sync/internal_api/public/change_record.h" 37#include "sync/internal_api/public/data_type_debug_info_listener.h" 38#include "sync/internal_api/public/read_node.h" 39#include "sync/internal_api/public/read_transaction.h" 40#include "sync/internal_api/public/write_node.h" 41#include "sync/internal_api/public/write_transaction.h" 42#include "sync/protocol/preference_specifics.pb.h" 43#include "testing/gmock/include/gmock/gmock.h" 44#include "testing/gtest/include/gtest/gtest.h" 45 46using base::JSONReader; 47using browser_sync::GenericChangeProcessor; 48using browser_sync::SharedChangeProcessor; 49using browser_sync::UIDataTypeController; 50using syncer::ChangeRecord; 51using testing::_; 52using testing::Invoke; 53using testing::Return; 54 55typedef std::map<const std::string, const Value*> PreferenceValues; 56 57ACTION_P(CreateAndSaveChangeProcessor, change_processor) { 58 syncer::UserShare* user_share = arg0->GetUserShare(); 59 *change_processor = new GenericChangeProcessor(arg1, 60 arg2, 61 arg3, 62 user_share); 63 return *change_processor; 64} 65 66ACTION_P(ReturnNewDataTypeManagerWithDebugListener, debug_listener) { 67 return new browser_sync::DataTypeManagerImpl( 68 debug_listener, 69 arg1, 70 arg2, 71 arg3, 72 arg4, 73 arg5); 74} 75 76// TODO(zea): Refactor to remove the ProfileSyncService usage. 77class ProfileSyncServicePreferenceTest 78 : public AbstractProfileSyncServiceTest, 79 public syncer::DataTypeDebugInfoListener { 80 public: 81 int64 SetSyncedValue(const std::string& name, const Value& value) { 82 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 83 syncer::ReadNode root(&trans); 84 if (root.InitByTagLookup(syncer::ModelTypeToRootTag( 85 syncer::PREFERENCES)) != syncer::BaseNode::INIT_OK) { 86 return syncer::kInvalidId; 87 } 88 89 syncer::WriteNode tag_node(&trans); 90 syncer::WriteNode node(&trans); 91 92 if (tag_node.InitByClientTagLookup(syncer::PREFERENCES, name) == 93 syncer::BaseNode::INIT_OK) { 94 return WriteSyncedValue(name, value, &tag_node); 95 } 96 97 syncer::WriteNode::InitUniqueByCreationResult result = 98 node.InitUniqueByCreation(syncer::PREFERENCES, root, name); 99 if (result == syncer::WriteNode::INIT_SUCCESS) 100 return WriteSyncedValue(name, value, &node); 101 102 return syncer::kInvalidId; 103 } 104 105 // DataTypeDebugInfoListener implementation. 106 virtual void OnSingleDataTypeConfigureComplete( 107 const syncer::DataTypeConfigurationStats& configuration_stats) OVERRIDE { 108 association_stats_ = configuration_stats.association_stats; 109 } 110 virtual void OnConfigureComplete() OVERRIDE { 111 // Do nothing. 112 } 113 114 protected: 115 ProfileSyncServicePreferenceTest() 116 : debug_ptr_factory_(this), 117 example_url0_("http://example.com/0"), 118 example_url1_("http://example.com/1"), 119 example_url2_("http://example.com/2"), 120 not_synced_preference_name_("nonsense_pref_name"), 121 not_synced_preference_default_value_("default"), 122 non_default_charset_value_("foo") {} 123 124 virtual void SetUp() { 125 AbstractProfileSyncServiceTest::SetUp(); 126 profile_.reset(new TestingProfile()); 127 invalidation::InvalidationServiceFactory::GetInstance()-> 128 SetBuildOnlyFakeInvalidatorsForTest(true); 129 prefs_ = profile_->GetTestingPrefService(); 130 131 prefs_->registry()->RegisterStringPref( 132 not_synced_preference_name_.c_str(), 133 not_synced_preference_default_value_, 134 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 135 } 136 137 virtual void TearDown() { 138 profile_.reset(); 139 AbstractProfileSyncServiceTest::TearDown(); 140 } 141 142 int GetSyncPreferenceCount() { 143 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 144 syncer::ReadNode node(&trans); 145 if (node.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::PREFERENCES)) != 146 syncer::BaseNode::INIT_OK) 147 return 0; 148 return node.GetTotalNodeCount() - 1; 149 } 150 151 bool StartSyncService(const base::Closure& callback, 152 bool will_fail_association) { 153 if (sync_service_) 154 return false; 155 156 SigninManagerBase* signin = 157 SigninManagerFactory::GetForProfile(profile_.get()); 158 signin->SetAuthenticatedUsername("test"); 159 ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory( 160 profile_.get(), FakeOAuth2TokenService::BuildTokenService); 161 sync_service_ = static_cast<TestProfileSyncService*>( 162 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( 163 profile_.get(), &TestProfileSyncService::BuildAutoStartAsyncInit)); 164 sync_service_->set_backend_init_callback(callback); 165 pref_sync_service_ = reinterpret_cast<PrefModelAssociator*>( 166 prefs_->GetSyncableService(syncer::PREFERENCES)); 167 if (!pref_sync_service_) 168 return false; 169 ProfileSyncComponentsFactoryMock* components = 170 sync_service_->components_factory_mock(); 171 EXPECT_CALL(*components, GetSyncableServiceForType(syncer::PREFERENCES)). 172 WillOnce(Return(pref_sync_service_->AsWeakPtr())); 173 174 EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)). 175 WillOnce(ReturnNewDataTypeManagerWithDebugListener( 176 syncer::MakeWeakHandle(debug_ptr_factory_.GetWeakPtr()))); 177 dtc_ = new UIDataTypeController(syncer::PREFERENCES, 178 components, 179 profile_.get(), 180 sync_service_); 181 EXPECT_CALL(*components, CreateSharedChangeProcessor()). 182 WillOnce(Return(new SharedChangeProcessor())); 183 EXPECT_CALL(*components, CreateGenericChangeProcessor(_, _, _, _)). 184 WillOnce(CreateAndSaveChangeProcessor( 185 &change_processor_)); 186 sync_service_->RegisterDataTypeController(dtc_); 187 TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest( 188 GaiaConstants::kGaiaOAuth2LoginRefreshToken, "oauth2_login_token"); 189 TokenServiceFactory::GetForProfile(profile_.get())->IssueAuthTokenForTest( 190 GaiaConstants::kSyncService, "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 std::string ValueString(const Value& value) { 249 std::string serialized; 250 JSONStringValueSerializer json(&serialized); 251 json.Serialize(value); 252 return serialized; 253 } 254 255 scoped_ptr<TestingProfile> profile_; 256 TestingPrefServiceSyncable* prefs_; 257 258 UIDataTypeController* dtc_; 259 PrefModelAssociator* pref_sync_service_; 260 GenericChangeProcessor* change_processor_; 261 syncer::DataTypeAssociationStats association_stats_; 262 base::WeakPtrFactory<DataTypeDebugInfoListener> debug_ptr_factory_; 263 264 std::string example_url0_; 265 std::string example_url1_; 266 std::string example_url2_; 267 std::string not_synced_preference_name_; 268 std::string not_synced_preference_default_value_; 269 std::string non_default_charset_value_; 270}; 271 272class AddPreferenceEntriesHelper { 273 public: 274 AddPreferenceEntriesHelper(ProfileSyncServicePreferenceTest* test, 275 const PreferenceValues& entries) 276 : callback_(base::Bind( 277 &AddPreferenceEntriesHelper::AddPreferenceEntriesCallback, 278 base::Unretained(this), test, entries)), 279 success_(false) { 280 } 281 282 const base::Closure& callback() const { return callback_; } 283 bool success() { return success_; } 284 285 private: 286 void AddPreferenceEntriesCallback(ProfileSyncServicePreferenceTest* test, 287 const PreferenceValues& entries) { 288 if (!test->CreateRoot(syncer::PREFERENCES)) 289 return; 290 291 for (PreferenceValues::const_iterator i = entries.begin(); 292 i != entries.end(); ++i) { 293 if (test->SetSyncedValue(i->first, *i->second) == syncer::kInvalidId) 294 return; 295 } 296 success_ = true; 297 } 298 299 base::Closure callback_; 300 bool success_; 301}; 302 303TEST_F(ProfileSyncServicePreferenceTest, CreatePrefSyncData) { 304 prefs_->SetString(prefs::kHomePage, example_url0_); 305 CreateRootHelper create_root(this, syncer::PREFERENCES); 306 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 307 ASSERT_TRUE(create_root.success()); 308 309 const PrefService::Preference* pref = 310 prefs_->FindPreference(prefs::kHomePage); 311 syncer::SyncData sync_data; 312 EXPECT_TRUE(pref_sync_service_->CreatePrefSyncData(pref->name(), 313 *pref->GetValue(), &sync_data)); 314 EXPECT_EQ(std::string(prefs::kHomePage), sync_data.GetTag()); 315 const sync_pb::PreferenceSpecifics& specifics(sync_data.GetSpecifics(). 316 preference()); 317 EXPECT_EQ(std::string(prefs::kHomePage), specifics.name()); 318 319 scoped_ptr<Value> value(base::JSONReader::Read(specifics.value())); 320 EXPECT_TRUE(pref->GetValue()->Equals(value.get())); 321} 322 323TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationDoNotSyncDefaults) { 324 const PrefService::Preference* pref = 325 prefs_->FindPreference(prefs::kHomePage); 326 EXPECT_TRUE(pref->IsDefaultValue()); 327 CreateRootHelper create_root(this, syncer::PREFERENCES); 328 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 329 ASSERT_TRUE(create_root.success()); 330 EXPECT_TRUE(IsSynced(prefs::kHomePage)); 331 EXPECT_TRUE(pref->IsDefaultValue()); 332 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 333 EXPECT_TRUE(GetSyncedValue(not_synced_preference_name_) == NULL); 334} 335 336TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationEmptyCloud) { 337 prefs_->SetString(prefs::kHomePage, example_url0_); 338 { 339 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 340 ListValue* url_list = update.Get(); 341 url_list->Append(Value::CreateStringValue(example_url0_)); 342 url_list->Append(Value::CreateStringValue(example_url1_)); 343 } 344 CreateRootHelper create_root(this, syncer::PREFERENCES); 345 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 346 ASSERT_TRUE(create_root.success()); 347 348 scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage)); 349 ASSERT_TRUE(value.get()); 350 EXPECT_TRUE(GetPreferenceValue(prefs::kHomePage).Equals(value.get())); 351 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 352 ASSERT_TRUE(value.get()); 353 EXPECT_TRUE( 354 GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get())); 355} 356 357TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationCloudHasData) { 358 prefs_->SetString(prefs::kHomePage, example_url0_); 359 { 360 ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup); 361 ListValue* url_list = update.Get(); 362 url_list->Append(Value::CreateStringValue(example_url0_)); 363 url_list->Append(Value::CreateStringValue(example_url1_)); 364 } 365 366 PreferenceValues cloud_data; 367 cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_); 368 ListValue* urls_to_restore = new ListValue; 369 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 370 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 371 cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore; 372 cloud_data[prefs::kDefaultCharset] = 373 Value::CreateStringValue(non_default_charset_value_); 374 375 AddPreferenceEntriesHelper helper(this, cloud_data); 376 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 377 ASSERT_TRUE(helper.success()); 378 379 scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage)); 380 ASSERT_TRUE(value.get()); 381 std::string string_value; 382 EXPECT_TRUE(value->GetAsString(&string_value)); 383 EXPECT_EQ(example_url1_, string_value); 384 EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage)); 385 386 scoped_ptr<ListValue> expected_urls(new ListValue); 387 expected_urls->Append(Value::CreateStringValue(example_url1_)); 388 expected_urls->Append(Value::CreateStringValue(example_url2_)); 389 expected_urls->Append(Value::CreateStringValue(example_url0_)); 390 value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 391 ASSERT_TRUE(value.get()); 392 EXPECT_TRUE(value->Equals(expected_urls.get())); 393 EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup). 394 Equals(expected_urls.get())); 395 396 value.reset(GetSyncedValue(prefs::kDefaultCharset)); 397 ASSERT_TRUE(value.get()); 398 EXPECT_TRUE(value->GetAsString(&string_value)); 399 EXPECT_EQ(non_default_charset_value_, string_value); 400 EXPECT_EQ(non_default_charset_value_, 401 prefs_->GetString(prefs::kDefaultCharset)); 402 STLDeleteValues(&cloud_data); 403} 404 405TEST_F(ProfileSyncServicePreferenceTest, FailModelAssociation) { 406 ASSERT_TRUE(StartSyncService(base::Closure(), true)); 407 EXPECT_TRUE(sync_service_->HasUnrecoverableError()); 408} 409 410TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithDefaultValue) { 411 const PrefService::Preference* pref = 412 prefs_->FindPreference(prefs::kHomePage); 413 EXPECT_TRUE(pref->IsDefaultValue()); 414 415 CreateRootHelper create_root(this, syncer::PREFERENCES); 416 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 417 ASSERT_TRUE(create_root.success()); 418 419 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 420 profile_->GetPrefs()->Set(prefs::kHomePage, *expected); 421 422 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 423 ASSERT_TRUE(actual.get()); 424 EXPECT_TRUE(expected->Equals(actual.get())); 425} 426 427TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithValue) { 428 profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_); 429 CreateRootHelper create_root(this, syncer::PREFERENCES); 430 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 431 ASSERT_TRUE(create_root.success()); 432 433 scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_)); 434 profile_->GetPrefs()->Set(prefs::kHomePage, *expected); 435 436 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 437 ASSERT_TRUE(actual.get()); 438 EXPECT_TRUE(expected->Equals(actual.get())); 439} 440 441TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionUpdate) { 442 profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_); 443 CreateRootHelper create_root(this, syncer::PREFERENCES); 444 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 445 ASSERT_TRUE(create_root.success()); 446 447 scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_)); 448 int64 node_id = SetSyncedValue(prefs::kHomePage, *expected); 449 ASSERT_NE(node_id, syncer::kInvalidId); 450 { 451 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 452 change_processor_->ApplyChangesFromSyncModel( 453 &trans, 0, 454 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 455 node_id, ChangeRecord::ACTION_UPDATE)); 456 } 457 change_processor_->CommitChangesFromSyncModel(); 458 459 const Value& actual = GetPreferenceValue(prefs::kHomePage); 460 EXPECT_TRUE(expected->Equals(&actual)); 461} 462 463TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionAdd) { 464 CreateRootHelper create_root(this, syncer::PREFERENCES); 465 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 466 ASSERT_TRUE(create_root.success()); 467 468 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 469 int64 node_id = SetSyncedValue(prefs::kHomePage, *expected); 470 ASSERT_NE(node_id, syncer::kInvalidId); 471 { 472 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 473 change_processor_->ApplyChangesFromSyncModel( 474 &trans, 0, 475 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 476 node_id, ChangeRecord::ACTION_ADD)); 477 } 478 change_processor_->CommitChangesFromSyncModel(); 479 480 const Value& actual = GetPreferenceValue(prefs::kHomePage); 481 EXPECT_TRUE(expected->Equals(&actual)); 482 EXPECT_EQ(1U, 483 pref_sync_service_->registered_preferences().count(prefs::kHomePage)); 484} 485 486TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeUnknownPreference) { 487 CreateRootHelper create_root(this, syncer::PREFERENCES); 488 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 489 ASSERT_TRUE(create_root.success()); 490 491 scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_)); 492 int64 node_id = SetSyncedValue("unknown preference", *expected); 493 ASSERT_NE(node_id, syncer::kInvalidId); 494 { 495 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 496 change_processor_->ApplyChangesFromSyncModel( 497 &trans, 0, 498 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 499 node_id, ChangeRecord::ACTION_UPDATE)); 500 } 501 change_processor_->CommitChangesFromSyncModel(); 502 503 // Nothing interesting happens on the client when it gets an update 504 // of an unknown preference. We just should not crash. 505} 506 507TEST_F(ProfileSyncServicePreferenceTest, ManagedPreferences) { 508 // Make the homepage preference managed. 509 scoped_ptr<Value> managed_value( 510 Value::CreateStringValue("http://example.com")); 511 prefs_->SetManagedPref(prefs::kHomePage, managed_value->DeepCopy()); 512 513 CreateRootHelper create_root(this, syncer::PREFERENCES); 514 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 515 ASSERT_TRUE(create_root.success()); 516 517 // Changing the homepage preference should not sync anything. 518 scoped_ptr<Value> user_value( 519 Value::CreateStringValue("http://chromium..com")); 520 prefs_->SetUserPref(prefs::kHomePage, user_value->DeepCopy()); 521 EXPECT_EQ(NULL, GetSyncedValue(prefs::kHomePage)); 522 523 // An incoming sync transaction should change the user value, not the managed 524 // value. 525 scoped_ptr<Value> sync_value( 526 Value::CreateStringValue("http://crbug.com")); 527 int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value); 528 ASSERT_NE(node_id, syncer::kInvalidId); 529 { 530 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 531 change_processor_->ApplyChangesFromSyncModel( 532 &trans, 0, 533 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 534 node_id, ChangeRecord::ACTION_UPDATE)); 535 } 536 change_processor_->CommitChangesFromSyncModel(); 537 538 EXPECT_TRUE(managed_value->Equals(prefs_->GetManagedPref(prefs::kHomePage))); 539 EXPECT_TRUE(sync_value->Equals(prefs_->GetUserPref(prefs::kHomePage))); 540} 541 542// List preferences have special handling at association time due to our ability 543// to merge the local and sync value. Make sure the merge logic doesn't merge 544// managed preferences. 545TEST_F(ProfileSyncServicePreferenceTest, ManagedListPreferences) { 546 // Make the list of urls to restore on startup managed. 547 ListValue managed_value; 548 managed_value.Append(Value::CreateStringValue(example_url0_)); 549 managed_value.Append(Value::CreateStringValue(example_url1_)); 550 prefs_->SetManagedPref(prefs::kURLsToRestoreOnStartup, 551 managed_value.DeepCopy()); 552 553 // Set a cloud version. 554 PreferenceValues cloud_data; 555 scoped_ptr<ListValue> urls_to_restore(new ListValue); 556 urls_to_restore->Append(Value::CreateStringValue(example_url1_)); 557 urls_to_restore->Append(Value::CreateStringValue(example_url2_)); 558 cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore.get(); 559 560 // Start sync and verify the synced value didn't get merged. 561 AddPreferenceEntriesHelper helper(this, cloud_data); 562 ASSERT_TRUE(StartSyncService(helper.callback(), false)); 563 ASSERT_TRUE(helper.success()); 564 scoped_ptr<const Value> actual( 565 GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 566 EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get())); 567 568 // Changing the user's urls to restore on startup pref should not sync 569 // anything. 570 ListValue user_value; 571 user_value.Append(Value::CreateStringValue("http://chromium.org")); 572 prefs_->SetUserPref(prefs::kURLsToRestoreOnStartup, user_value.DeepCopy()); 573 actual.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup)); 574 EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get())); 575 576 // An incoming sync transaction should change the user value, not the managed 577 // value. 578 ListValue sync_value; 579 sync_value.Append(Value::CreateStringValue("http://crbug.com")); 580 int64 node_id = SetSyncedValue(prefs::kURLsToRestoreOnStartup, sync_value); 581 ASSERT_NE(node_id, syncer::kInvalidId); 582 { 583 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 584 change_processor_->ApplyChangesFromSyncModel( 585 &trans, 0, 586 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 587 node_id, ChangeRecord::ACTION_UPDATE)); 588 } 589 change_processor_->CommitChangesFromSyncModel(); 590 591 EXPECT_TRUE(managed_value.Equals( 592 prefs_->GetManagedPref(prefs::kURLsToRestoreOnStartup))); 593 EXPECT_TRUE(sync_value.Equals( 594 prefs_->GetUserPref(prefs::kURLsToRestoreOnStartup))); 595} 596 597TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedPreferences) { 598 CreateRootHelper create_root(this, syncer::PREFERENCES); 599 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 600 ASSERT_TRUE(create_root.success()); 601 602 scoped_ptr<Value> initial_value( 603 Value::CreateStringValue("http://example.com/initial")); 604 profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value); 605 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 606 ASSERT_TRUE(actual.get()); 607 EXPECT_TRUE(initial_value->Equals(actual.get())); 608 609 // Switch kHomePage to managed and set a different value. 610 scoped_ptr<Value> managed_value( 611 Value::CreateStringValue("http://example.com/managed")); 612 profile_->GetTestingPrefService()->SetManagedPref( 613 prefs::kHomePage, managed_value->DeepCopy()); 614 615 // The pref value should be the one dictated by policy. 616 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 617 618 // Switch kHomePage back to unmanaged. 619 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 620 621 // The original value should be picked up. 622 EXPECT_TRUE(initial_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 623} 624 625TEST_F(ProfileSyncServicePreferenceTest, 626 DynamicManagedPreferencesWithSyncChange) { 627 CreateRootHelper create_root(this, syncer::PREFERENCES); 628 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 629 ASSERT_TRUE(create_root.success()); 630 631 scoped_ptr<Value> initial_value( 632 Value::CreateStringValue("http://example.com/initial")); 633 profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value); 634 scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage)); 635 EXPECT_TRUE(initial_value->Equals(actual.get())); 636 637 // Switch kHomePage to managed and set a different value. 638 scoped_ptr<Value> managed_value( 639 Value::CreateStringValue("http://example.com/managed")); 640 profile_->GetTestingPrefService()->SetManagedPref( 641 prefs::kHomePage, managed_value->DeepCopy()); 642 643 // Change the sync value. 644 scoped_ptr<Value> sync_value( 645 Value::CreateStringValue("http://example.com/sync")); 646 int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value); 647 ASSERT_NE(node_id, syncer::kInvalidId); 648 { 649 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 650 change_processor_->ApplyChangesFromSyncModel( 651 &trans, 0, 652 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList( 653 node_id, ChangeRecord::ACTION_ADD)); 654 } 655 change_processor_->CommitChangesFromSyncModel(); 656 657 // The pref value should still be the one dictated by policy. 658 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 659 660 // Switch kHomePage back to unmanaged. 661 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 662 663 // Sync value should be picked up. 664 EXPECT_TRUE(sync_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 665} 666 667TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedDefaultPreferences) { 668 const PrefService::Preference* pref = 669 prefs_->FindPreference(prefs::kHomePage); 670 EXPECT_TRUE(pref->IsDefaultValue()); 671 CreateRootHelper create_root(this, syncer::PREFERENCES); 672 ASSERT_TRUE(StartSyncService(create_root.callback(), false)); 673 ASSERT_TRUE(create_root.success()); 674 EXPECT_TRUE(IsSynced(prefs::kHomePage)); 675 EXPECT_TRUE(pref->IsDefaultValue()); 676 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 677 // Switch kHomePage to managed and set a different value. 678 scoped_ptr<Value> managed_value( 679 Value::CreateStringValue("http://example.com/managed")); 680 profile_->GetTestingPrefService()->SetManagedPref( 681 prefs::kHomePage, managed_value->DeepCopy()); 682 // The pref value should be the one dictated by policy. 683 EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage))); 684 EXPECT_FALSE(pref->IsDefaultValue()); 685 // There should be no synced value. 686 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 687 // Switch kHomePage back to unmanaged. 688 profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage); 689 // The original value should be picked up. 690 EXPECT_TRUE(pref->IsDefaultValue()); 691 // There should still be no synced value. 692 EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL); 693} 694