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