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