Upstream version 10.39.225.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   virtual void SetUp() OVERRIDE;
137   virtual 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   virtual void SetUp() OVERRIDE {
180     DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(true);
181     TemplateURLServiceTest::SetUp();
182   }
183
184   virtual 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   TemplateURL* original1 = 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   // Add an extension keyword that conflicts with each of the above three
412   // keywords.
413   // Both replaceable and non-replaceable keywords should be uniquified.
414   model()->RegisterOmniboxKeyword("test4", "test", "keyword1", "http://test4");
415   TemplateURL* extension1 =
416       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1"));
417   ASSERT_TRUE(extension1);
418   EXPECT_EQ(original1,
419             model()->GetTemplateURLForKeyword(ASCIIToUTF16("test1")));
420
421   model()->RegisterOmniboxKeyword("test5", "test", "keyword2", "http://test5");
422   TemplateURL* extension2 =
423       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2"));
424   ASSERT_TRUE(extension2);
425   EXPECT_EQ(original2,
426             model()->GetTemplateURLForKeyword(ASCIIToUTF16("test2")));
427
428   // They should override extension keywords added earlier.
429   model()->RegisterOmniboxKeyword("test6", "test", "keyword3", "http://test6");
430   TemplateURL* extension3 =
431       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3"));
432   ASSERT_TRUE(extension3);
433   EXPECT_EQ(original3,
434             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3_")));
435 }
436
437 TEST_F(TemplateURLServiceTest, AddSameKeywordWithExtensionPresent) {
438   test_util()->VerifyLoad();
439
440   // Similar to the AddSameKeyword test, but with an extension keyword masking a
441   // replaceable TemplateURL.  We should still do correct conflict resolution
442   // between the non-template URLs.
443   model()->RegisterOmniboxKeyword("test2", "extension", "keyword",
444                                   "http://test2");
445   TemplateURL* extension =
446       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
447   ASSERT_TRUE(extension);
448   // Adding a keyword that matches the extension should cause the extension
449   // to uniquify.
450   AddKeywordWithDate(
451       "replaceable", "keyword", "http://test1", std::string(),  std::string(),
452       std::string(), true, "UTF-8", Time(), Time());
453
454   // Adding another replaceable keyword should remove the existing one, but
455   // leave the extension as is.
456   TemplateURLData data;
457   data.short_name = ASCIIToUTF16("name1");
458   data.SetKeyword(ASCIIToUTF16("keyword"));
459   data.SetURL("http://test3");
460   data.safe_for_autoreplace = true;
461   TemplateURL* t_url = new TemplateURL(data);
462   model()->Add(t_url);
463   EXPECT_EQ(extension,
464             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
465   EXPECT_TRUE(model()->GetTemplateURLForHost("test1") == NULL);
466   EXPECT_EQ(t_url, model()->GetTemplateURLForHost("test3"));
467
468   // Adding a nonreplaceable keyword should remove the existing replaceable
469   // keyword.
470   data.short_name = ASCIIToUTF16("name2");
471   data.SetURL("http://test4");
472   data.safe_for_autoreplace = false;
473   TemplateURL* t_url2 = new TemplateURL(data);
474   model()->Add(t_url2);
475   EXPECT_EQ(t_url2,
476             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
477   EXPECT_TRUE(model()->GetTemplateURLForHost("test3") == NULL);
478   EXPECT_EQ(extension,
479             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
480 }
481
482 TEST_F(TemplateURLServiceTest, RestoreOmniboxExtensionKeyword) {
483   test_util()->VerifyLoad();
484
485   // Register an omnibox keyword.
486   model()->RegisterOmniboxKeyword("test", "extension", "keyword",
487                                   "chrome-extension://test");
488   ASSERT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
489
490   // Reload the data.
491   test_util()->ResetModel(true);
492
493   // Ensure the omnibox keyword is restored correctly.
494   TemplateURL* t_url =
495       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
496   ASSERT_TRUE(t_url);
497   ASSERT_EQ(TemplateURL::OMNIBOX_API_EXTENSION, t_url->GetType());
498   EXPECT_EQ("test", t_url->GetExtensionId());
499 }
500
501 TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
502   Time now = Time::Now();
503   TimeDelta one_day = TimeDelta::FromDays(1);
504   Time month_ago = now - TimeDelta::FromDays(30);
505
506   // Nothing has been added.
507   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
508
509   // Create one with a 0 time.
510   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
511                      std::string(), "http://icon1", true, "UTF-8;UTF-16",
512                      Time(), Time());
513   // Create one for now and +/- 1 day.
514   AddKeywordWithDate("name2", "key2", "http://foo2", "http://suggest2",
515                      std::string(),  "http://icon2", true, "UTF-8;UTF-16",
516                      now - one_day, Time());
517   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
518                      std::string(), std::string(), true, std::string(), now,
519                      Time());
520   AddKeywordWithDate("name4", "key4", "http://foo4", std::string(),
521                      std::string(), std::string(), true, std::string(),
522                      now + one_day, Time());
523   // Try the other three states.
524   AddKeywordWithDate("name5", "key5", "http://foo5", "http://suggest5",
525                      std::string(), "http://icon5", false, "UTF-8;UTF-16", now,
526                      Time());
527   AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
528                      std::string(), "http://icon6", false, "UTF-8;UTF-16",
529                      month_ago, Time());
530
531   // We just added a few items, validate them.
532   EXPECT_EQ(6U, model()->GetTemplateURLs().size());
533
534   // Try removing from current timestamp. This should delete the one in the
535   // future and one very recent one.
536   model()->RemoveAutoGeneratedSince(now);
537   EXPECT_EQ(4U, model()->GetTemplateURLs().size());
538
539   // Try removing from two months ago. This should only delete items that are
540   // auto-generated.
541   model()->RemoveAutoGeneratedBetween(now - TimeDelta::FromDays(60), now);
542   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
543
544   // Make sure the right values remain.
545   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
546   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
547   EXPECT_EQ(0U,
548             model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
549
550   EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
551   EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
552   EXPECT_EQ(now.ToInternalValue(),
553             model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
554
555   EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
556   EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
557   EXPECT_EQ(month_ago.ToInternalValue(),
558             model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
559
560   // Try removing from Time=0. This should delete one more.
561   model()->RemoveAutoGeneratedSince(Time());
562   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
563 }
564
565 TEST_F(TemplateURLServiceTest, ClearBrowsingData_KeywordsForOrigin) {
566   Time now = Time::Now();
567   TimeDelta one_day = TimeDelta::FromDays(1);
568   Time month_ago = now - TimeDelta::FromDays(30);
569
570   // Nothing has been added.
571   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
572
573   // Create one for now and +/- 1 day.
574   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
575                      std::string(), "http://icon2", true, "UTF-8;UTF-16",
576                      now - one_day, Time());
577   AddKeywordWithDate("name2", "key2", "http://foo2", std::string(),
578                      std::string(), std::string(), true, std::string(), now,
579                      Time());
580   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
581                      std::string(), std::string(), true, std::string(),
582                      now + one_day, Time());
583
584   // We just added a few items, validate them.
585   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
586
587   // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
588   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago,
589       now + one_day);
590   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
591   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
592   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
593   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
594   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
595
596   // Try removing foo1, but outside the range in which it was modified. It
597   // should remain untouched.
598   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo1"), now,
599       now + one_day);
600   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
601   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
602   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
603   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
604   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
605
606
607   // Try removing foo3. This should delete foo3, but leave foo1 untouched.
608   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo3"), month_ago,
609       now + one_day + one_day);
610   EXPECT_EQ(1U, model()->GetTemplateURLs().size());
611   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
612   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
613 }
614
615 TEST_F(TemplateURLServiceTest, Reset) {
616   // Add a new TemplateURL.
617   test_util()->VerifyLoad();
618   const size_t initial_count = model()->GetTemplateURLs().size();
619   TemplateURLData data;
620   data.short_name = ASCIIToUTF16("google");
621   data.SetKeyword(ASCIIToUTF16("keyword"));
622   data.SetURL("http://www.google.com/foo/bar");
623   data.favicon_url = GURL("http://favicon.url");
624   data.date_created = Time::FromTimeT(100);
625   data.last_modified = Time::FromTimeT(100);
626   TemplateURL* t_url = new TemplateURL(data);
627   model()->Add(t_url);
628
629   VerifyObserverCount(1);
630   base::RunLoop().RunUntilIdle();
631
632   StrictMock<base::MockTimeProvider> mock_time;
633   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
634   EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
635
636   // Reset the short name, keyword, url and make sure it takes.
637   const base::string16 new_short_name(ASCIIToUTF16("a"));
638   const base::string16 new_keyword(ASCIIToUTF16("b"));
639   const std::string new_url("c");
640   model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
641   ASSERT_EQ(new_short_name, t_url->short_name());
642   ASSERT_EQ(new_keyword, t_url->keyword());
643   ASSERT_EQ(new_url, t_url->url());
644
645   // Make sure the mappings in the model were updated.
646   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword));
647   ASSERT_TRUE(
648       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
649
650   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
651
652   // Reload the model from the database and make sure the change took.
653   test_util()->ResetModel(true);
654   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
655   const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
656   ASSERT_TRUE(read_url);
657   AssertEquals(*cloned_url, *read_url);
658   ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified());
659 }
660
661 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
662   // Add a new TemplateURL.
663   test_util()->VerifyLoad();
664   const size_t initial_count = model()->GetTemplateURLs().size();
665   TemplateURL* t_url = AddKeywordWithDate(
666       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
667       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
668   test_util()->ResetObserverCount();
669
670   model()->SetUserSelectedDefaultSearchProvider(t_url);
671   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
672   ASSERT_TRUE(t_url->safe_for_autoreplace());
673   ASSERT_TRUE(t_url->show_in_default_list());
674
675   // Setting the default search provider should have caused notification.
676   VerifyObserverCount(1);
677   base::RunLoop().RunUntilIdle();
678
679   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
680
681   // Make sure when we reload we get a default search provider.
682   test_util()->ResetModel(true);
683   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
684   ASSERT_TRUE(model()->GetDefaultSearchProvider());
685   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
686 }
687
688 TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
689   test_util()->ChangeModelToLoadState();
690   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
691   TemplateURL* t_url = AddKeywordWithDate(
692       "name1", "foo", "http://foo1", "http://sugg1", std::string(),
693       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
694
695   // Can still replace, newly added template url is marked safe to replace.
696   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
697                                          GURL("http://foo2"), NULL));
698
699   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
700   // no longer be replaceable.
701   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
702                             t_url->url());
703
704   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
705                                           GURL("http://foo2"), NULL));
706 }
707
708 TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
709   test_util()->ChangeModelToLoadState();
710   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
711                                          GURL("http://foo.com"), NULL));
712   TemplateURL* t_url = AddKeywordWithDate(
713       "name1", "foo", "http://foo.com", "http://sugg1", std::string(),
714       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
715
716   // Can still replace, newly added template url is marked safe to replace.
717   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
718                                          GURL("http://foo.com"), NULL));
719
720   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
721   // no longer be replaceable.
722   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
723                             t_url->url());
724
725   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
726                                           GURL("http://foo.com"), NULL));
727 }
728
729 TEST_F(TemplateURLServiceTest, HasDefaultSearchProvider) {
730   // We should have a default search provider even if we haven't loaded.
731   ASSERT_TRUE(model()->GetDefaultSearchProvider());
732
733   // Now force the model to load and make sure we still have a default.
734   test_util()->VerifyLoad();
735
736   ASSERT_TRUE(model()->GetDefaultSearchProvider());
737 }
738
739 TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
740   test_util()->VerifyLoad();
741
742   TemplateURLData data;
743   data.short_name = ASCIIToUTF16("a");
744   data.safe_for_autoreplace = true;
745   data.SetURL("http://url/{searchTerms}");
746   data.suggestions_url = "http://url2";
747   data.instant_url = "http://instant";
748   data.date_created = Time::FromTimeT(100);
749   data.last_modified = Time::FromTimeT(100);
750   TemplateURL* t_url = new TemplateURL(data);
751   model()->Add(t_url);
752   const TemplateURLID id = t_url->id();
753
754   model()->SetUserSelectedDefaultSearchProvider(t_url);
755   base::RunLoop().RunUntilIdle();
756   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
757
758   // Reset the model and don't load it. The template url we set as the default
759   // should be pulled from prefs now.
760   test_util()->ResetModel(false);
761
762   // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
763   // value are persisted to prefs.
764   const TemplateURL* default_turl = model()->GetDefaultSearchProvider();
765   ASSERT_TRUE(default_turl);
766   EXPECT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
767   EXPECT_EQ("http://url/{searchTerms}", default_turl->url());
768   EXPECT_EQ("http://url2", default_turl->suggestions_url());
769   EXPECT_EQ("http://instant", default_turl->instant_url());
770   EXPECT_EQ(id, default_turl->id());
771
772   // Now do a load and make sure the default search provider really takes.
773   test_util()->VerifyLoad();
774
775   ASSERT_TRUE(model()->GetDefaultSearchProvider());
776   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
777 }
778
779 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
780   test_util()->VerifyLoad();
781
782   // Edit Google search engine.
783   TemplateURL* google = model()->GetTemplateURLForKeyword(
784       ASCIIToUTF16("google.com"));
785   ASSERT_TRUE(google);
786   model()->ResetTemplateURL(google, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"),
787                             "http://www.foo.com/s?q={searchTerms}");
788   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
789   EXPECT_EQ(ASCIIToUTF16("xxx"), google->keyword());
790
791   // Add third-party default search engine.
792   TemplateURL* user_dse = AddKeywordWithDate(
793       "malware", "google.com", "http://www.goo.com/s?q={searchTerms}",
794       std::string(), std::string(), std::string(),
795       true, "UTF-8", Time(), Time());
796   model()->SetUserSelectedDefaultSearchProvider(user_dse);
797   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
798
799   // Remove bing.
800   TemplateURL* bing = model()->GetTemplateURLForKeyword(
801       ASCIIToUTF16("bing.com"));
802   ASSERT_TRUE(bing);
803   model()->Remove(bing);
804   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
805
806   // Register an extension with bing keyword.
807   model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com",
808                                   "http://abcdefg");
809   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
810
811   model()->RepairPrepopulatedSearchEngines();
812
813   // Google is default.
814   ASSERT_EQ(google, model()->GetDefaultSearchProvider());
815   // The keyword wasn't reverted.
816   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
817   EXPECT_EQ("www.google.com",
818             google->GenerateSearchURL(model()->search_terms_data()).host());
819
820   // Bing was repaired.
821   bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
822   ASSERT_TRUE(bing);
823   EXPECT_EQ(TemplateURL::NORMAL, bing->GetType());
824
825   // User search engine is preserved.
826   EXPECT_EQ(user_dse, model()->GetTemplateURLForHost("www.goo.com"));
827   EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse->keyword());
828 }
829
830 TEST_F(TemplateURLServiceTest, RepairSearchEnginesWithManagedDefault) {
831   // Set a managed preference that establishes a default search provider.
832   const char kName[] = "test1";
833   const char kKeyword[] = "test.com";
834   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
835   const char kIconURL[] = "http://test.com/icon.jpg";
836   const char kEncodings[] = "UTF-16;UTF-32";
837   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
838   const char kSearchTermsReplacementKey[] = "espv";
839   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
840                                                   kSearchURL, std::string(),
841                                                   kIconURL, kEncodings,
842                                                   kAlternateURL,
843                                                   kSearchTermsReplacementKey);
844   test_util()->VerifyLoad();
845   // Verify that the default manager we are getting is the managed one.
846   TemplateURLData data;
847   data.short_name = ASCIIToUTF16(kName);
848   data.SetKeyword(ASCIIToUTF16(kKeyword));
849   data.SetURL(kSearchURL);
850   data.favicon_url = GURL(kIconURL);
851   data.show_in_default_list = true;
852   base::SplitString(kEncodings, ';', &data.input_encodings);
853   data.alternate_urls.push_back(kAlternateURL);
854   data.search_terms_replacement_key = kSearchTermsReplacementKey;
855   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(data));
856   EXPECT_TRUE(model()->is_default_search_managed());
857   const TemplateURL* actual_managed_default =
858       model()->GetDefaultSearchProvider();
859   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
860
861   // The following call has no effect on the managed search engine.
862   model()->RepairPrepopulatedSearchEngines();
863
864   EXPECT_TRUE(model()->is_default_search_managed());
865   actual_managed_default = model()->GetDefaultSearchProvider();
866   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
867 }
868
869 TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
870   struct TestData {
871     const std::string url;
872     const base::string16 term;
873   } data[] = {
874     { "http://foo/", base::string16() },
875     { "http://foo/foo?q=xx", base::string16() },
876     { "http://x/bar?q=xx", base::string16() },
877     { "http://x/foo?y=xx", base::string16() },
878     { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
879     { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
880     { "http://x/foo?q=b&q=xx", base::string16() },
881     { "http://x/foo#query=xx", ASCIIToUTF16("xx") },
882     { "http://x/foo?q=b#query=xx", ASCIIToUTF16("xx") },
883     { "http://x/foo?q=b#q=xx", ASCIIToUTF16("b") },
884     { "http://x/foo?query=b#q=xx", base::string16() },
885   };
886
887   test_util()->ChangeModelToLoadState();
888   AddKeywordWithDate("name", "x", "http://x/foo?q={searchTerms}",
889                      "http://sugg1", "http://x/foo#query={searchTerms}",
890                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
891
892   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
893     TemplateURLService::URLVisitedDetails details = {
894       GURL(data[i].url), false
895     };
896     model()->UpdateKeywordSearchTermsForURL(details);
897     EXPECT_EQ(data[i].term, test_util()->GetAndClearSearchTerm());
898   }
899 }
900
901 TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
902   struct TestData {
903     const std::string url;
904   } data[] = {
905     { "http://foo/" },
906     { "http://x/bar?q=xx" },
907     { "http://x/foo?y=xx" },
908   };
909
910   test_util()->ChangeModelToLoadState();
911   AddKeywordWithDate("name", "x", "http://x/foo", "http://sugg1", std::string(),
912                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
913
914   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
915     TemplateURLService::URLVisitedDetails details = {
916       GURL(data[i].url), false
917     };
918     model()->UpdateKeywordSearchTermsForURL(details);
919     ASSERT_EQ(base::string16(), test_util()->GetAndClearSearchTerm());
920   }
921 }
922
923 TEST_F(TemplateURLServiceWithoutFallbackTest, ChangeGoogleBaseValue) {
924   // NOTE: Do not load the prepopulate data, which also has a {google:baseURL}
925   // keyword in it and would confuse this test.
926   test_util()->ChangeModelToLoadState();
927
928   test_util()->SetGoogleBaseURL(GURL("http://google.com/"));
929   const TemplateURL* t_url = AddKeywordWithDate(
930       "name", "google.com", "{google:baseURL}?q={searchTerms}", "http://sugg1",
931       std::string(), "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
932   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
933   EXPECT_EQ("google.com", t_url->url_ref().GetHost(search_terms_data()));
934   EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
935
936   // Change the Google base url.
937   test_util()->ResetObserverCount();
938   test_util()->SetGoogleBaseURL(GURL("http://google.co.uk/"));
939   VerifyObserverCount(1);
940
941   // Make sure the host->TemplateURL map was updated appropriately.
942   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.co.uk"));
943   EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
944   EXPECT_EQ("google.co.uk", t_url->url_ref().GetHost(search_terms_data()));
945   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
946   EXPECT_EQ("http://google.co.uk/?q=x", t_url->url_ref().ReplaceSearchTerms(
947       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x")), search_terms_data()));
948
949   // Now add a manual entry and then change the Google base URL such that the
950   // autogenerated Google search keyword would conflict.
951   TemplateURL* manual = AddKeywordWithDate(
952     "manual", "google.de", "http://google.de/search?q={searchTerms}",
953     std::string(), std::string(), std::string(), false, "UTF-8", Time(),
954     Time());
955   test_util()->SetGoogleBaseURL(GURL("http://google.de"));
956
957   // Verify that the manual entry is untouched, and the autogenerated keyword
958   // has not changed.
959   ASSERT_EQ(manual,
960             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
961   EXPECT_EQ("google.de", manual->url_ref().GetHost(search_terms_data()));
962   ASSERT_EQ(t_url,
963             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.co.uk")));
964   EXPECT_EQ("google.de", t_url->url_ref().GetHost(search_terms_data()));
965   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
966
967   // Change the base URL again and verify that the autogenerated keyword follows
968   // even though it didn't match the base URL, while the manual entry is still
969   // untouched.
970   test_util()->SetGoogleBaseURL(GURL("http://google.fr/"));
971   ASSERT_EQ(manual, model()->GetTemplateURLForHost("google.de"));
972   EXPECT_EQ("google.de", manual->url_ref().GetHost(search_terms_data()));
973   EXPECT_EQ(ASCIIToUTF16("google.de"), manual->keyword());
974   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.fr"));
975   EXPECT_TRUE(model()->GetTemplateURLForHost("google.co.uk") == NULL);
976   EXPECT_EQ("google.fr", t_url->url_ref().GetHost(search_terms_data()));
977   EXPECT_EQ(ASCIIToUTF16("google.fr"), t_url->keyword());
978 }
979
980 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
981 // KEYWORD visits.
982 TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
983   test_util()->VerifyLoad();
984   ASSERT_TRUE(test_util()->profile()->CreateHistoryService(true, false));
985
986   // Create a keyword.
987   TemplateURL* t_url = AddKeywordWithDate(
988       "keyword", "keyword", "http://foo.com/foo?query={searchTerms}",
989       "http://sugg1", std::string(), "http://icon1", true, "UTF-8;UTF-16",
990       base::Time::Now(), base::Time::Now());
991
992   // Add a visit that matches the url of the keyword.
993   HistoryService* history =
994       HistoryServiceFactory::GetForProfile(test_util()->profile(),
995                                            Profile::EXPLICIT_ACCESS);
996   history->AddPage(
997       GURL(t_url->url_ref().ReplaceSearchTerms(
998           TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah")),
999           search_terms_data())),
1000       base::Time::Now(), NULL, 0, GURL(), history::RedirectList(),
1001       ui::PAGE_TRANSITION_KEYWORD, history::SOURCE_BROWSED, false);
1002
1003   // Wait for history to finish processing the request.
1004   test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
1005
1006   // Query history for the generated url.
1007   base::CancelableTaskTracker tracker;
1008   QueryHistoryCallbackImpl callback;
1009   history->QueryURL(GURL("http://keyword"),
1010                     true,
1011                     base::Bind(&QueryHistoryCallbackImpl::Callback,
1012                                base::Unretained(&callback)),
1013                     &tracker);
1014
1015   // Wait for the request to be processed.
1016   test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
1017
1018   // And make sure the url and visit were added.
1019   EXPECT_TRUE(callback.success);
1020   EXPECT_NE(0, callback.row.id());
1021   ASSERT_EQ(1U, callback.visits.size());
1022   EXPECT_EQ(ui::PAGE_TRANSITION_KEYWORD_GENERATED,
1023       ui::PageTransitionStripQualifier(callback.visits[0].transition));
1024 }
1025
1026 // Make sure that the load routine deletes prepopulated engines that no longer
1027 // exist in the prepopulate data.
1028 TEST_F(TemplateURLServiceTest, LoadDeletesUnusedProvider) {
1029   // Create a preloaded template url. Add it to a loaded model and wait for the
1030   // saves to finish.
1031   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1032   test_util()->ChangeModelToLoadState();
1033   model()->Add(t_url);
1034   ASSERT_TRUE(
1035       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1036   base::RunLoop().RunUntilIdle();
1037
1038   // Ensure that merging clears this engine.
1039   test_util()->ResetModel(true);
1040   ASSERT_TRUE(
1041       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1042
1043   // Wait for any saves to finish.
1044   base::RunLoop().RunUntilIdle();
1045
1046   // Reload the model to verify that the database was updated as a result of the
1047   // merge.
1048   test_util()->ResetModel(true);
1049   ASSERT_TRUE(
1050       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1051 }
1052
1053 // Make sure that load routine doesn't delete prepopulated engines that no
1054 // longer exist in the prepopulate data if it has been modified by the user.
1055 TEST_F(TemplateURLServiceTest, LoadRetainsModifiedProvider) {
1056   // Create a preloaded template url and add it to a loaded model.
1057   TemplateURL* t_url = CreatePreloadedTemplateURL(false, 999999);
1058   test_util()->ChangeModelToLoadState();
1059   model()->Add(t_url);
1060
1061   // Do the copy after t_url is added so that the id is set.
1062   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
1063   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1064
1065   // Wait for any saves to finish.
1066   base::RunLoop().RunUntilIdle();
1067
1068   // Ensure that merging won't clear it if the user has edited it.
1069   test_util()->ResetModel(true);
1070   const TemplateURL* url_for_unittest =
1071       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1072   ASSERT_TRUE(url_for_unittest != NULL);
1073   AssertEquals(*cloned_url, *url_for_unittest);
1074
1075   // Wait for any saves to finish.
1076   base::RunLoop().RunUntilIdle();
1077
1078   // Reload the model to verify that save/reload retains the item.
1079   test_util()->ResetModel(true);
1080   ASSERT_TRUE(
1081       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1082 }
1083
1084 // Make sure that load routine doesn't delete
1085 // prepopulated engines that no longer exist in the prepopulate data if
1086 // it has been modified by the user.
1087 TEST_F(TemplateURLServiceTest, LoadSavesPrepopulatedDefaultSearchProvider) {
1088   test_util()->VerifyLoad();
1089   // Verify that the default search provider is set to something.
1090   TemplateURL* default_search = model()->GetDefaultSearchProvider();
1091   ASSERT_TRUE(default_search != NULL);
1092   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(default_search->data()));
1093
1094   // Wait for any saves to finish.
1095   base::RunLoop().RunUntilIdle();
1096
1097   // Reload the model and check that the default search provider
1098   // was properly saved.
1099   test_util()->ResetModel(true);
1100   default_search = model()->GetDefaultSearchProvider();
1101   ASSERT_TRUE(default_search != NULL);
1102   AssertEquals(*cloned_url, *default_search);
1103 }
1104
1105 // Make sure that the load routine doesn't delete
1106 // prepopulated engines that no longer exist in the prepopulate data if
1107 // it is the default search provider.
1108 TEST_F(TemplateURLServiceTest, LoadRetainsDefaultProvider) {
1109   // Set the default search provider to a preloaded template url which
1110   // is not in the current set of preloaded template urls and save
1111   // the result.
1112   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1113   test_util()->ChangeModelToLoadState();
1114   model()->Add(t_url);
1115   model()->SetUserSelectedDefaultSearchProvider(t_url);
1116   // Do the copy after t_url is added and set as default so that its
1117   // internal state is correct.
1118   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data()));
1119
1120   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1121   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
1122   base::RunLoop().RunUntilIdle();
1123
1124   // Ensure that merging won't clear the prepopulated template url
1125   // which is no longer present if it's the default engine.
1126   test_util()->ResetModel(true);
1127   {
1128     const TemplateURL* keyword_url =
1129         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1130     ASSERT_TRUE(keyword_url != NULL);
1131     AssertEquals(*cloned_url, *keyword_url);
1132     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1133   }
1134
1135   // Wait for any saves to finish.
1136   base::RunLoop().RunUntilIdle();
1137
1138   // Reload the model to verify that the update was saved.
1139   test_util()->ResetModel(true);
1140   {
1141     const TemplateURL* keyword_url =
1142         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1143     ASSERT_TRUE(keyword_url != NULL);
1144     AssertEquals(*cloned_url, *keyword_url);
1145     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1146   }
1147 }
1148
1149 // Make sure that the load routine sets a default search provider if it was
1150 // missing and not managed.
1151 TEST_F(TemplateURLServiceTest, LoadEnsuresDefaultSearchProviderExists) {
1152   // Force the model to load and make sure we have a default search provider.
1153   test_util()->VerifyLoad();
1154   EXPECT_TRUE(model()->GetDefaultSearchProvider());
1155
1156   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1157       search_terms_data()));
1158
1159   // Make default search provider unusable (no search terms).
1160   model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
1161                             ASCIIToUTF16("test"), ASCIIToUTF16("test"),
1162                             "http://example.com/");
1163   base::RunLoop().RunUntilIdle();
1164
1165   // Reset the model and load it. There should be a usable default search
1166   // provider.
1167   test_util()->ResetModel(true);
1168
1169   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1170   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1171       search_terms_data()));
1172 }
1173
1174 // Simulates failing to load the webdb and makes sure the default search
1175 // provider is valid.
1176 TEST_F(TemplateURLServiceTest, FailedInit) {
1177   test_util()->VerifyLoad();
1178
1179   test_util()->ClearModel();
1180   test_util()->web_data_service()->ShutdownDatabase();
1181
1182   test_util()->ResetModel(false);
1183   model()->Load();
1184   base::RunLoop().RunUntilIdle();
1185
1186   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1187 }
1188
1189 // Verifies that if the default search URL preference is managed, we report
1190 // the default search as managed.  Also check that we are getting the right
1191 // values.
1192 TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
1193   test_util()->VerifyLoad();
1194   const size_t initial_count = model()->GetTemplateURLs().size();
1195   test_util()->ResetObserverCount();
1196
1197   // Set a regular default search provider.
1198   TemplateURL* regular_default = AddKeywordWithDate(
1199       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
1200       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
1201   VerifyObserverCount(1);
1202   model()->SetUserSelectedDefaultSearchProvider(regular_default);
1203   // Adding the URL and setting the default search provider should have caused
1204   // notifications.
1205   VerifyObserverCount(1);
1206   EXPECT_FALSE(model()->is_default_search_managed());
1207   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1208
1209   // Set a managed preference that establishes a default search provider.
1210   const char kName[] = "test1";
1211   const char kKeyword[] = "test.com";
1212   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1213   const char kIconURL[] = "http://test.com/icon.jpg";
1214   const char kEncodings[] = "UTF-16;UTF-32";
1215   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1216   const char kSearchTermsReplacementKey[] = "espv";
1217   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1218       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1219       kSearchTermsReplacementKey);
1220   VerifyObserverFired();
1221   EXPECT_TRUE(model()->is_default_search_managed());
1222   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1223
1224   // Verify that the default manager we are getting is the managed one.
1225   TemplateURLData data;
1226   data.short_name = ASCIIToUTF16(kName);
1227   data.SetKeyword(ASCIIToUTF16(kKeyword));
1228   data.SetURL(kSearchURL);
1229   data.favicon_url = GURL(kIconURL);
1230   data.show_in_default_list = true;
1231   base::SplitString(kEncodings, ';', &data.input_encodings);
1232   data.alternate_urls.push_back(kAlternateURL);
1233   data.search_terms_replacement_key = kSearchTermsReplacementKey;
1234   scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL(data));
1235   const TemplateURL* actual_managed_default =
1236       model()->GetDefaultSearchProvider();
1237   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1238   EXPECT_TRUE(actual_managed_default->show_in_default_list());
1239
1240   // Update the managed preference and check that the model has changed.
1241   const char kNewName[] = "test2";
1242   const char kNewKeyword[] = "other.com";
1243   const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}";
1244   const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}";
1245   test_util()->SetManagedDefaultSearchPreferences(true, kNewName, kNewKeyword,
1246       kNewSearchURL, kNewSuggestURL, std::string(), std::string(),
1247       std::string(), std::string());
1248   VerifyObserverFired();
1249   EXPECT_TRUE(model()->is_default_search_managed());
1250   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1251
1252   // Verify that the default manager we are now getting is the correct one.
1253   TemplateURLData data2;
1254   data2.short_name = ASCIIToUTF16(kNewName);
1255   data2.SetKeyword(ASCIIToUTF16(kNewKeyword));
1256   data2.SetURL(kNewSearchURL);
1257   data2.suggestions_url = kNewSuggestURL;
1258   data2.show_in_default_list = true;
1259   scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL(data2));
1260   actual_managed_default = model()->GetDefaultSearchProvider();
1261   ExpectSimilar(expected_managed_default2.get(), actual_managed_default);
1262   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1263
1264   // Remove all the managed prefs and check that we are no longer managed.
1265   test_util()->RemoveManagedDefaultSearchPreferences();
1266   VerifyObserverFired();
1267   EXPECT_FALSE(model()->is_default_search_managed());
1268   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1269
1270   // The default should now be the user preference.
1271   const TemplateURL* actual_final_managed_default =
1272       model()->GetDefaultSearchProvider();
1273   ExpectSimilar(regular_default, actual_final_managed_default);
1274   EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true);
1275
1276   // Disable the default search provider through policy.
1277   test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1278       std::string(), std::string(), std::string(), std::string(),
1279       std::string(), std::string(), std::string());
1280   VerifyObserverFired();
1281   EXPECT_TRUE(model()->is_default_search_managed());
1282   EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider());
1283   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1284
1285   // Re-enable it.
1286   test_util()->SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1287       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1288       kSearchTermsReplacementKey);
1289   VerifyObserverFired();
1290   EXPECT_TRUE(model()->is_default_search_managed());
1291   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1292
1293   // Verify that the default manager we are getting is the managed one.
1294   actual_managed_default = model()->GetDefaultSearchProvider();
1295   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1296   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1297
1298   // Clear the model and disable the default search provider through policy.
1299   // Verify that there is no default search provider after loading the model.
1300   // This checks against regressions of http://crbug.com/67180
1301
1302   // First, remove the preferences, reset the model, and set a default.
1303   test_util()->RemoveManagedDefaultSearchPreferences();
1304   test_util()->ResetModel(true);
1305   TemplateURL* new_default =
1306       model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1"));
1307   ASSERT_FALSE(new_default == NULL);
1308   model()->SetUserSelectedDefaultSearchProvider(new_default);
1309   EXPECT_EQ(new_default, model()->GetDefaultSearchProvider());
1310
1311   // Now reset the model again but load it after setting the preferences.
1312   test_util()->ResetModel(false);
1313   test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1314       std::string(), std::string(), std::string(), std::string(),
1315       std::string(), std::string(), std::string());
1316   test_util()->VerifyLoad();
1317   EXPECT_TRUE(model()->is_default_search_managed());
1318   EXPECT_TRUE(model()->GetDefaultSearchProvider() == NULL);
1319 }
1320
1321 // Test that if we load a TemplateURL with an empty GUID, the load process
1322 // assigns it a newly generated GUID.
1323 TEST_F(TemplateURLServiceTest, PatchEmptySyncGUID) {
1324   // Add a new TemplateURL.
1325   test_util()->VerifyLoad();
1326   const size_t initial_count = model()->GetTemplateURLs().size();
1327
1328   TemplateURLData data;
1329   data.short_name = ASCIIToUTF16("google");
1330   data.SetKeyword(ASCIIToUTF16("keyword"));
1331   data.SetURL("http://www.google.com/foo/bar");
1332   data.sync_guid.clear();
1333   TemplateURL* t_url = new TemplateURL(data);
1334   model()->Add(t_url);
1335
1336   VerifyObserverCount(1);
1337   base::RunLoop().RunUntilIdle();
1338   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1339
1340   // Reload the model to verify it was actually saved to the database and
1341   // assigned a new GUID when brought back.
1342   test_util()->ResetModel(true);
1343   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1344   const TemplateURL* loaded_url =
1345       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1346   ASSERT_FALSE(loaded_url == NULL);
1347   ASSERT_FALSE(loaded_url->sync_guid().empty());
1348 }
1349
1350 // Test that if we load a TemplateURL with duplicate input encodings, the load
1351 // process de-dupes them.
1352 TEST_F(TemplateURLServiceTest, DuplicateInputEncodings) {
1353   // Add a new TemplateURL.
1354   test_util()->VerifyLoad();
1355   const size_t initial_count = model()->GetTemplateURLs().size();
1356
1357   TemplateURLData data;
1358   data.short_name = ASCIIToUTF16("google");
1359   data.SetKeyword(ASCIIToUTF16("keyword"));
1360   data.SetURL("http://www.google.com/foo/bar");
1361   std::vector<std::string> encodings;
1362   data.input_encodings.push_back("UTF-8");
1363   data.input_encodings.push_back("UTF-8");
1364   data.input_encodings.push_back("UTF-16");
1365   data.input_encodings.push_back("UTF-8");
1366   data.input_encodings.push_back("Big5");
1367   data.input_encodings.push_back("UTF-16");
1368   data.input_encodings.push_back("Big5");
1369   data.input_encodings.push_back("Windows-1252");
1370   TemplateURL* t_url = new TemplateURL(data);
1371   model()->Add(t_url);
1372
1373   VerifyObserverCount(1);
1374   base::RunLoop().RunUntilIdle();
1375   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1376   const TemplateURL* loaded_url =
1377       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1378   ASSERT_TRUE(loaded_url != NULL);
1379   EXPECT_EQ(8U, loaded_url->input_encodings().size());
1380
1381   // Reload the model to verify it was actually saved to the database and the
1382   // duplicate encodings were removed.
1383   test_util()->ResetModel(true);
1384   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1385   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1386   ASSERT_FALSE(loaded_url == NULL);
1387   EXPECT_EQ(4U, loaded_url->input_encodings().size());
1388 }
1389
1390 TEST_F(TemplateURLServiceTest, DefaultExtensionEngine) {
1391   test_util()->VerifyLoad();
1392   // Add third-party default search engine.
1393   TemplateURL* user_dse = AddKeywordWithDate(
1394       "user", "user", "http://www.goo.com/s?q={searchTerms}",
1395       std::string(), std::string(), std::string(),
1396       true, "UTF-8", Time(), Time());
1397   model()->SetUserSelectedDefaultSearchProvider(user_dse);
1398   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1399
1400   TemplateURL* ext_dse = CreateKeywordWithDate(
1401       model(), "ext", "ext", "http://www.search.com/s?q={searchTerms}",
1402       std::string(), std::string(), std::string(),
1403       true, true, "UTF-8", Time(), Time());
1404   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1405       new TemplateURL::AssociatedExtensionInfo(
1406           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext"));
1407   extension_info->wants_to_be_default_engine = true;
1408   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1409   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1410
1411   model()->RemoveExtensionControlledTURL(
1412       "ext", TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION);
1413   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1414 }
1415
1416 TEST_F(TemplateURLServiceTest, ExtensionEnginesNotPersist) {
1417   test_util()->VerifyLoad();
1418   // Add third-party default search engine.
1419   TemplateURL* user_dse = AddKeywordWithDate(
1420       "user", "user", "http://www.goo.com/s?q={searchTerms}",
1421       std::string(), std::string(), std::string(),
1422       true, "UTF-8", Time(), Time());
1423   model()->SetUserSelectedDefaultSearchProvider(user_dse);
1424   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1425
1426   TemplateURL* ext_dse = CreateKeywordWithDate(
1427       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1428       std::string(), std::string(), std::string(),
1429       true, false, "UTF-8", Time(), Time());
1430   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1431       new TemplateURL::AssociatedExtensionInfo(
1432           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1"));
1433   extension_info->wants_to_be_default_engine = false;
1434   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1435   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1436
1437   ext_dse = CreateKeywordWithDate(
1438       model(), "ext2", "ext2", "http://www.ext2.com/s?q={searchTerms}",
1439       std::string(), std::string(), std::string(),
1440       true, true, "UTF-8", Time(), Time());
1441   extension_info.reset(new TemplateURL::AssociatedExtensionInfo(
1442       TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext2"));
1443   extension_info->wants_to_be_default_engine = true;
1444   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1445   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1446
1447   test_util()->ResetModel(true);
1448   user_dse = model()->GetTemplateURLForKeyword(ASCIIToUTF16("user"));
1449   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1450   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1451   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext2")));
1452 }
1453
1454 TEST_F(TemplateURLServiceTest, ExtensionEngineVsPolicy) {
1455   // Set a managed preference that establishes a default search provider.
1456   const char kName[] = "test";
1457   const char kKeyword[] = "test.com";
1458   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1459   const char kIconURL[] = "http://test.com/icon.jpg";
1460   const char kEncodings[] = "UTF-16;UTF-32";
1461   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1462   const char kSearchTermsReplacementKey[] = "espv";
1463   test_util()->SetManagedDefaultSearchPreferences(
1464       true, kName, kKeyword, kSearchURL, std::string(), kIconURL, kEncodings,
1465       kAlternateURL, kSearchTermsReplacementKey);
1466   test_util()->VerifyLoad();
1467   // Verify that the default manager we are getting is the managed one.
1468   TemplateURLData data;
1469   data.short_name = ASCIIToUTF16(kName);
1470   data.SetKeyword(ASCIIToUTF16(kKeyword));
1471   data.SetURL(kSearchURL);
1472   data.favicon_url = GURL(kIconURL);
1473   data.show_in_default_list = true;
1474   base::SplitString(kEncodings, ';', &data.input_encodings);
1475   data.alternate_urls.push_back(kAlternateURL);
1476   data.search_terms_replacement_key = kSearchTermsReplacementKey;
1477   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(data));
1478   EXPECT_TRUE(model()->is_default_search_managed());
1479   const TemplateURL* actual_managed_default =
1480       model()->GetDefaultSearchProvider();
1481   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
1482
1483   TemplateURL* ext_dse = CreateKeywordWithDate(
1484       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1485       std::string(), std::string(), std::string(),
1486       true, true, "UTF-8", Time(), Time());
1487   scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info(
1488       new TemplateURL::AssociatedExtensionInfo(
1489           TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1"));
1490   extension_info->wants_to_be_default_engine = true;
1491   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1492   EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1493   EXPECT_TRUE(model()->is_default_search_managed());
1494   actual_managed_default = model()->GetDefaultSearchProvider();
1495   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
1496 }