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