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