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.
5 #include "components/search_engines/template_url_service.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/task/cancelable_task_tracker.h"
17 #include "base/test/simple_test_clock.h"
18 #include "base/threading/thread.h"
19 #include "base/time/time.h"
20 #include "chrome/browser/history/history_service_factory.h"
21 #include "chrome/browser/search_engines/template_url_service_test_util.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/history/core/browser/history_service.h"
24 #include "components/search_engines/keyword_web_data_service.h"
25 #include "components/search_engines/search_host_to_urls_map.h"
26 #include "components/search_engines/search_terms_data.h"
27 #include "components/search_engines/template_url.h"
28 #include "components/search_engines/template_url_prepopulate_data.h"
29 #include "content/public/test/test_browser_thread_bundle.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 using base::ASCIIToUTF16
;
34 using base::TimeDelta
;
38 // QueryHistoryCallbackImpl ---------------------------------------------------
40 struct QueryHistoryCallbackImpl
{
41 QueryHistoryCallbackImpl() : success(false) {}
43 void Callback(bool success
,
44 const history::URLRow
& row
,
45 const history::VisitVector
& visits
) {
46 this->success
= success
;
49 this->visits
= visits
;
55 history::VisitVector visits
;
58 TemplateURL
* CreateKeywordWithDate(
59 TemplateURLService
* model
,
60 const std::string
& short_name
,
61 const std::string
& keyword
,
62 const std::string
& url
,
63 const std::string
& suggest_url
,
64 const std::string
& alternate_url
,
65 const std::string
& favicon_url
,
66 bool safe_for_autoreplace
,
67 bool show_in_default_list
,
68 const std::string
& encodings
,
72 data
.SetShortName(base::UTF8ToUTF16(short_name
));
73 data
.SetKeyword(base::UTF8ToUTF16(keyword
));
75 data
.suggestions_url
= suggest_url
;
76 if (!alternate_url
.empty())
77 data
.alternate_urls
.push_back(alternate_url
);
78 data
.favicon_url
= GURL(favicon_url
);
79 data
.safe_for_autoreplace
= safe_for_autoreplace
;
80 data
.show_in_default_list
= show_in_default_list
;
81 data
.input_encodings
= base::SplitString(
82 encodings
, ";", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
83 data
.date_created
= date_created
;
84 data
.last_modified
= last_modified
;
85 return new TemplateURL(data
);
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
,
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
);
104 EXPECT_NE(0, t_url
->id());
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());
129 // TemplateURLServiceTest -----------------------------------------------------
131 class TemplateURLServiceTest
: public testing::Test
{
133 TemplateURLServiceTest();
136 void SetUp() override
;
137 void TearDown() override
;
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
,
150 // Verifies the two TemplateURLs are equal.
151 void AssertEquals(const TemplateURL
& expected
, const TemplateURL
& actual
);
153 // Verifies the two timestamps are equal, within the expected degree of
155 void AssertTimesEqual(const base::Time
& expected
, const base::Time
& actual
);
157 // Create an URL that appears to have been prepopulated, but won't be in the
158 // current data. The caller owns the returned TemplateURL*.
159 TemplateURL
* CreatePreloadedTemplateURL(bool safe_for_autoreplace
,
162 // Helper methods to make calling TemplateURLServiceTestUtil methods less
163 // visually noisy in the test code.
164 void VerifyObserverCount(int expected_changed_count
);
165 void VerifyObserverFired();
166 TemplateURLServiceTestUtil
* test_util() { return test_util_
.get(); }
167 TemplateURLService
* model() { return test_util_
->model(); }
168 const SearchTermsData
& search_terms_data() {
169 return model()->search_terms_data();
173 content::TestBrowserThreadBundle thread_bundle_
; // To set up BrowserThreads.
174 scoped_ptr
<TemplateURLServiceTestUtil
> test_util_
;
176 DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest
);
179 class TemplateURLServiceWithoutFallbackTest
: public TemplateURLServiceTest
{
181 TemplateURLServiceWithoutFallbackTest() : TemplateURLServiceTest() {}
183 void SetUp() override
{
184 DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(true);
185 TemplateURLServiceTest::SetUp();
188 void TearDown() override
{
189 TemplateURLServiceTest::TearDown();
190 DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(false);
194 TemplateURLServiceTest::TemplateURLServiceTest() {
197 void TemplateURLServiceTest::SetUp() {
198 test_util_
.reset(new TemplateURLServiceTestUtil
);
201 void TemplateURLServiceTest::TearDown() {
205 TemplateURL
* TemplateURLServiceTest::AddKeywordWithDate(
206 const std::string
& short_name
,
207 const std::string
& keyword
,
208 const std::string
& url
,
209 const std::string
& suggest_url
,
210 const std::string
& alternate_url
,
211 const std::string
& favicon_url
,
212 bool safe_for_autoreplace
,
213 const std::string
& encodings
,
215 Time last_modified
) {
216 return ::AddKeywordWithDate(model(), short_name
, keyword
, url
, suggest_url
,
217 alternate_url
, favicon_url
, safe_for_autoreplace
,
218 encodings
, date_created
, last_modified
);
221 void TemplateURLServiceTest::AssertEquals(const TemplateURL
& expected
,
222 const TemplateURL
& actual
) {
223 ASSERT_EQ(expected
.short_name(), actual
.short_name());
224 ASSERT_EQ(expected
.keyword(), actual
.keyword());
225 ASSERT_EQ(expected
.url(), actual
.url());
226 ASSERT_EQ(expected
.suggestions_url(), actual
.suggestions_url());
227 ASSERT_EQ(expected
.favicon_url(), actual
.favicon_url());
228 ASSERT_EQ(expected
.alternate_urls(), actual
.alternate_urls());
229 ASSERT_EQ(expected
.show_in_default_list(), actual
.show_in_default_list());
230 ASSERT_EQ(expected
.safe_for_autoreplace(), actual
.safe_for_autoreplace());
231 ASSERT_EQ(expected
.input_encodings(), actual
.input_encodings());
232 ASSERT_EQ(expected
.id(), actual
.id());
233 ASSERT_EQ(expected
.date_created(), actual
.date_created());
234 AssertTimesEqual(expected
.last_modified(), actual
.last_modified());
235 ASSERT_EQ(expected
.sync_guid(), actual
.sync_guid());
236 ASSERT_EQ(expected
.search_terms_replacement_key(),
237 actual
.search_terms_replacement_key());
240 void TemplateURLServiceTest::AssertTimesEqual(const base::Time
& expected
,
241 const base::Time
& actual
) {
242 // Because times are stored with a granularity of one second, there is a loss
243 // of precision when serializing and deserializing the timestamps. Hence, only
244 // expect timestamps to be equal to within one second of one another.
245 ASSERT_LT((expected
- actual
).magnitude(), base::TimeDelta::FromSeconds(1));
248 TemplateURL
* TemplateURLServiceTest::CreatePreloadedTemplateURL(
249 bool safe_for_autoreplace
,
250 int prepopulate_id
) {
251 TemplateURLData data
;
252 data
.SetShortName(ASCIIToUTF16("unittest"));
253 data
.SetKeyword(ASCIIToUTF16("unittest"));
254 data
.SetURL("http://www.unittest.com/{searchTerms}");
255 data
.favicon_url
= GURL("http://favicon.url");
256 data
.show_in_default_list
= true;
257 data
.safe_for_autoreplace
= safe_for_autoreplace
;
258 data
.input_encodings
.push_back("UTF-8");
259 data
.date_created
= Time::FromTimeT(100);
260 data
.last_modified
= Time::FromTimeT(100);
261 data
.prepopulate_id
= prepopulate_id
;
262 return new TemplateURL(data
);
265 void TemplateURLServiceTest::VerifyObserverCount(int expected_changed_count
) {
266 EXPECT_EQ(expected_changed_count
, test_util_
->GetObserverCount());
267 test_util_
->ResetObserverCount();
270 void TemplateURLServiceTest::VerifyObserverFired() {
271 EXPECT_LE(1, test_util_
->GetObserverCount());
272 test_util_
->ResetObserverCount();
276 // Actual tests ---------------------------------------------------------------
278 TEST_F(TemplateURLServiceTest
, Load
) {
279 test_util()->VerifyLoad();
282 TEST_F(TemplateURLServiceTest
, AddUpdateRemove
) {
283 // Add a new TemplateURL.
284 test_util()->VerifyLoad();
285 const size_t initial_count
= model()->GetTemplateURLs().size();
287 TemplateURLData data
;
288 data
.SetShortName(ASCIIToUTF16("google"));
289 data
.SetKeyword(ASCIIToUTF16("keyword"));
290 data
.SetURL("http://www.google.com/foo/bar");
291 data
.favicon_url
= GURL("http://favicon.url");
292 data
.safe_for_autoreplace
= true;
293 data
.date_created
= Time::FromTimeT(100);
294 data
.last_modified
= Time::FromTimeT(100);
295 data
.sync_guid
= "00000000-0000-0000-0000-000000000001";
296 TemplateURL
* t_url
= new TemplateURL(data
);
298 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("keyword"),
300 VerifyObserverCount(1);
301 base::RunLoop().RunUntilIdle();
302 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
303 ASSERT_EQ(t_url
, model()->GetTemplateURLForKeyword(t_url
->keyword()));
304 // We need to make a second copy as the model takes ownership of |t_url| and
305 // will delete it. We have to do this after calling Add() since that gives
307 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
309 // Reload the model to verify it was actually saved to the database.
310 test_util()->ResetModel(true);
311 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
312 TemplateURL
* loaded_url
=
313 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
314 ASSERT_TRUE(loaded_url
!= NULL
);
315 AssertEquals(*cloned_url
, *loaded_url
);
316 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("keyword"),
319 // We expect the last_modified time to be updated to the present time on an
321 base::Time now
= base::Time::Now();
322 scoped_ptr
<base::SimpleTestClock
> clock(new base::SimpleTestClock
);
324 model()->set_clock(clock
.Pass());
326 // Mutate an element and verify it succeeded.
327 model()->ResetTemplateURL(loaded_url
, ASCIIToUTF16("a"), ASCIIToUTF16("b"),
329 ASSERT_EQ(ASCIIToUTF16("a"), loaded_url
->short_name());
330 ASSERT_EQ(ASCIIToUTF16("b"), loaded_url
->keyword());
331 ASSERT_EQ("c", loaded_url
->url());
332 ASSERT_FALSE(loaded_url
->safe_for_autoreplace());
333 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("keyword"),
335 ASSERT_FALSE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("b"), GURL(),
337 cloned_url
.reset(new TemplateURL(loaded_url
->data()));
338 base::RunLoop().RunUntilIdle();
339 test_util()->ResetModel(true);
340 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
341 loaded_url
= model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
342 ASSERT_TRUE(loaded_url
!= NULL
);
343 AssertEquals(*cloned_url
, *loaded_url
);
344 // We changed a TemplateURL in the service, so ensure that the time was
346 AssertTimesEqual(now
, loaded_url
->last_modified());
348 // Remove an element and verify it succeeded.
349 model()->Remove(loaded_url
);
350 VerifyObserverCount(1);
351 test_util()->ResetModel(true);
352 ASSERT_EQ(initial_count
, model()->GetTemplateURLs().size());
353 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL
);
356 TEST_F(TemplateURLServiceTest
, AddSameKeyword
) {
357 test_util()->VerifyLoad();
360 "first", "keyword", "http://test1", std::string(), std::string(),
361 std::string(), true, "UTF-8", Time(), Time());
362 VerifyObserverCount(1);
364 // Test what happens when we try to add a TemplateURL with the same keyword as
366 TemplateURLData data
;
367 data
.SetShortName(ASCIIToUTF16("second"));
368 data
.SetKeyword(ASCIIToUTF16("keyword"));
369 data
.SetURL("http://test2");
370 data
.safe_for_autoreplace
= false;
371 TemplateURL
* t_url
= new TemplateURL(data
);
374 // Because the old TemplateURL was replaceable and the new one wasn't, the new
375 // one should have replaced the old.
376 VerifyObserverCount(1);
377 EXPECT_EQ(t_url
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
378 EXPECT_EQ(ASCIIToUTF16("second"), t_url
->short_name());
379 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url
->keyword());
380 EXPECT_FALSE(t_url
->safe_for_autoreplace());
382 // Now try adding a replaceable TemplateURL. This should just delete the
384 data
.SetShortName(ASCIIToUTF16("third"));
385 data
.SetURL("http://test3");
386 data
.safe_for_autoreplace
= true;
387 model()->Add(new TemplateURL(data
));
388 VerifyObserverCount(0);
389 EXPECT_EQ(t_url
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
390 EXPECT_EQ(ASCIIToUTF16("second"), t_url
->short_name());
391 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url
->keyword());
392 EXPECT_FALSE(t_url
->safe_for_autoreplace());
394 // Now try adding a non-replaceable TemplateURL again. This should uniquify
395 // the existing entry's keyword.
396 data
.SetShortName(ASCIIToUTF16("fourth"));
397 data
.SetURL("http://test4");
398 data
.safe_for_autoreplace
= false;
399 TemplateURL
* t_url2
= new TemplateURL(data
);
400 model()->Add(t_url2
);
401 VerifyObserverCount(1);
402 EXPECT_EQ(t_url2
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
403 EXPECT_EQ(ASCIIToUTF16("fourth"), t_url2
->short_name());
404 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url2
->keyword());
405 EXPECT_EQ(ASCIIToUTF16("second"), t_url
->short_name());
406 EXPECT_EQ(ASCIIToUTF16("test2"), t_url
->keyword());
409 TEST_F(TemplateURLServiceTest
, AddExtensionKeyword
) {
410 test_util()->VerifyLoad();
413 "replaceable", "keyword1", "http://test1", std::string(), std::string(),
414 std::string(), true, "UTF-8", Time(), Time());
415 TemplateURL
* original2
= AddKeywordWithDate(
416 "nonreplaceable", "keyword2", "http://test2", std::string(),
417 std::string(), std::string(), false, "UTF-8", Time(), Time());
418 model()->RegisterOmniboxKeyword("test3", "extension", "keyword3",
420 TemplateURL
* original3
=
421 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3"));
422 ASSERT_TRUE(original3
);
424 // Extension keywords should override replaceable keywords.
425 model()->RegisterOmniboxKeyword("id1", "test", "keyword1", "http://test4");
426 TemplateURL
* extension1
= model()->FindTemplateURLForExtension(
427 "id1", TemplateURL::OMNIBOX_API_EXTENSION
);
428 EXPECT_TRUE(extension1
);
429 EXPECT_EQ(extension1
,
430 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
432 // They should not override non-replaceable keywords.
433 model()->RegisterOmniboxKeyword("id2", "test", "keyword2", "http://test5");
434 TemplateURL
* extension2
= model()->FindTemplateURLForExtension(
435 "id2", TemplateURL::OMNIBOX_API_EXTENSION
);
436 ASSERT_TRUE(extension2
);
438 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2")));
440 // They should override extension keywords added earlier.
441 model()->RegisterOmniboxKeyword("id3", "test", "keyword3", "http://test6");
442 TemplateURL
* extension3
= model()->FindTemplateURLForExtension(
443 "id3", TemplateURL::OMNIBOX_API_EXTENSION
);
444 ASSERT_TRUE(extension3
);
445 EXPECT_EQ(extension3
,
446 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3")));
449 TEST_F(TemplateURLServiceTest
, AddSameKeywordWithExtensionPresent
) {
450 test_util()->VerifyLoad();
452 // Similar to the AddSameKeyword test, but with an extension keyword masking a
453 // replaceable TemplateURL. We should still do correct conflict resolution
454 // between the non-template URLs.
455 model()->RegisterOmniboxKeyword("test2", "extension", "keyword",
457 TemplateURL
* extension
=
458 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
459 ASSERT_TRUE(extension
);
460 // Adding a keyword that matches the extension.
462 "replaceable", "keyword", "http://test1", std::string(), std::string(),
463 std::string(), true, "UTF-8", Time(), Time());
465 // Adding another replaceable keyword should remove the existing one, but
466 // leave the extension as is.
467 TemplateURLData data
;
468 data
.SetShortName(ASCIIToUTF16("name1"));
469 data
.SetKeyword(ASCIIToUTF16("keyword"));
470 data
.SetURL("http://test3");
471 data
.safe_for_autoreplace
= true;
472 TemplateURL
* t_url
= new TemplateURL(data
);
475 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
476 EXPECT_EQ(t_url
, model()->GetTemplateURLForHost("test3"));
478 // Adding a nonreplaceable keyword should remove the existing replaceable
479 // keyword and replace the extension as the associated URL for this keyword,
480 // but not evict the extension from the service entirely.
481 data
.SetShortName(ASCIIToUTF16("name2"));
482 data
.SetURL("http://test4");
483 data
.safe_for_autoreplace
= false;
484 TemplateURL
* t_url2
= new TemplateURL(data
);
485 model()->Add(t_url2
);
487 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
490 TEST_F(TemplateURLServiceTest
, NotPersistOmniboxExtensionKeyword
) {
491 test_util()->VerifyLoad();
493 // Register an omnibox keyword.
494 model()->RegisterOmniboxKeyword("test", "extension", "keyword",
495 "chrome-extension://test");
496 ASSERT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
499 test_util()->ResetModel(true);
501 // Ensure the omnibox keyword is not persisted.
502 ASSERT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
505 TEST_F(TemplateURLServiceTest
, ClearBrowsingData_Keywords
) {
506 Time now
= Time::Now();
507 TimeDelta one_day
= TimeDelta::FromDays(1);
508 Time month_ago
= now
- TimeDelta::FromDays(30);
510 // Nothing has been added.
511 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
513 // Create one with a 0 time.
514 AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
515 std::string(), "http://icon1", true, "UTF-8;UTF-16",
517 // Create one for now and +/- 1 day.
518 AddKeywordWithDate("name2", "key2", "http://foo2", "http://suggest2",
519 std::string(), "http://icon2", true, "UTF-8;UTF-16",
520 now
- one_day
, Time());
521 AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
522 std::string(), std::string(), true, std::string(), now
,
524 AddKeywordWithDate("name4", "key4", "http://foo4", std::string(),
525 std::string(), std::string(), true, std::string(),
526 now
+ one_day
, Time());
527 // Try the other three states.
528 AddKeywordWithDate("name5", "key5", "http://foo5", "http://suggest5",
529 std::string(), "http://icon5", false, "UTF-8;UTF-16", now
,
531 AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
532 std::string(), "http://icon6", false, "UTF-8;UTF-16",
535 // We just added a few items, validate them.
536 EXPECT_EQ(6U, model()->GetTemplateURLs().size());
538 // Try removing from current timestamp. This should delete the one in the
539 // future and one very recent one.
540 model()->RemoveAutoGeneratedSince(now
);
541 EXPECT_EQ(4U, model()->GetTemplateURLs().size());
543 // Try removing from two months ago. This should only delete items that are
545 model()->RemoveAutoGeneratedBetween(now
- TimeDelta::FromDays(60), now
);
546 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
548 // Make sure the right values remain.
549 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
550 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
552 model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
554 EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
555 EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
556 EXPECT_EQ(now
.ToInternalValue(),
557 model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
559 EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
560 EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
561 EXPECT_EQ(month_ago
.ToInternalValue(),
562 model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
564 // Try removing from Time=0. This should delete one more.
565 model()->RemoveAutoGeneratedSince(Time());
566 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
569 TEST_F(TemplateURLServiceTest
, ClearBrowsingData_KeywordsForOrigin
) {
570 Time now
= Time::Now();
571 TimeDelta one_day
= TimeDelta::FromDays(1);
572 Time month_ago
= now
- TimeDelta::FromDays(30);
574 // Nothing has been added.
575 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
577 // Create one for now and +/- 1 day.
578 AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
579 std::string(), "http://icon2", true, "UTF-8;UTF-16",
580 now
- one_day
, Time());
581 AddKeywordWithDate("name2", "key2", "http://foo2", std::string(),
582 std::string(), std::string(), true, std::string(), now
,
584 AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
585 std::string(), std::string(), true, std::string(),
586 now
+ one_day
, Time());
588 // We just added a few items, validate them.
589 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
591 // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
592 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago
,
594 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
595 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
596 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
597 EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
598 EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
600 // Try removing foo1, but outside the range in which it was modified. It
601 // should remain untouched.
602 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo1"), now
,
604 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
605 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
606 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
607 EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
608 EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
611 // Try removing foo3. This should delete foo3, but leave foo1 untouched.
612 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo3"), month_ago
,
613 now
+ one_day
+ one_day
);
614 EXPECT_EQ(1U, model()->GetTemplateURLs().size());
615 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
616 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
619 TEST_F(TemplateURLServiceTest
, Reset
) {
620 // Add a new TemplateURL.
621 test_util()->VerifyLoad();
622 const size_t initial_count
= model()->GetTemplateURLs().size();
623 TemplateURLData data
;
624 data
.SetShortName(ASCIIToUTF16("google"));
625 data
.SetKeyword(ASCIIToUTF16("keyword"));
626 data
.SetURL("http://www.google.com/foo/bar");
627 data
.favicon_url
= GURL("http://favicon.url");
628 data
.date_created
= Time::FromTimeT(100);
629 data
.last_modified
= Time::FromTimeT(100);
630 TemplateURL
* t_url
= new TemplateURL(data
);
633 VerifyObserverCount(1);
634 base::RunLoop().RunUntilIdle();
636 base::Time now
= base::Time::Now();
637 scoped_ptr
<base::SimpleTestClock
> clock(new base::SimpleTestClock
);
639 model()->set_clock(clock
.Pass());
641 // Reset the short name, keyword, url and make sure it takes.
642 const base::string16
new_short_name(ASCIIToUTF16("a"));
643 const base::string16
new_keyword(ASCIIToUTF16("b"));
644 const std::string
new_url("c");
645 model()->ResetTemplateURL(t_url
, new_short_name
, new_keyword
, new_url
);
646 ASSERT_EQ(new_short_name
, t_url
->short_name());
647 ASSERT_EQ(new_keyword
, t_url
->keyword());
648 ASSERT_EQ(new_url
, t_url
->url());
650 // Make sure the mappings in the model were updated.
651 ASSERT_EQ(t_url
, model()->GetTemplateURLForKeyword(new_keyword
));
653 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL
);
655 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
657 // Reload the model from the database and make sure the change took.
658 test_util()->ResetModel(true);
659 EXPECT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
660 const TemplateURL
* read_url
= model()->GetTemplateURLForKeyword(new_keyword
);
661 ASSERT_TRUE(read_url
);
662 AssertEquals(*cloned_url
, *read_url
);
663 AssertTimesEqual(now
, read_url
->last_modified());
666 TEST_F(TemplateURLServiceTest
, DefaultSearchProvider
) {
667 // Add a new TemplateURL.
668 test_util()->VerifyLoad();
669 const size_t initial_count
= model()->GetTemplateURLs().size();
670 TemplateURL
* t_url
= AddKeywordWithDate(
671 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
672 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
673 test_util()->ResetObserverCount();
675 model()->SetUserSelectedDefaultSearchProvider(t_url
);
676 ASSERT_EQ(t_url
, model()->GetDefaultSearchProvider());
677 ASSERT_TRUE(t_url
->safe_for_autoreplace());
678 ASSERT_TRUE(t_url
->show_in_default_list());
680 // Setting the default search provider should have caused notification.
681 VerifyObserverCount(1);
682 base::RunLoop().RunUntilIdle();
684 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
686 // Make sure when we reload we get a default search provider.
687 test_util()->ResetModel(true);
688 EXPECT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
689 ASSERT_TRUE(model()->GetDefaultSearchProvider());
690 AssertEquals(*cloned_url
, *model()->GetDefaultSearchProvider());
693 TEST_F(TemplateURLServiceTest
, CantReplaceWithSameKeyword
) {
694 test_util()->ChangeModelToLoadState();
695 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("foo"), GURL(),
697 TemplateURL
* t_url
= AddKeywordWithDate(
698 "name1", "foo", "http://foo1", "http://sugg1", std::string(),
699 "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
701 // Can still replace, newly added template url is marked safe to replace.
702 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("foo"),
703 GURL("http://foo2"), NULL
));
705 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
706 // no longer be replaceable.
707 model()->ResetTemplateURL(t_url
, t_url
->short_name(), t_url
->keyword(),
710 ASSERT_FALSE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("foo"),
711 GURL("http://foo2"), NULL
));
714 TEST_F(TemplateURLServiceTest
, CantReplaceWithSameHosts
) {
715 test_util()->ChangeModelToLoadState();
716 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("foo"),
717 GURL("http://foo.com"), NULL
));
718 TemplateURL
* t_url
= AddKeywordWithDate(
719 "name1", "foo", "http://foo.com", "http://sugg1", std::string(),
720 "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
722 // Can still replace, newly added template url is marked safe to replace.
723 ASSERT_TRUE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("bar"),
724 GURL("http://foo.com"), NULL
));
726 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
727 // no longer be replaceable.
728 model()->ResetTemplateURL(t_url
, t_url
->short_name(), t_url
->keyword(),
731 ASSERT_FALSE(model()->CanAddAutogeneratedKeyword(ASCIIToUTF16("bar"),
732 GURL("http://foo.com"), NULL
));
735 TEST_F(TemplateURLServiceTest
, HasDefaultSearchProvider
) {
736 // We should have a default search provider even if we haven't loaded.
737 ASSERT_TRUE(model()->GetDefaultSearchProvider());
739 // Now force the model to load and make sure we still have a default.
740 test_util()->VerifyLoad();
742 ASSERT_TRUE(model()->GetDefaultSearchProvider());
745 TEST_F(TemplateURLServiceTest
, DefaultSearchProviderLoadedFromPrefs
) {
746 test_util()->VerifyLoad();
748 TemplateURLData data
;
749 data
.SetShortName(ASCIIToUTF16("a"));
750 data
.safe_for_autoreplace
= true;
751 data
.SetURL("http://url/{searchTerms}");
752 data
.suggestions_url
= "http://url2";
753 data
.instant_url
= "http://instant";
754 data
.date_created
= Time::FromTimeT(100);
755 data
.last_modified
= Time::FromTimeT(100);
756 TemplateURL
* t_url
= new TemplateURL(data
);
758 const TemplateURLID id
= t_url
->id();
760 model()->SetUserSelectedDefaultSearchProvider(t_url
);
761 base::RunLoop().RunUntilIdle();
762 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
764 // Reset the model and don't load it. The template url we set as the default
765 // should be pulled from prefs now.
766 test_util()->ResetModel(false);
768 // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
769 // value are persisted to prefs.
770 const TemplateURL
* default_turl
= model()->GetDefaultSearchProvider();
771 ASSERT_TRUE(default_turl
);
772 EXPECT_EQ(ASCIIToUTF16("a"), default_turl
->short_name());
773 EXPECT_EQ("http://url/{searchTerms}", default_turl
->url());
774 EXPECT_EQ("http://url2", default_turl
->suggestions_url());
775 EXPECT_EQ("http://instant", default_turl
->instant_url());
776 EXPECT_EQ(id
, default_turl
->id());
778 // Now do a load and make sure the default search provider really takes.
779 test_util()->VerifyLoad();
781 ASSERT_TRUE(model()->GetDefaultSearchProvider());
782 AssertEquals(*cloned_url
, *model()->GetDefaultSearchProvider());
785 TEST_F(TemplateURLServiceTest
, RepairPrepopulatedSearchEngines
) {
786 test_util()->VerifyLoad();
788 // Edit Google search engine.
789 TemplateURL
* google
= model()->GetTemplateURLForKeyword(
790 ASCIIToUTF16("google.com"));
792 model()->ResetTemplateURL(google
, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"),
793 "http://www.foo.com/s?q={searchTerms}");
794 EXPECT_EQ(ASCIIToUTF16("trash"), google
->short_name());
795 EXPECT_EQ(ASCIIToUTF16("xxx"), google
->keyword());
797 // Add third-party default search engine.
798 TemplateURL
* user_dse
= AddKeywordWithDate(
799 "malware", "google.com", "http://www.goo.com/s?q={searchTerms}",
800 std::string(), std::string(), std::string(),
801 true, "UTF-8", Time(), Time());
802 model()->SetUserSelectedDefaultSearchProvider(user_dse
);
803 EXPECT_EQ(user_dse
, model()->GetDefaultSearchProvider());
806 TemplateURL
* bing
= model()->GetTemplateURLForKeyword(
807 ASCIIToUTF16("bing.com"));
809 model()->Remove(bing
);
810 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
812 // Register an extension with bing keyword.
813 model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com",
815 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
817 model()->RepairPrepopulatedSearchEngines();
819 // Google is default.
820 ASSERT_EQ(google
, model()->GetDefaultSearchProvider());
821 // The keyword wasn't reverted.
822 EXPECT_EQ(ASCIIToUTF16("trash"), google
->short_name());
823 EXPECT_EQ("www.google.com",
824 google
->GenerateSearchURL(model()->search_terms_data()).host());
826 // Bing was repaired.
827 bing
= model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
829 EXPECT_EQ(TemplateURL::NORMAL
, bing
->GetType());
831 // User search engine is preserved.
832 EXPECT_EQ(user_dse
, model()->GetTemplateURLForHost("www.goo.com"));
833 EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse
->keyword());
836 TEST_F(TemplateURLServiceTest
, RepairSearchEnginesWithManagedDefault
) {
837 // Set a managed preference that establishes a default search provider.
838 const char kName
[] = "test1";
839 const char kKeyword
[] = "test.com";
840 const char kSearchURL
[] = "http://test.com/search?t={searchTerms}";
841 const char kIconURL
[] = "http://test.com/icon.jpg";
842 const char kEncodings
[] = "UTF-16;UTF-32";
843 const char kAlternateURL
[] = "http://test.com/search#t={searchTerms}";
844 const char kSearchTermsReplacementKey
[] = "espv";
845 test_util()->SetManagedDefaultSearchPreferences(true, kName
, kKeyword
,
846 kSearchURL
, std::string(),
847 kIconURL
, kEncodings
,
849 kSearchTermsReplacementKey
);
850 test_util()->VerifyLoad();
851 // Verify that the default manager we are getting is the managed one.
852 TemplateURLData data
;
853 data
.SetShortName(ASCIIToUTF16(kName
));
854 data
.SetKeyword(ASCIIToUTF16(kKeyword
));
855 data
.SetURL(kSearchURL
);
856 data
.favicon_url
= GURL(kIconURL
);
857 data
.show_in_default_list
= true;
858 data
.input_encodings
= base::SplitString(
859 kEncodings
, ";", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
860 data
.alternate_urls
.push_back(kAlternateURL
);
861 data
.search_terms_replacement_key
= kSearchTermsReplacementKey
;
862 scoped_ptr
<TemplateURL
> expected_managed_default(new TemplateURL(data
));
863 EXPECT_TRUE(model()->is_default_search_managed());
864 const TemplateURL
* actual_managed_default
=
865 model()->GetDefaultSearchProvider();
866 ExpectSimilar(expected_managed_default
.get(), actual_managed_default
);
868 // The following call has no effect on the managed search engine.
869 model()->RepairPrepopulatedSearchEngines();
871 EXPECT_TRUE(model()->is_default_search_managed());
872 actual_managed_default
= model()->GetDefaultSearchProvider();
873 ExpectSimilar(expected_managed_default
.get(), actual_managed_default
);
876 TEST_F(TemplateURLServiceTest
, UpdateKeywordSearchTermsForURL
) {
878 const std::string url
;
879 const base::string16 term
;
881 { "http://foo/", base::string16() },
882 { "http://foo/foo?q=xx", base::string16() },
883 { "http://x/bar?q=xx", base::string16() },
884 { "http://x/foo?y=xx", base::string16() },
885 { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
886 { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
887 { "http://x/foo?q=b&q=xx", base::string16() },
888 { "http://x/foo#query=xx", ASCIIToUTF16("xx") },
889 { "http://x/foo?q=b#query=xx", ASCIIToUTF16("xx") },
890 { "http://x/foo?q=b#q=xx", ASCIIToUTF16("b") },
891 { "http://x/foo?query=b#q=xx", base::string16() },
894 test_util()->ChangeModelToLoadState();
895 AddKeywordWithDate("name", "x", "http://x/foo?q={searchTerms}",
896 "http://sugg1", "http://x/foo#query={searchTerms}",
897 "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
899 for (size_t i
= 0; i
< arraysize(data
); ++i
) {
900 TemplateURLService::URLVisitedDetails details
= {
901 GURL(data
[i
].url
), false
903 model()->UpdateKeywordSearchTermsForURL(details
);
904 EXPECT_EQ(data
[i
].term
, test_util()->GetAndClearSearchTerm());
908 TEST_F(TemplateURLServiceTest
, DontUpdateKeywordSearchForNonReplaceable
) {
910 const std::string url
;
913 { "http://x/bar?q=xx" },
914 { "http://x/foo?y=xx" },
917 test_util()->ChangeModelToLoadState();
918 AddKeywordWithDate("name", "x", "http://x/foo", "http://sugg1", std::string(),
919 "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
921 for (size_t i
= 0; i
< arraysize(data
); ++i
) {
922 TemplateURLService::URLVisitedDetails details
= {
923 GURL(data
[i
].url
), false
925 model()->UpdateKeywordSearchTermsForURL(details
);
926 ASSERT_EQ(base::string16(), test_util()->GetAndClearSearchTerm());
930 TEST_F(TemplateURLServiceWithoutFallbackTest
, ChangeGoogleBaseValue
) {
931 // NOTE: Do not load the prepopulate data, which also has a {google:baseURL}
932 // keyword in it and would confuse this test.
933 test_util()->ChangeModelToLoadState();
935 test_util()->SetGoogleBaseURL(GURL("http://google.com/"));
936 const TemplateURL
* t_url
= AddKeywordWithDate(
937 "name", "google.com", "{google:baseURL}?q={searchTerms}", "http://sugg1",
938 std::string(), "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
939 ASSERT_EQ(t_url
, model()->GetTemplateURLForHost("google.com"));
940 EXPECT_EQ("google.com", t_url
->url_ref().GetHost(search_terms_data()));
941 EXPECT_EQ(ASCIIToUTF16("google.com"), t_url
->keyword());
943 // Change the Google base url.
944 test_util()->ResetObserverCount();
945 test_util()->SetGoogleBaseURL(GURL("http://google.co.uk/"));
946 VerifyObserverCount(1);
948 // Make sure the host->TemplateURL map was updated appropriately.
949 ASSERT_EQ(t_url
, model()->GetTemplateURLForHost("google.co.uk"));
950 EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL
);
951 EXPECT_EQ("google.co.uk", t_url
->url_ref().GetHost(search_terms_data()));
952 EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url
->keyword());
953 EXPECT_EQ("http://google.co.uk/?q=x", t_url
->url_ref().ReplaceSearchTerms(
954 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x")), search_terms_data()));
956 // Now add a manual entry and then change the Google base URL such that the
957 // autogenerated Google search keyword would conflict.
958 TemplateURL
* manual
= AddKeywordWithDate(
959 "manual", "google.de", "http://google.de/search?q={searchTerms}",
960 std::string(), std::string(), std::string(), false, "UTF-8", Time(),
962 test_util()->SetGoogleBaseURL(GURL("http://google.de"));
964 // Verify that the manual entry is untouched, and the autogenerated keyword
967 model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
968 EXPECT_EQ("google.de", manual
->url_ref().GetHost(search_terms_data()));
970 model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.co.uk")));
971 EXPECT_EQ("google.de", t_url
->url_ref().GetHost(search_terms_data()));
972 EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url
->keyword());
974 // Change the base URL again and verify that the autogenerated keyword follows
975 // even though it didn't match the base URL, while the manual entry is still
977 test_util()->SetGoogleBaseURL(GURL("http://google.fr/"));
978 ASSERT_EQ(manual
, model()->GetTemplateURLForHost("google.de"));
979 EXPECT_EQ("google.de", manual
->url_ref().GetHost(search_terms_data()));
980 EXPECT_EQ(ASCIIToUTF16("google.de"), manual
->keyword());
981 ASSERT_EQ(t_url
, model()->GetTemplateURLForHost("google.fr"));
982 EXPECT_TRUE(model()->GetTemplateURLForHost("google.co.uk") == NULL
);
983 EXPECT_EQ("google.fr", t_url
->url_ref().GetHost(search_terms_data()));
984 EXPECT_EQ(ASCIIToUTF16("google.fr"), t_url
->keyword());
987 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
989 TEST_F(TemplateURLServiceTest
, GenerateVisitOnKeyword
) {
990 test_util()->profile()->CreateBookmarkModel(false);
991 ASSERT_TRUE(test_util()->profile()->CreateHistoryService(true, false));
992 test_util()->ResetModel(true);
995 TemplateURL
* t_url
= AddKeywordWithDate(
996 "keyword", "keyword", "http://foo.com/foo?query={searchTerms}",
997 "http://sugg1", std::string(), "http://icon1", true, "UTF-8;UTF-16",
998 base::Time::Now(), base::Time::Now());
1000 // Add a visit that matches the url of the keyword.
1001 history::HistoryService
* history
= HistoryServiceFactory::GetForProfile(
1002 test_util()->profile(), ServiceAccessType::EXPLICIT_ACCESS
);
1004 GURL(t_url
->url_ref().ReplaceSearchTerms(
1005 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah")),
1006 search_terms_data())),
1007 base::Time::Now(), NULL
, 0, GURL(), history::RedirectList(),
1008 ui::PAGE_TRANSITION_KEYWORD
, history::SOURCE_BROWSED
, false);
1010 // Wait for history to finish processing the request.
1011 test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
1013 // Query history for the generated url.
1014 base::CancelableTaskTracker tracker
;
1015 QueryHistoryCallbackImpl callback
;
1016 history
->QueryURL(GURL("http://keyword"),
1018 base::Bind(&QueryHistoryCallbackImpl::Callback
,
1019 base::Unretained(&callback
)),
1022 // Wait for the request to be processed.
1023 test_util()->profile()->BlockUntilHistoryProcessesPendingRequests();
1025 // And make sure the url and visit were added.
1026 EXPECT_TRUE(callback
.success
);
1027 EXPECT_NE(0, callback
.row
.id());
1028 ASSERT_EQ(1U, callback
.visits
.size());
1029 EXPECT_EQ(ui::PAGE_TRANSITION_KEYWORD_GENERATED
,
1030 ui::PageTransitionStripQualifier(callback
.visits
[0].transition
));
1033 // Make sure that the load routine deletes prepopulated engines that no longer
1034 // exist in the prepopulate data.
1035 TEST_F(TemplateURLServiceTest
, LoadDeletesUnusedProvider
) {
1036 // Create a preloaded template url. Add it to a loaded model and wait for the
1038 TemplateURL
* t_url
= CreatePreloadedTemplateURL(true, 999999);
1039 test_util()->ChangeModelToLoadState();
1040 model()->Add(t_url
);
1042 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL
);
1043 base::RunLoop().RunUntilIdle();
1045 // Ensure that merging clears this engine.
1046 test_util()->ResetModel(true);
1048 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL
);
1050 // Wait for any saves to finish.
1051 base::RunLoop().RunUntilIdle();
1053 // Reload the model to verify that the database was updated as a result of the
1055 test_util()->ResetModel(true);
1057 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL
);
1060 // Make sure that load routine doesn't delete prepopulated engines that no
1061 // longer exist in the prepopulate data if it has been modified by the user.
1062 TEST_F(TemplateURLServiceTest
, LoadRetainsModifiedProvider
) {
1063 // Create a preloaded template url and add it to a loaded model.
1064 TemplateURL
* t_url
= CreatePreloadedTemplateURL(false, 999999);
1065 test_util()->ChangeModelToLoadState();
1066 model()->Add(t_url
);
1068 // Do the copy after t_url is added so that the id is set.
1069 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
1070 ASSERT_EQ(t_url
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1072 // Wait for any saves to finish.
1073 base::RunLoop().RunUntilIdle();
1075 // Ensure that merging won't clear it if the user has edited it.
1076 test_util()->ResetModel(true);
1077 const TemplateURL
* url_for_unittest
=
1078 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1079 ASSERT_TRUE(url_for_unittest
!= NULL
);
1080 AssertEquals(*cloned_url
, *url_for_unittest
);
1082 // Wait for any saves to finish.
1083 base::RunLoop().RunUntilIdle();
1085 // Reload the model to verify that save/reload retains the item.
1086 test_util()->ResetModel(true);
1088 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL
);
1091 // Make sure that load routine doesn't delete
1092 // prepopulated engines that no longer exist in the prepopulate data if
1093 // it has been modified by the user.
1094 TEST_F(TemplateURLServiceTest
, LoadSavesPrepopulatedDefaultSearchProvider
) {
1095 test_util()->VerifyLoad();
1096 // Verify that the default search provider is set to something.
1097 TemplateURL
* default_search
= model()->GetDefaultSearchProvider();
1098 ASSERT_TRUE(default_search
!= NULL
);
1099 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(default_search
->data()));
1101 // Wait for any saves to finish.
1102 base::RunLoop().RunUntilIdle();
1104 // Reload the model and check that the default search provider
1105 // was properly saved.
1106 test_util()->ResetModel(true);
1107 default_search
= model()->GetDefaultSearchProvider();
1108 ASSERT_TRUE(default_search
!= NULL
);
1109 AssertEquals(*cloned_url
, *default_search
);
1112 // Make sure that the load routine doesn't delete
1113 // prepopulated engines that no longer exist in the prepopulate data if
1114 // it is the default search provider.
1115 TEST_F(TemplateURLServiceTest
, LoadRetainsDefaultProvider
) {
1116 // Set the default search provider to a preloaded template url which
1117 // is not in the current set of preloaded template urls and save
1119 TemplateURL
* t_url
= CreatePreloadedTemplateURL(true, 999999);
1120 test_util()->ChangeModelToLoadState();
1121 model()->Add(t_url
);
1122 model()->SetUserSelectedDefaultSearchProvider(t_url
);
1123 // Do the copy after t_url is added and set as default so that its
1124 // internal state is correct.
1125 scoped_ptr
<TemplateURL
> cloned_url(new TemplateURL(t_url
->data()));
1127 ASSERT_EQ(t_url
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1128 ASSERT_EQ(t_url
, model()->GetDefaultSearchProvider());
1129 base::RunLoop().RunUntilIdle();
1131 // Ensure that merging won't clear the prepopulated template url
1132 // which is no longer present if it's the default engine.
1133 test_util()->ResetModel(true);
1135 const TemplateURL
* keyword_url
=
1136 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1137 ASSERT_TRUE(keyword_url
!= NULL
);
1138 AssertEquals(*cloned_url
, *keyword_url
);
1139 ASSERT_EQ(keyword_url
, model()->GetDefaultSearchProvider());
1142 // Wait for any saves to finish.
1143 base::RunLoop().RunUntilIdle();
1145 // Reload the model to verify that the update was saved.
1146 test_util()->ResetModel(true);
1148 const TemplateURL
* keyword_url
=
1149 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1150 ASSERT_TRUE(keyword_url
!= NULL
);
1151 AssertEquals(*cloned_url
, *keyword_url
);
1152 ASSERT_EQ(keyword_url
, model()->GetDefaultSearchProvider());
1156 // Make sure that the load routine sets a default search provider if it was
1157 // missing and not managed.
1158 TEST_F(TemplateURLServiceTest
, LoadEnsuresDefaultSearchProviderExists
) {
1159 // Force the model to load and make sure we have a default search provider.
1160 test_util()->VerifyLoad();
1161 EXPECT_TRUE(model()->GetDefaultSearchProvider());
1163 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1164 search_terms_data()));
1166 // Make default search provider unusable (no search terms).
1167 model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
1168 ASCIIToUTF16("test"), ASCIIToUTF16("test"),
1169 "http://example.com/");
1170 base::RunLoop().RunUntilIdle();
1172 // Reset the model and load it. There should be a usable default search
1174 test_util()->ResetModel(true);
1176 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1177 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement(
1178 search_terms_data()));
1181 // Simulates failing to load the webdb and makes sure the default search
1182 // provider is valid.
1183 TEST_F(TemplateURLServiceTest
, FailedInit
) {
1184 test_util()->VerifyLoad();
1186 test_util()->ClearModel();
1187 test_util()->web_data_service()->ShutdownDatabase();
1189 test_util()->ResetModel(false);
1191 base::RunLoop().RunUntilIdle();
1193 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1196 // Verifies that if the default search URL preference is managed, we report
1197 // the default search as managed. Also check that we are getting the right
1199 TEST_F(TemplateURLServiceTest
, TestManagedDefaultSearch
) {
1200 test_util()->VerifyLoad();
1201 const size_t initial_count
= model()->GetTemplateURLs().size();
1202 test_util()->ResetObserverCount();
1204 // Set a regular default search provider.
1205 TemplateURL
* regular_default
= AddKeywordWithDate(
1206 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
1207 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
1208 VerifyObserverCount(1);
1209 model()->SetUserSelectedDefaultSearchProvider(regular_default
);
1210 // Adding the URL and setting the default search provider should have caused
1212 VerifyObserverCount(1);
1213 EXPECT_FALSE(model()->is_default_search_managed());
1214 EXPECT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1216 // Set a managed preference that establishes a default search provider.
1217 const char kName
[] = "test1";
1218 const char kKeyword
[] = "test.com";
1219 const char kSearchURL
[] = "http://test.com/search?t={searchTerms}";
1220 const char kIconURL
[] = "http://test.com/icon.jpg";
1221 const char kEncodings
[] = "UTF-16;UTF-32";
1222 const char kAlternateURL
[] = "http://test.com/search#t={searchTerms}";
1223 const char kSearchTermsReplacementKey
[] = "espv";
1224 test_util()->SetManagedDefaultSearchPreferences(true, kName
, kKeyword
,
1225 kSearchURL
, std::string(), kIconURL
, kEncodings
, kAlternateURL
,
1226 kSearchTermsReplacementKey
);
1227 VerifyObserverFired();
1228 EXPECT_TRUE(model()->is_default_search_managed());
1229 EXPECT_EQ(initial_count
+ 2, model()->GetTemplateURLs().size());
1231 // Verify that the default manager we are getting is the managed one.
1232 TemplateURLData data
;
1233 data
.SetShortName(ASCIIToUTF16(kName
));
1234 data
.SetKeyword(ASCIIToUTF16(kKeyword
));
1235 data
.SetURL(kSearchURL
);
1236 data
.favicon_url
= GURL(kIconURL
);
1237 data
.show_in_default_list
= true;
1238 data
.input_encodings
= base::SplitString(
1239 kEncodings
, ";", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
1240 data
.alternate_urls
.push_back(kAlternateURL
);
1241 data
.search_terms_replacement_key
= kSearchTermsReplacementKey
;
1242 scoped_ptr
<TemplateURL
> expected_managed_default1(new TemplateURL(data
));
1243 const TemplateURL
* actual_managed_default
=
1244 model()->GetDefaultSearchProvider();
1245 ExpectSimilar(expected_managed_default1
.get(), actual_managed_default
);
1246 EXPECT_TRUE(actual_managed_default
->show_in_default_list());
1248 // Update the managed preference and check that the model has changed.
1249 const char kNewName
[] = "test2";
1250 const char kNewKeyword
[] = "other.com";
1251 const char kNewSearchURL
[] = "http://other.com/search?t={searchTerms}";
1252 const char kNewSuggestURL
[] = "http://other.com/suggest?t={searchTerms}";
1253 test_util()->SetManagedDefaultSearchPreferences(true, kNewName
, kNewKeyword
,
1254 kNewSearchURL
, kNewSuggestURL
, std::string(), std::string(),
1255 std::string(), std::string());
1256 VerifyObserverFired();
1257 EXPECT_TRUE(model()->is_default_search_managed());
1258 EXPECT_EQ(initial_count
+ 2, model()->GetTemplateURLs().size());
1260 // Verify that the default manager we are now getting is the correct one.
1261 TemplateURLData data2
;
1262 data2
.SetShortName(ASCIIToUTF16(kNewName
));
1263 data2
.SetKeyword(ASCIIToUTF16(kNewKeyword
));
1264 data2
.SetURL(kNewSearchURL
);
1265 data2
.suggestions_url
= kNewSuggestURL
;
1266 data2
.show_in_default_list
= true;
1267 scoped_ptr
<TemplateURL
> expected_managed_default2(new TemplateURL(data2
));
1268 actual_managed_default
= model()->GetDefaultSearchProvider();
1269 ExpectSimilar(expected_managed_default2
.get(), actual_managed_default
);
1270 EXPECT_EQ(actual_managed_default
->show_in_default_list(), true);
1272 // Remove all the managed prefs and check that we are no longer managed.
1273 test_util()->RemoveManagedDefaultSearchPreferences();
1274 VerifyObserverFired();
1275 EXPECT_FALSE(model()->is_default_search_managed());
1276 EXPECT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1278 // The default should now be the user preference.
1279 const TemplateURL
* actual_final_managed_default
=
1280 model()->GetDefaultSearchProvider();
1281 ExpectSimilar(regular_default
, actual_final_managed_default
);
1282 EXPECT_EQ(actual_final_managed_default
->show_in_default_list(), true);
1284 // Disable the default search provider through policy.
1285 test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1286 std::string(), std::string(), std::string(), std::string(),
1287 std::string(), std::string(), std::string());
1288 VerifyObserverFired();
1289 EXPECT_TRUE(model()->is_default_search_managed());
1290 EXPECT_TRUE(NULL
== model()->GetDefaultSearchProvider());
1291 EXPECT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1294 test_util()->SetManagedDefaultSearchPreferences(true, kName
, kKeyword
,
1295 kSearchURL
, std::string(), kIconURL
, kEncodings
, kAlternateURL
,
1296 kSearchTermsReplacementKey
);
1297 VerifyObserverFired();
1298 EXPECT_TRUE(model()->is_default_search_managed());
1299 EXPECT_EQ(initial_count
+ 2, model()->GetTemplateURLs().size());
1301 // Verify that the default manager we are getting is the managed one.
1302 actual_managed_default
= model()->GetDefaultSearchProvider();
1303 ExpectSimilar(expected_managed_default1
.get(), actual_managed_default
);
1304 EXPECT_EQ(actual_managed_default
->show_in_default_list(), true);
1306 // Clear the model and disable the default search provider through policy.
1307 // Verify that there is no default search provider after loading the model.
1308 // This checks against regressions of http://crbug.com/67180
1310 // First, remove the preferences, reset the model, and set a default.
1311 test_util()->RemoveManagedDefaultSearchPreferences();
1312 test_util()->ResetModel(true);
1313 TemplateURL
* new_default
=
1314 model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1"));
1315 ASSERT_FALSE(new_default
== NULL
);
1316 model()->SetUserSelectedDefaultSearchProvider(new_default
);
1317 EXPECT_EQ(new_default
, model()->GetDefaultSearchProvider());
1319 // Now reset the model again but load it after setting the preferences.
1320 test_util()->ResetModel(false);
1321 test_util()->SetManagedDefaultSearchPreferences(false, std::string(),
1322 std::string(), std::string(), std::string(), std::string(),
1323 std::string(), std::string(), std::string());
1324 test_util()->VerifyLoad();
1325 EXPECT_TRUE(model()->is_default_search_managed());
1326 EXPECT_TRUE(model()->GetDefaultSearchProvider() == NULL
);
1329 // Test that if we load a TemplateURL with an empty GUID, the load process
1330 // assigns it a newly generated GUID.
1331 TEST_F(TemplateURLServiceTest
, PatchEmptySyncGUID
) {
1332 // Add a new TemplateURL.
1333 test_util()->VerifyLoad();
1334 const size_t initial_count
= model()->GetTemplateURLs().size();
1336 TemplateURLData data
;
1337 data
.SetShortName(ASCIIToUTF16("google"));
1338 data
.SetKeyword(ASCIIToUTF16("keyword"));
1339 data
.SetURL("http://www.google.com/foo/bar");
1340 data
.sync_guid
.clear();
1341 TemplateURL
* t_url
= new TemplateURL(data
);
1342 model()->Add(t_url
);
1344 VerifyObserverCount(1);
1345 base::RunLoop().RunUntilIdle();
1346 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1348 // Reload the model to verify it was actually saved to the database and
1349 // assigned a new GUID when brought back.
1350 test_util()->ResetModel(true);
1351 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1352 const TemplateURL
* loaded_url
=
1353 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1354 ASSERT_FALSE(loaded_url
== NULL
);
1355 ASSERT_FALSE(loaded_url
->sync_guid().empty());
1358 // Test that if we load a TemplateURL with duplicate input encodings, the load
1359 // process de-dupes them.
1360 TEST_F(TemplateURLServiceTest
, DuplicateInputEncodings
) {
1361 // Add a new TemplateURL.
1362 test_util()->VerifyLoad();
1363 const size_t initial_count
= model()->GetTemplateURLs().size();
1365 TemplateURLData data
;
1366 data
.SetShortName(ASCIIToUTF16("google"));
1367 data
.SetKeyword(ASCIIToUTF16("keyword"));
1368 data
.SetURL("http://www.google.com/foo/bar");
1369 std::vector
<std::string
> encodings
;
1370 data
.input_encodings
.push_back("UTF-8");
1371 data
.input_encodings
.push_back("UTF-8");
1372 data
.input_encodings
.push_back("UTF-16");
1373 data
.input_encodings
.push_back("UTF-8");
1374 data
.input_encodings
.push_back("Big5");
1375 data
.input_encodings
.push_back("UTF-16");
1376 data
.input_encodings
.push_back("Big5");
1377 data
.input_encodings
.push_back("Windows-1252");
1378 TemplateURL
* t_url
= new TemplateURL(data
);
1379 model()->Add(t_url
);
1381 VerifyObserverCount(1);
1382 base::RunLoop().RunUntilIdle();
1383 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1384 const TemplateURL
* loaded_url
=
1385 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1386 ASSERT_TRUE(loaded_url
!= NULL
);
1387 EXPECT_EQ(8U, loaded_url
->input_encodings().size());
1389 // Reload the model to verify it was actually saved to the database and the
1390 // duplicate encodings were removed.
1391 test_util()->ResetModel(true);
1392 ASSERT_EQ(initial_count
+ 1, model()->GetTemplateURLs().size());
1393 loaded_url
= model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1394 ASSERT_FALSE(loaded_url
== NULL
);
1395 EXPECT_EQ(4U, loaded_url
->input_encodings().size());
1398 TEST_F(TemplateURLServiceTest
, DefaultExtensionEngine
) {
1399 test_util()->VerifyLoad();
1400 // Add third-party default search engine.
1401 TemplateURL
* user_dse
= AddKeywordWithDate(
1402 "user", "user", "http://www.goo.com/s?q={searchTerms}",
1403 std::string(), std::string(), std::string(),
1404 true, "UTF-8", Time(), Time());
1405 model()->SetUserSelectedDefaultSearchProvider(user_dse
);
1406 EXPECT_EQ(user_dse
, model()->GetDefaultSearchProvider());
1408 TemplateURL
* ext_dse
= CreateKeywordWithDate(
1409 model(), "ext", "ext", "http://www.search.com/s?q={searchTerms}",
1410 std::string(), std::string(), std::string(),
1411 true, true, "UTF-8", Time(), Time());
1412 scoped_ptr
<TemplateURL::AssociatedExtensionInfo
> extension_info(
1413 new TemplateURL::AssociatedExtensionInfo(
1414 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION
, "ext"));
1415 extension_info
->wants_to_be_default_engine
= true;
1416 model()->AddExtensionControlledTURL(ext_dse
, extension_info
.Pass());
1417 EXPECT_EQ(ext_dse
, model()->GetDefaultSearchProvider());
1419 model()->RemoveExtensionControlledTURL(
1420 "ext", TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION
);
1421 ExpectSimilar(user_dse
, model()->GetDefaultSearchProvider());
1424 TEST_F(TemplateURLServiceTest
, ExtensionEnginesNotPersist
) {
1425 test_util()->VerifyLoad();
1426 // Add third-party default search engine.
1427 TemplateURL
* user_dse
= AddKeywordWithDate(
1428 "user", "user", "http://www.goo.com/s?q={searchTerms}",
1429 std::string(), std::string(), std::string(),
1430 true, "UTF-8", Time(), Time());
1431 model()->SetUserSelectedDefaultSearchProvider(user_dse
);
1432 EXPECT_EQ(user_dse
, model()->GetDefaultSearchProvider());
1434 TemplateURL
* ext_dse
= CreateKeywordWithDate(
1435 model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1436 std::string(), std::string(), std::string(),
1437 true, false, "UTF-8", Time(), Time());
1438 scoped_ptr
<TemplateURL::AssociatedExtensionInfo
> extension_info(
1439 new TemplateURL::AssociatedExtensionInfo(
1440 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION
, "ext1"));
1441 extension_info
->wants_to_be_default_engine
= false;
1442 model()->AddExtensionControlledTURL(ext_dse
, extension_info
.Pass());
1443 EXPECT_EQ(user_dse
, model()->GetDefaultSearchProvider());
1445 ext_dse
= CreateKeywordWithDate(
1446 model(), "ext2", "ext2", "http://www.ext2.com/s?q={searchTerms}",
1447 std::string(), std::string(), std::string(),
1448 true, true, "UTF-8", Time(), Time());
1449 extension_info
.reset(new TemplateURL::AssociatedExtensionInfo(
1450 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION
, "ext2"));
1451 extension_info
->wants_to_be_default_engine
= true;
1452 model()->AddExtensionControlledTURL(ext_dse
, extension_info
.Pass());
1453 EXPECT_EQ(ext_dse
, model()->GetDefaultSearchProvider());
1455 test_util()->ResetModel(true);
1456 user_dse
= model()->GetTemplateURLForKeyword(ASCIIToUTF16("user"));
1457 ExpectSimilar(user_dse
, model()->GetDefaultSearchProvider());
1458 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1459 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext2")));
1462 TEST_F(TemplateURLServiceTest
, ExtensionEngineVsPolicy
) {
1463 // Set a managed preference that establishes a default search provider.
1464 const char kName
[] = "test";
1465 const char kKeyword
[] = "test.com";
1466 const char kSearchURL
[] = "http://test.com/search?t={searchTerms}";
1467 const char kIconURL
[] = "http://test.com/icon.jpg";
1468 const char kEncodings
[] = "UTF-16;UTF-32";
1469 const char kAlternateURL
[] = "http://test.com/search#t={searchTerms}";
1470 const char kSearchTermsReplacementKey
[] = "espv";
1471 test_util()->SetManagedDefaultSearchPreferences(
1472 true, kName
, kKeyword
, kSearchURL
, std::string(), kIconURL
, kEncodings
,
1473 kAlternateURL
, kSearchTermsReplacementKey
);
1474 test_util()->VerifyLoad();
1475 // Verify that the default manager we are getting is the managed one.
1476 TemplateURLData data
;
1477 data
.SetShortName(ASCIIToUTF16(kName
));
1478 data
.SetKeyword(ASCIIToUTF16(kKeyword
));
1479 data
.SetURL(kSearchURL
);
1480 data
.favicon_url
= GURL(kIconURL
);
1481 data
.show_in_default_list
= true;
1482 data
.input_encodings
= base::SplitString(
1483 kEncodings
, ";", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
);
1484 data
.alternate_urls
.push_back(kAlternateURL
);
1485 data
.search_terms_replacement_key
= kSearchTermsReplacementKey
;
1486 scoped_ptr
<TemplateURL
> expected_managed_default(new TemplateURL(data
));
1487 EXPECT_TRUE(model()->is_default_search_managed());
1488 const TemplateURL
* actual_managed_default
=
1489 model()->GetDefaultSearchProvider();
1490 ExpectSimilar(expected_managed_default
.get(), actual_managed_default
);
1492 TemplateURL
* ext_dse
= CreateKeywordWithDate(
1493 model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1494 std::string(), std::string(), std::string(),
1495 true, true, "UTF-8", Time(), Time());
1496 scoped_ptr
<TemplateURL::AssociatedExtensionInfo
> extension_info(
1497 new TemplateURL::AssociatedExtensionInfo(
1498 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION
, "ext1"));
1499 extension_info
->wants_to_be_default_engine
= true;
1500 model()->AddExtensionControlledTURL(ext_dse
, extension_info
.Pass());
1501 EXPECT_EQ(ext_dse
, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1502 EXPECT_TRUE(model()->is_default_search_managed());
1503 actual_managed_default
= model()->GetDefaultSearchProvider();
1504 ExpectSimilar(expected_managed_default
.get(), actual_managed_default
);