Home | History | Annotate | Download | only in search_engines
      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 "base/memory/scoped_ptr.h"
      6 #include "base/memory/scoped_vector.h"
      7 #include "base/run_loop.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "base/time/time.h"
     11 #include "chrome/browser/search_engines/template_url.h"
     12 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
     13 #include "chrome/browser/search_engines/template_url_service.h"
     14 #include "chrome/browser/search_engines/template_url_service_factory.h"
     15 #include "chrome/browser/search_engines/template_url_service_test_util.h"
     16 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
     17 #include "chrome/common/pref_names.h"
     18 #include "chrome/common/url_constants.h"
     19 #include "chrome/test/base/testing_pref_service_syncable.h"
     20 #include "chrome/test/base/testing_profile.h"
     21 #include "extensions/common/constants.h"
     22 #include "net/base/net_util.h"
     23 #include "sync/api/sync_change_processor_wrapper_for_test.h"
     24 #include "sync/api/sync_error_factory.h"
     25 #include "sync/api/sync_error_factory_mock.h"
     26 #include "sync/protocol/search_engine_specifics.pb.h"
     27 #include "sync/protocol/sync.pb.h"
     28 #include "testing/gtest/include/gtest/gtest.h"
     29 
     30 using base::ASCIIToUTF16;
     31 using base::UTF8ToUTF16;
     32 using base::Time;
     33 
     34 namespace {
     35 
     36 // Extract the GUID from a search engine syncer::SyncData.
     37 std::string GetGUID(const syncer::SyncData& sync_data) {
     38   return sync_data.GetSpecifics().search_engine().sync_guid();
     39 }
     40 
     41 // Extract the URL from a search engine syncer::SyncData.
     42 std::string GetURL(const syncer::SyncData& sync_data) {
     43   return sync_data.GetSpecifics().search_engine().url();
     44 }
     45 
     46 // Extract the keyword from a search engine syncer::SyncData.
     47 std::string GetKeyword(const syncer::SyncData& sync_data) {
     48   return sync_data.GetSpecifics().search_engine().keyword();
     49 }
     50 
     51 // Much like TemplateURLService::CreateSyncDataFromTemplateURL(), but allows the
     52 // caller to override the keyword, URL, or GUID fields with empty strings, in
     53 // order to create custom data that should be handled specially when synced to a
     54 // client.
     55 syncer::SyncData CreateCustomSyncData(const TemplateURL& turl,
     56                               bool autogenerate_keyword,
     57                               const std::string& url,
     58                               const std::string& sync_guid) {
     59   sync_pb::EntitySpecifics specifics;
     60   sync_pb::SearchEngineSpecifics* se_specifics =
     61       specifics.mutable_search_engine();
     62   se_specifics->set_short_name(base::UTF16ToUTF8(turl.short_name()));
     63   se_specifics->set_keyword(
     64       autogenerate_keyword ? std::string() : base::UTF16ToUTF8(turl.keyword()));
     65   se_specifics->set_favicon_url(turl.favicon_url().spec());
     66   se_specifics->set_url(url);
     67   se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
     68   se_specifics->set_originating_url(turl.originating_url().spec());
     69   se_specifics->set_date_created(turl.date_created().ToInternalValue());
     70   se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
     71   se_specifics->set_show_in_default_list(turl.show_in_default_list());
     72   se_specifics->set_suggestions_url(turl.suggestions_url());
     73   se_specifics->set_prepopulate_id(turl.prepopulate_id());
     74   se_specifics->set_autogenerate_keyword(autogenerate_keyword);
     75   se_specifics->set_instant_url(turl.instant_url());
     76   se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
     77   se_specifics->set_sync_guid(sync_guid);
     78   return syncer::SyncData::CreateLocalData(turl.sync_guid(),  // Must be valid!
     79                                    se_specifics->keyword(), specifics);
     80 }
     81 
     82 
     83 // TestChangeProcessor --------------------------------------------------------
     84 
     85 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
     86 // back up to Sync.
     87 class TestChangeProcessor : public syncer::SyncChangeProcessor {
     88  public:
     89   TestChangeProcessor();
     90   virtual ~TestChangeProcessor();
     91 
     92   // Store a copy of all the changes passed in so we can examine them later.
     93   virtual syncer::SyncError ProcessSyncChanges(
     94       const tracked_objects::Location& from_here,
     95       const syncer::SyncChangeList& change_list) OVERRIDE;
     96 
     97   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
     98       OVERRIDE {
     99     return syncer::SyncDataList();
    100   }
    101 
    102   bool contains_guid(const std::string& guid) const {
    103     return change_map_.count(guid) != 0;
    104   }
    105 
    106   syncer::SyncChange change_for_guid(const std::string& guid) const {
    107     DCHECK(contains_guid(guid));
    108     return change_map_.find(guid)->second;
    109   }
    110 
    111   size_t change_list_size() { return change_map_.size(); }
    112 
    113   void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
    114 
    115  private:
    116   // Track the changes received in ProcessSyncChanges.
    117   std::map<std::string, syncer::SyncChange> change_map_;
    118   bool erroneous_;
    119 
    120   DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
    121 };
    122 
    123 TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
    124 }
    125 
    126 TestChangeProcessor::~TestChangeProcessor() {
    127 }
    128 
    129 syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
    130     const tracked_objects::Location& from_here,
    131     const syncer::SyncChangeList& change_list) {
    132   if (erroneous_)
    133     return syncer::SyncError(
    134         FROM_HERE,
    135         syncer::SyncError::DATATYPE_ERROR,
    136         "Some error.",
    137         syncer::SEARCH_ENGINES);
    138 
    139   change_map_.erase(change_map_.begin(), change_map_.end());
    140   for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
    141       iter != change_list.end(); ++iter)
    142     change_map_[GetGUID(iter->sync_data())] = *iter;
    143   return syncer::SyncError();
    144 }
    145 
    146 
    147 }  // namespace
    148 
    149 
    150 // TemplateURLServiceSyncTest -------------------------------------------------
    151 
    152 class TemplateURLServiceSyncTest : public testing::Test {
    153  public:
    154   typedef TemplateURLService::SyncDataMap SyncDataMap;
    155 
    156   TemplateURLServiceSyncTest();
    157 
    158   virtual void SetUp() OVERRIDE;
    159   virtual void TearDown() OVERRIDE;
    160 
    161   TemplateURLService* model() { return test_util_a_.model(); }
    162   // For readability, we redefine an accessor for Model A for use in tests that
    163   // involve syncing two models.
    164   TemplateURLService* model_a() { return test_util_a_.model(); }
    165   TemplateURLService* model_b() { return model_b_.get(); }
    166   TestingProfile* profile_a() { return test_util_a_.profile(); }
    167   TestChangeProcessor* processor() { return sync_processor_.get(); }
    168   scoped_ptr<syncer::SyncChangeProcessor> PassProcessor();
    169   scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
    170 
    171   // Create a TemplateURL with some test values. The caller owns the returned
    172   // TemplateURL*.
    173   TemplateURL* CreateTestTemplateURL(const base::string16& keyword,
    174                                      const std::string& url,
    175                                      const std::string& guid = std::string(),
    176                                      time_t last_mod = 100,
    177                                      bool safe_for_autoreplace = false,
    178                                      bool created_by_policy = false) const;
    179 
    180   // Verifies the two TemplateURLs are equal.
    181   // TODO(stevet): Share this with TemplateURLServiceTest.
    182   void AssertEquals(const TemplateURL& expected,
    183                     const TemplateURL& actual) const;
    184 
    185   // Expect that two syncer::SyncDataLists have equal contents, in terms of the
    186   // sync_guid, keyword, and url fields.
    187   void AssertEquals(const syncer::SyncDataList& data1,
    188                     const syncer::SyncDataList& data2) const;
    189 
    190   // Convenience helper for creating SyncChanges. Takes ownership of |turl|.
    191   syncer::SyncChange CreateTestSyncChange(
    192       syncer::SyncChange::SyncChangeType type,
    193       TemplateURL* turl) const;
    194 
    195   // Helper that creates some initial sync data. We cheat a little by specifying
    196   // GUIDs for easy identification later. We also make the last_modified times
    197   // slightly older than CreateTestTemplateURL's default, to test conflict
    198   // resolution.
    199   syncer::SyncDataList CreateInitialSyncData() const;
    200 
    201   // Syntactic sugar.
    202   TemplateURL* Deserialize(const syncer::SyncData& sync_data);
    203 
    204   // Creates a new TemplateURL copying the fields of |turl| but replacing
    205   // the |url| and |guid| and initializing the date_created and last_modified
    206   // timestamps to a default value of 100. The caller owns the returned
    207   // TemplateURL*.
    208   TemplateURL* CopyTemplateURL(const TemplateURLData* turl,
    209                                const std::string& url,
    210                                const std::string& guid);
    211 
    212  protected:
    213   // We keep two TemplateURLServices to test syncing between them.
    214   TemplateURLServiceTestUtil test_util_a_;
    215   scoped_ptr<TestingProfile> profile_b_;
    216   scoped_ptr<TemplateURLService> model_b_;
    217 
    218   // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
    219   scoped_ptr<TestChangeProcessor> sync_processor_;
    220   scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> sync_processor_wrapper_;
    221 
    222   DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceSyncTest);
    223 };
    224 
    225 TemplateURLServiceSyncTest::TemplateURLServiceSyncTest()
    226     : sync_processor_(new TestChangeProcessor),
    227       sync_processor_wrapper_(new syncer::SyncChangeProcessorWrapperForTest(
    228           sync_processor_.get())) {}
    229 
    230 void TemplateURLServiceSyncTest::SetUp() {
    231   DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(true);
    232   test_util_a_.SetUp();
    233   // Use ChangeToLoadState() instead of VerifyLoad() so we don't actually pull
    234   // in the prepopulate data, which the sync tests don't care about (and would
    235   // just foul them up).
    236   test_util_a_.ChangeModelToLoadState();
    237   profile_b_.reset(new TestingProfile);
    238   TemplateURLServiceFactory::GetInstance()->
    239       RegisterUserPrefsOnBrowserContextForTest(profile_b_.get());
    240   model_b_.reset(new TemplateURLService(profile_b_.get()));
    241   model_b_->Load();
    242 }
    243 
    244 void TemplateURLServiceSyncTest::TearDown() {
    245   test_util_a_.TearDown();
    246   DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(false);
    247 }
    248 
    249 scoped_ptr<syncer::SyncChangeProcessor>
    250 TemplateURLServiceSyncTest::PassProcessor() {
    251   return sync_processor_wrapper_.PassAs<syncer::SyncChangeProcessor>();
    252 }
    253 
    254 scoped_ptr<syncer::SyncErrorFactory> TemplateURLServiceSyncTest::
    255     CreateAndPassSyncErrorFactory() {
    256   return scoped_ptr<syncer::SyncErrorFactory>(
    257       new syncer::SyncErrorFactoryMock());
    258 }
    259 
    260 TemplateURL* TemplateURLServiceSyncTest::CreateTestTemplateURL(
    261     const base::string16& keyword,
    262     const std::string& url,
    263     const std::string& guid,
    264     time_t last_mod,
    265     bool safe_for_autoreplace,
    266     bool created_by_policy) const {
    267   TemplateURLData data;
    268   data.short_name = ASCIIToUTF16("unittest");
    269   data.SetKeyword(keyword);
    270   data.SetURL(url);
    271   data.favicon_url = GURL("http://favicon.url");
    272   data.safe_for_autoreplace = safe_for_autoreplace;
    273   data.date_created = Time::FromTimeT(100);
    274   data.last_modified = Time::FromTimeT(last_mod);
    275   data.created_by_policy = created_by_policy;
    276   data.prepopulate_id = 999999;
    277   if (!guid.empty())
    278     data.sync_guid = guid;
    279   return new TemplateURL(data);
    280 }
    281 
    282 void TemplateURLServiceSyncTest::AssertEquals(const TemplateURL& expected,
    283                                               const TemplateURL& actual) const {
    284   ASSERT_EQ(expected.short_name(), actual.short_name());
    285   ASSERT_EQ(expected.keyword(), actual.keyword());
    286   ASSERT_EQ(expected.url(), actual.url());
    287   ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
    288   ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
    289   ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
    290   ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
    291   ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
    292   ASSERT_EQ(expected.date_created(), actual.date_created());
    293   ASSERT_EQ(expected.last_modified(), actual.last_modified());
    294 }
    295 
    296 void TemplateURLServiceSyncTest::AssertEquals(
    297     const syncer::SyncDataList& data1,
    298     const syncer::SyncDataList& data2) const {
    299   SyncDataMap map1 = TemplateURLService::CreateGUIDToSyncDataMap(data1);
    300   SyncDataMap map2 = TemplateURLService::CreateGUIDToSyncDataMap(data2);
    301 
    302   for (SyncDataMap::const_iterator iter1 = map1.begin();
    303       iter1 != map1.end(); iter1++) {
    304     SyncDataMap::iterator iter2 = map2.find(iter1->first);
    305     if (iter2 != map2.end()) {
    306       ASSERT_EQ(GetKeyword(iter1->second), GetKeyword(iter2->second));
    307       ASSERT_EQ(GetURL(iter1->second), GetURL(iter2->second));
    308       map2.erase(iter2);
    309     }
    310   }
    311   EXPECT_EQ(0U, map2.size());
    312 }
    313 
    314 syncer::SyncChange TemplateURLServiceSyncTest::CreateTestSyncChange(
    315     syncer::SyncChange::SyncChangeType type,
    316     TemplateURL* turl) const {
    317   // We take control of the TemplateURL so make sure it's cleaned up after
    318   // we create data out of it.
    319   scoped_ptr<TemplateURL> scoped_turl(turl);
    320   return syncer::SyncChange(
    321       FROM_HERE,
    322       type,
    323       TemplateURLService::CreateSyncDataFromTemplateURL(*scoped_turl));
    324 }
    325 
    326 syncer::SyncDataList TemplateURLServiceSyncTest::CreateInitialSyncData() const {
    327   syncer::SyncDataList list;
    328 
    329   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
    330       "http://key1.com", "key1", 90));
    331   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
    332   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
    333                                    "key2", 90));
    334   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
    335   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
    336                                    "key3", 90));
    337   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
    338 
    339   return list;
    340 }
    341 
    342 TemplateURL* TemplateURLServiceSyncTest::Deserialize(
    343     const syncer::SyncData& sync_data) {
    344   syncer::SyncChangeList dummy;
    345   return TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData(NULL,
    346       NULL, sync_data, &dummy);
    347 }
    348 
    349 TemplateURL* TemplateURLServiceSyncTest::CopyTemplateURL(
    350     const TemplateURLData* turl,
    351     const std::string& url,
    352     const std::string& guid) {
    353   TemplateURLData data = *turl;
    354   data.SetURL(url);
    355   data.date_created = Time::FromTimeT(100);
    356   data.last_modified = Time::FromTimeT(100);
    357   data.sync_guid = guid;
    358   return new TemplateURL(data);
    359 }
    360 
    361 // Actual tests ---------------------------------------------------------------
    362 
    363 TEST_F(TemplateURLServiceSyncTest, SerializeDeserialize) {
    364   // Create a TemplateURL and convert it into a sync specific type.
    365   scoped_ptr<TemplateURL> turl(
    366       CreateTestTemplateURL(
    367           ASCIIToUTF16("unittest"), "http://www.unittest.com/"));
    368   syncer::SyncData sync_data =
    369       TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
    370   // Convert the specifics back to a TemplateURL.
    371   scoped_ptr<TemplateURL> deserialized(Deserialize(sync_data));
    372   EXPECT_TRUE(deserialized.get());
    373   // Ensure that the original and the deserialized TURLs are equal in values.
    374   AssertEquals(*turl, *deserialized);
    375 }
    376 
    377 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataBasic) {
    378   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
    379   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
    380   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com"));
    381   syncer::SyncDataList all_sync_data =
    382       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
    383 
    384   EXPECT_EQ(3U, all_sync_data.size());
    385 
    386   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
    387       iter != all_sync_data.end(); ++iter) {
    388     std::string guid = GetGUID(*iter);
    389     const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
    390     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
    391     AssertEquals(*service_turl, *deserialized);
    392   }
    393 }
    394 
    395 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataWithExtension) {
    396   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
    397   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
    398   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"),
    399       std::string(extensions::kExtensionScheme) + "://blahblahblah"));
    400   syncer::SyncDataList all_sync_data =
    401       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
    402 
    403   EXPECT_EQ(3U, all_sync_data.size());
    404 
    405   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
    406       iter != all_sync_data.end(); ++iter) {
    407     std::string guid = GetGUID(*iter);
    408     const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
    409     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
    410     AssertEquals(*service_turl, *deserialized);
    411   }
    412 }
    413 
    414 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataNoManagedEngines) {
    415   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
    416   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
    417   TemplateURL* managed_turl = CreateTestTemplateURL(ASCIIToUTF16("key3"),
    418       "http://key3.com", std::string(), 100, false, true);
    419   model()->Add(managed_turl);
    420   syncer::SyncDataList all_sync_data =
    421       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
    422 
    423   EXPECT_EQ(2U, all_sync_data.size());
    424 
    425   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
    426       iter != all_sync_data.end(); ++iter) {
    427     std::string guid = GetGUID(*iter);
    428     TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
    429     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
    430     ASSERT_FALSE(service_turl->created_by_policy());
    431     AssertEquals(*service_turl, *deserialized);
    432   }
    433 }
    434 
    435 TEST_F(TemplateURLServiceSyncTest, UniquifyKeyword) {
    436   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
    437   // Create a key that conflicts with something in the model.
    438   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
    439                                                      "http://new.com", "xyz"));
    440   base::string16 new_keyword = model()->UniquifyKeyword(*turl, false);
    441   EXPECT_EQ(ASCIIToUTF16("new.com"), new_keyword);
    442   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
    443   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("new.com"), "http://new.com",
    444                                      "xyz"));
    445 
    446   // Test a second collision. This time it should be resolved by actually
    447   // modifying the original keyword, since the autogenerated keyword is already
    448   // used.
    449   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
    450   new_keyword = model()->UniquifyKeyword(*turl, false);
    451   EXPECT_EQ(ASCIIToUTF16("key1_"), new_keyword);
    452   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
    453   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1_"), "http://new.com"));
    454 
    455   // Test a third collision. This should collide on both the autogenerated
    456   // keyword and the first uniquification attempt.
    457   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
    458   new_keyword = model()->UniquifyKeyword(*turl, false);
    459   EXPECT_EQ(ASCIIToUTF16("key1__"), new_keyword);
    460   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
    461 
    462   // If we force the method, it should uniquify the keyword even if it is
    463   // currently unique, and skip the host-based autogenerated keyword.
    464   turl.reset(
    465       CreateTestTemplateURL(ASCIIToUTF16("unique"), "http://unique.com"));
    466   new_keyword = model()->UniquifyKeyword(*turl, true);
    467   EXPECT_EQ(ASCIIToUTF16("unique_"), new_keyword);
    468   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
    469 }
    470 
    471 TEST_F(TemplateURLServiceSyncTest, IsLocalTemplateURLBetter) {
    472   // Test some edge cases of this function.
    473   const struct {
    474     time_t local_time;
    475     time_t sync_time;
    476     bool local_is_default;
    477     bool local_created_by_policy;
    478     bool expected_result;
    479   } test_cases[] = {
    480     // Sync is better by timestamp but local is Default.
    481     {10, 100, true, false, true},
    482     // Sync is better by timestamp but local is Create by Policy.
    483     {10, 100, false, true, true},
    484     // Tie. Sync wins.
    485     {100, 100, false, false, false},
    486   };
    487 
    488   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
    489     TemplateURL* local_turl = CreateTestTemplateURL(
    490         ASCIIToUTF16("localkey"), "www.local.com", "localguid",
    491         test_cases[i].local_time, true, test_cases[i].local_created_by_policy);
    492     model()->Add(local_turl);
    493     if (test_cases[i].local_is_default)
    494       model()->SetUserSelectedDefaultSearchProvider(local_turl);
    495 
    496     scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
    497           ASCIIToUTF16("synckey"), "www.sync.com", "syncguid",
    498           test_cases[i].sync_time));
    499     EXPECT_EQ(test_cases[i].expected_result,
    500         model()->IsLocalTemplateURLBetter(local_turl, sync_turl.get()));
    501 
    502     // Undo the changes.
    503     if (test_cases[i].local_is_default)
    504       model()->SetUserSelectedDefaultSearchProvider(NULL);
    505     model()->Remove(local_turl);
    506   }
    507 }
    508 
    509 TEST_F(TemplateURLServiceSyncTest, ResolveSyncKeywordConflict) {
    510   // This tests cases where neither the sync nor the local TemplateURL are
    511   // marked safe_for_autoreplace.
    512 
    513   // Create a keyword that conflicts, and make it older.  Sync keyword is
    514   // uniquified, and a syncer::SyncChange is added.
    515   base::string16 original_turl_keyword = ASCIIToUTF16("key1");
    516   TemplateURL* original_turl = CreateTestTemplateURL(original_turl_keyword,
    517       "http://key1.com", std::string(), 9000);
    518   model()->Add(original_turl);
    519   scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(original_turl_keyword,
    520       "http://new.com", "remote", 8999));
    521   syncer::SyncChangeList changes;
    522   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
    523   EXPECT_NE(original_turl_keyword, sync_turl->keyword());
    524   EXPECT_EQ(original_turl_keyword, original_turl->keyword());
    525   ASSERT_EQ(1U, changes.size());
    526   EXPECT_EQ("remote", GetGUID(changes[0].sync_data()));
    527   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    528   changes.clear();
    529   model()->Remove(original_turl);
    530 
    531   // Sync is newer.  Original TemplateURL keyword is uniquified.  A SyncChange
    532   // is added (which in a normal run would be deleted by PruneSyncChanges() when
    533   // the local GUID doesn't appear in the sync GUID list).  Also ensure that
    534   // this does not change the safe_for_autoreplace flag or the TemplateURLID in
    535   // the original.
    536   original_turl = CreateTestTemplateURL(original_turl_keyword,
    537                                         "http://key1.com", "local", 9000);
    538   model()->Add(original_turl);
    539   TemplateURLID original_id = original_turl->id();
    540   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
    541                                         std::string(), 9001));
    542   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
    543   EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
    544   EXPECT_NE(original_turl_keyword, original_turl->keyword());
    545   EXPECT_FALSE(original_turl->safe_for_autoreplace());
    546   EXPECT_EQ(original_id, original_turl->id());
    547   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
    548   ASSERT_EQ(1U, changes.size());
    549   EXPECT_EQ("local", GetGUID(changes[0].sync_data()));
    550   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    551   changes.clear();
    552   model()->Remove(original_turl);
    553 
    554   // Equal times. Same result as above. Sync left alone, original uniquified so
    555   // sync_turl can fit.
    556   original_turl = CreateTestTemplateURL(original_turl_keyword,
    557                                         "http://key1.com", "local2", 9000);
    558   model()->Add(original_turl);
    559   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
    560                                         std::string(), 9000));
    561   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
    562   EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
    563   EXPECT_NE(original_turl_keyword, original_turl->keyword());
    564   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
    565   ASSERT_EQ(1U, changes.size());
    566   EXPECT_EQ("local2", GetGUID(changes[0].sync_data()));
    567   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    568   changes.clear();
    569   model()->Remove(original_turl);
    570 
    571   // Sync is newer, but original TemplateURL is created by policy, so it wins.
    572   // Sync keyword is uniquified, and a syncer::SyncChange is added.
    573   original_turl = CreateTestTemplateURL(original_turl_keyword,
    574       "http://key1.com", std::string(), 9000, false, true);
    575   model()->Add(original_turl);
    576   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
    577                                         "remote2", 9999));
    578   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
    579   EXPECT_NE(original_turl_keyword, sync_turl->keyword());
    580   EXPECT_EQ(original_turl_keyword, original_turl->keyword());
    581   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword()));
    582   ASSERT_EQ(1U, changes.size());
    583   EXPECT_EQ("remote2", GetGUID(changes[0].sync_data()));
    584   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    585   changes.clear();
    586   model()->Remove(original_turl);
    587 }
    588 
    589 TEST_F(TemplateURLServiceSyncTest, StartSyncEmpty) {
    590   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    591       syncer::SEARCH_ENGINES, syncer::SyncDataList(),
    592       PassProcessor(), CreateAndPassSyncErrorFactory());
    593 
    594   EXPECT_EQ(0U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    595   EXPECT_EQ(0U, processor()->change_list_size());
    596   EXPECT_EQ(0, merge_result.num_items_added());
    597   EXPECT_EQ(0, merge_result.num_items_modified());
    598   EXPECT_EQ(0, merge_result.num_items_deleted());
    599   EXPECT_EQ(0, merge_result.num_items_before_association());
    600   EXPECT_EQ(0, merge_result.num_items_after_association());
    601 }
    602 
    603 TEST_F(TemplateURLServiceSyncTest, MergeIntoEmpty) {
    604   syncer::SyncDataList initial_data = CreateInitialSyncData();
    605 
    606   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    607       syncer::SEARCH_ENGINES, initial_data,
    608       PassProcessor(), CreateAndPassSyncErrorFactory());
    609 
    610   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    611   // We expect the model to have accepted all of the initial sync data. Search
    612   // through the model using the GUIDs to ensure that they're present.
    613   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
    614       iter != initial_data.end(); ++iter) {
    615     std::string guid = GetGUID(*iter);
    616     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
    617   }
    618 
    619   EXPECT_EQ(0U, processor()->change_list_size());
    620 
    621   // Locally the three new TemplateURL's should have been added.
    622   EXPECT_EQ(3, merge_result.num_items_added());
    623   EXPECT_EQ(0, merge_result.num_items_modified());
    624   EXPECT_EQ(0, merge_result.num_items_deleted());
    625   EXPECT_EQ(0, merge_result.num_items_before_association());
    626   EXPECT_EQ(3, merge_result.num_items_after_association());
    627 }
    628 
    629 TEST_F(TemplateURLServiceSyncTest, MergeInAllNewData) {
    630   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("abc.com"), "http://abc.com",
    631                                      "abc"));
    632   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("def.com"), "http://def.com",
    633                                      "def"));
    634   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("xyz.com"), "http://xyz.com",
    635                                      "xyz"));
    636   syncer::SyncDataList initial_data = CreateInitialSyncData();
    637 
    638   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    639       syncer::SEARCH_ENGINES, initial_data,
    640       PassProcessor(), CreateAndPassSyncErrorFactory());
    641 
    642   EXPECT_EQ(6U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    643   // We expect the model to have accepted all of the initial sync data. Search
    644   // through the model using the GUIDs to ensure that they're present.
    645   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
    646       iter != initial_data.end(); ++iter) {
    647     std::string guid = GetGUID(*iter);
    648     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
    649   }
    650   // All the original TemplateURLs should also remain in the model.
    651   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("abc.com")));
    652   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("def.com")));
    653   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("xyz.com")));
    654   // Ensure that Sync received the expected changes.
    655   EXPECT_EQ(3U, processor()->change_list_size());
    656   EXPECT_TRUE(processor()->contains_guid("abc"));
    657   EXPECT_TRUE(processor()->contains_guid("def"));
    658   EXPECT_TRUE(processor()->contains_guid("xyz"));
    659 
    660   // Locally the three new TemplateURL's should have been added.
    661   EXPECT_EQ(3, merge_result.num_items_added());
    662   EXPECT_EQ(0, merge_result.num_items_modified());
    663   EXPECT_EQ(0, merge_result.num_items_deleted());
    664   EXPECT_EQ(3, merge_result.num_items_before_association());
    665   EXPECT_EQ(6, merge_result.num_items_after_association());
    666 }
    667 
    668 TEST_F(TemplateURLServiceSyncTest, MergeSyncIsTheSame) {
    669   // The local data is the same as the sync data merged in. i.e. - There have
    670   // been no changes since the last time we synced. Even the last_modified
    671   // timestamps are the same.
    672   syncer::SyncDataList initial_data = CreateInitialSyncData();
    673   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
    674       iter != initial_data.end(); ++iter) {
    675     TemplateURL* converted = Deserialize(*iter);
    676     model()->Add(converted);
    677   }
    678 
    679   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    680       syncer::SEARCH_ENGINES, initial_data,
    681       PassProcessor(), CreateAndPassSyncErrorFactory());
    682 
    683   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    684   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
    685       iter != initial_data.end(); ++iter) {
    686     std::string guid = GetGUID(*iter);
    687     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
    688   }
    689   EXPECT_EQ(0U, processor()->change_list_size());
    690 
    691   // Locally everything should remain the same.
    692   EXPECT_EQ(0, merge_result.num_items_added());
    693   EXPECT_EQ(0, merge_result.num_items_modified());
    694   EXPECT_EQ(0, merge_result.num_items_deleted());
    695   EXPECT_EQ(3, merge_result.num_items_before_association());
    696   EXPECT_EQ(3, merge_result.num_items_after_association());
    697 }
    698 
    699 TEST_F(TemplateURLServiceSyncTest, MergeUpdateFromSync) {
    700   // The local data is the same as the sync data merged in, but timestamps have
    701   // changed. Ensure the right fields are merged in.
    702   syncer::SyncDataList initial_data;
    703   TemplateURL* turl1 = CreateTestTemplateURL(ASCIIToUTF16("abc.com"),
    704                                              "http://abc.com", "abc", 9000);
    705   model()->Add(turl1);
    706   TemplateURL* turl2 = CreateTestTemplateURL(ASCIIToUTF16("xyz.com"),
    707                                              "http://xyz.com", "xyz", 9000);
    708   model()->Add(turl2);
    709 
    710   scoped_ptr<TemplateURL> turl1_newer(CreateTestTemplateURL(
    711       ASCIIToUTF16("abc.com"), "http://abc.ca", "abc", 9999));
    712   initial_data.push_back(
    713       TemplateURLService::CreateSyncDataFromTemplateURL(*turl1_newer));
    714 
    715   scoped_ptr<TemplateURL> turl2_older(CreateTestTemplateURL(
    716       ASCIIToUTF16("xyz.com"), "http://xyz.ca", "xyz", 8888));
    717   initial_data.push_back(
    718       TemplateURLService::CreateSyncDataFromTemplateURL(*turl2_older));
    719 
    720   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    721       syncer::SEARCH_ENGINES, initial_data,
    722       PassProcessor(), CreateAndPassSyncErrorFactory());
    723 
    724   // Both were local updates, so we expect the same count.
    725   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    726 
    727   // Check that the first replaced the initial abc TemplateURL.
    728   EXPECT_EQ(turl1, model()->GetTemplateURLForGUID("abc"));
    729   EXPECT_EQ("http://abc.ca", turl1->url());
    730 
    731   // Check that the second produced an upstream update to the xyz TemplateURL.
    732   EXPECT_EQ(1U, processor()->change_list_size());
    733   ASSERT_TRUE(processor()->contains_guid("xyz"));
    734   syncer::SyncChange change = processor()->change_for_guid("xyz");
    735   EXPECT_TRUE(change.change_type() == syncer::SyncChange::ACTION_UPDATE);
    736   EXPECT_EQ("http://xyz.com", GetURL(change.sync_data()));
    737 
    738   // Locally only the older item should have been modified.
    739   EXPECT_EQ(0, merge_result.num_items_added());
    740   EXPECT_EQ(1, merge_result.num_items_modified());
    741   EXPECT_EQ(0, merge_result.num_items_deleted());
    742   EXPECT_EQ(2, merge_result.num_items_before_association());
    743   EXPECT_EQ(2, merge_result.num_items_after_association());
    744 }
    745 
    746 TEST_F(TemplateURLServiceSyncTest, MergeAddFromOlderSyncData) {
    747   // GUIDs all differ, so this is data to be added from Sync, but the timestamps
    748   // from Sync are older. Set up the local data so that one is a dupe, one has a
    749   // conflicting keyword, and the last has no conflicts (a clean ADD).
    750   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
    751                                      "aaa", 100));  // dupe
    752 
    753   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
    754       "http://expected.com", "bbb", 100));  // keyword conflict
    755 
    756   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
    757                                      "http://unique.com", "ccc"));  // add
    758 
    759   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    760       syncer::SEARCH_ENGINES,
    761       CreateInitialSyncData(), PassProcessor(),
    762       CreateAndPassSyncErrorFactory());
    763 
    764   // The dupe and conflict results in merges, as local values are always merged
    765   // with sync values if there is a keyword conflict. The unique keyword should
    766   // be added.
    767   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    768 
    769   // The key1 duplicate results in the local copy winning. Ensure that Sync's
    770   // copy was not added, and the local copy is pushed upstream to Sync as an
    771   // update. The local copy should have received the sync data's GUID.
    772   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
    773   // Check changes for the UPDATE.
    774   ASSERT_TRUE(processor()->contains_guid("key1"));
    775   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
    776   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
    777   // The local sync_guid should no longer be found.
    778   EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
    779 
    780   // The key2 keyword conflict results in a merge, with the values of the local
    781   // copy winning, so ensure it retains the original URL, and that an update to
    782   // the sync guid is pushed upstream to Sync.
    783   const TemplateURL* key2 = model()->GetTemplateURLForGUID("key2");
    784   ASSERT_TRUE(key2);
    785   EXPECT_EQ(ASCIIToUTF16("key2"), key2->keyword());
    786   EXPECT_EQ("http://expected.com", key2->url());
    787   // Check changes for the UPDATE.
    788   ASSERT_TRUE(processor()->contains_guid("key2"));
    789   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
    790   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
    791   EXPECT_EQ("key2", GetKeyword(key2_change.sync_data()));
    792   EXPECT_EQ("http://expected.com", GetURL(key2_change.sync_data()));
    793   // The local sync_guid should no longer be found.
    794   EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
    795 
    796   // The last TemplateURL should have had no conflicts and was just added. It
    797   // should not have replaced the third local TemplateURL.
    798   EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
    799   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
    800 
    801   // Two UPDATEs and one ADD.
    802   EXPECT_EQ(3U, processor()->change_list_size());
    803   // One ADDs should be pushed up to Sync.
    804   ASSERT_TRUE(processor()->contains_guid("ccc"));
    805   EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
    806             processor()->change_for_guid("ccc").change_type());
    807 
    808   // All the sync items had new guids, but only one doesn't conflict and is
    809   // added. The other two conflicting cases result in local modifications
    810   // to override the local guids but preserve the local data.
    811   EXPECT_EQ(1, merge_result.num_items_added());
    812   EXPECT_EQ(2, merge_result.num_items_modified());
    813   EXPECT_EQ(0, merge_result.num_items_deleted());
    814   EXPECT_EQ(3, merge_result.num_items_before_association());
    815   EXPECT_EQ(4, merge_result.num_items_after_association());
    816 }
    817 
    818 TEST_F(TemplateURLServiceSyncTest, MergeAddFromNewerSyncData) {
    819   // GUIDs all differ, so Sync may overtake some entries, but the timestamps
    820   // from Sync are newer. Set up the local data so that one is a dupe, one has a
    821   // conflicting keyword, and the last has no conflicts (a clean ADD).
    822   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
    823                                      "aaa", 10));  // dupe
    824 
    825   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
    826       "http://expected.com", "bbb", 10));  // keyword conflict
    827 
    828   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
    829                                      "http://unique.com", "ccc", 10));  // add
    830 
    831   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
    832       syncer::SEARCH_ENGINES,
    833       CreateInitialSyncData(), PassProcessor(),
    834       CreateAndPassSyncErrorFactory());
    835 
    836   // The dupe and keyword conflict results in merges. The unique keyword be
    837   // added to the model.
    838   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    839 
    840   // The key1 duplicate results in Sync's copy winning. Ensure that Sync's
    841   // copy replaced the local copy.
    842   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
    843   EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
    844   EXPECT_FALSE(processor()->contains_guid("key1"));
    845   EXPECT_FALSE(processor()->contains_guid("aaa"));
    846 
    847   // The key2 keyword conflict results in Sync's copy winning, so ensure it
    848   // retains the original keyword and is added. The local copy should be
    849   // removed.
    850   const TemplateURL* key2_sync = model()->GetTemplateURLForGUID("key2");
    851   ASSERT_TRUE(key2_sync);
    852   EXPECT_EQ(ASCIIToUTF16("key2"), key2_sync->keyword());
    853   EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
    854 
    855   // The last TemplateURL should have had no conflicts and was just added. It
    856   // should not have replaced the third local TemplateURL.
    857   EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
    858   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
    859 
    860   // One ADD.
    861   EXPECT_EQ(1U, processor()->change_list_size());
    862   // One ADDs should be pushed up to Sync.
    863   ASSERT_TRUE(processor()->contains_guid("ccc"));
    864   EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
    865             processor()->change_for_guid("ccc").change_type());
    866 
    867   // One of the sync items is added directly without conflict. The other two
    868   // conflict but are newer than the local items so are added while the local
    869   // is deleted.
    870   EXPECT_EQ(3, merge_result.num_items_added());
    871   EXPECT_EQ(0, merge_result.num_items_modified());
    872   EXPECT_EQ(2, merge_result.num_items_deleted());
    873   EXPECT_EQ(3, merge_result.num_items_before_association());
    874   EXPECT_EQ(4, merge_result.num_items_after_association());
    875 }
    876 
    877 TEST_F(TemplateURLServiceSyncTest, ProcessChangesEmptyModel) {
    878   // We initially have no data.
    879   model()->MergeDataAndStartSyncing(
    880       syncer::SEARCH_ENGINES, syncer::SyncDataList(),
    881       PassProcessor(), CreateAndPassSyncErrorFactory());
    882 
    883   // Set up a bunch of ADDs.
    884   syncer::SyncChangeList changes;
    885   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    886       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1")));
    887   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    888       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com", "key2")));
    889   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    890       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
    891 
    892   model()->ProcessSyncChanges(FROM_HERE, changes);
    893 
    894   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    895   EXPECT_EQ(0U, processor()->change_list_size());
    896   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
    897   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
    898   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
    899 }
    900 
    901 TEST_F(TemplateURLServiceSyncTest, ProcessChangesNoConflicts) {
    902   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
    903                                     CreateInitialSyncData(), PassProcessor(),
    904                                     CreateAndPassSyncErrorFactory());
    905 
    906   // Process different types of changes, without conflicts.
    907   syncer::SyncChangeList changes;
    908   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    909       CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com", "key4")));
    910   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
    911       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
    912                             "key2")));
    913   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
    914       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
    915 
    916   model()->ProcessSyncChanges(FROM_HERE, changes);
    917 
    918   // Add one, remove one, update one, so the number shouldn't change.
    919   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    920   EXPECT_EQ(0U, processor()->change_list_size());
    921   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
    922   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
    923   const TemplateURL* turl = model()->GetTemplateURLForGUID("key2");
    924   EXPECT_TRUE(turl);
    925   EXPECT_EQ(ASCIIToUTF16("newkeyword"), turl->keyword());
    926   EXPECT_EQ("http://new.com", turl->url());
    927   EXPECT_FALSE(model()->GetTemplateURLForGUID("key3"));
    928   EXPECT_TRUE(model()->GetTemplateURLForGUID("key4"));
    929 }
    930 
    931 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsSyncWins) {
    932   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
    933                                     CreateInitialSyncData(), PassProcessor(),
    934                                     CreateAndPassSyncErrorFactory());
    935 
    936   // Process different types of changes, with conflicts. Note that all this data
    937   // has a newer timestamp, so Sync will win in these scenarios.
    938   syncer::SyncChangeList changes;
    939   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    940       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa")));
    941   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
    942       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1")));
    943 
    944   model()->ProcessSyncChanges(FROM_HERE, changes);
    945 
    946   // Add one, update one, so we're up to 4.
    947   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    948   // Sync is always newer here, so it should always win.  We should create
    949   // SyncChanges for the changes to the local entities, since they're synced
    950   // too.
    951   EXPECT_EQ(2U, processor()->change_list_size());
    952   ASSERT_TRUE(processor()->contains_guid("key2"));
    953   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
    954             processor()->change_for_guid("key2").change_type());
    955   ASSERT_TRUE(processor()->contains_guid("key3"));
    956   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
    957             processor()->change_for_guid("key3").change_type());
    958 
    959   // aaa conflicts with key2 and wins, forcing key2's keyword to update.
    960   EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
    961   EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
    962             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
    963   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
    964   EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
    965             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2.com")));
    966   // key1 update conflicts with key3 and wins, forcing key3's keyword to update.
    967   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
    968   EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
    969             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
    970   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
    971   EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
    972             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
    973 }
    974 
    975 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsLocalWins) {
    976   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
    977                                     CreateInitialSyncData(), PassProcessor(),
    978                                     CreateAndPassSyncErrorFactory());
    979 
    980   // Process different types of changes, with conflicts. Note that all this data
    981   // has an older timestamp, so the local data will win in these scenarios.
    982   syncer::SyncChangeList changes;
    983   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
    984       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa",
    985                             10)));
    986   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
    987       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1",
    988                             10)));
    989 
    990   model()->ProcessSyncChanges(FROM_HERE, changes);
    991 
    992   // Add one, update one, so we're up to 4.
    993   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
    994   // Local data wins twice so two updates are pushed up to Sync.
    995   EXPECT_EQ(2U, processor()->change_list_size());
    996 
    997   // aaa conflicts with key2 and loses, forcing it's keyword to update.
    998   EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
    999   EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
   1000             model()->GetTemplateURLForKeyword(ASCIIToUTF16("new.com")));
   1001   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
   1002   EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
   1003             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
   1004   // key1 update conflicts with key3 and loses, forcing key1's keyword to
   1005   // update.
   1006   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
   1007   EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
   1008             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
   1009   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
   1010   EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
   1011             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
   1012 
   1013   ASSERT_TRUE(processor()->contains_guid("aaa"));
   1014   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
   1015             processor()->change_for_guid("aaa").change_type());
   1016   ASSERT_TRUE(processor()->contains_guid("key1"));
   1017   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
   1018             processor()->change_for_guid("key1").change_type());
   1019 }
   1020 
   1021 TEST_F(TemplateURLServiceSyncTest, ProcessTemplateURLChange) {
   1022   // Ensure that ProcessTemplateURLChange is called and pushes the correct
   1023   // changes to Sync whenever local changes are made to TemplateURLs.
   1024   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1025                                     CreateInitialSyncData(), PassProcessor(),
   1026                                     CreateAndPassSyncErrorFactory());
   1027 
   1028   // Add a new search engine.
   1029   TemplateURL* new_turl =
   1030       CreateTestTemplateURL(ASCIIToUTF16("baidu"), "http://baidu.cn", "new");
   1031   model()->Add(new_turl);
   1032   EXPECT_EQ(1U, processor()->change_list_size());
   1033   ASSERT_TRUE(processor()->contains_guid("new"));
   1034   syncer::SyncChange change = processor()->change_for_guid("new");
   1035   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, change.change_type());
   1036   EXPECT_EQ("baidu", GetKeyword(change.sync_data()));
   1037   EXPECT_EQ("http://baidu.cn", GetURL(change.sync_data()));
   1038 
   1039   // Change a keyword.
   1040   TemplateURL* existing_turl = model()->GetTemplateURLForGUID("key1");
   1041   model()->ResetTemplateURL(existing_turl, existing_turl->short_name(),
   1042                             ASCIIToUTF16("k"), existing_turl->url());
   1043   EXPECT_EQ(1U, processor()->change_list_size());
   1044   ASSERT_TRUE(processor()->contains_guid("key1"));
   1045   change = processor()->change_for_guid("key1");
   1046   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
   1047   EXPECT_EQ("k", GetKeyword(change.sync_data()));
   1048 
   1049   // Remove an existing search engine.
   1050   existing_turl = model()->GetTemplateURLForGUID("key2");
   1051   model()->Remove(existing_turl);
   1052   EXPECT_EQ(1U, processor()->change_list_size());
   1053   ASSERT_TRUE(processor()->contains_guid("key2"));
   1054   change = processor()->change_for_guid("key2");
   1055   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
   1056 }
   1057 
   1058 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithLocalExtensions) {
   1059   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1060                                     CreateInitialSyncData(), PassProcessor(),
   1061                                     CreateAndPassSyncErrorFactory());
   1062 
   1063   // Add some extension keywords locally.
   1064   TemplateURL* extension1 = CreateTestTemplateURL(ASCIIToUTF16("keyword1"),
   1065       std::string(extensions::kExtensionScheme) + "://extension1");
   1066   model()->Add(extension1);
   1067   EXPECT_EQ(1U, processor()->change_list_size());
   1068   TemplateURL* extension2 = CreateTestTemplateURL(ASCIIToUTF16("keyword2"),
   1069       std::string(extensions::kExtensionScheme) + "://extension2");
   1070   model()->Add(extension2);
   1071   EXPECT_EQ(1U, processor()->change_list_size());
   1072 
   1073   // Create some sync changes that will conflict with the extension keywords.
   1074   syncer::SyncChangeList changes;
   1075   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1076     CreateTestTemplateURL(ASCIIToUTF16("keyword1"), "http://aaa.com",
   1077                           std::string(), 100, true)));
   1078   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1079     CreateTestTemplateURL(ASCIIToUTF16("keyword2"), "http://bbb.com")));
   1080   model()->ProcessSyncChanges(FROM_HERE, changes);
   1081 
   1082   // The existing extension keywords should be uniquified.
   1083   EXPECT_FALSE(model()->GetTemplateURLForHost("aaa.com") == NULL);
   1084   EXPECT_EQ(model()->GetTemplateURLForHost("aaa.com"),
   1085             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
   1086   TemplateURL* url_for_keyword2 =
   1087       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2"));
   1088   EXPECT_NE(extension2, url_for_keyword2);
   1089   EXPECT_EQ("http://bbb.com", url_for_keyword2->url());
   1090 
   1091   // Replaced extension keywords should be uniquified.
   1092   EXPECT_EQ(extension1,
   1093             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1_")));
   1094   EXPECT_EQ(extension2,
   1095             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2_")));
   1096 }
   1097 
   1098 TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordMigrated) {
   1099   // Create a couple of sync entries with autogenerated keywords.
   1100   syncer::SyncDataList initial_data;
   1101   scoped_ptr<TemplateURL> turl(
   1102       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
   1103   initial_data.push_back(
   1104       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1105   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
   1106       "{google:baseURL}search?q={searchTerms}", "key2"));
   1107   initial_data.push_back(
   1108       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1109 
   1110   // Now try to sync the data locally.
   1111   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1112       PassProcessor(), CreateAndPassSyncErrorFactory());
   1113 
   1114   // Both entries should have been added, with explicit keywords.
   1115   TemplateURL* key1 = model()->GetTemplateURLForHost("key1.com");
   1116   ASSERT_FALSE(key1 == NULL);
   1117   EXPECT_EQ(ASCIIToUTF16("key1.com"), key1->keyword());
   1118   GURL google_url(UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue());
   1119   TemplateURL* key2 = model()->GetTemplateURLForHost(google_url.host());
   1120   ASSERT_FALSE(key2 == NULL);
   1121   base::string16 google_keyword(net::StripWWWFromHost(google_url));
   1122   EXPECT_EQ(google_keyword, key2->keyword());
   1123 
   1124   // We should also have gotten some corresponding UPDATEs pushed upstream.
   1125   EXPECT_GE(processor()->change_list_size(), 2U);
   1126   ASSERT_TRUE(processor()->contains_guid("key1"));
   1127   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
   1128   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
   1129   EXPECT_EQ("key1.com", GetKeyword(key1_change.sync_data()));
   1130   ASSERT_TRUE(processor()->contains_guid("key2"));
   1131   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
   1132   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
   1133   EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
   1134 }
   1135 
   1136 TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordConflicts) {
   1137   // Sync brings in some autogenerated keywords, but the generated keywords we
   1138   // try to create conflict with ones in the model.
   1139   base::string16 google_keyword(net::StripWWWFromHost(GURL(
   1140       UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
   1141   const std::string local_google_url =
   1142       "{google:baseURL}1/search?q={searchTerms}";
   1143   TemplateURL* google = CreateTestTemplateURL(google_keyword, local_google_url);
   1144   model()->Add(google);
   1145   TemplateURL* other =
   1146       CreateTestTemplateURL(ASCIIToUTF16("other.com"), "http://other.com/foo");
   1147   model()->Add(other);
   1148   syncer::SyncDataList initial_data;
   1149   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("sync1"),
   1150       "{google:baseURL}2/search?q={searchTerms}", "sync1", 50));
   1151   initial_data.push_back(
   1152       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1153   const std::string synced_other_url =
   1154       "http://other.com/search?q={searchTerms}";
   1155   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("sync2"),
   1156       synced_other_url, "sync2", 150));
   1157   initial_data.push_back(
   1158       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1159 
   1160   // Before we merge the data, grab the local sync_guids so we can ensure that
   1161   // they've been replaced.
   1162   const std::string local_google_guid = google->sync_guid();
   1163   const std::string local_other_guid = other->sync_guid();
   1164 
   1165   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1166       PassProcessor(), CreateAndPassSyncErrorFactory());
   1167 
   1168   // In this case, the conflicts should be handled just like any other keyword
   1169   // conflicts -- the later-modified TemplateURL is assumed to be authoritative.
   1170   // Since the initial TemplateURLs were local only, they should be merged with
   1171   // the sync TemplateURLs (GUIDs transferred over).
   1172   EXPECT_FALSE(model()->GetTemplateURLForGUID(local_google_guid));
   1173   ASSERT_TRUE(model()->GetTemplateURLForGUID("sync1"));
   1174   EXPECT_EQ(google_keyword, model()->GetTemplateURLForGUID("sync1")->keyword());
   1175   EXPECT_FALSE(model()->GetTemplateURLForGUID(local_other_guid));
   1176   ASSERT_TRUE(model()->GetTemplateURLForGUID("sync2"));
   1177   EXPECT_EQ(ASCIIToUTF16("other.com"),
   1178             model()->GetTemplateURLForGUID("sync2")->keyword());
   1179 
   1180   // Both synced URLs should have associated UPDATEs, since both needed their
   1181   // keywords to be generated.
   1182   EXPECT_EQ(processor()->change_list_size(), 2U);
   1183   ASSERT_TRUE(processor()->contains_guid("sync1"));
   1184   syncer::SyncChange sync1_change = processor()->change_for_guid("sync1");
   1185   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync1_change.change_type());
   1186   EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(sync1_change.sync_data())));
   1187   EXPECT_EQ(local_google_url, GetURL(sync1_change.sync_data()));
   1188   ASSERT_TRUE(processor()->contains_guid("sync2"));
   1189   syncer::SyncChange sync2_change = processor()->change_for_guid("sync2");
   1190   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync2_change.change_type());
   1191   EXPECT_EQ("other.com", GetKeyword(sync2_change.sync_data()));
   1192   EXPECT_EQ(synced_other_url, GetURL(sync2_change.sync_data()));
   1193 }
   1194 
   1195 TEST_F(TemplateURLServiceSyncTest, TwoAutogeneratedKeywordsUsingGoogleBaseURL) {
   1196   // Sync brings in two autogenerated keywords and both use Google base URLs.
   1197   // We make the first older so that it will get renamed once before the second
   1198   // and then again once after (when we resolve conflicts for the second).
   1199   syncer::SyncDataList initial_data;
   1200   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
   1201       "{google:baseURL}1/search?q={searchTerms}", "key1", 50));
   1202   initial_data.push_back(
   1203       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1204   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
   1205       "{google:baseURL}2/search?q={searchTerms}", "key2"));
   1206   initial_data.push_back(
   1207       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
   1208   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1209       PassProcessor(), CreateAndPassSyncErrorFactory());
   1210 
   1211   // We should still have coalesced the updates to one each.
   1212   base::string16 google_keyword(net::StripWWWFromHost(GURL(
   1213       UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
   1214   TemplateURL* keyword1 =
   1215       model()->GetTemplateURLForKeyword(google_keyword + ASCIIToUTF16("_"));
   1216   ASSERT_FALSE(keyword1 == NULL);
   1217   EXPECT_EQ("key1", keyword1->sync_guid());
   1218   TemplateURL* keyword2 = model()->GetTemplateURLForKeyword(google_keyword);
   1219   ASSERT_FALSE(keyword2 == NULL);
   1220   EXPECT_EQ("key2", keyword2->sync_guid());
   1221 
   1222   EXPECT_GE(processor()->change_list_size(), 2U);
   1223   ASSERT_TRUE(processor()->contains_guid("key1"));
   1224   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
   1225   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
   1226   EXPECT_EQ(keyword1->keyword(),
   1227             base::UTF8ToUTF16(GetKeyword(key1_change.sync_data())));
   1228   ASSERT_TRUE(processor()->contains_guid("key2"));
   1229   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
   1230   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
   1231   EXPECT_EQ(keyword2->keyword(),
   1232             base::UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
   1233 }
   1234 
   1235 TEST_F(TemplateURLServiceSyncTest, DuplicateEncodingsRemoved) {
   1236   // Create a sync entry with duplicate encodings.
   1237   syncer::SyncDataList initial_data;
   1238 
   1239   TemplateURLData data;
   1240   data.short_name = ASCIIToUTF16("test");
   1241   data.SetKeyword(ASCIIToUTF16("keyword"));
   1242   data.SetURL("http://test/%s");
   1243   data.input_encodings.push_back("UTF-8");
   1244   data.input_encodings.push_back("UTF-8");
   1245   data.input_encodings.push_back("UTF-16");
   1246   data.input_encodings.push_back("UTF-8");
   1247   data.input_encodings.push_back("Big5");
   1248   data.input_encodings.push_back("UTF-16");
   1249   data.input_encodings.push_back("Big5");
   1250   data.input_encodings.push_back("Windows-1252");
   1251   data.date_created = Time::FromTimeT(100);
   1252   data.last_modified = Time::FromTimeT(100);
   1253   data.sync_guid = "keyword";
   1254   scoped_ptr<TemplateURL> turl(new TemplateURL(data));
   1255   initial_data.push_back(
   1256       TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
   1257 
   1258   // Now try to sync the data locally.
   1259   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1260       PassProcessor(), CreateAndPassSyncErrorFactory());
   1261 
   1262   // The entry should have been added, with duplicate encodings removed.
   1263   TemplateURL* keyword =
   1264       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
   1265   ASSERT_FALSE(keyword == NULL);
   1266   EXPECT_EQ(4U, keyword->input_encodings().size());
   1267 
   1268   // We should also have gotten a corresponding UPDATE pushed upstream.
   1269   EXPECT_GE(processor()->change_list_size(), 1U);
   1270   ASSERT_TRUE(processor()->contains_guid("keyword"));
   1271   syncer::SyncChange keyword_change = processor()->change_for_guid("keyword");
   1272   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, keyword_change.change_type());
   1273   EXPECT_EQ("UTF-8;UTF-16;Big5;Windows-1252", keyword_change.sync_data().
   1274       GetSpecifics().search_engine().input_encodings());
   1275 }
   1276 
   1277 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsBasic) {
   1278   // Start off B with some empty data.
   1279   model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1280                                       CreateInitialSyncData(), PassProcessor(),
   1281                                       CreateAndPassSyncErrorFactory());
   1282 
   1283   // Merge A and B. All of B's data should transfer over to A, which initially
   1284   // has no data.
   1285   scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> delegate_b(
   1286       new syncer::SyncChangeProcessorWrapperForTest(model_b()));
   1287   model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1288       model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
   1289       delegate_b.PassAs<syncer::SyncChangeProcessor>(),
   1290       CreateAndPassSyncErrorFactory());
   1291 
   1292   // They should be consistent.
   1293   AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
   1294                model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
   1295 }
   1296 
   1297 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsDupesAndConflicts) {
   1298   // Start off B with some empty data.
   1299   model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1300                                       CreateInitialSyncData(), PassProcessor(),
   1301                                       CreateAndPassSyncErrorFactory());
   1302 
   1303   // Set up A so we have some interesting duplicates and conflicts.
   1304   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com",
   1305                                        "key4"));  // Added
   1306   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
   1307                                        "key2"));  // Merge - Copy of key2.
   1308   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
   1309                                        "key5", 10));  // Merge - Dupe of key3.
   1310   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key6.com",
   1311                                        "key6", 10));  // Conflict with key1
   1312 
   1313   // Merge A and B.
   1314   scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> delegate_b(
   1315       new syncer::SyncChangeProcessorWrapperForTest(model_b()));
   1316   model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
   1317       model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
   1318       delegate_b.PassAs<syncer::SyncChangeProcessor>(),
   1319       CreateAndPassSyncErrorFactory());
   1320 
   1321   // They should be consistent.
   1322   AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
   1323                model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
   1324 }
   1325 
   1326 TEST_F(TemplateURLServiceSyncTest, StopSyncing) {
   1327   syncer::SyncError error =
   1328       model()->MergeDataAndStartSyncing(
   1329           syncer::SEARCH_ENGINES,
   1330           CreateInitialSyncData(),
   1331           PassProcessor(),
   1332           CreateAndPassSyncErrorFactory()).error();
   1333   ASSERT_FALSE(error.IsSet());
   1334   model()->StopSyncing(syncer::SEARCH_ENGINES);
   1335 
   1336   syncer::SyncChangeList changes;
   1337   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
   1338       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
   1339                             "key2")));
   1340   error = model()->ProcessSyncChanges(FROM_HERE, changes);
   1341   EXPECT_TRUE(error.IsSet());
   1342 
   1343   // Ensure that the sync changes were not accepted.
   1344   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
   1345   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
   1346 }
   1347 
   1348 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnInitialSync) {
   1349   processor()->set_erroneous(true);
   1350   syncer::SyncError error =
   1351       model()->MergeDataAndStartSyncing(
   1352           syncer::SEARCH_ENGINES,
   1353           CreateInitialSyncData(),
   1354           PassProcessor(),
   1355           CreateAndPassSyncErrorFactory()).error();
   1356   EXPECT_TRUE(error.IsSet());
   1357 
   1358   // Ensure that if the initial merge was erroneous, then subsequence attempts
   1359   // to push data into the local model are rejected, since the model was never
   1360   // successfully associated with Sync in the first place.
   1361   syncer::SyncChangeList changes;
   1362   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
   1363       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
   1364                             "key2")));
   1365   processor()->set_erroneous(false);
   1366   error = model()->ProcessSyncChanges(FROM_HERE, changes);
   1367   EXPECT_TRUE(error.IsSet());
   1368 
   1369   // Ensure that the sync changes were not accepted.
   1370   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
   1371   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
   1372 }
   1373 
   1374 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnLaterSync) {
   1375   // Ensure that if the SyncProcessor succeeds in the initial merge, but fails
   1376   // in future ProcessSyncChanges, we still return an error.
   1377   syncer::SyncError error =
   1378       model()->MergeDataAndStartSyncing(
   1379           syncer::SEARCH_ENGINES,
   1380           CreateInitialSyncData(),
   1381           PassProcessor(),
   1382           CreateAndPassSyncErrorFactory()).error();
   1383   ASSERT_FALSE(error.IsSet());
   1384 
   1385   syncer::SyncChangeList changes;
   1386   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
   1387       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
   1388                             "key2")));
   1389   processor()->set_erroneous(true);
   1390   error = model()->ProcessSyncChanges(FROM_HERE, changes);
   1391   EXPECT_TRUE(error.IsSet());
   1392 }
   1393 
   1394 TEST_F(TemplateURLServiceSyncTest, MergeTwiceWithSameSyncData) {
   1395   // Ensure that a second merge with the same data as the first does not
   1396   // actually update the local data.
   1397   syncer::SyncDataList initial_data;
   1398   initial_data.push_back(CreateInitialSyncData()[0]);
   1399 
   1400   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
   1401                                      "key1", 10));  // earlier
   1402 
   1403   syncer::SyncError error =
   1404       model()->MergeDataAndStartSyncing(
   1405           syncer::SEARCH_ENGINES,
   1406           initial_data,
   1407           PassProcessor(),
   1408           CreateAndPassSyncErrorFactory()).error();
   1409   ASSERT_FALSE(error.IsSet());
   1410 
   1411   // We should have updated the original TemplateURL with Sync's version.
   1412   // Keep a copy of it so we can compare it after we re-merge.
   1413   TemplateURL* key1_url = model()->GetTemplateURLForGUID("key1");
   1414   ASSERT_TRUE(key1_url);
   1415   scoped_ptr<TemplateURL> updated_turl(new TemplateURL(key1_url->data()));
   1416   EXPECT_EQ(Time::FromTimeT(90), updated_turl->last_modified());
   1417 
   1418   // Modify a single field of the initial data. This should not be updated in
   1419   // the second merge, as the last_modified timestamp remains the same.
   1420   scoped_ptr<TemplateURL> temp_turl(Deserialize(initial_data[0]));
   1421   TemplateURLData data(temp_turl->data());
   1422   data.short_name = ASCIIToUTF16("SomethingDifferent");
   1423   temp_turl.reset(new TemplateURL(data));
   1424   initial_data.clear();
   1425   initial_data.push_back(
   1426       TemplateURLService::CreateSyncDataFromTemplateURL(*temp_turl));
   1427 
   1428   // Remerge the data again. This simulates shutting down and syncing again
   1429   // at a different time, but the cloud data has not changed.
   1430   model()->StopSyncing(syncer::SEARCH_ENGINES);
   1431   sync_processor_wrapper_.reset(
   1432       new syncer::SyncChangeProcessorWrapperForTest(sync_processor_.get()));
   1433   error = model()->MergeDataAndStartSyncing(
   1434       syncer::SEARCH_ENGINES,
   1435       initial_data,
   1436       PassProcessor(),
   1437       CreateAndPassSyncErrorFactory()).error();
   1438   ASSERT_FALSE(error.IsSet());
   1439 
   1440   // Check that the TemplateURL was not modified.
   1441   const TemplateURL* reupdated_turl = model()->GetTemplateURLForGUID("key1");
   1442   ASSERT_TRUE(reupdated_turl);
   1443   AssertEquals(*updated_turl, *reupdated_turl);
   1444 }
   1445 
   1446 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultGUIDArrivesFirst) {
   1447   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1448   // The default search provider should support replacement.
   1449   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
   1450       "http://key2.com/{searchTerms}", "key2", 90));
   1451   initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
   1452   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1453       PassProcessor(), CreateAndPassSyncErrorFactory());
   1454   model()->SetUserSelectedDefaultSearchProvider(
   1455       model()->GetTemplateURLForGUID("key2"));
   1456 
   1457   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1458   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
   1459   ASSERT_TRUE(default_search);
   1460 
   1461   // Change kSyncedDefaultSearchProviderGUID to a GUID that does not exist in
   1462   // the model yet. Ensure that the default has not changed in any way.
   1463   profile_a()->GetTestingPrefService()->SetString(
   1464       prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
   1465 
   1466   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
   1467 
   1468   // Bring in a random new search engine with a different GUID. Ensure that
   1469   // it doesn't change the default.
   1470   syncer::SyncChangeList changes1;
   1471   changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1472       CreateTestTemplateURL(ASCIIToUTF16("random"), "http://random.com",
   1473                             "random")));
   1474   model()->ProcessSyncChanges(FROM_HERE, changes1);
   1475 
   1476   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1477   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
   1478 
   1479   // Finally, bring in the expected entry with the right GUID. Ensure that
   1480   // the default has changed to the new search engine.
   1481   syncer::SyncChangeList changes2;
   1482   changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1483       CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
   1484                             "newdefault")));
   1485   model()->ProcessSyncChanges(FROM_HERE, changes2);
   1486 
   1487   EXPECT_EQ(5U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1488   ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
   1489   ASSERT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
   1490 }
   1491 
   1492 TEST_F(TemplateURLServiceSyncTest, DefaultGuidDeletedBeforeNewDSPArrives) {
   1493   syncer::SyncDataList initial_data;
   1494   // The default search provider should support replacement.
   1495   scoped_ptr<TemplateURL> turl1(CreateTestTemplateURL(ASCIIToUTF16("key1"),
   1496       "http://key1.com/{searchTerms}", "key1", 90));
   1497   // Create a second default search provider for the
   1498   // FindNewDefaultSearchProvider method to find.
   1499   TemplateURLData data;
   1500   data.short_name = ASCIIToUTF16("unittest");
   1501   data.SetKeyword(ASCIIToUTF16("key2"));
   1502   data.SetURL("http://key2.com/{searchTerms}");
   1503   data.favicon_url = GURL("http://favicon.url");
   1504   data.safe_for_autoreplace = false;
   1505   data.date_created = Time::FromTimeT(100);
   1506   data.last_modified = Time::FromTimeT(100);
   1507   data.created_by_policy = false;
   1508   data.prepopulate_id = 999999;
   1509   data.sync_guid = "key2";
   1510   data.show_in_default_list = true;
   1511   scoped_ptr<TemplateURL> turl2(new TemplateURL(data));
   1512   initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
   1513       *turl1));
   1514   initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
   1515       *turl2));
   1516   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1517       PassProcessor(), CreateAndPassSyncErrorFactory());
   1518   model()->SetUserSelectedDefaultSearchProvider(
   1519       model()->GetTemplateURLForGUID("key1"));
   1520   ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
   1521 
   1522   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1523   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
   1524   ASSERT_TRUE(default_search);
   1525 
   1526   // Change kSyncedDefaultSearchProviderGUID to a GUID that does not exist in
   1527   // the model yet. Ensure that the default has not changed in any way.
   1528   profile_a()->GetTestingPrefService()->SetString(
   1529       prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
   1530 
   1531   ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
   1532   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
   1533       prefs::kSyncedDefaultSearchProviderGUID));
   1534 
   1535   // Simulate a situation where an ACTION_DELETE on the default arrives before
   1536   // the new default search provider entry. This should fail to delete the
   1537   // target entry, and instead send up an "undelete" to the server, after
   1538   // further uniquifying the keyword to avoid infinite sync loops. The synced
   1539   // default GUID should not be changed so that when the expected default entry
   1540   // arrives, it can still be set as the default.
   1541   syncer::SyncChangeList changes1;
   1542   changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
   1543                                           turl1.release()));
   1544   model()->ProcessSyncChanges(FROM_HERE, changes1);
   1545 
   1546   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1_")));
   1547   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1548   EXPECT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
   1549   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
   1550       prefs::kSyncedDefaultSearchProviderGUID));
   1551   syncer::SyncChange undelete = processor()->change_for_guid("key1");
   1552   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, undelete.change_type());
   1553   EXPECT_EQ("key1_",
   1554             undelete.sync_data().GetSpecifics().search_engine().keyword());
   1555 
   1556   // Finally, bring in the expected entry with the right GUID. Ensure that
   1557   // the default has changed to the new search engine.
   1558   syncer::SyncChangeList changes2;
   1559   changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1560       CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
   1561                             "newdefault")));
   1562   model()->ProcessSyncChanges(FROM_HERE, changes2);
   1563 
   1564   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1565   EXPECT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
   1566   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
   1567       prefs::kSyncedDefaultSearchProviderGUID));
   1568 }
   1569 
   1570 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultArrivesAfterStartup) {
   1571   // Start with the default set to something in the model before we start
   1572   // syncing.
   1573   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
   1574                                      "http://thewhat.com/{searchTerms}",
   1575                                      "initdefault"));
   1576   model()->SetUserSelectedDefaultSearchProvider(
   1577       model()->GetTemplateURLForGUID("initdefault"));
   1578 
   1579   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
   1580   ASSERT_TRUE(default_search);
   1581 
   1582   // Set kSyncedDefaultSearchProviderGUID to something that is not yet in
   1583   // the model but is expected in the initial sync. Ensure that this doesn't
   1584   // change our default since we're not quite syncing yet.
   1585   profile_a()->GetTestingPrefService()->SetString(
   1586       prefs::kSyncedDefaultSearchProviderGUID, "key2");
   1587 
   1588   EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
   1589 
   1590   // Now sync the initial data, which will include the search engine entry
   1591   // destined to become the new default.
   1592   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1593   // The default search provider should support replacement.
   1594   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
   1595       "http://key2.com/{searchTerms}", "key2", 90));
   1596   initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
   1597 
   1598   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1599       PassProcessor(), CreateAndPassSyncErrorFactory());
   1600 
   1601   // Ensure that the new default has been set.
   1602   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1603   ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
   1604   ASSERT_EQ("key2", model()->GetDefaultSearchProvider()->sync_guid());
   1605 }
   1606 
   1607 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultAlreadySetOnStartup) {
   1608   // Start with the default set to something in the model before we start
   1609   // syncing.
   1610   const char kGUID[] = "initdefault";
   1611   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
   1612                                      "http://thewhat.com/{searchTerms}",
   1613                                      kGUID));
   1614   model()->SetUserSelectedDefaultSearchProvider(
   1615       model()->GetTemplateURLForGUID(kGUID));
   1616 
   1617   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
   1618   ASSERT_TRUE(default_search);
   1619 
   1620   // Set kSyncedDefaultSearchProviderGUID to the current default.
   1621   profile_a()->GetTestingPrefService()->SetString(
   1622       prefs::kSyncedDefaultSearchProviderGUID, kGUID);
   1623 
   1624   EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
   1625 
   1626   // Now sync the initial data.
   1627   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1628   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1629       PassProcessor(), CreateAndPassSyncErrorFactory());
   1630 
   1631   // Ensure that the new entries were added and the default has not changed.
   1632   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1633   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
   1634 }
   1635 
   1636 TEST_F(TemplateURLServiceSyncTest, SyncWithManagedDefaultSearch) {
   1637   // First start off with a few entries and make sure we can set an unmanaged
   1638   // default search provider.
   1639   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1640   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1641       PassProcessor(), CreateAndPassSyncErrorFactory());
   1642   model()->SetUserSelectedDefaultSearchProvider(
   1643       model()->GetTemplateURLForGUID("key2"));
   1644 
   1645   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1646   ASSERT_FALSE(model()->is_default_search_managed());
   1647   ASSERT_TRUE(model()->GetDefaultSearchProvider());
   1648 
   1649   // Change the default search provider to a managed one.
   1650   const char kName[] = "manageddefault";
   1651   const char kSearchURL[] = "http://manageddefault.com/search?t={searchTerms}";
   1652   const char kIconURL[] = "http://manageddefault.com/icon.jpg";
   1653   const char kEncodings[] = "UTF-16;UTF-32";
   1654   const char kAlternateURL[] =
   1655       "http://manageddefault.com/search#t={searchTerms}";
   1656   const char kSearchTermsReplacementKey[] = "espv";
   1657   test_util_a_.SetManagedDefaultSearchPreferences(true, kName, kName,
   1658       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
   1659       kSearchTermsReplacementKey);
   1660   const TemplateURL* dsp_turl = model()->GetDefaultSearchProvider();
   1661 
   1662   EXPECT_TRUE(model()->is_default_search_managed());
   1663 
   1664   // Add a new entry from Sync. It should still sync in despite the default
   1665   // being managed.
   1666   syncer::SyncChangeList changes;
   1667   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   1668       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"),
   1669                             "http://new.com/{searchTerms}",
   1670                             "newdefault")));
   1671   model()->ProcessSyncChanges(FROM_HERE, changes);
   1672 
   1673   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1674 
   1675   // Change kSyncedDefaultSearchProviderGUID to point to the new entry and
   1676   // ensure that the DSP remains managed.
   1677   profile_a()->GetTestingPrefService()->SetString(
   1678       prefs::kSyncedDefaultSearchProviderGUID,
   1679       "newdefault");
   1680 
   1681   EXPECT_EQ(dsp_turl, model()->GetDefaultSearchProvider());
   1682   EXPECT_TRUE(model()->is_default_search_managed());
   1683 
   1684   // Go unmanaged. Ensure that the DSP changes to the expected pending entry
   1685   // from Sync.
   1686   const TemplateURL* expected_default =
   1687       model()->GetTemplateURLForGUID("newdefault");
   1688   test_util_a_.RemoveManagedDefaultSearchPreferences();
   1689 
   1690   EXPECT_EQ(expected_default, model()->GetDefaultSearchProvider());
   1691 }
   1692 
   1693 TEST_F(TemplateURLServiceSyncTest, SyncMergeDeletesDefault) {
   1694   // If the value from Sync is a duplicate of the local default and is newer, it
   1695   // should safely replace the local value and set as the new default.
   1696   TemplateURL* default_turl = CreateTestTemplateURL(ASCIIToUTF16("key1"),
   1697       "http://key1.com/{searchTerms}", "whateverguid", 10);
   1698   model()->Add(default_turl);
   1699   model()->SetUserSelectedDefaultSearchProvider(default_turl);
   1700 
   1701   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1702   // The key1 entry should be a duplicate of the default.
   1703   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
   1704       "http://key1.com/{searchTerms}", "key1", 90));
   1705   initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
   1706 
   1707   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1708       PassProcessor(), CreateAndPassSyncErrorFactory());
   1709 
   1710   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1711   EXPECT_FALSE(model()->GetTemplateURLForGUID("whateverguid"));
   1712   EXPECT_EQ(model()->GetDefaultSearchProvider(),
   1713             model()->GetTemplateURLForGUID("key1"));
   1714 }
   1715 
   1716 TEST_F(TemplateURLServiceSyncTest, LocalDefaultWinsConflict) {
   1717   // We expect that the local default always wins keyword conflict resolution.
   1718   const base::string16 keyword(ASCIIToUTF16("key1"));
   1719   const std::string url("http://whatever.com/{searchTerms}");
   1720   TemplateURL* default_turl = CreateTestTemplateURL(keyword,
   1721                                                     url,
   1722                                                     "whateverguid",
   1723                                                     10);
   1724   model()->Add(default_turl);
   1725   model()->SetUserSelectedDefaultSearchProvider(default_turl);
   1726 
   1727   syncer::SyncDataList initial_data = CreateInitialSyncData();
   1728   // The key1 entry should be different from the default but conflict in the
   1729   // keyword.
   1730   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(keyword,
   1731       "http://key1.com/{searchTerms}", "key1", 90));
   1732   initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
   1733 
   1734   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1735       PassProcessor(), CreateAndPassSyncErrorFactory());
   1736 
   1737   // Since the local default was not yet synced, it should be merged with the
   1738   // conflicting TemplateURL. However, its values should have been preserved
   1739   // since it would have won conflict resolution due to being the default.
   1740   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
   1741   const TemplateURL* winner = model()->GetTemplateURLForGUID("key1");
   1742   ASSERT_TRUE(winner);
   1743   EXPECT_EQ(model()->GetDefaultSearchProvider(), winner);
   1744   EXPECT_EQ(keyword, winner->keyword());
   1745   EXPECT_EQ(url, winner->url());
   1746   ASSERT_TRUE(processor()->contains_guid("key1"));
   1747   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
   1748             processor()->change_for_guid("key1").change_type());
   1749   EXPECT_EQ(url, GetURL(processor()->change_for_guid("key1").sync_data()));
   1750 
   1751   // There is no loser, as the two were merged together. The local sync_guid
   1752   // should no longer be found in the model.
   1753   const TemplateURL* loser = model()->GetTemplateURLForGUID("whateverguid");
   1754   ASSERT_FALSE(loser);
   1755 }
   1756 
   1757 TEST_F(TemplateURLServiceSyncTest, DeleteBogusData) {
   1758   // Create a couple of bogus entries to sync.
   1759   syncer::SyncDataList initial_data;
   1760   scoped_ptr<TemplateURL> turl(
   1761       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
   1762   initial_data.push_back(
   1763       CreateCustomSyncData(*turl, false, std::string(), turl->sync_guid()));
   1764   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
   1765   initial_data.push_back(
   1766       CreateCustomSyncData(*turl, false, turl->url(), std::string()));
   1767 
   1768   // Now try to sync the data locally.
   1769   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1770       PassProcessor(), CreateAndPassSyncErrorFactory());
   1771 
   1772   // Nothing should have been added, and both bogus entries should be marked for
   1773   // deletion.
   1774   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
   1775   EXPECT_EQ(2U, processor()->change_list_size());
   1776   ASSERT_TRUE(processor()->contains_guid("key1"));
   1777   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
   1778             processor()->change_for_guid("key1").change_type());
   1779   ASSERT_TRUE(processor()->contains_guid(std::string()));
   1780   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
   1781             processor()->change_for_guid(std::string()).change_type());
   1782 }
   1783 
   1784 TEST_F(TemplateURLServiceSyncTest, PreSyncDeletes) {
   1785   model()->pre_sync_deletes_.insert("key1");
   1786   model()->pre_sync_deletes_.insert("key2");
   1787   model()->pre_sync_deletes_.insert("aaa");
   1788   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("whatever"),
   1789       "http://key1.com", "bbb"));
   1790   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   1791       syncer::SEARCH_ENGINES,
   1792       CreateInitialSyncData(), PassProcessor(),
   1793       CreateAndPassSyncErrorFactory());
   1794 
   1795   // We expect the model to have GUIDs {bbb, key3} after our initial merge.
   1796   EXPECT_TRUE(model()->GetTemplateURLForGUID("bbb"));
   1797   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
   1798   syncer::SyncChange change = processor()->change_for_guid("key1");
   1799   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
   1800   change = processor()->change_for_guid("key2");
   1801   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
   1802   // "aaa" should have been pruned out on account of not being from Sync.
   1803   EXPECT_FALSE(processor()->contains_guid("aaa"));
   1804   // The set of pre-sync deletes should be cleared so they're not reused if
   1805   // MergeDataAndStartSyncing gets called again.
   1806   EXPECT_TRUE(model()->pre_sync_deletes_.empty());
   1807 
   1808   // Those sync items deleted via pre-sync-deletes should not get added. The
   1809   // remaining sync item (key3) should though.
   1810   EXPECT_EQ(1, merge_result.num_items_added());
   1811   EXPECT_EQ(0, merge_result.num_items_modified());
   1812   EXPECT_EQ(0, merge_result.num_items_deleted());
   1813   EXPECT_EQ(1, merge_result.num_items_before_association());
   1814   EXPECT_EQ(2, merge_result.num_items_after_association());
   1815 }
   1816 
   1817 TEST_F(TemplateURLServiceSyncTest, PreSyncUpdates) {
   1818   const char* kNewKeyword = "somethingnew";
   1819   // Fetch the prepopulate search engines so we know what they are.
   1820   size_t default_search_provider_index = 0;
   1821   ScopedVector<TemplateURLData> prepop_turls =
   1822       TemplateURLPrepopulateData::GetPrepopulatedEngines(
   1823           profile_a()->GetTestingPrefService(), &default_search_provider_index);
   1824 
   1825   // We have to prematurely exit this test if for some reason this machine does
   1826   // not have any prepopulate TemplateURLs.
   1827   ASSERT_FALSE(prepop_turls.empty());
   1828 
   1829   // Create a copy of the first TemplateURL with a really old timestamp and a
   1830   // new keyword. Add it to the model.
   1831   TemplateURLData data_copy(*prepop_turls[0]);
   1832   data_copy.last_modified = Time::FromTimeT(10);
   1833   base::string16 original_keyword = data_copy.keyword();
   1834   data_copy.SetKeyword(ASCIIToUTF16(kNewKeyword));
   1835   // Set safe_for_autoreplace to false so our keyword survives.
   1836   data_copy.safe_for_autoreplace = false;
   1837   model()->Add(new TemplateURL(data_copy));
   1838 
   1839   // Merge the prepopulate search engines.
   1840   base::Time pre_merge_time = base::Time::Now();
   1841   base::RunLoop().RunUntilIdle();
   1842   test_util_a_.ResetModel(true);
   1843 
   1844   // The newly added search engine should have been safely merged, with an
   1845   // updated time.
   1846   TemplateURL* added_turl = model()->GetTemplateURLForKeyword(
   1847       ASCIIToUTF16(kNewKeyword));
   1848   ASSERT_TRUE(added_turl);
   1849   base::Time new_timestamp = added_turl->last_modified();
   1850   EXPECT_GE(new_timestamp, pre_merge_time);
   1851   std::string sync_guid = added_turl->sync_guid();
   1852 
   1853   // Bring down a copy of the prepopulate engine from Sync with the old values,
   1854   // including the old timestamp and the same GUID. Ensure that it loses
   1855   // conflict resolution against the local value, and an update is sent to the
   1856   // server. The new timestamp should be preserved.
   1857   syncer::SyncDataList initial_data;
   1858   data_copy.SetKeyword(original_keyword);
   1859   data_copy.sync_guid = sync_guid;
   1860   scoped_ptr<TemplateURL> sync_turl(new TemplateURL(data_copy));
   1861   initial_data.push_back(
   1862       TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
   1863 
   1864   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   1865       syncer::SEARCH_ENGINES,
   1866       initial_data, PassProcessor(), CreateAndPassSyncErrorFactory());
   1867 
   1868   ASSERT_EQ(added_turl, model()->GetTemplateURLForKeyword(
   1869       ASCIIToUTF16(kNewKeyword)));
   1870   EXPECT_EQ(new_timestamp, added_turl->last_modified());
   1871   syncer::SyncChange change = processor()->change_for_guid(sync_guid);
   1872   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
   1873   EXPECT_EQ(kNewKeyword,
   1874             change.sync_data().GetSpecifics().search_engine().keyword());
   1875   EXPECT_EQ(new_timestamp, base::Time::FromInternalValue(
   1876       change.sync_data().GetSpecifics().search_engine().last_modified()));
   1877 
   1878   // All the sync data is old, so nothing should change locally.
   1879   EXPECT_EQ(0, merge_result.num_items_added());
   1880   EXPECT_EQ(0, merge_result.num_items_modified());
   1881   EXPECT_EQ(0, merge_result.num_items_deleted());
   1882   EXPECT_EQ(static_cast<int>(prepop_turls.size()),
   1883             merge_result.num_items_before_association());
   1884   EXPECT_EQ(static_cast<int>(prepop_turls.size()),
   1885             merge_result.num_items_after_association());
   1886 }
   1887 
   1888 TEST_F(TemplateURLServiceSyncTest, SyncBaseURLs) {
   1889   // Verify that bringing in a remote TemplateURL that uses Google base URLs
   1890   // causes it to get a local keyword that matches the local base URL.
   1891   test_util_a_.SetGoogleBaseURL(GURL("http://google.com/"));
   1892   syncer::SyncDataList initial_data;
   1893   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(
   1894       ASCIIToUTF16("google.co.uk"), "{google:baseURL}search?q={searchTerms}",
   1895       "guid"));
   1896   initial_data.push_back(
   1897       TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
   1898   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
   1899       PassProcessor(), CreateAndPassSyncErrorFactory());
   1900   TemplateURL* synced_turl = model()->GetTemplateURLForGUID("guid");
   1901   ASSERT_TRUE(synced_turl);
   1902   EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
   1903   EXPECT_EQ(0U, processor()->change_list_size());
   1904 
   1905   // Remote updates to this URL's keyword should be silently ignored.
   1906   syncer::SyncChangeList changes;
   1907   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
   1908       CreateTestTemplateURL(ASCIIToUTF16("google.de"),
   1909           "{google:baseURL}search?q={searchTerms}", "guid")));
   1910   model()->ProcessSyncChanges(FROM_HERE, changes);
   1911   EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
   1912   EXPECT_EQ(0U, processor()->change_list_size());
   1913 
   1914   // A local change to the Google base URL should update the keyword and
   1915   // generate a sync change.
   1916   test_util_a_.SetGoogleBaseURL(GURL("http://google.co.in/"));
   1917   EXPECT_EQ(ASCIIToUTF16("google.co.in"), synced_turl->keyword());
   1918   EXPECT_EQ(1U, processor()->change_list_size());
   1919   ASSERT_TRUE(processor()->contains_guid("guid"));
   1920   syncer::SyncChange change(processor()->change_for_guid("guid"));
   1921   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
   1922   EXPECT_EQ("google.co.in", GetKeyword(change.sync_data()));
   1923 }
   1924 
   1925 TEST_F(TemplateURLServiceSyncTest, MergeInSyncTemplateURL) {
   1926   // An enumeration used to indicate which TemplateURL test value is expected
   1927   // for a particular test result.
   1928   enum ExpectedTemplateURL {
   1929     LOCAL,
   1930     SYNC,
   1931     BOTH,
   1932     NEITHER,
   1933   };
   1934 
   1935   // Sets up and executes a MergeInSyncTemplateURL test given a number of
   1936   // expected start and end states:
   1937   //  * |conflict_winner| denotes which TemplateURL should win the
   1938   //    conflict.
   1939   //  * |synced_at_start| denotes which of the TemplateURLs should known
   1940   //    to Sync.
   1941   //  * |update_sent| denotes which TemplateURL should have an
   1942   //    ACTION_UPDATE sent to the server after the merge.
   1943   //  * |turl_uniquified| denotes which TemplateURL should have its
   1944   //    keyword updated after the merge.
   1945   //  * |present_in_model| denotes which TemplateURL should be found in
   1946   //    the model after the merge.
   1947   //  * If |keywords_conflict| is true, the TemplateURLs are set up with
   1948   //    the same keyword.
   1949   const struct {
   1950     ExpectedTemplateURL conflict_winner;
   1951     ExpectedTemplateURL synced_at_start;
   1952     ExpectedTemplateURL update_sent;
   1953     ExpectedTemplateURL turl_uniquified;
   1954     ExpectedTemplateURL present_in_model;
   1955     bool keywords_conflict;
   1956     int merge_results[3];  // in Added, Modified, Deleted order.
   1957   } test_cases[] = {
   1958     // Both are synced and the new sync entry is better: Local is uniquified and
   1959     // UPDATE sent. Sync is added.
   1960     {SYNC, BOTH, LOCAL, LOCAL, BOTH, true, {1, 1, 0}},
   1961     // Both are synced and the local entry is better: Sync is uniquified and
   1962     // added to the model. An UPDATE is sent for it.
   1963     {LOCAL, BOTH, SYNC, SYNC, BOTH, true, {1, 1, 0}},
   1964     // Local was not known to Sync and the new sync entry is better: Sync is
   1965     // added. Local is removed. No updates.
   1966     {SYNC, SYNC, NEITHER, NEITHER, SYNC, true, {1, 0, 1}},
   1967     // Local was not known to sync and the local entry is better: Local is
   1968     // updated with sync GUID, Sync is not added. UPDATE sent for Sync.
   1969     {LOCAL, SYNC, SYNC, NEITHER, SYNC, true, {0, 1, 0}},
   1970     // No conflicting keyword. Both should be added with their original
   1971     // keywords, with no updates sent. Note that MergeDataAndStartSyncing is
   1972     // responsible for creating the ACTION_ADD for the local TemplateURL.
   1973     {NEITHER, SYNC, NEITHER, NEITHER, BOTH, false, {1, 0, 0}},
   1974   };
   1975 
   1976   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
   1977     // Assert all the valid states of ExpectedTemplateURLs.
   1978     ASSERT_FALSE(test_cases[i].conflict_winner == BOTH);
   1979     ASSERT_FALSE(test_cases[i].synced_at_start == NEITHER);
   1980     ASSERT_FALSE(test_cases[i].synced_at_start == LOCAL);
   1981     ASSERT_FALSE(test_cases[i].update_sent == BOTH);
   1982     ASSERT_FALSE(test_cases[i].turl_uniquified == BOTH);
   1983     ASSERT_FALSE(test_cases[i].present_in_model == NEITHER);
   1984 
   1985     const base::string16 local_keyword = ASCIIToUTF16("localkeyword");
   1986     const base::string16 sync_keyword = test_cases[i].keywords_conflict ?
   1987         local_keyword : ASCIIToUTF16("synckeyword");
   1988     const std::string local_url = "www.localurl.com";
   1989     const std::string sync_url = "www.syncurl.com";
   1990     const time_t local_last_modified = 100;
   1991     const time_t sync_last_modified =
   1992         test_cases[i].conflict_winner == SYNC ? 110 : 90;
   1993     const std::string local_guid = "local_guid";
   1994     const std::string sync_guid = "sync_guid";
   1995 
   1996     // Initialize expectations.
   1997     base::string16 expected_local_keyword = local_keyword;
   1998     base::string16 expected_sync_keyword = sync_keyword;
   1999 
   2000     // Create the data and run the actual test.
   2001     TemplateURL* local_turl = CreateTestTemplateURL(
   2002         local_keyword, local_url, local_guid, local_last_modified);
   2003     model()->Add(local_turl);
   2004     scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
   2005         sync_keyword, sync_url, sync_guid, sync_last_modified));
   2006 
   2007     SyncDataMap sync_data;
   2008     if (test_cases[i].synced_at_start == SYNC ||
   2009         test_cases[i].synced_at_start == BOTH) {
   2010       sync_data[sync_turl->sync_guid()] =
   2011           TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl);
   2012     }
   2013     if (test_cases[i].synced_at_start == BOTH) {
   2014       sync_data[local_turl->sync_guid()] =
   2015           TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
   2016     }
   2017     SyncDataMap initial_data;
   2018     initial_data[local_turl->sync_guid()] =
   2019         TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
   2020 
   2021     syncer::SyncChangeList change_list;
   2022     syncer::SyncMergeResult merge_result(syncer::SEARCH_ENGINES);
   2023     model()->MergeInSyncTemplateURL(sync_turl.get(),
   2024                                     sync_data,
   2025                                     &change_list,
   2026                                     &initial_data,
   2027                                     &merge_result);
   2028 
   2029     // Verify the merge results were set appropriately.
   2030     EXPECT_EQ(test_cases[i].merge_results[0], merge_result.num_items_added());
   2031     EXPECT_EQ(test_cases[i].merge_results[1],
   2032               merge_result.num_items_modified());
   2033     EXPECT_EQ(test_cases[i].merge_results[2], merge_result.num_items_deleted());
   2034 
   2035     // Check for expected updates, if any.
   2036     std::string expected_update_guid;
   2037     if (test_cases[i].update_sent == LOCAL)
   2038       expected_update_guid = local_guid;
   2039     else if (test_cases[i].update_sent == SYNC)
   2040       expected_update_guid = sync_guid;
   2041     if (!expected_update_guid.empty()) {
   2042       ASSERT_EQ(1U, change_list.size());
   2043       EXPECT_EQ(expected_update_guid, GetGUID(change_list[0].sync_data()));
   2044       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
   2045                 change_list[0].change_type());
   2046     } else {
   2047       EXPECT_EQ(0U, change_list.size());
   2048     }
   2049 
   2050     // Adjust the expectations based on the expectation enums.
   2051     if (test_cases[i].turl_uniquified == LOCAL) {
   2052       DCHECK(test_cases[i].keywords_conflict);
   2053       expected_local_keyword = ASCIIToUTF16("localkeyword_");
   2054     }
   2055     if (test_cases[i].turl_uniquified == SYNC) {
   2056       DCHECK(test_cases[i].keywords_conflict);
   2057       expected_sync_keyword = ASCIIToUTF16("localkeyword_");
   2058     }
   2059 
   2060     // Check for TemplateURLs expected in the model. Note that this is checked
   2061     // by GUID rather than the initial pointer, as a merge could occur (the
   2062     // Sync TemplateURL overtakes the local one). Also remove the present
   2063     // TemplateURL when done so the next test case starts with a clean slate.
   2064     if (test_cases[i].present_in_model == LOCAL ||
   2065         test_cases[i].present_in_model == BOTH) {
   2066       ASSERT_TRUE(model()->GetTemplateURLForGUID(local_guid));
   2067       EXPECT_EQ(expected_local_keyword, local_turl->keyword());
   2068       EXPECT_EQ(local_url, local_turl->url());
   2069       EXPECT_EQ(local_last_modified, local_turl->last_modified().ToTimeT());
   2070       model()->Remove(model()->GetTemplateURLForGUID(local_guid));
   2071     }
   2072     if (test_cases[i].present_in_model == SYNC ||
   2073         test_cases[i].present_in_model == BOTH) {
   2074       ASSERT_TRUE(model()->GetTemplateURLForGUID(sync_guid));
   2075       EXPECT_EQ(expected_sync_keyword, sync_turl->keyword());
   2076       EXPECT_EQ(sync_url, sync_turl->url());
   2077       EXPECT_EQ(sync_last_modified, sync_turl->last_modified().ToTimeT());
   2078       model()->Remove(model()->GetTemplateURLForGUID(sync_guid));
   2079     }
   2080   }  // for
   2081 }
   2082 
   2083 TEST_F(TemplateURLServiceSyncTest, MergePrepopulatedEngine) {
   2084   scoped_ptr<TemplateURLData> default_turl(
   2085       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
   2086 
   2087   // Merge with an initial list containing a prepopulated engine with a wrong
   2088   // URL.
   2089   syncer::SyncDataList list;
   2090   scoped_ptr<TemplateURL> sync_turl(CopyTemplateURL(default_turl.get(),
   2091       "http://wrong.url.com?q={searchTerms}", "default"));
   2092   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
   2093   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   2094       syncer::SEARCH_ENGINES, list, PassProcessor(),
   2095       CreateAndPassSyncErrorFactory());
   2096 
   2097   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
   2098   EXPECT_TRUE(result_turl);
   2099   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
   2100   EXPECT_EQ(default_turl->short_name, result_turl->short_name());
   2101   EXPECT_EQ(default_turl->url(), result_turl->url());
   2102 }
   2103 
   2104 TEST_F(TemplateURLServiceSyncTest, AddPrepopulatedEngine) {
   2105   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   2106       syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
   2107       CreateAndPassSyncErrorFactory());
   2108 
   2109   scoped_ptr<TemplateURLData> default_turl(
   2110       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
   2111   TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
   2112       "http://wrong.url.com?q={searchTerms}", "default");
   2113 
   2114   // Add a prepopulated engine with a wrong URL.
   2115   syncer::SyncChangeList changes;
   2116   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
   2117                                          sync_turl));
   2118   model()->ProcessSyncChanges(FROM_HERE, changes);
   2119 
   2120   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
   2121   EXPECT_TRUE(result_turl);
   2122   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
   2123   EXPECT_EQ(default_turl->short_name, result_turl->short_name());
   2124   EXPECT_EQ(default_turl->url(), result_turl->url());
   2125 }
   2126 
   2127 TEST_F(TemplateURLServiceSyncTest, UpdatePrepopulatedEngine) {
   2128   scoped_ptr<TemplateURLData> default_turl(
   2129       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
   2130 
   2131   TemplateURLData data = *default_turl;
   2132   data.SetURL("http://old.wrong.url.com?q={searchTerms}");
   2133   data.sync_guid = "default";
   2134   model()->Add(new TemplateURL(data));
   2135 
   2136   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   2137       syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
   2138       CreateAndPassSyncErrorFactory());
   2139 
   2140   TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
   2141       "http://new.wrong.url.com?q={searchTerms}", "default");
   2142 
   2143   // Update the engine in the model, which is prepopulated, with a new one.
   2144   // Both have wrong URLs, but it should still get corrected.
   2145   syncer::SyncChangeList changes;
   2146   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
   2147                                          sync_turl));
   2148   model()->ProcessSyncChanges(FROM_HERE, changes);
   2149 
   2150   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
   2151   EXPECT_TRUE(result_turl);
   2152   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
   2153   EXPECT_EQ(default_turl->short_name, result_turl->short_name());
   2154   EXPECT_EQ(default_turl->url(), result_turl->url());
   2155 }
   2156 
   2157 TEST_F(TemplateURLServiceSyncTest, MergeEditedPrepopulatedEngine) {
   2158   scoped_ptr<TemplateURLData> default_turl(
   2159       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
   2160 
   2161   TemplateURLData data(*default_turl);
   2162   data.safe_for_autoreplace = false;
   2163   data.SetKeyword(ASCIIToUTF16("new_kw"));
   2164   data.short_name = ASCIIToUTF16("my name");
   2165   data.SetURL("http://wrong.url.com?q={searchTerms}");
   2166   data.date_created = Time::FromTimeT(50);
   2167   data.last_modified = Time::FromTimeT(50);
   2168   data.sync_guid = "default";
   2169   model()->Add(new TemplateURL(data));
   2170 
   2171   data.date_created = Time::FromTimeT(100);
   2172   data.last_modified = Time::FromTimeT(100);
   2173   scoped_ptr<TemplateURL> sync_turl(new TemplateURL(data));
   2174   syncer::SyncDataList list;
   2175   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
   2176   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   2177       syncer::SEARCH_ENGINES, list, PassProcessor(),
   2178       CreateAndPassSyncErrorFactory());
   2179 
   2180   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
   2181   EXPECT_TRUE(result_turl);
   2182   EXPECT_EQ(ASCIIToUTF16("new_kw"), result_turl->keyword());
   2183   EXPECT_EQ(ASCIIToUTF16("my name"), result_turl->short_name());
   2184   EXPECT_EQ(default_turl->url(), result_turl->url());
   2185 }
   2186 
   2187 TEST_F(TemplateURLServiceSyncTest, MergeNonEditedPrepopulatedEngine) {
   2188   scoped_ptr<TemplateURLData> default_turl(
   2189       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
   2190 
   2191   TemplateURLData data(*default_turl);
   2192   data.safe_for_autoreplace = true;  // Can be replaced with built-in values.
   2193   data.SetKeyword(ASCIIToUTF16("new_kw"));
   2194   data.short_name = ASCIIToUTF16("my name");
   2195   data.SetURL("http://wrong.url.com?q={searchTerms}");
   2196   data.date_created = Time::FromTimeT(50);
   2197   data.last_modified = Time::FromTimeT(50);
   2198   data.sync_guid = "default";
   2199   model()->Add(new TemplateURL(data));
   2200 
   2201   data.date_created = Time::FromTimeT(100);
   2202   data.last_modified = Time::FromTimeT(100);
   2203   scoped_ptr<TemplateURL> sync_turl(new TemplateURL(data));
   2204   syncer::SyncDataList list;
   2205   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
   2206   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
   2207       syncer::SEARCH_ENGINES, list, PassProcessor(),
   2208       CreateAndPassSyncErrorFactory());
   2209 
   2210   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
   2211   EXPECT_TRUE(result_turl);
   2212   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
   2213   EXPECT_EQ(default_turl->short_name, result_turl->short_name());
   2214   EXPECT_EQ(default_turl->url(), result_turl->url());
   2215 }
   2216 
   2217 TEST_F(TemplateURLServiceSyncTest, GUIDUpdatedOnDefaultSearchChange) {
   2218   const char kGUID[] = "initdefault";
   2219   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
   2220                                      "http://thewhat.com/{searchTerms}",
   2221                                      kGUID));
   2222   model()->SetUserSelectedDefaultSearchProvider(
   2223       model()->GetTemplateURLForGUID(kGUID));
   2224 
   2225   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
   2226   ASSERT_TRUE(default_search);
   2227 
   2228   const char kNewGUID[] = "newdefault";
   2229   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
   2230                                      "http://thewhat.com/{searchTerms}",
   2231                                      kNewGUID));
   2232   model()->SetUserSelectedDefaultSearchProvider(
   2233       model()->GetTemplateURLForGUID(kNewGUID));
   2234 
   2235   EXPECT_EQ(kNewGUID, profile_a()->GetTestingPrefService()->GetString(
   2236       prefs::kSyncedDefaultSearchProviderGUID));
   2237 }
   2238