Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / search_engines / template_url_service_unittest.cc
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/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/callback.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_vector.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/task/cancelable_task_tracker.h"
15 #include "base/test/mock_time_provider.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "chrome/browser/history/history_service.h"
19 #include "chrome/browser/history/history_service_factory.h"
20 #include "chrome/browser/search_engines/template_url_service_test_util.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "components/search_engines/keyword_web_data_service.h"
23 #include "components/search_engines/search_host_to_urls_map.h"
24 #include "components/search_engines/search_terms_data.h"
25 #include "components/search_engines/template_url.h"
26 #include "components/search_engines/template_url_prepopulate_data.h"
27 #include "components/search_engines/template_url_service.h"
28 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using base::ASCIIToUTF16;
32 using base::Time;
33 using base::TimeDelta;
34 using ::testing::Return;
35 using ::testing::StrictMock;
36
37 namespace {
38
39 // QueryHistoryCallbackImpl ---------------------------------------------------
40
41 struct QueryHistoryCallbackImpl {
42   QueryHistoryCallbackImpl() : success(false) {}
43
44   void Callback(bool success,
45                 const history::URLRow& row,
46                 const history::VisitVector& visits) {
47     this->success = success;
48     if (success) {
49       this->row = row;
50       this->visits = visits;
51     }
52   }
53
54   bool success;
55   history::URLRow row;
56   history::VisitVector visits;
57 };
58
59 TemplateURL* CreateKeywordWithDate(
60     TemplateURLService* model,
61     const std::string& short_name,
62     const std::string& keyword,
63     const std::string& url,
64     const std::string& suggest_url,
65     const std::string& alternate_url,
66     const std::string& favicon_url,
67     bool safe_for_autoreplace,
68     bool show_in_default_list,
69     const std::string& encodings,
70     Time date_created,
71     Time last_modified) {
72   TemplateURLData data;
73   data.short_name = base::UTF8ToUTF16(short_name);
74   data.SetKeyword(base::UTF8ToUTF16(keyword));
75   data.SetURL(url);
76   data.suggestions_url = suggest_url;
77   if (!alternate_url.empty())
78     data.alternate_urls.push_back(alternate_url);
79   data.favicon_url = GURL(favicon_url);
80   data.safe_for_autoreplace = safe_for_autoreplace;
81   data.show_in_default_list = show_in_default_list;
82   base::SplitString(encodings, ';', &data.input_encodings);
83   data.date_created = date_created;
84   data.last_modified = last_modified;
85   return new TemplateURL(data);
86 }
87
88 TemplateURL* AddKeywordWithDate(
89     TemplateURLService* model,
90     const std::string& short_name,
91     const std::string& keyword,
92     const std::string& url,
93     const std::string& suggest_url,
94     const std::string& alternate_url,
95     const std::string& favicon_url,
96     bool safe_for_autoreplace,
97     const std::string& encodings,
98     Time date_created,
99     Time last_modified) {
100   TemplateURL* t_url = CreateKeywordWithDate(
101       model, short_name, keyword, url, suggest_url, alternate_url,favicon_url,
102       safe_for_autoreplace, false, encodings, date_created, last_modified);
103   model->Add(t_url);
104   EXPECT_NE(0, t_url->id());
105   return t_url;
106 }
107
108 // Checks that the two TemplateURLs are similar. It does not check the id, the
109 // date_created or the last_modified time.  Neither pointer should be NULL.
110 void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) {
111   ASSERT_TRUE(expected != NULL);
112   ASSERT_TRUE(actual != NULL);
113   EXPECT_EQ(expected->short_name(), actual->short_name());
114   EXPECT_EQ(expected->keyword(), actual->keyword());
115   EXPECT_EQ(expected->url(), actual->url());
116   EXPECT_EQ(expected->suggestions_url(), actual->suggestions_url());
117   EXPECT_EQ(expected->favicon_url(), actual->favicon_url());
118   EXPECT_EQ(expected->alternate_urls(), actual->alternate_urls());
119   EXPECT_EQ(expected->show_in_default_list(), actual->show_in_default_list());
120   EXPECT_EQ(expected->safe_for_autoreplace(), actual->safe_for_autoreplace());
121   EXPECT_EQ(expected->input_encodings(), actual->input_encodings());
122   EXPECT_EQ(expected->search_terms_replacement_key(),
123             actual->search_terms_replacement_key());
124 }
125
126 }  // namespace
127
128
129 // TemplateURLServiceTest -----------------------------------------------------
130
131 class TemplateURLServiceTest : public testing::Test {
132  public:
133   TemplateURLServiceTest();
134
135   // testing::Test:
136   void SetUp() override;
137   void TearDown() override;
138
139   TemplateURL* AddKeywordWithDate(const std::string& short_name,
140                                   const std::string& keyword,
141                                   const std::string& url,
142                                   const std::string& suggest_url,
143                                   const std::string& alternate_url,
144                                   const std::string& favicon_url,
145                                   bool safe_for_autoreplace,
146                                   const std::string& encodings,
147                                   Time date_created,
148                                   Time last_modified);
149
150   // Verifies the two TemplateURLs are equal.
151   void AssertEquals(const TemplateURL& expected, const TemplateURL& actual);
152
153   // Create an URL that appears to have been prepopulated, but won't be in the
154   // current data. The caller owns the returned TemplateURL*.
155   TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace,
156                                           int prepopulate_id);
157
158   // Helper methods to make calling TemplateURLServiceTestUtil methods less
159   // visually noisy in the test code.
160   void VerifyObserverCount(int expected_changed_count);
161   void VerifyObserverFired();
162   TemplateURLServiceTestUtil* test_util() { return test_util_.get(); }
163   TemplateURLService* model() { return test_util_->model(); }
164   const SearchTermsData& search_terms_data() {
165     return model()->search_terms_data();
166   }
167
168  private:
169   content::TestBrowserThreadBundle thread_bundle_;  // To set up BrowserThreads.
170   scoped_ptr<TemplateURLServiceTestUtil> test_util_;
171
172   DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest);
173 };
174
175 class TemplateURLServiceWithoutFallbackTest : public TemplateURLServiceTest {
176  public:
177   TemplateURLServiceWithoutFallbackTest() : TemplateURLServiceTest() {}
178
179   void SetUp() override {
180     DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(true);
181     TemplateURLServiceTest::SetUp();
182   }
183
184   void TearDown() override {
185     TemplateURLServiceTest::TearDown();
186     DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(false);
187   }
188 };
189
190 TemplateURLServiceTest::TemplateURLServiceTest() {
191 }
192
193 void TemplateURLServiceTest::SetUp() {
194   test_util_.reset(new TemplateURLServiceTestUtil);
195 }
196
197 void TemplateURLServiceTest::TearDown() {
198   test_util_.reset();
199 }
200
201 TemplateURL* TemplateURLServiceTest::AddKeywordWithDate(
202     const std::string& short_name,
203     const std::string& keyword,
204     const std::string& url,
205     const std::string& suggest_url,
206     const std::string& alternate_url,
207     const std::string& favicon_url,
208     bool safe_for_autoreplace,
209     const std::string& encodings,
210     Time date_created,
211     Time last_modified) {
212   return ::AddKeywordWithDate(model(), short_name, keyword, url, suggest_url,
213                               alternate_url, favicon_url, safe_for_autoreplace,
214                               encodings, date_created, last_modified);
215 }
216
217 void TemplateURLServiceTest::AssertEquals(const TemplateURL& expected,
218                                           const TemplateURL& actual) {
219   ASSERT_EQ(expected.short_name(), actual.short_name());
220   ASSERT_EQ(expected.keyword(), actual.keyword());
221   ASSERT_EQ(expected.url(), actual.url());
222   ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
223   ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
224   ASSERT_EQ(expected.alternate_urls(), actual.alternate_urls());
225   ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
226   ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
227   ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
228   ASSERT_EQ(expected.id(), actual.id());
229   ASSERT_EQ(expected.date_created(), actual.date_created());
230   ASSERT_EQ(expected.last_modified(), actual.last_modified());
231   ASSERT_EQ(expected.sync_guid(), actual.sync_guid());
232   ASSERT_EQ(expected.search_terms_replacement_key(),
233             actual.search_terms_replacement_key());
234 }
235
236 TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL(
237     bool safe_for_autoreplace,
238     int prepopulate_id) {
239   TemplateURLData data;
240   data.short_name = ASCIIToUTF16("unittest");
241   data.SetKeyword(ASCIIToUTF16("unittest"));
242   data.SetURL("http://www.unittest.com/{searchTerms}");
243   data.favicon_url = GURL("http://favicon.url");
244   data.show_in_default_list = true;
245   data.safe_for_autoreplace = safe_for_autoreplace;
246   data.input_encodings.push_back("UTF-8");
247   data.date_created = Time::FromTimeT(100);
248   data.last_modified = Time::FromTimeT(100);
249   data.prepopulate_id = prepopulate_id;
250   return new TemplateURL(data);
251 }
252
253 void TemplateURLServiceTest::VerifyObserverCount(int expected_changed_count) {
254   EXPECT_EQ(expected_changed_count, test_util_->GetObserverCount());
255   test_util_->ResetObserverCount();
256 }
257
258 void TemplateURLServiceTest::VerifyObserverFired() {
259   EXPECT_LE(1, test_util_->GetObserverCount());
260   test_util_->ResetObserverCount();
261 }
262
263
264 // Actual tests ---------------------------------------------------------------
265
266 TEST_F(TemplateURLServiceTest, Load) {
267   test_util()->VerifyLoad();
268 }
269
270 TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
271   // Add a new TemplateURL.
272   test_util()->VerifyLoad();
273   const size_t initial_count = model()->GetTemplateURLs().size();
274
275   TemplateURLData data;
276   data.short_name = ASCIIToUTF16("google");
277   data.SetKeyword(ASCIIToUTF16("keyword"));
278   data.SetURL("http://www.google.com/foo/bar");
279   data.favicon_url = GURL("http://favicon.url");
280   data.safe_for_autoreplace = true;
281   data.date_created = Time::FromTimeT(100);
282   data.last_modified = Time::FromTimeT(100);
283   data.sync_guid = "00000000-0000-0000-0000-000000000001";
284   TemplateURL* t_url = new TemplateURL(data);
285   model()->Add(t_url);
286   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
287                                          NULL));
288   VerifyObserverCount(1);
289   base::RunLoop().RunUntilIdle();
290   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
291   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(t_url->keyword()));
292   // We need to make a second copy as the model takes ownership of |t_url| and
293   // will delete it.  We have to do this after calling Add() since that gives
294   // |t_url| its ID.
295   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
296
297   // Reload the model to verify it was actually saved to the database.
298   test_util()->ResetModel(true);
299   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
300   TemplateURL* loaded_url =
301       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
302   ASSERT_TRUE(loaded_url != NULL);
303   AssertEquals(*cloned_url, *loaded_url);
304   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
305                                          NULL));
306
307   // We expect the last_modified time to be updated to the present time on an
308   // explicit reset. We have to set up the expectation here because ResetModel
309   // resets the TimeProvider in the TemplateURLService.
310   StrictMock<base::MockTimeProvider> mock_time;
311   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
312   EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
313
314   // Mutate an element and verify it succeeded.
315   model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"),
316                             "c");
317   ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name());
318   ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword());
319   ASSERT_EQ("c", loaded_url->url());
320   ASSERT_FALSE(loaded_url->safe_for_autoreplace());
321   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
322                                          NULL));
323   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
324   cloned_url.reset(new TemplateURL(loaded_url->data()));
325   base::RunLoop().RunUntilIdle();
326   test_util()->ResetModel(true);
327   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
328   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
329   ASSERT_TRUE(loaded_url != NULL);
330   AssertEquals(*cloned_url, *loaded_url);
331   // We changed a TemplateURL in the service, so ensure that the time was
332   // updated.
333   ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified());
334
335   // Remove an element and verify it succeeded.
336   model()->Remove(loaded_url);
337   VerifyObserverCount(1);
338   test_util()->ResetModel(true);
339   ASSERT_EQ(initial_count, model()->GetTemplateURLs().size());
340   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL);
341 }
342
343 TEST_F(TemplateURLServiceTest, AddSameKeyword) {
344   test_util()->VerifyLoad();
345
346   AddKeywordWithDate(
347       "first", "keyword", "http://test1", std::string(), std::string(),
348       std::string(), true, "UTF-8", Time(), Time());
349   VerifyObserverCount(1);
350
351   // Test what happens when we try to add a TemplateURL with the same keyword as
352   // one in the model.
353   TemplateURLData data;
354   data.short_name = ASCIIToUTF16("second");
355   data.SetKeyword(ASCIIToUTF16("keyword"));
356   data.SetURL("http://test2");
357   data.safe_for_autoreplace = false;
358   TemplateURL* t_url = new TemplateURL(data);
359   model()->Add(t_url);
360
361   // Because the old TemplateURL was replaceable and the new one wasn't, the new
362   // one should have replaced the old.
363   VerifyObserverCount(1);
364   EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
365   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
366   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
367   EXPECT_FALSE(t_url->safe_for_autoreplace());
368
369   // Now try adding a replaceable TemplateURL.  This should just delete the
370   // passed-in URL.
371   data.short_name = ASCIIToUTF16("third");
372   data.SetURL("http://test3");
373   data.safe_for_autoreplace = true;
374   model()->Add(new TemplateURL(data));
375   VerifyObserverCount(0);
376   EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
377   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
378   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
379   EXPECT_FALSE(t_url->safe_for_autoreplace());
380
381   // Now try adding a non-replaceable TemplateURL again.  This should uniquify
382   // the existing entry's keyword.
383   data.short_name = ASCIIToUTF16("fourth");
384   data.SetURL("http://test4");
385   data.safe_for_autoreplace = false;
386   TemplateURL* t_url2 = new TemplateURL(data);
387   model()->Add(t_url2);
388   VerifyObserverCount(1);
389   EXPECT_EQ(t_url2, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
390   EXPECT_EQ(ASCIIToUTF16("fourth"), t_url2->short_name());
391   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url2->keyword());
392   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
393   EXPECT_EQ(ASCIIToUTF16("test2"), t_url->keyword());
394 }
395
396 TEST_F(TemplateURLServiceTest, AddExtensionKeyword) {
397   test_util()->VerifyLoad();
398
399   AddKeywordWithDate(
400       "replaceable", "keyword1", "http://test1", std::string(), std::string(),
401       std::string(), true, "UTF-8", Time(), Time());
402   TemplateURL* original2 = AddKeywordWithDate(
403       "nonreplaceable", "keyword2", "http://test2", std::string(),
404       std::string(), std::string(), false, "UTF-8", Time(), Time());
405   model()->RegisterOmniboxKeyword("test3", "extension", "keyword3",
406                                   "http://test3");
407   TemplateURL* original3 =
408       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3"));
409   ASSERT_TRUE(original3);
410
411   // Extension keywords should override replaceable keywords.
412   model()->RegisterOmniboxKeyword("id1", "test", "keyword1", "http://test4");
413   TemplateURL* extension1 = model()->FindTemplateURLForExtension(
414       "id1", TemplateURL::OMNIBOX_API_EXTENSION);
415   EXPECT_TRUE(extension1);
416   EXPECT_EQ(extension1,
417             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
418
419   // They should not override non-replaceable keywords.
420   model()->RegisterOmniboxKeyword("id2", "test", "keyword2", "http://test5");
421   TemplateURL* extension2 = model()->FindTemplateURLForExtension(
422       "id2", TemplateURL::OMNIBOX_API_EXTENSION);
423   ASSERT_TRUE(extension2);
424   EXPECT_EQ(original2,
425             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2")));
426
427   // They should override extension keywords added earlier.
428   model()->RegisterOmniboxKeyword("id3", "test", "keyword3", "http://test6");
429   TemplateURL* extension3 = model()->FindTemplateURLForExtension(
430       "id3", TemplateURL::OMNIBOX_API_EXTENSION);
431   ASSERT_TRUE(extension3);
432   EXPECT_EQ(extension3,
433             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3")));
434 }
435
436 TEST_F(TemplateURLServiceTest, AddSameKeywordWithExtensionPresent) {
437   test_util()->VerifyLoad();
438
439   // Similar to the AddSameKeyword test, but with an extension keyword masking a
440   // replaceable TemplateURL.  We should still do correct conflict resolution
441   // between the non-template URLs.
442   model()->RegisterOmniboxKeyword("test2", "extension", "keyword",
443                                   "http://test2");
444   TemplateURL* extension =
445       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
446   ASSERT_TRUE(extension);
447   // Adding a keyword that matches the extension.
448   AddKeywordWithDate(
449       "replaceable", "keyword", "http://test1", std::string(),  std::string(),
450       std::string(), true, "UTF-8", Time(), Time());
451
452   // Adding another replaceable keyword should remove the existing one, but
453   // leave the extension as is.
454   TemplateURLData data;
455   data.short_name = ASCIIToUTF16("name1");
456   data.SetKeyword(ASCIIToUTF16("keyword"));
457   data.SetURL("http://test3");
458   data.safe_for_autoreplace = true;
459   TemplateURL* t_url = new TemplateURL(data);
460   model()->Add(t_url);
461   EXPECT_EQ(extension,
462             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
463   EXPECT_EQ(t_url, model()->GetTemplateURLForHost("test3"));
464
465   // Adding a nonreplaceable keyword should remove the existing replaceable
466   // keyword and replace the extension as the associated URL for this keyword,
467   // but not evict the extension from the service entirely.
468   data.short_name = ASCIIToUTF16("name2");
469   data.SetURL("http://test4");
470   data.safe_for_autoreplace = false;
471   TemplateURL* t_url2 = new TemplateURL(data);
472   model()->Add(t_url2);
473   EXPECT_EQ(t_url2,
474             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
475 }
476
477 TEST_F(TemplateURLServiceTest, NotPersistOmniboxExtensionKeyword) {
478   test_util()->VerifyLoad();
479
480   // Register an omnibox keyword.
481   model()->RegisterOmniboxKeyword("test", "extension", "keyword",
482                                   "chrome-extension://test");
483   ASSERT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
484
485   // Reload the data.
486   test_util()->ResetModel(true);
487
488   // Ensure the omnibox keyword is not persisted.
489   ASSERT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
490 }
491
492 TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
493   Time now = Time::Now();
494   TimeDelta one_day = TimeDelta::FromDays(1);
495   Time month_ago = now - TimeDelta::FromDays(30);
496
497   // Nothing has been added.
498   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
499
500   // Create one with a 0 time.
501   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
502                      std::string(), "http://icon1", true, "UTF-8;UTF-16",
503                      Time(), Time());
504   // Create one for now and +/- 1 day.
505   AddKeywordWithDate("name2", "key2", "http://foo2", "http://suggest2",
506                      std::string(),  "http://icon2", true, "UTF-8;UTF-16",
507                      now - one_day, Time());
508   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
509                      std::string(), std::string(), true, std::string(), now,
510                      Time());
511   AddKeywordWithDate("name4", "key4", "http://foo4", std::string(),
512                      std::string(), std::string(), true, std::string(),
513                      now + one_day, Time());
514   // Try the other three states.
515   AddKeywordWithDate("name5", "key5", "http://foo5", "http://suggest5",
516                      std::string(), "http://icon5", false, "UTF-8;UTF-16", now,
517                      Time());
518   AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
519                      std::string(), "http://icon6", false, "UTF-8;UTF-16",
520                      month_ago, Time());
521
522   // We just added a few items, validate them.
523   EXPECT_EQ(6U, model()->GetTemplateURLs().size());
524
525   // Try removing from current timestamp. This should delete the one in the
526   // future and one very recent one.
527   model()->RemoveAutoGeneratedSince(now);
528   EXPECT_EQ(4U, model()->GetTemplateURLs().size());
529
530   // Try removing from two months ago. This should only delete items that are
531   // auto-generated.
532   model()->RemoveAutoGeneratedBetween(now - TimeDelta::FromDays(60), now);
533   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
534
535   // Make sure the right values remain.
536   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
537   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
538   EXPECT_EQ(0U,
539             model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
540
541   EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
542   EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
543   EXPECT_EQ(now.ToInternalValue(),
544             model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
545
546   EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
547   EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
548   EXPECT_EQ(month_ago.ToInternalValue(),
549             model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
550
551   // Try removing from Time=0. This should delete one more.
552   model()->RemoveAutoGeneratedSince(Time());
553   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
554 }
555
556 TEST_F(TemplateURLServiceTest, ClearBrowsingData_KeywordsForOrigin) {
557   Time now = Time::Now();
558   TimeDelta one_day = TimeDelta::FromDays(1);
559   Time month_ago = now - TimeDelta::FromDays(30);
560
561   // Nothing has been added.
562   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
563
564   // Create one for now and +/- 1 day.
565   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
566                      std::string(), "http://icon2", true, "UTF-8;UTF-16",
567                      now - one_day, Time());
568   AddKeywordWithDate("name2", "key2", "http://foo2", std::string(),
569                      std::string(), std::string(), true, std::string(), now,
570                      Time());
571   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
572                      std::string(), std::string(), true, std::string(),
573                      now + one_day, Time());
574
575   // We just added a few items, validate them.
576   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
577
578   // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
579   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago,
580       now + one_day);
581   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
582   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
583   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
584   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
585   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
586
587   // Try removing foo1, but outside the range in which it was modified. It
588   // should remain untouched.
589   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo1"), now,
590       now + one_day);
591   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
592   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
593   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
594   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
595   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
596
597
598   // Try removing foo3. This should delete foo3, but leave foo1 untouched.
599   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo3"), month_ago,
600       now + one_day + one_day);
601   EXPECT_EQ(1U, model()->GetTemplateURLs().size());
602   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
603   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
604 }
605
606 TEST_F(TemplateURLServiceTest, Reset) {
607   // Add a new TemplateURL.
608   test_util()->VerifyLoad();
609   const size_t initial_count = model()->GetTemplateURLs().size();
610   TemplateURLData data;
611   data.short_name = ASCIIToUTF16("google");
612   data.SetKeyword(ASCIIToUTF16("keyword"));
613   data.SetURL("http://www.google.com/foo/bar");
614   data.favicon_url = GURL("http://favicon.url");
615   data.date_created = Time::FromTimeT(100);
616   data.last_modified = Time::FromTimeT(100);
617   TemplateURL* t_url = new TemplateURL(data);
618   model()->Add(t_url);
619
620   VerifyObserverCount(1);
621   base::RunLoop().RunUntilIdle();
622
623   StrictMock<base::MockTimeProvider> mock_time;
624   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
625   EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
626
627   // Reset the short name, keyword, url and make sure it takes.
628   const base::string16 new_short_name(ASCIIToUTF16("a"));
629   const base::string16 new_keyword(ASCIIToUTF16("b"));
630   const std::string new_url("c");
631   model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
632   ASSERT_EQ(new_short_name, t_url->short_name());
633   ASSERT_EQ(new_keyword, t_url->keyword());
634   ASSERT_EQ(new_url, t_url->url());
635
636   // Make sure the mappings in the model were updated.
637   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword));
638   ASSERT_TRUE(
639       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
640
641   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
642
643   // Reload the model from the database and make sure the change took.
644   test_util()->ResetModel(true);
645   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
646   const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
647   ASSERT_TRUE(read_url);
648   AssertEquals(*cloned_url, *read_url);
649   ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified());
650 }
651
652 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
653   // Add a new TemplateURL.
654   test_util()->VerifyLoad();
655   const size_t initial_count = model()->GetTemplateURLs().size();
656   TemplateURL* t_url = AddKeywordWithDate(
657       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
658       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
659   test_util()->ResetObserverCount();
660
661   model()->SetUserSelectedDefaultSearchProvider(t_url);
662   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
663   ASSERT_TRUE(t_url->safe_for_autoreplace());
664   ASSERT_TRUE(t_url->show_in_default_list());
665
666   // Setting the default search provider should have caused notification.
667   VerifyObserverCount(1);
668   base::RunLoop().RunUntilIdle();
669
670   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
671
672   // Make sure when we reload we get a default search provider.
673   test_util()->ResetModel(true);
674   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
675   ASSERT_TRUE(model()->GetDefaultSearchProvider());
676   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
677 }
678
679 TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
680   test_util()->ChangeModelToLoadState();
681   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
682   TemplateURL* t_url = AddKeywordWithDate(
683       "name1", "foo", "http://foo1", "http://sugg1", std::string(),
684       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
685
686   // Can still replace, newly added template url is marked safe to replace.
687   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
688                                          GURL("http://foo2"), NULL));
689
690   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
691   // no longer be replaceable.
692   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
693                             t_url->url());
694
695   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
696                                           GURL("http://foo2"), NULL));
697 }
698
699 TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
700   test_util()->ChangeModelToLoadState();
701   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
702                                          GURL("http://foo.com"), NULL));
703   TemplateURL* t_url = AddKeywordWithDate(
704       "name1", "foo", "http://foo.com", "http://sugg1", std::string(),
705       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
706
707   // Can still replace, newly added template url is marked safe to replace.
708   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
709                                          GURL("http://foo.com"), NULL));
710
711   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
712   // no longer be replaceable.
713   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
714                             t_url->url());
715
716   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
717                                           GURL("http://foo.com"), NULL));
718 }
719
720 TEST_F(TemplateURLServiceTest, HasDefaultSearchProvider) {
721   // We should have a default search provider even if we haven't loaded.
722   ASSERT_TRUE(model()->GetDefaultSearchProvider());
723
724   // Now force the model to load and make sure we still have a default.
725   test_util()->VerifyLoad();
726
727   ASSERT_TRUE(model()->GetDefaultSearchProvider());
728 }
729
730 TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
731   test_util()->VerifyLoad();
732
733   TemplateURLData data;
734   data.short_name = ASCIIToUTF16("a");
735   data.safe_for_autoreplace = true;
736   data.SetURL("http://url/{searchTerms}");
737   data.suggestions_url = "http://url2";
738   data.instant_url = "http://instant";
739   data.date_created = Time::FromTimeT(100);
740   data.last_modified = Time::FromTimeT(100);
741   TemplateURL* t_url = new TemplateURL(data);
742   model()->Add(t_url);
743   const TemplateURLID id = t_url->id();
744
745   model()->SetUserSelectedDefaultSearchProvider(t_url);
746   base::RunLoop().RunUntilIdle();
747   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
748
749   // Reset the model and don't load it. The template url we set as the default
750   // should be pulled from prefs now.
751   test_util()->ResetModel(false);
752
753   // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
754   // value are persisted to prefs.
755   const TemplateURL* default_turl = model()->GetDefaultSearchProvider();
756   ASSERT_TRUE(default_turl);
757   EXPECT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
758   EXPECT_EQ("http://url/{searchTerms}", default_turl->url());
759   EXPECT_EQ("http://url2", default_turl->suggestions_url());
760   EXPECT_EQ("http://instant", default_turl->instant_url());
761   EXPECT_EQ(id, default_turl->id());
762
763   // Now do a load and make sure the default search provider really takes.
764   test_util()->VerifyLoad();
765
766   ASSERT_TRUE(model()->GetDefaultSearchProvider());
767   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
768 }
769
770 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
771   test_util()->VerifyLoad();
772
773   // Edit Google search engine.
774   TemplateURL* google = model()->GetTemplateURLForKeyword(
775       ASCIIToUTF16("google.com"));
776   ASSERT_TRUE(google);
777   model()->ResetTemplateURL(google, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"),
778                             "http://www.foo.com/s?q={searchTerms}");
779   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
780   EXPECT_EQ(ASCIIToUTF16("xxx"), google->keyword());
781
782   // Add third-party default search engine.
783   TemplateURL* user_dse = AddKeywordWithDate(
784       "malware", "google.com", "http://www.goo.com/s?q={searchTerms}",
785       std::string(), std::string(), std::string(),
786       true, "UTF-8", Time(), Time());
787   model()->SetUserSelectedDefaultSearchProvider(user_dse);
788   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
789
790   // Remove bing.
791   TemplateURL* bing = model()->GetTemplateURLForKeyword(
792       ASCIIToUTF16("bing.com"));
793   ASSERT_TRUE(bing);
794   model()->Remove(bing);
795   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
796
797   // Register an extension with bing keyword.
798   model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com",
799                                   "http://abcdefg");
800   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
801
802   model()->RepairPrepopulatedSearchEngines();
803
804   // Google is default.
805   ASSERT_EQ(google, model()->GetDefaultSearchProvider());
806   // The keyword wasn't reverted.
807   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
808   EXPECT_EQ("www.google.com",
809             google->GenerateSearchURL(model()->search_terms_data()).host());
810
811   // Bing was repaired.
812   bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
813   ASSERT_TRUE(bing);
814   EXPECT_EQ(TemplateURL::NORMAL, bing->GetType());
815
816   // User search engine is preserved.
817   EXPECT_EQ(user_dse, model()->GetTemplateURLForHost("www.goo.com"));
818   EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse->keyword());
819 }
820
821 TEST_F(TemplateURLServiceTest, RepairSearchEnginesWithManagedDefault) {
822   // Set a managed preference that establishes a default search provider.
823   const char kName[] = "test1";
824   const char kKeyword[] = "test.com";
825   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
826   const char kIconURL[] = "http://test.com/icon.jpg";
827   const char kEncodings[] = "UTF-16;UTF-32";
828   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
829   const char kSearchTermsReplacementKey[] = "espv";
830   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
831                                                   kSearchURL, std::string(),
832                                                   kIconURL, kEncodings,
833                                                   kAlternateURL,
834                                                   kSearchTermsReplacementKey);
835   test_util()->VerifyLoad();
836   // Verify that the default manager we are getting is the managed one.
837   TemplateURLData data;
838   data.short_name = ASCIIToUTF16(kName);
839   data.SetKeyword(ASCIIToUTF16(kKeyword));
840   data.SetURL(kSearchURL);
841   data.favicon_url = GURL(kIconURL);
842   data.show_in_default_list = true;
843   base::SplitString(kEncodings, ';', &data.input_encodings);
844   data.alternate_urls.push_back(kAlternateURL);
845   data.search_terms_replacement_key = kSearchTermsReplacementKey;
846   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(data));
847   EXPECT_TRUE(model()->is_default_search_managed());
848   const TemplateURL* actual_managed_default =
849       model()->GetDefaultSearchProvider();
850   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
851
852   // The following call has no effect on the managed search engine.
853   model()->RepairPrepopulatedSearchEngines();
854
855   EXPECT_TRUE(model()->is_default_search_managed());
856   actual_managed_default = model()->GetDefaultSearchProvider();
857   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
858 }
859
860 TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
861   struct TestData {
862     const std::string url;
863     const base::string16 term;
864   } data[] = {
865     { "http://foo/", base::string16() },
866     { "http://foo/foo?q=xx", base::string16() },
867     { "http://x/bar?q=xx", base::string16() },
868     { "http://x/foo?y=xx", base::string16() },
869     { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
870     { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
871     { "http://x/foo?q=b&q=xx", base::string16() },
872     { "http://x/foo#query=xx", ASCIIToUTF16("xx") },
873     { "http://x/foo?q=b#query=xx", ASCIIToUTF16("xx") },
874     { "http://x/foo?q=b#q=xx", ASCIIToUTF16("b") },
875     { "http://x/foo?query=b#q=xx", base::string16() },
876   };
877
878   test_util()->ChangeModelToLoadState();
879   AddKeywordWithDate("name", "x", "http://x/foo?q={searchTerms}",
880                      "http://sugg1", "http://x/foo#query={searchTerms}",
881                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
882
883   for (size_t i = 0; i < arraysize(data); ++i) {
884     TemplateURLService::URLVisitedDetails details = {
885       GURL(data[i].url), false
886     };
887     model()->UpdateKeywordSearchTermsForURL(details);
888     EXPECT_EQ(data[i].term, test_util()->GetAndClearSearchTerm());
889   }
890 }
891
892 TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
893   struct TestData {
894     const std::string url;
895   } data[] = {
896     { "http://foo/" },
897     { "http://x/bar?q=xx" },
898     { "http://x/foo?y=xx" },
899   };
900
901   test_util()->ChangeModelToLoadState();
902   AddKeywordWithDate("name", "x", "http://x/foo", "http://sugg1", std::string(),
903                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
904
905   for (size_t i = 0; i < arraysize(data); ++i) {
906     TemplateURLService::URLVisitedDetails details = {
907       GURL(data[i].url), false
908     };
909     model()->UpdateKeywordSearchTermsForURL(details);
910     ASSERT_EQ(base::string16(), test_util()->GetAndClearSearchTerm());
911   }
912 }
913
914 TEST_F(TemplateURLServiceWithoutFallbackTest, ChangeGoogleBaseValue) {
915   // NOTE: Do not load the prepopulate data, which also has a {google:baseURL}
916   // keyword in it and would confuse this test.
917   test_util()->ChangeModelToLoadState();
918
919   test_util()->SetGoogleBaseURL(GURL("http://google.com/"));
920   const TemplateURL* t_url = AddKeywordWithDate(
921       "name", "google.com", "{google:baseURL}?q={searchTerms}", "http://sugg1",
922       std::string(), "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
923   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
924   EXPECT_EQ("google.com", t_url->url_ref().GetHost(search_terms_data()));
925   EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
926
927   // Change the Google base url.
928   test_util()->ResetObserverCount();
929   test_util()->SetGoogleBaseURL(GURL("http://google.co.uk/"));
930   VerifyObserverCount(1);
931
932   // Make sure the host->TemplateURL map was updated appropriately.
933   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.co.uk"));
934   EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
935   EXPECT_EQ("google.co.uk", t_url->url_ref().GetHost(search_terms_data()));
936   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
937   EXPECT_EQ("http://google.co.uk/?q=x", t_url->url_ref().ReplaceSearchTerms(
938       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x")), search_terms_data()));
939
940   // Now add a manual entry and then change the Google base URL such that the
941   // autogenerated Google search keyword would conflict.
942   TemplateURL* manual = AddKeywordWithDate(
943     "manual", "google.de", "http://google.de/search?q={searchTerms}",
944     std::string(), std::string(), std::string(), false, "UTF-8", Time(),
945     Time());
946   test_util()->SetGoogleBaseURL(GURL("http://google.de"));
947
948   // Verify that the manual entry is untouched, and the autogenerated keyword
949   // has not changed.
950   ASSERT_EQ(manual,
951             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
952   EXPECT_EQ("google.de", manual->url_ref().GetHost(search_terms_data()));
953   ASSERT_EQ(t_url,
954             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.co.uk")));
955   EXPECT_EQ("google.de", t_url->url_ref().GetHost(search_terms_data()));
956   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
957
958   // Change the base URL again and verify that the autogenerated keyword follows
959   // even though it didn't match the base URL, while the manual entry is still
960   // untouched.
961   test_util()->SetGoogleBaseURL(GURL("http://google.fr/"));
962   ASSERT_EQ(manual, model()->GetTemplateURLForHost("google.de"));
963   EXPECT_EQ("google.de", manual->url_ref().GetHost(search_terms_data()));
964   EXPECT_EQ(ASCIIToUTF16("google.de"), manual->keyword());
965   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.fr"));
966   EXPECT_TRUE(model()->GetTemplateURLForHost("google.co.uk") == NULL);
967   EXPECT_EQ("google.fr", t_url->url_ref().GetHost(search_terms_data()));
968   EXPECT_EQ(ASCIIToUTF16("google.fr"), t_url->keyword());
969 }
970
971 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
972 // KEYWORD visits.
973 TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
974   test_util()->profile()->CreateBookmarkModel(false);
975   ASSERT_TRUE(test_util()->profile()->CreateHistoryService(true, false));
976   test_util()->ResetModel(true);
977
978   // Create a keyword.
979   TemplateURL* t_url = AddKeywordWithDate(
980       "keyword", "keyword", "http://foo.com/foo?query={searchTerms}",
981       "http://sugg1", std::string(), "http://icon1", true, "UTF-8;UTF-16",
982       base::Time::Now(), base::Time::Now());
983
984   // Add a visit that matches the url of the keyword.
985   HistoryService* history =
986       HistoryServiceFactory::GetForProfile(test_util()->profile(),
987                                            Profile::EXPLICIT_ACCESS);
988   history->AddPage(
989       GURL(t_url->url_ref().ReplaceSearchTerms(
990           TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah")),
991           search_terms_data())),
992       base::Time::Now(), NULL, 0, GURL(), history::RedirectList(),
993       ui::PAGE_TRANSITION_KEYWORD, history::SOURCE_BROWSED, false);
994
995   // Wait for history to finish processing the request.
996   test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
997
998   // Query history for the generated url.
999   base::CancelableTaskTracker tracker;
1000   QueryHistoryCallbackImpl callback;
1001   history->QueryURL(GURL("http://keyword"),
1002                     true,
1003                     base::Bind(&QueryHistoryCallbackImpl::Callback,
1004                                base::Unretained(&callback)),
1005                     &tracker);
1006
1007   // Wait for the request to be processed.
1008   test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
1009
1010   // And make sure the url and visit were added.
1011   EXPECT_TRUE(callback.success);
1012   EXPECT_NE(0, callback.row.id());
1013   ASSERT_EQ(1U, callback.visits.size());
1014   EXPECT_EQ(ui::PAGE_TRANSITION_KEYWORD_GENERATED,
1015       ui::PageTransitionStripQualifier(callback.visits[0].transition));
1016 }
1017
1018 // Make sure that the load routine deletes prepopulated engines that no longer
1019 // exist in the prepopulate data.
1020 TEST_F(TemplateURLServiceTest, LoadDeletesUnusedProvider) {
1021   // Create a preloaded template url. Add it to a loaded model and wait for the
1022   // saves to finish.
1023   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1024   test_util()->ChangeModelToLoadState();
1025   model()->Add(t_url);
1026   ASSERT_TRUE(
1027       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1028   base::RunLoop().RunUntilIdle();
1029
1030   // Ensure that merging clears this engine.
1031   test_util()->ResetModel(true);
1032   ASSERT_TRUE(
1033       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1034
1035   // Wait for any saves to finish.
1036   base::RunLoop().RunUntilIdle();
1037
1038   // Reload the model to verify that the database was updated as a result of the
1039   // merge.
1040   test_util()->ResetModel(true);
1041   ASSERT_TRUE(
1042       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1043 }
1044
1045 // Make sure that load routine doesn't delete prepopulated engines that no
1046 // longer exist in the prepopulate data if it has been modified by the user.
1047 TEST_F(TemplateURLServiceTest, LoadRetainsModifiedProvider) {
1048   // Create a preloaded template url and add it to a loaded model.
1049   TemplateURL* t_url = CreatePreloadedTemplateURL(false, 999999);
1050   test_util()->ChangeModelToLoadState();
1051   model()->Add(t_url);
1052
1053   // Do the copy after t_url is added so that the id is set.
1054   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
1055   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1056
1057   // Wait for any saves to finish.
1058   base::RunLoop().RunUntilIdle();
1059
1060   // Ensure that merging won't clear it if the user has edited it.
1061   test_util()->ResetModel(true);
1062   const TemplateURL* url_for_unittest =
1063       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1064   ASSERT_TRUE(url_for_unittest != NULL);
1065   AssertEquals(*cloned_url, *url_for_unittest);
1066
1067   // Wait for any saves to finish.
1068   base::RunLoop().RunUntilIdle();
1069
1070   // Reload the model to verify that save/reload retains the item.
1071   test_util()->ResetModel(true);
1072   ASSERT_TRUE(
1073       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1074 }
1075
1076 // Make sure that load routine doesn't delete
1077 // prepopulated engines that no longer exist in the prepopulate data if
1078 // it has been modified by the user.
1079 TEST_F(TemplateURLServiceTest, LoadSavesPrepopulatedDefaultSearchProvider) {
1080   test_util()->VerifyLoad();
1081   // Verify that the default search provider is set to something.
1082   TemplateURL* default_search = model()->GetDefaultSearchProvider();
1083   ASSERT_TRUE(default_search != NULL);
1084   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(default_search->data()));
1085
1086   // Wait for any saves to finish.
1087   base::RunLoop().RunUntilIdle();
1088
1089   // Reload the model and check that the default search provider
1090   // was properly saved.
1091   test_util()->ResetModel(true);
1092   default_search = model()->GetDefaultSearchProvider();
1093   ASSERT_TRUE(default_search != NULL);
1094   AssertEquals(*cloned_url, *default_search);
1095 }
1096
1097 // Make sure that the load routine doesn't delete
1098 // prepopulated engines that no longer exist in the prepopulate data if
1099 // it is the default search provider.
1100 TEST_F(TemplateURLServiceTest, LoadRetainsDefaultProvider) {
1101   // Set the default search provider to a preloaded template url which
1102   // is not in the current set of preloaded template urls and save
1103   // the result.
1104   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1105   test_util()->ChangeModelToLoadState();
1106   model()->Add(t_url);
1107   model()->SetUserSelectedDefaultSearchProvider(t_url);
1108   // Do the copy after t_url is added and set as default so that its
1109   // internal state is correct.
1110   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
1111
1112   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1113   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
1114   base::RunLoop().RunUntilIdle();
1115
1116   // Ensure that merging won't clear the prepopulated template url
1117   // which is no longer present if it's the default engine.
1118   test_util()->ResetModel(true);
1119   {
1120     const TemplateURL* keyword_url =
1121         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1122     ASSERT_TRUE(keyword_url != NULL);
1123     AssertEquals(*cloned_url, *keyword_url);
1124     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1125   }
1126
1127   // Wait for any saves to finish.
1128   base::RunLoop().RunUntilIdle();
1129
1130   // Reload the model to verify that the update was saved.
1131   test_util()->ResetModel(true);
1132   {
1133     const TemplateURL* keyword_url =
1134         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1135     ASSERT_TRUE(keyword_url != NULL);
1136     AssertEquals(*cloned_url, *keyword_url);
1137     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1138   }
1139 }
1140
1141 // Make sure that the load routine sets a default search provider if it was
1142 // missing and not managed.
1143 TEST_F(TemplateURLServiceTest, LoadEnsuresDefaultSearchProviderExists) {
1144   // Force the model to load and make sure we have a default search provider.
1145   test_util()->VerifyLoad();
1146   EXPECT_TRUE(model()->GetDefaultSearchProvider());
1147
1148   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1149       search_terms_data()));
1150
1151   // Make default search provider unusable (no search terms).
1152   model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
1153                             ASCIIToUTF16("test"), ASCIIToUTF16("test"),
1154                             "http://example.com/");
1155   base::RunLoop().RunUntilIdle();
1156
1157   // Reset the model and load it. There should be a usable default search
1158   // provider.
1159   test_util()->ResetModel(true);
1160
1161   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1162   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1163       search_terms_data()));
1164 }
1165
1166 // Simulates failing to load the webdb and makes sure the default search
1167 // provider is valid.
1168 TEST_F(TemplateURLServiceTest, FailedInit) {
1169   test_util()->VerifyLoad();
1170
1171   test_util()->ClearModel();
1172   test_util()->web_data_service()->ShutdownDatabase();
1173
1174   test_util()->ResetModel(false);
1175   model()->Load();
1176   base::RunLoop().RunUntilIdle();
1177
1178   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1179 }
1180
1181 // Verifies that if the default search URL preference is managed, we report
1182 // the default search as managed.  Also check that we are getting the right
1183 // values.
1184 TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
1185   test_util()->VerifyLoad();
1186   const size_t initial_count = model()->GetTemplateURLs().size();
1187   test_util()->ResetObserverCount();
1188
1189   // Set a regular default search provider.
1190   TemplateURL* regular_default = AddKeywordWithDate(
1191       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
1192       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
1193   VerifyObserverCount(1);
1194   model()->SetUserSelectedDefaultSearchProvider(regular_default);
1195   // Adding the URL and setting the default search provider should have caused
1196   // notifications.
1197   VerifyObserverCount(1);
1198   EXPECT_FALSE(model()->is_default_search_managed());
1199   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1200
1201   // Set a managed preference that establishes a default search provider.
1202   const char kName[] = "test1";
1203   const char kKeyword[] = "test.com";
1204   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1205   const char kIconURL[] = "http://test.com/icon.jpg";
1206   const char kEncodings[] = "UTF-16;UTF-32";
1207   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1208   const char kSearchTermsReplacementKey[] = "espv";
1209   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1210       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1211       kSearchTermsReplacementKey);
1212   VerifyObserverFired();
1213   EXPECT_TRUE(model()->is_default_search_managed());
1214   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1215
1216   // Verify that the default manager we are getting is the managed one.
1217   TemplateURLData data;
1218   data.short_name = ASCIIToUTF16(kName);
1219   data.SetKeyword(ASCIIToUTF16(kKeyword));
1220   data.SetURL(kSearchURL);
1221   data.favicon_url = GURL(kIconURL);
1222   data.show_in_default_list = true;
1223   base::SplitString(kEncodings, ';', &data.input_encodings);
1224   data.alternate_urls.push_back(kAlternateURL);
1225   data.search_terms_replacement_key = kSearchTermsReplacementKey;
1226   scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL(data));
1227   const TemplateURL* actual_managed_default =
1228       model()->GetDefaultSearchProvider();
1229   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1230   EXPECT_TRUE(actual_managed_default->show_in_default_list());
1231
1232   // Update the managed preference and check that the model has changed.
1233   const char kNewName[] = "test2";
1234   const char kNewKeyword[] = "other.com";
1235   const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}";
1236   const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}";
1237   test_util()->SetManagedDefaultSearchPreferences(true, kNewName, kNewKeyword,
1238       kNewSearchURL, kNewSuggestURL, std::string(), std::string(),
1239       std::string(), std::string());
1240   VerifyObserverFired();
1241   EXPECT_TRUE(model()->is_default_search_managed());
1242   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1243
1244   // Verify that the default manager we are now getting is the correct one.
1245   TemplateURLData data2;
1246   data2.short_name = ASCIIToUTF16(kNewName);
1247   data2.SetKeyword(ASCIIToUTF16(kNewKeyword));
1248   data2.SetURL(kNewSearchURL);
1249   data2.suggestions_url = kNewSuggestURL;
1250   data2.show_in_default_list = true;
1251   scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL(data2));
1252   actual_managed_default = model()->GetDefaultSearchProvider();
1253   ExpectSimilar(expected_managed_default2.get(), actual_managed_default);
1254   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1255
1256   // Remove all the managed prefs and check that we are no longer managed.
1257   test_util()->RemoveManagedDefaultSearchPreferences();
1258   VerifyObserverFired();
1259   EXPECT_FALSE(model()->is_default_search_managed());
1260   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1261
1262   // The default should now be the user preference.
1263   const TemplateURL* actual_final_managed_default =
1264       model()->GetDefaultSearchProvider();
1265   ExpectSimilar(regular_default, actual_final_managed_default);
1266   EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true);
1267
1268   // Disable the default search provider through policy.
1269   test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1270       std::string(), std::string(), std::string(), std::string(),
1271       std::string(), std::string(), std::string());
1272   VerifyObserverFired();
1273   EXPECT_TRUE(model()->is_default_search_managed());
1274   EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider());
1275   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1276
1277   // Re-enable it.
1278   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1279       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1280       kSearchTermsReplacementKey);
1281   VerifyObserverFired();
1282   EXPECT_TRUE(model()->is_default_search_managed());
1283   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1284
1285   // Verify that the default manager we are getting is the managed one.
1286   actual_managed_default = model()->GetDefaultSearchProvider();
1287   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1288   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1289
1290   // Clear the model and disable the default search provider through policy.
1291   // Verify that there is no default search provider after loading the model.
1292   // This checks against regressions of http://crbug.com/67180
1293
1294   // First, remove the preferences, reset the model, and set a default.
1295   test_util()->RemoveManagedDefaultSearchPreferences();
1296   test_util()->ResetModel(true);
1297   TemplateURL* new_default =
1298       model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1"));
1299   ASSERT_FALSE(new_default == NULL);
1300   model()->SetUserSelectedDefaultSearchProvider(new_default);
1301   EXPECT_EQ(new_default, model()->GetDefaultSearchProvider());
1302
1303   // Now reset the model again but load it after setting the preferences.
1304   test_util()->ResetModel(false);
1305   test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1306       std::string(), std::string(), std::string(), std::string(),
1307       std::string(), std::string(), std::string());
1308   test_util()->VerifyLoad();
1309   EXPECT_TRUE(model()->is_default_search_managed());
1310   EXPECT_TRUE(model()->GetDefaultSearchProvider() == NULL);
1311 }
1312
1313 // Test that if we load a TemplateURL with an empty GUID, the load process
1314 // assigns it a newly generated GUID.
1315 TEST_F(TemplateURLServiceTest, PatchEmptySyncGUID) {
1316   // Add a new TemplateURL.
1317   test_util()->VerifyLoad();
1318   const size_t initial_count = model()->GetTemplateURLs().size();
1319
1320   TemplateURLData data;
1321   data.short_name = ASCIIToUTF16("google");
1322   data.SetKeyword(ASCIIToUTF16("keyword"));
1323   data.SetURL("http://www.google.com/foo/bar");
1324   data.sync_guid.clear();
1325   TemplateURL* t_url = new TemplateURL(data);
1326   model()->Add(t_url);
1327
1328   VerifyObserverCount(1);
1329   base::RunLoop().RunUntilIdle();
1330   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1331
1332   // Reload the model to verify it was actually saved to the database and
1333   // assigned a new GUID when brought back.
1334   test_util()->ResetModel(true);
1335   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1336   const TemplateURL* loaded_url =
1337       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1338   ASSERT_FALSE(loaded_url == NULL);
1339   ASSERT_FALSE(loaded_url->sync_guid().empty());
1340 }
1341
1342 // Test that if we load a TemplateURL with duplicate input encodings, the load
1343 // process de-dupes them.
1344 TEST_F(TemplateURLServiceTest, DuplicateInputEncodings) {
1345   // Add a new TemplateURL.
1346   test_util()->VerifyLoad();
1347   const size_t initial_count = model()->GetTemplateURLs().size();
1348
1349   TemplateURLData data;
1350   data.short_name = ASCIIToUTF16("google");
1351   data.SetKeyword(ASCIIToUTF16("keyword"));
1352   data.SetURL("http://www.google.com/foo/bar");
1353   std::vector<std::string> encodings;
1354   data.input_encodings.push_back("UTF-8");
1355   data.input_encodings.push_back("UTF-8");
1356   data.input_encodings.push_back("UTF-16");
1357   data.input_encodings.push_back("UTF-8");
1358   data.input_encodings.push_back("Big5");
1359   data.input_encodings.push_back("UTF-16");
1360   data.input_encodings.push_back("Big5");
1361   data.input_encodings.push_back("Windows-1252");
1362   TemplateURL* t_url = new TemplateURL(data);
1363   model()->Add(t_url);
1364
1365   VerifyObserverCount(1);
1366   base::RunLoop().RunUntilIdle();
1367   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1368   const TemplateURL* loaded_url =
1369       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1370   ASSERT_TRUE(loaded_url != NULL);
1371   EXPECT_EQ(8U, loaded_url->input_encodings().size());
1372
1373   // Reload the model to verify it was actually saved to the database and the
1374   // duplicate encodings were removed.
1375   test_util()->ResetModel(true);
1376   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1377   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1378   ASSERT_FALSE(loaded_url == NULL);
1379   EXPECT_EQ(4U, loaded_url->input_encodings().size());
1380 }
1381
1382 TEST_F(TemplateURLServiceTest, DefaultExtensionEngine) {
1383   test_util()->VerifyLoad();
1384   // Add third-party default search engine.
1385   TemplateURL* user_dse = AddKeywordWithDate(
1386       "user", "user", "http://www.goo.com/s?q={searchTerms}",
1387       std::string(), std::string(), std::string(),
1388       true, "UTF-8", Time(), Time());
1389   model()->SetUserSelectedDefaultSearchProvider(user_dse);
1390   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1391
1392   TemplateURL* ext_dse = CreateKeywordWithDate(
1393       model(), "ext", "ext", "http://www.search.com/s?q={searchTerms}",
1394       std::string(), std::string(), std::string(),
1395       true, true, "UTF-8", Time(), Time());
1396   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1397       new TemplateURL::AssociatedExtensionInfo(
1398           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext"));
1399   extension_info->wants_to_be_default_engine = true;
1400   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1401   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1402
1403   model()->RemoveExtensionControlledTURL(
1404       "ext", TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION);
1405   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1406 }
1407
1408 TEST_F(TemplateURLServiceTest, ExtensionEnginesNotPersist) {
1409   test_util()->VerifyLoad();
1410   // Add third-party default search engine.
1411   TemplateURL* user_dse = AddKeywordWithDate(
1412       "user", "user", "http://www.goo.com/s?q={searchTerms}",
1413       std::string(), std::string(), std::string(),
1414       true, "UTF-8", Time(), Time());
1415   model()->SetUserSelectedDefaultSearchProvider(user_dse);
1416   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1417
1418   TemplateURL* ext_dse = CreateKeywordWithDate(
1419       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1420       std::string(), std::string(), std::string(),
1421       true, false, "UTF-8", Time(), Time());
1422   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1423       new TemplateURL::AssociatedExtensionInfo(
1424           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1"));
1425   extension_info->wants_to_be_default_engine = false;
1426   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1427   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1428
1429   ext_dse = CreateKeywordWithDate(
1430       model(), "ext2", "ext2", "http://www.ext2.com/s?q={searchTerms}",
1431       std::string(), std::string(), std::string(),
1432       true, true, "UTF-8", Time(), Time());
1433   extension_info.reset(new TemplateURL::AssociatedExtensionInfo(
1434       TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext2"));
1435   extension_info->wants_to_be_default_engine = true;
1436   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1437   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1438
1439   test_util()->ResetModel(true);
1440   user_dse = model()->GetTemplateURLForKeyword(ASCIIToUTF16("user"));
1441   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1442   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1443   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext2")));
1444 }
1445
1446 TEST_F(TemplateURLServiceTest, ExtensionEngineVsPolicy) {
1447   // Set a managed preference that establishes a default search provider.
1448   const char kName[] = "test";
1449   const char kKeyword[] = "test.com";
1450   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1451   const char kIconURL[] = "http://test.com/icon.jpg";
1452   const char kEncodings[] = "UTF-16;UTF-32";
1453   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1454   const char kSearchTermsReplacementKey[] = "espv";
1455   test_util()->SetManagedDefaultSearchPreferences(
1456       true, kName, kKeyword, kSearchURL, std::string(), kIconURL, kEncodings,
1457       kAlternateURL, kSearchTermsReplacementKey);
1458   test_util()->VerifyLoad();
1459   // Verify that the default manager we are getting is the managed one.
1460   TemplateURLData data;
1461   data.short_name = ASCIIToUTF16(kName);
1462   data.SetKeyword(ASCIIToUTF16(kKeyword));
1463   data.SetURL(kSearchURL);
1464   data.favicon_url = GURL(kIconURL);
1465   data.show_in_default_list = true;
1466   base::SplitString(kEncodings, ';', &data.input_encodings);
1467   data.alternate_urls.push_back(kAlternateURL);
1468   data.search_terms_replacement_key = kSearchTermsReplacementKey;
1469   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(data));
1470   EXPECT_TRUE(model()->is_default_search_managed());
1471   const TemplateURL* actual_managed_default =
1472       model()->GetDefaultSearchProvider();
1473   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
1474
1475   TemplateURL* ext_dse = CreateKeywordWithDate(
1476       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1477       std::string(), std::string(), std::string(),
1478       true, true, "UTF-8", Time(), Time());
1479   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1480       new TemplateURL::AssociatedExtensionInfo(
1481           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1"));
1482   extension_info->wants_to_be_default_engine = true;
1483   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1484   EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1485   EXPECT_TRUE(model()->is_default_search_managed());
1486   actual_managed_default = model()->GetDefaultSearchProvider();
1487   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
1488 }