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