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