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