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.
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"
37 using base::ASCIIToUTF16;
39 using base::TimeDelta;
40 using content::BrowserThread;
41 using ::testing::Return;
42 using ::testing::StrictMock;
46 // TestSearchTermsData --------------------------------------------------------
48 // Simple implementation of SearchTermsData.
49 class TestSearchTermsData : public SearchTermsData {
51 explicit TestSearchTermsData(const char* google_base_url);
53 virtual std::string GoogleBaseURLValue() const OVERRIDE;
56 std::string google_base_url_;
58 DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
61 TestSearchTermsData::TestSearchTermsData(const char* google_base_url)
62 : google_base_url_(google_base_url) {
65 std::string TestSearchTermsData::GoogleBaseURLValue() const {
66 return google_base_url_;
70 // QueryHistoryCallbackImpl ---------------------------------------------------
72 struct QueryHistoryCallbackImpl {
73 QueryHistoryCallbackImpl() : success(false) {}
75 void Callback(HistoryService::Handle handle,
77 const history::URLRow* row,
78 history::VisitVector* visits) {
79 this->success = success;
83 this->visits = *visits;
88 history::VisitVector visits;
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,
103 Time last_modified) {
104 TemplateURLData data;
105 data.short_name = base::UTF8ToUTF16(short_name);
106 data.SetKeyword(base::UTF8ToUTF16(keyword));
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);
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,
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);
136 EXPECT_NE(0, t_url->id());
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());
161 // TemplateURLServiceTest -----------------------------------------------------
163 class TemplateURLServiceTest : public testing::Test {
165 TemplateURLServiceTest();
168 virtual void SetUp();
169 virtual void TearDown();
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,
182 // Verifies the two TemplateURLs are equal.
183 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual);
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,
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(); }
197 TemplateURLServiceTestUtil test_util_;
199 void TestGenerateSearchURL(SearchTermsData* search_terms_data) {
200 struct GenerateSearchURLCase {
201 const char* test_name;
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" }
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);
216 if (search_terms_data) {
217 result = TemplateURLService::GenerateSearchURLUsingTermsData(
218 &t_url, *search_terms_data).spec();
220 result = TemplateURLService::GenerateSearchURL(&t_url).spec();
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;
229 DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest);
232 class TemplateURLServiceWithoutFallbackTest : public TemplateURLServiceTest {
234 TemplateURLServiceWithoutFallbackTest() : TemplateURLServiceTest() {}
236 virtual void SetUp() OVERRIDE {
237 TemplateURLService::set_fallback_search_engines_disabled(true);
238 TemplateURLServiceTest::SetUp();
241 virtual void TearDown() OVERRIDE {
242 TemplateURLServiceTest::TearDown();
243 TemplateURLService::set_fallback_search_engines_disabled(false);
247 TemplateURLServiceTest::TemplateURLServiceTest() {
250 void TemplateURLServiceTest::SetUp() {
254 void TemplateURLServiceTest::TearDown() {
255 test_util_.TearDown();
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,
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);
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());
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);
310 void TemplateURLServiceTest::VerifyObserverCount(int expected_changed_count) {
311 EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount());
312 test_util_.ResetObserverCount();
315 void TemplateURLServiceTest::VerifyObserverFired() {
316 EXPECT_LE(1, test_util_.GetObserverCount());
317 test_util_.ResetObserverCount();
321 // Actual tests ---------------------------------------------------------------
323 TEST_F(TemplateURLServiceTest, Load) {
324 test_util_.VerifyLoad();
327 TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
328 // Add a new TemplateURL.
329 test_util_.VerifyLoad();
330 const size_t initial_count = model()->GetTemplateURLs().size();
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);
343 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
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
352 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
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(),
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)));
372 // Mutate an element and verify it succeeded.
373 model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"),
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(),
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
391 ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified());
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);
401 TEST_F(TemplateURLServiceTest, AddSameKeyword) {
402 test_util_.VerifyLoad();
405 "first", "keyword", "http://test1", std::string(), std::string(),
406 std::string(), true, "UTF-8", Time(), Time());
407 VerifyObserverCount(1);
409 // Test what happens when we try to add a TemplateURL with the same keyword as
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);
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());
427 // Now try adding a replaceable TemplateURL. This should just delete the
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());
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());
454 TEST_F(TemplateURLServiceTest, AddExtensionKeyword) {
455 test_util_.VerifyLoad();
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());
468 // Add an extension keyword that conflicts with each of the above three
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;
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")));
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")));
489 model()->GetTemplateURLForKeyword(ASCIIToUTF16("test2")));
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")));
498 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3_")));
501 TEST_F(TemplateURLServiceTest, AddSameKeywordWithExtensionPresent) {
502 test_util_.VerifyLoad();
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
514 "replaceable", "keyword", "http://test1", std::string(), std::string(),
515 std::string(), true, "UTF-8", Time(), Time());
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);
527 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
528 EXPECT_TRUE(model()->GetTemplateURLForHost("test1") == NULL);
529 EXPECT_EQ(t_url, model()->GetTemplateURLForHost("test3"));
531 // Adding a nonreplaceable keyword should remove the existing replaceable
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);
539 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
540 EXPECT_TRUE(model()->GetTemplateURLForHost("test3") == NULL);
542 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
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.")));
559 TEST_F(TemplateURLServiceTest, GenerateSearchURL) {
560 TestGenerateSearchURL(NULL);
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);
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);
575 // Nothing has been added.
576 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
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",
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,
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,
596 AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
597 std::string(), "http://icon6", false, "UTF-8;UTF-16",
600 // We just added a few items, validate them.
601 EXPECT_EQ(6U, model()->GetTemplateURLs().size());
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());
608 // Try removing from two months ago. This should only delete items that are
610 model()->RemoveAutoGeneratedBetween(now - TimeDelta::FromDays(60), now);
611 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
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());
617 model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
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());
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());
629 // Try removing from Time=0. This should delete one more.
630 model()->RemoveAutoGeneratedSince(Time());
631 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
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);
639 // Nothing has been added.
640 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
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,
649 AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
650 std::string(), std::string(), true, std::string(),
651 now + one_day, Time());
653 // We just added a few items, validate them.
654 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
656 // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
657 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago,
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());
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,
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());
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());
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);
698 VerifyObserverCount(1);
699 base::RunLoop().RunUntilIdle();
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)));
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());
714 // Make sure the mappings in the model were updated.
715 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword));
717 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
719 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
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());
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();
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());
745 // Setting the default search provider should have caused notification.
746 VerifyObserverCount(1);
747 base::RunLoop().RunUntilIdle();
749 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
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());
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());
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));
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(),
775 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
776 GURL("http://foo2"), NULL));
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());
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));
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(),
796 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
797 GURL("http://foo.com"), NULL));
800 TEST_F(TemplateURLServiceTest, HasDefaultSearchProvider) {
801 // We should have a default search provider even if we haven't loaded.
802 ASSERT_TRUE(model()->GetDefaultSearchProvider());
804 // Now force the model to load and make sure we still have a default.
805 test_util_.VerifyLoad();
807 ASSERT_TRUE(model()->GetDefaultSearchProvider());
810 TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
811 test_util_.VerifyLoad();
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);
823 const TemplateURLID id = t_url->id();
825 model()->SetUserSelectedDefaultSearchProvider(t_url);
826 base::RunLoop().RunUntilIdle();
827 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
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);
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());
844 // Now do a load and make sure the default search provider really takes.
845 test_util_.VerifyLoad();
847 ASSERT_TRUE(model()->GetDefaultSearchProvider());
848 AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
851 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
852 test_util_.VerifyLoad();
854 // Edit Google search engine.
855 TemplateURL* google = model()->GetTemplateURLForKeyword(
856 ASCIIToUTF16("google.com"));
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());
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());
872 TemplateURL* bing = model()->GetTemplateURLForKeyword(
873 ASCIIToUTF16("bing.com"));
875 model()->Remove(bing);
876 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
878 // Register an extension with bing keyword.
879 model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com");
880 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
882 model()->RepairPrepopulatedSearchEngines();
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());
891 // Bing was repaired.
892 bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
894 EXPECT_EQ(TemplateURL::NORMAL, bing->GetType());
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());
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,
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);
933 // The following call has no effect on the managed search engine.
934 model()->RepairPrepopulatedSearchEngines();
936 EXPECT_TRUE(model()->is_default_search_managed());
937 actual_managed_default = model()->GetDefaultSearchProvider();
938 ExpectSimilar(expected_managed_default.get(), actual_managed_default);
941 TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
943 const std::string url;
944 const base::string16 term;
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() },
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());
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());
973 TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
975 const std::string url;
978 { "http://x/bar?q=xx" },
979 { "http://x/foo?y=xx" },
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());
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());
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();
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());
1008 // Change the Google base url.
1009 test_util_.ResetObserverCount();
1010 test_util_.SetGoogleBaseURL(GURL("http://google.co.uk/"));
1011 VerifyObserverCount(1);
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"))));
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(),
1027 test_util_.SetGoogleBaseURL(GURL("http://google.de"));
1029 // Verify that the manual entry is untouched, and the autogenerated keyword
1032 model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
1033 EXPECT_EQ("google.de", manual->url_ref().GetHost());
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());
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
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());
1052 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
1054 TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
1055 test_util_.VerifyLoad();
1056 ASSERT_TRUE(test_util_.profile()->CreateHistoryService(true, false));
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());
1064 // Add a visit that matches the url of the keyword.
1065 HistoryService* history =
1066 HistoryServiceFactory::GetForProfile(test_util_.profile(),
1067 Profile::EXPLICIT_ACCESS);
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);
1074 // Wait for history to finish processing the request.
1075 test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
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)));
1084 // Wait for the request to be processed.
1085 test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
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));
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
1100 TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1101 test_util_.ChangeModelToLoadState();
1102 model()->Add(t_url);
1104 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1105 base::RunLoop().RunUntilIdle();
1107 // Ensure that merging clears this engine.
1108 test_util_.ResetModel(true);
1110 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1112 // Wait for any saves to finish.
1113 base::RunLoop().RunUntilIdle();
1115 // Reload the model to verify that the database was updated as a result of the
1117 test_util_.ResetModel(true);
1119 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
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);
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(),
1133 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1135 // Wait for any saves to finish.
1136 base::RunLoop().RunUntilIdle();
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);
1145 // Wait for any saves to finish.
1146 base::RunLoop().RunUntilIdle();
1148 // Reload the model to verify that save/reload retains the item.
1149 test_util_.ResetModel(true);
1151 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
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()));
1165 // Wait for any saves to finish.
1166 base::RunLoop().RunUntilIdle();
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);
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
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(),
1192 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1193 ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
1194 base::RunLoop().RunUntilIdle();
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);
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());
1207 // Wait for any saves to finish.
1208 base::RunLoop().RunUntilIdle();
1210 // Reload the model to verify that the update was saved.
1211 test_util_.ResetModel(true);
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());
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());
1228 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
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();
1236 // Reset the model and load it. There should be a usable default search
1238 test_util_.ResetModel(true);
1240 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1241 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
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();
1249 test_util_.ClearModel();
1250 scoped_refptr<WebDataService> web_service =
1251 WebDataService::FromBrowserContext(test_util_.profile());
1252 web_service->ShutdownDatabase();
1254 test_util_.ResetModel(false);
1256 base::RunLoop().RunUntilIdle();
1258 ASSERT_TRUE(model()->GetDefaultSearchProvider());
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
1264 TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
1265 test_util_.VerifyLoad();
1266 const size_t initial_count = model()->GetTemplateURLs().size();
1267 test_util_.ResetObserverCount();
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
1277 VerifyObserverCount(1);
1278 EXPECT_FALSE(model()->is_default_search_managed());
1279 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
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());
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,
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());
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());
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,
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);
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());
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);
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());
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());
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);
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
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());
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);
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();
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);
1411 VerifyObserverCount(1);
1412 base::RunLoop().RunUntilIdle();
1413 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
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());
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();
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);
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());
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());
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());
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());
1486 model()->RemoveExtensionControlledTURL("ext");
1487 ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
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());
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());
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());
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")));
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);
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);