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/extensions/extension.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/test/base/testing_profile.h"
31 #include "components/webdata/common/web_database.h"
32 #include "content/public/test/test_browser_thread.h"
33 #include "extensions/common/constants.h"
34 #include "extensions/common/manifest_constants.h"
35 #include "testing/gtest/include/gtest/gtest.h"
38 using base::TimeDelta;
39 using content::BrowserThread;
40 using ::testing::Return;
41 using ::testing::StrictMock;
45 // TestSearchTermsData --------------------------------------------------------
47 // Simple implementation of SearchTermsData.
48 class TestSearchTermsData : public SearchTermsData {
50 explicit TestSearchTermsData(const char* google_base_url);
52 virtual std::string GoogleBaseURLValue() const OVERRIDE;
55 std::string google_base_url_;
57 DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
60 TestSearchTermsData::TestSearchTermsData(const char* google_base_url)
61 : google_base_url_(google_base_url) {
64 std::string TestSearchTermsData::GoogleBaseURLValue() const {
65 return google_base_url_;
69 // QueryHistoryCallbackImpl ---------------------------------------------------
71 struct QueryHistoryCallbackImpl {
72 QueryHistoryCallbackImpl() : success(false) {}
74 void Callback(HistoryService::Handle handle,
76 const history::URLRow* row,
77 history::VisitVector* visits) {
78 this->success = success;
82 this->visits = *visits;
87 history::VisitVector visits;
90 TemplateURL* CreateKeywordWithDate(
91 TemplateURLService* model,
92 const std::string& short_name,
93 const std::string& keyword,
94 const std::string& url,
95 const std::string& suggest_url,
96 const std::string& alternate_url,
97 const std::string& favicon_url,
98 bool safe_for_autoreplace,
99 const std::string& encodings,
101 Time last_modified) {
102 TemplateURLData data;
103 data.short_name = UTF8ToUTF16(short_name);
104 data.SetKeyword(UTF8ToUTF16(keyword));
106 data.suggestions_url = suggest_url;
107 if (!alternate_url.empty())
108 data.alternate_urls.push_back(alternate_url);
109 data.favicon_url = GURL(favicon_url);
110 data.safe_for_autoreplace = safe_for_autoreplace;
111 base::SplitString(encodings, ';', &data.input_encodings);
112 data.date_created = date_created;
113 data.last_modified = last_modified;
114 return new TemplateURL(model->profile(), data);
117 TemplateURL* AddKeywordWithDate(
118 TemplateURLService* model,
119 const std::string& short_name,
120 const std::string& keyword,
121 const std::string& url,
122 const std::string& suggest_url,
123 const std::string& alternate_url,
124 const std::string& favicon_url,
125 bool safe_for_autoreplace,
126 const std::string& encodings,
128 Time last_modified) {
129 TemplateURL* t_url = CreateKeywordWithDate(
130 model, short_name, keyword, url, suggest_url, alternate_url,favicon_url,
131 safe_for_autoreplace, encodings, date_created, last_modified);
133 EXPECT_NE(0, t_url->id());
137 // Checks that the two TemplateURLs are similar. It does not check the id, the
138 // date_created or the last_modified time. Neither pointer should be NULL.
139 void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) {
140 ASSERT_TRUE(expected != NULL);
141 ASSERT_TRUE(actual != NULL);
142 EXPECT_EQ(expected->short_name(), actual->short_name());
143 EXPECT_EQ(expected->keyword(), actual->keyword());
144 EXPECT_EQ(expected->url(), actual->url());
145 EXPECT_EQ(expected->suggestions_url(), actual->suggestions_url());
146 EXPECT_EQ(expected->favicon_url(), actual->favicon_url());
147 EXPECT_EQ(expected->alternate_urls(), actual->alternate_urls());
148 EXPECT_EQ(expected->show_in_default_list(), actual->show_in_default_list());
149 EXPECT_EQ(expected->safe_for_autoreplace(), actual->safe_for_autoreplace());
150 EXPECT_EQ(expected->input_encodings(), actual->input_encodings());
151 EXPECT_EQ(expected->search_terms_replacement_key(),
152 actual->search_terms_replacement_key());
158 // TemplateURLServiceTest -----------------------------------------------------
160 class TemplateURLServiceTest : public testing::Test {
162 TemplateURLServiceTest();
165 virtual void SetUp();
166 virtual void TearDown();
168 TemplateURL* AddKeywordWithDate(const std::string& short_name,
169 const std::string& keyword,
170 const std::string& url,
171 const std::string& suggest_url,
172 const std::string& alternate_url,
173 const std::string& favicon_url,
174 bool safe_for_autoreplace,
175 const std::string& encodings,
179 // Verifies the two TemplateURLs are equal.
180 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual);
182 // Create an URL that appears to have been prepopulated, but won't be in the
183 // current data. The caller owns the returned TemplateURL*.
184 TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace,
187 // Creates a TemplateURL with the same prepopulated id as a real prepopulated
188 // item. The input number determines which prepopulated item. The caller is
189 // responsible for owning the returned TemplateURL*.
190 TemplateURL* CreateReplaceablePreloadedTemplateURL(
191 bool safe_for_autoreplace,
192 size_t index_offset_from_default,
193 string16* prepopulated_display_url);
195 // Verifies the behavior of when a preloaded url later gets changed.
196 // Since the input is the offset from the default, when one passes in
197 // 0, it tests the default. Passing in a number > 0 will verify what
198 // happens when a preloaded url that is not the default gets updated.
199 void TestLoadUpdatingPreloadedURL(size_t index_offset_from_default);
201 // Helper methods to make calling TemplateURLServiceTestUtil methods less
202 // visually noisy in the test code.
203 void VerifyObserverCount(int expected_changed_count);
204 void VerifyObserverFired();
205 TemplateURLService* model() { return test_util_.model(); }
208 TemplateURLServiceTestUtil test_util_;
210 void TestGenerateSearchURL(SearchTermsData* search_terms_data) {
211 struct GenerateSearchURLCase {
212 const char* test_name;
214 const char* expected;
215 } generate_url_cases[] = {
216 { "invalid URL", "foo{searchTerms}", "" },
217 { "URL with no replacements", "http://foo/", "http://foo/" },
218 { "basic functionality", "http://foo/{searchTerms}",
219 "http://foo/blah.blah.blah.blah.blah" }
222 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
223 TemplateURLData data;
224 data.SetURL(generate_url_cases[i].url);
225 TemplateURL t_url(NULL, data);
227 if (search_terms_data) {
228 result = TemplateURLService::GenerateSearchURLUsingTermsData(
229 &t_url, *search_terms_data).spec();
231 result = TemplateURLService::GenerateSearchURL(&t_url).spec();
233 EXPECT_EQ(result, generate_url_cases[i].expected)
234 << generate_url_cases[i].test_name << " failed. Expected "
235 << generate_url_cases[i].expected << " Actual " << result;
240 DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest);
243 TemplateURLServiceTest::TemplateURLServiceTest() {
246 void TemplateURLServiceTest::SetUp() {
250 void TemplateURLServiceTest::TearDown() {
251 test_util_.TearDown();
254 TemplateURL* TemplateURLServiceTest::AddKeywordWithDate(
255 const std::string& short_name,
256 const std::string& keyword,
257 const std::string& url,
258 const std::string& suggest_url,
259 const std::string& alternate_url,
260 const std::string& favicon_url,
261 bool safe_for_autoreplace,
262 const std::string& encodings,
264 Time last_modified) {
265 return ::AddKeywordWithDate(model(), short_name, keyword, url, suggest_url,
266 alternate_url, favicon_url, safe_for_autoreplace,
267 encodings, date_created, last_modified);
270 void TemplateURLServiceTest::AssertEquals(const TemplateURL& expected,
271 const TemplateURL& actual) {
272 ASSERT_EQ(expected.short_name(), actual.short_name());
273 ASSERT_EQ(expected.keyword(), actual.keyword());
274 ASSERT_EQ(expected.url(), actual.url());
275 ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
276 ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
277 ASSERT_EQ(expected.alternate_urls(), actual.alternate_urls());
278 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
279 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
280 ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
281 ASSERT_EQ(expected.id(), actual.id());
282 ASSERT_EQ(expected.date_created(), actual.date_created());
283 ASSERT_EQ(expected.last_modified(), actual.last_modified());
284 ASSERT_EQ(expected.sync_guid(), actual.sync_guid());
285 ASSERT_EQ(expected.search_terms_replacement_key(),
286 actual.search_terms_replacement_key());
289 TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL(
290 bool safe_for_autoreplace,
291 int prepopulate_id) {
292 TemplateURLData data;
293 data.short_name = ASCIIToUTF16("unittest");
294 data.SetKeyword(ASCIIToUTF16("unittest"));
295 data.SetURL("http://www.unittest.com/{searchTerms}");
296 data.favicon_url = GURL("http://favicon.url");
297 data.show_in_default_list = true;
298 data.safe_for_autoreplace = safe_for_autoreplace;
299 data.input_encodings.push_back("UTF-8");
300 data.date_created = Time::FromTimeT(100);
301 data.last_modified = Time::FromTimeT(100);
302 data.prepopulate_id = prepopulate_id;
303 return new TemplateURL(test_util_.profile(), data);
306 TemplateURL* TemplateURLServiceTest::CreateReplaceablePreloadedTemplateURL(
307 bool safe_for_autoreplace,
308 size_t index_offset_from_default,
309 string16* prepopulated_display_url) {
310 size_t default_search_provider_index = 0;
311 ScopedVector<TemplateURL> prepopulated_urls =
312 TemplateURLPrepopulateData::GetPrepopulatedEngines(
313 test_util_.profile(), &default_search_provider_index);
314 EXPECT_LT(index_offset_from_default, prepopulated_urls.size());
315 size_t prepopulated_index = (default_search_provider_index +
316 index_offset_from_default) % prepopulated_urls.size();
317 TemplateURL* t_url = CreatePreloadedTemplateURL(safe_for_autoreplace,
318 prepopulated_urls[prepopulated_index]->prepopulate_id());
319 *prepopulated_display_url =
320 prepopulated_urls[prepopulated_index]->url_ref().DisplayURL();
324 void TemplateURLServiceTest::TestLoadUpdatingPreloadedURL(
325 size_t index_offset_from_default) {
326 string16 prepopulated_url;
327 TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(false,
328 index_offset_from_default, &prepopulated_url);
330 string16 original_url = t_url->url_ref().DisplayURL();
331 std::string original_guid = t_url->sync_guid();
332 EXPECT_NE(prepopulated_url, original_url);
334 // Then add it to the model and save it all.
335 test_util_.ChangeModelToLoadState();
337 const TemplateURL* keyword_url =
338 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
339 ASSERT_TRUE(keyword_url != NULL);
340 EXPECT_EQ(t_url, keyword_url);
341 EXPECT_EQ(original_url, keyword_url->url_ref().DisplayURL());
342 base::RunLoop().RunUntilIdle();
344 // Now reload the model and verify that the merge updates the url, and
345 // preserves the sync GUID.
346 test_util_.ResetModel(true);
347 keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
348 ASSERT_TRUE(keyword_url != NULL);
349 EXPECT_EQ(prepopulated_url, keyword_url->url_ref().DisplayURL());
350 EXPECT_EQ(original_guid, keyword_url->sync_guid());
352 // Wait for any saves to finish.
353 base::RunLoop().RunUntilIdle();
355 // Reload the model to verify that change was saved correctly.
356 test_util_.ResetModel(true);
357 keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
358 ASSERT_TRUE(keyword_url != NULL);
359 EXPECT_EQ(prepopulated_url, keyword_url->url_ref().DisplayURL());
360 EXPECT_EQ(original_guid, keyword_url->sync_guid());
363 void TemplateURLServiceTest::VerifyObserverCount(int expected_changed_count) {
364 EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount());
365 test_util_.ResetObserverCount();
368 void TemplateURLServiceTest::VerifyObserverFired() {
369 EXPECT_LE(1, test_util_.GetObserverCount());
370 test_util_.ResetObserverCount();
374 // Actual tests ---------------------------------------------------------------
376 TEST_F(TemplateURLServiceTest, Load) {
377 test_util_.VerifyLoad();
380 TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
381 // Add a new TemplateURL.
382 test_util_.VerifyLoad();
383 const size_t initial_count = model()->GetTemplateURLs().size();
385 TemplateURLData data;
386 data.short_name = ASCIIToUTF16("google");
387 data.SetKeyword(ASCIIToUTF16("keyword"));
388 data.SetURL("http://www.google.com/foo/bar");
389 data.favicon_url = GURL("http://favicon.url");
390 data.safe_for_autoreplace = true;
391 data.date_created = Time::FromTimeT(100);
392 data.last_modified = Time::FromTimeT(100);
393 data.sync_guid = "00000000-0000-0000-0000-000000000001";
394 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
396 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
398 VerifyObserverCount(1);
399 base::RunLoop().RunUntilIdle();
400 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
401 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(t_url->keyword()));
402 // We need to make a second copy as the model takes ownership of |t_url| and
403 // will delete it. We have to do this after calling Add() since that gives
405 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
408 // Reload the model to verify it was actually saved to the database.
409 test_util_.ResetModel(true);
410 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
411 TemplateURL* loaded_url =
412 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
413 ASSERT_TRUE(loaded_url != NULL);
414 AssertEquals(*cloned_url, *loaded_url);
415 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
418 // We expect the last_modified time to be updated to the present time on an
419 // explicit reset. We have to set up the expectation here because ResetModel
420 // resets the TimeProvider in the TemplateURLService.
421 StrictMock<base::MockTimeProvider> mock_time;
422 model()->set_time_provider(&base::MockTimeProvider::StaticNow);
423 EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
425 // Mutate an element and verify it succeeded.
426 model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"),
428 ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name());
429 ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword());
430 ASSERT_EQ("c", loaded_url->url());
431 ASSERT_FALSE(loaded_url->safe_for_autoreplace());
432 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
434 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
435 cloned_url.reset(new TemplateURL(loaded_url->profile(), loaded_url->data()));
436 base::RunLoop().RunUntilIdle();
437 test_util_.ResetModel(true);
438 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
439 loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
440 ASSERT_TRUE(loaded_url != NULL);
441 AssertEquals(*cloned_url, *loaded_url);
442 // We changed a TemplateURL in the service, so ensure that the time was
444 ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified());
446 // Remove an element and verify it succeeded.
447 model()->Remove(loaded_url);
448 VerifyObserverCount(1);
449 test_util_.ResetModel(true);
450 ASSERT_EQ(initial_count, model()->GetTemplateURLs().size());
451 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL);
454 TEST_F(TemplateURLServiceTest, AddSameKeyword) {
455 test_util_.VerifyLoad();
458 "first", "keyword", "http://test1", std::string(), std::string(),
459 std::string(), true, "UTF-8", Time(), Time());
460 VerifyObserverCount(1);
462 // Test what happens when we try to add a TemplateURL with the same keyword as
464 TemplateURLData data;
465 data.short_name = ASCIIToUTF16("second");
466 data.SetKeyword(ASCIIToUTF16("keyword"));
467 data.SetURL("http://test2");
468 data.safe_for_autoreplace = false;
469 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
472 // Because the old TemplateURL was replaceable and the new one wasn't, the new
473 // one should have replaced the old.
474 VerifyObserverCount(1);
475 EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
476 EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
477 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
478 EXPECT_FALSE(t_url->safe_for_autoreplace());
480 // Now try adding a replaceable TemplateURL. This should just delete the
482 data.short_name = ASCIIToUTF16("third");
483 data.SetURL("http://test3");
484 data.safe_for_autoreplace = true;
485 model()->Add(new TemplateURL(test_util_.profile(), data));
486 VerifyObserverCount(0);
487 EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
488 EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
489 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
490 EXPECT_FALSE(t_url->safe_for_autoreplace());
492 // Now try adding a non-replaceable TemplateURL again. This should uniquify
493 // the existing entry's keyword.
494 data.short_name = ASCIIToUTF16("fourth");
495 data.SetURL("http://test4");
496 data.safe_for_autoreplace = false;
497 TemplateURL* t_url2 = new TemplateURL(test_util_.profile(), data);
498 model()->Add(t_url2);
499 VerifyObserverCount(2);
500 EXPECT_EQ(t_url2, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
501 EXPECT_EQ(ASCIIToUTF16("fourth"), t_url2->short_name());
502 EXPECT_EQ(ASCIIToUTF16("keyword"), t_url2->keyword());
503 EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
504 EXPECT_EQ(ASCIIToUTF16("test2"), t_url->keyword());
507 TEST_F(TemplateURLServiceTest, AddExtensionKeyword) {
508 test_util_.VerifyLoad();
510 TemplateURL* original1 = AddKeywordWithDate(
511 "replaceable", "keyword1", "http://test1", std::string(), std::string(),
512 std::string(), true, "UTF-8", Time(), Time());
513 TemplateURL* original2 = AddKeywordWithDate(
514 "nonreplaceable", "keyword2", "http://test2", std::string(),
515 std::string(), std::string(), false, "UTF-8", Time(), Time());
516 TemplateURL* original3 = AddKeywordWithDate(
517 "extension", "keyword3",
518 std::string(extensions::kExtensionScheme) + "://test3", std::string(),
519 std::string(), std::string(), false, "UTF-8", Time(), Time());
521 // Add an extension keyword that conflicts with each of the above three
523 TemplateURLData data;
524 data.short_name = ASCIIToUTF16("test");
525 data.SetKeyword(ASCIIToUTF16("keyword1"));
526 data.SetURL(std::string(extensions::kExtensionScheme) + "://test4");
527 data.safe_for_autoreplace = false;
529 // Both replaceable and non-replaceable keywords should be uniquified.
530 TemplateURL* extension1 = new TemplateURL(test_util_.profile(), data);
531 model()->Add(extension1);
532 ASSERT_EQ(extension1,
533 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
535 model()->GetTemplateURLForKeyword(ASCIIToUTF16("test1")));
536 data.SetKeyword(ASCIIToUTF16("keyword2"));
537 TemplateURL* extension2 = new TemplateURL(test_util_.profile(), data);
538 model()->Add(extension2);
539 ASSERT_EQ(extension2,
540 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2")));
542 model()->GetTemplateURLForKeyword(ASCIIToUTF16("test2")));
544 // They should override extension keywords added earlier.
545 data.SetKeyword(ASCIIToUTF16("keyword3"));
546 TemplateURL* extension3 = new TemplateURL(test_util_.profile(), data);
547 model()->Add(extension3);
548 ASSERT_EQ(extension3,
549 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3")));
551 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3_")));
554 TEST_F(TemplateURLServiceTest, AddSameKeywordWithExtensionPresent) {
555 test_util_.VerifyLoad();
557 // Similar to the AddSameKeyword test, but with an extension keyword masking a
558 // replaceable TemplateURL. We should still do correct conflict resolution
559 // between the non-template URLs.
560 TemplateURL* extension = AddKeywordWithDate(
561 "extension", "keyword",
562 std::string(extensions::kExtensionScheme) + "://test2", std::string(),
563 std::string(), std::string(), false, "UTF-8", Time(), Time());
564 // Adding a keyword that matches the extension should cause the extension
567 "replaceable", "keyword", "http://test1", std::string(), std::string(),
568 std::string(), true, "UTF-8", Time(), Time());
570 // Adding another replaceable keyword should remove the existing one, but
571 // leave the extension as is.
572 TemplateURLData data;
573 data.short_name = ASCIIToUTF16("name1");
574 data.SetKeyword(ASCIIToUTF16("keyword"));
575 data.SetURL("http://test3");
576 data.safe_for_autoreplace = true;
577 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
580 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
581 EXPECT_TRUE(model()->GetTemplateURLForHost("test1") == NULL);
582 EXPECT_EQ(t_url, model()->GetTemplateURLForHost("test3"));
584 // Adding a nonreplaceable keyword should remove the existing replaceable
586 data.short_name = ASCIIToUTF16("name2");
587 data.SetURL("http://test4");
588 data.safe_for_autoreplace = false;
589 TemplateURL* t_url2 = new TemplateURL(test_util_.profile(), data);
590 model()->Add(t_url2);
592 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
593 EXPECT_TRUE(model()->GetTemplateURLForHost("test3") == NULL);
595 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
598 TEST_F(TemplateURLServiceTest, GenerateKeyword) {
599 ASSERT_EQ(ASCIIToUTF16("foo"),
600 TemplateURLService::GenerateKeyword(GURL("http://foo")));
601 // www. should be stripped.
602 ASSERT_EQ(ASCIIToUTF16("foo"),
603 TemplateURLService::GenerateKeyword(GURL("http://www.foo")));
604 // Make sure we don't get a trailing '/'.
605 ASSERT_EQ(ASCIIToUTF16("blah"),
606 TemplateURLService::GenerateKeyword(GURL("http://blah/")));
607 // Don't generate the empty string.
608 ASSERT_EQ(ASCIIToUTF16("www"),
609 TemplateURLService::GenerateKeyword(GURL("http://www.")));
612 TEST_F(TemplateURLServiceTest, GenerateSearchURL) {
613 TestGenerateSearchURL(NULL);
616 TEST_F(TemplateURLServiceTest, GenerateSearchURLUsingTermsData) {
617 // Run the test for GenerateSearchURLUsingTermsData on the "IO" thread and
618 // wait for it to finish.
619 TestSearchTermsData search_terms_data("http://google.com/");
620 TestGenerateSearchURL(&search_terms_data);
623 TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
624 Time now = Time::Now();
625 TimeDelta one_day = TimeDelta::FromDays(1);
626 Time month_ago = now - TimeDelta::FromDays(30);
628 // Nothing has been added.
629 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
631 // Create one with a 0 time.
632 AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
633 std::string(), "http://icon1", true, "UTF-8;UTF-16",
635 // Create one for now and +/- 1 day.
636 AddKeywordWithDate("name2", "key2", "http://foo2", "http://suggest2",
637 std::string(), "http://icon2", true, "UTF-8;UTF-16",
638 now - one_day, Time());
639 AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
640 std::string(), std::string(), true, std::string(), now,
642 AddKeywordWithDate("name4", "key4", "http://foo4", std::string(),
643 std::string(), std::string(), true, std::string(),
644 now + one_day, Time());
645 // Try the other three states.
646 AddKeywordWithDate("name5", "key5", "http://foo5", "http://suggest5",
647 std::string(), "http://icon5", false, "UTF-8;UTF-16", now,
649 AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
650 std::string(), "http://icon6", false, "UTF-8;UTF-16",
653 // We just added a few items, validate them.
654 EXPECT_EQ(6U, model()->GetTemplateURLs().size());
656 // Try removing from current timestamp. This should delete the one in the
657 // future and one very recent one.
658 model()->RemoveAutoGeneratedSince(now);
659 EXPECT_EQ(4U, model()->GetTemplateURLs().size());
661 // Try removing from two months ago. This should only delete items that are
663 model()->RemoveAutoGeneratedBetween(now - TimeDelta::FromDays(60), now);
664 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
666 // Make sure the right values remain.
667 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
668 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
670 model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
672 EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
673 EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
674 EXPECT_EQ(now.ToInternalValue(),
675 model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
677 EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
678 EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
679 EXPECT_EQ(month_ago.ToInternalValue(),
680 model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
682 // Try removing from Time=0. This should delete one more.
683 model()->RemoveAutoGeneratedSince(Time());
684 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
687 TEST_F(TemplateURLServiceTest, ClearBrowsingData_KeywordsForOrigin) {
688 Time now = Time::Now();
689 TimeDelta one_day = TimeDelta::FromDays(1);
690 Time month_ago = now - TimeDelta::FromDays(30);
692 // Nothing has been added.
693 EXPECT_EQ(0U, model()->GetTemplateURLs().size());
695 // Create one for now and +/- 1 day.
696 AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
697 std::string(), "http://icon2", true, "UTF-8;UTF-16",
698 now - one_day, Time());
699 AddKeywordWithDate("name2", "key2", "http://foo2", std::string(),
700 std::string(), std::string(), true, std::string(), now,
702 AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
703 std::string(), std::string(), true, std::string(),
704 now + one_day, Time());
706 // We just added a few items, validate them.
707 EXPECT_EQ(3U, model()->GetTemplateURLs().size());
709 // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
710 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago,
712 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
713 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
714 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
715 EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
716 EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
718 // Try removing foo1, but outside the range in which it was modified. It
719 // should remain untouched.
720 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo1"), now,
722 EXPECT_EQ(2U, model()->GetTemplateURLs().size());
723 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
724 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
725 EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
726 EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
729 // Try removing foo3. This should delete foo3, but leave foo1 untouched.
730 model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo3"), month_ago,
731 now + one_day + one_day);
732 EXPECT_EQ(1U, model()->GetTemplateURLs().size());
733 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
734 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
737 TEST_F(TemplateURLServiceTest, Reset) {
738 // Add a new TemplateURL.
739 test_util_.VerifyLoad();
740 const size_t initial_count = model()->GetTemplateURLs().size();
741 TemplateURLData data;
742 data.short_name = ASCIIToUTF16("google");
743 data.SetKeyword(ASCIIToUTF16("keyword"));
744 data.SetURL("http://www.google.com/foo/bar");
745 data.favicon_url = GURL("http://favicon.url");
746 data.date_created = Time::FromTimeT(100);
747 data.last_modified = Time::FromTimeT(100);
748 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
751 VerifyObserverCount(1);
752 base::RunLoop().RunUntilIdle();
754 StrictMock<base::MockTimeProvider> mock_time;
755 model()->set_time_provider(&base::MockTimeProvider::StaticNow);
756 EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
758 // Reset the short name, keyword, url and make sure it takes.
759 const string16 new_short_name(ASCIIToUTF16("a"));
760 const string16 new_keyword(ASCIIToUTF16("b"));
761 const std::string new_url("c");
762 model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
763 ASSERT_EQ(new_short_name, t_url->short_name());
764 ASSERT_EQ(new_keyword, t_url->keyword());
765 ASSERT_EQ(new_url, t_url->url());
767 // Make sure the mappings in the model were updated.
768 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword));
770 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
772 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
775 // Reload the model from the database and make sure the change took.
776 test_util_.ResetModel(true);
777 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
778 const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
779 ASSERT_TRUE(read_url);
780 AssertEquals(*cloned_url, *read_url);
781 ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified());
784 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
785 // Add a new TemplateURL.
786 test_util_.VerifyLoad();
787 const size_t initial_count = model()->GetTemplateURLs().size();
788 TemplateURL* t_url = AddKeywordWithDate(
789 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
790 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
791 test_util_.ResetObserverCount();
793 model()->SetDefaultSearchProvider(t_url);
794 ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
795 ASSERT_TRUE(t_url->safe_for_autoreplace());
796 ASSERT_TRUE(t_url->show_in_default_list());
798 // Setting the default search provider should have caused notification.
799 VerifyObserverCount(1);
800 base::RunLoop().RunUntilIdle();
802 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
805 // Make sure when we reload we get a default search provider.
806 test_util_.ResetModel(true);
807 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
808 ASSERT_TRUE(model()->GetDefaultSearchProvider());
809 AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
812 TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
813 test_util_.ChangeModelToLoadState();
814 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
815 TemplateURL* t_url = AddKeywordWithDate(
816 "name1", "foo", "http://foo1", "http://sugg1", std::string(),
817 "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
819 // Can still replace, newly added template url is marked safe to replace.
820 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
821 GURL("http://foo2"), NULL));
823 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
824 // no longer be replaceable.
825 model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
828 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
829 GURL("http://foo2"), NULL));
832 TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
833 test_util_.ChangeModelToLoadState();
834 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
835 GURL("http://foo.com"), NULL));
836 TemplateURL* t_url = AddKeywordWithDate(
837 "name1", "foo", "http://foo.com", "http://sugg1", std::string(),
838 "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
840 // Can still replace, newly added template url is marked safe to replace.
841 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
842 GURL("http://foo.com"), NULL));
844 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
845 // no longer be replaceable.
846 model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
849 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
850 GURL("http://foo.com"), NULL));
853 TEST_F(TemplateURLServiceTest, HasDefaultSearchProvider) {
854 // We should have a default search provider even if we haven't loaded.
855 ASSERT_TRUE(model()->GetDefaultSearchProvider());
857 // Now force the model to load and make sure we still have a default.
858 test_util_.VerifyLoad();
860 ASSERT_TRUE(model()->GetDefaultSearchProvider());
863 TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
864 test_util_.VerifyLoad();
866 TemplateURLData data;
867 data.short_name = ASCIIToUTF16("a");
868 data.safe_for_autoreplace = true;
869 data.SetURL("http://url/{searchTerms}");
870 data.suggestions_url = "http://url2";
871 data.instant_url = "http://instant";
872 data.date_created = Time::FromTimeT(100);
873 data.last_modified = Time::FromTimeT(100);
874 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
876 const TemplateURLID id = t_url->id();
878 model()->SetDefaultSearchProvider(t_url);
879 base::RunLoop().RunUntilIdle();
880 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
883 // Reset the model and don't load it. The template url we set as the default
884 // should be pulled from prefs now.
885 test_util_.ResetModel(false);
887 // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
888 // value are persisted to prefs.
889 const TemplateURL* default_turl = model()->GetDefaultSearchProvider();
890 ASSERT_TRUE(default_turl);
891 EXPECT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
892 EXPECT_EQ("http://url/{searchTerms}", default_turl->url());
893 EXPECT_EQ("http://url2", default_turl->suggestions_url());
894 EXPECT_EQ("http://instant", default_turl->instant_url());
895 EXPECT_EQ(id, default_turl->id());
897 // Now do a load and make sure the default search provider really takes.
898 test_util_.VerifyLoad();
900 ASSERT_TRUE(model()->GetDefaultSearchProvider());
901 AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
904 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
905 test_util_.VerifyLoad();
907 // Edit Google search engine.
908 TemplateURL* google = model()->GetTemplateURLForKeyword(
909 ASCIIToUTF16("google.com"));
911 model()->ResetTemplateURL(google, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"),
912 "http://www.foo.com/s?q={searchTerms}");
913 EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
914 EXPECT_EQ(ASCIIToUTF16("xxx"), google->keyword());
916 // Add third-party default search engine.
917 TemplateURL* user_dse = AddKeywordWithDate(
918 "malware", "google.com", "http://www.goo.com/s?q={searchTerms}",
919 std::string(), std::string(), std::string(),
920 true, "UTF-8", Time(), Time());
921 model()->SetDefaultSearchProvider(user_dse);
922 EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
925 TemplateURL* bing = model()->GetTemplateURLForKeyword(
926 ASCIIToUTF16("bing.com"));
928 model()->Remove(bing);
929 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
931 // Register an extension with bing keyword.
932 model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com");
933 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
935 model()->RepairPrepopulatedSearchEngines();
937 // Google is default.
938 ASSERT_EQ(google, model()->GetDefaultSearchProvider());
939 // The keyword wasn't reverted.
940 EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
941 EXPECT_EQ("www.google.com",
942 TemplateURLService::GenerateSearchURL(google).host());
944 // Bing was repaired.
945 bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
947 EXPECT_EQ(TemplateURL::NORMAL, bing->GetType());
949 // User search engine is preserved.
950 EXPECT_EQ(user_dse, model()->GetTemplateURLForHost("www.goo.com"));
951 EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse->keyword());
954 TEST_F(TemplateURLServiceTest, RepairSearchEnginesWithManagedDefault) {
955 // Set a managed preference that establishes a default search provider.
956 const char kName[] = "test1";
957 const char kKeyword[] = "test.com";
958 const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
959 const char kIconURL[] = "http://test.com/icon.jpg";
960 const char kEncodings[] = "UTF-16;UTF-32";
961 const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
962 const char kSearchTermsReplacementKey[] = "espv";
963 test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
964 kSearchURL, std::string(),
965 kIconURL, kEncodings,
967 kSearchTermsReplacementKey);
968 test_util_.VerifyLoad();
969 // Verify that the default manager we are getting is the managed one.
970 TemplateURLData data;
971 data.short_name = ASCIIToUTF16(kName);
972 data.SetKeyword(ASCIIToUTF16(kKeyword));
973 data.SetURL(kSearchURL);
974 data.favicon_url = GURL(kIconURL);
975 data.show_in_default_list = true;
976 base::SplitString(kEncodings, ';', &data.input_encodings);
977 data.alternate_urls.push_back(kAlternateURL);
978 data.search_terms_replacement_key = kSearchTermsReplacementKey;
979 scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(
980 test_util_.profile(), data));
981 EXPECT_TRUE(model()->is_default_search_managed());
982 const TemplateURL* actual_managed_default =
983 model()->GetDefaultSearchProvider();
984 ExpectSimilar(expected_managed_default.get(), actual_managed_default);
986 // The following call has no effect on the managed search engine.
987 model()->RepairPrepopulatedSearchEngines();
989 EXPECT_TRUE(model()->is_default_search_managed());
990 actual_managed_default = model()->GetDefaultSearchProvider();
991 ExpectSimilar(expected_managed_default.get(), actual_managed_default);
994 TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
996 const std::string url;
999 { "http://foo/", string16() },
1000 { "http://foo/foo?q=xx", string16() },
1001 { "http://x/bar?q=xx", string16() },
1002 { "http://x/foo?y=xx", string16() },
1003 { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
1004 { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
1005 { "http://x/foo?q=b&q=xx", string16() },
1006 { "http://x/foo#query=xx", ASCIIToUTF16("xx") },
1007 { "http://x/foo?q=b#query=xx", ASCIIToUTF16("xx") },
1008 { "http://x/foo?q=b#q=xx", ASCIIToUTF16("b") },
1009 { "http://x/foo?query=b#q=xx", string16() },
1012 test_util_.ChangeModelToLoadState();
1013 AddKeywordWithDate("name", "x", "http://x/foo?q={searchTerms}",
1014 "http://sugg1", "http://x/foo#query={searchTerms}",
1015 "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
1017 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
1018 history::URLVisitedDetails details;
1019 details.row = history::URLRow(GURL(data[i].url));
1020 details.transition = content::PageTransitionFromInt(0);
1021 model()->UpdateKeywordSearchTermsForURL(details);
1022 EXPECT_EQ(data[i].term, test_util_.GetAndClearSearchTerm());
1026 TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
1028 const std::string url;
1031 { "http://x/bar?q=xx" },
1032 { "http://x/foo?y=xx" },
1035 test_util_.ChangeModelToLoadState();
1036 AddKeywordWithDate("name", "x", "http://x/foo", "http://sugg1", std::string(),
1037 "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
1039 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
1040 history::URLVisitedDetails details;
1041 details.row = history::URLRow(GURL(data[i].url));
1042 details.transition = content::PageTransitionFromInt(0);
1043 model()->UpdateKeywordSearchTermsForURL(details);
1044 ASSERT_EQ(string16(), test_util_.GetAndClearSearchTerm());
1048 TEST_F(TemplateURLServiceTest, ChangeGoogleBaseValue) {
1049 // NOTE: Do not do a VerifyLoad() here as it will load the prepopulate data,
1050 // which also has a {google:baseURL} keyword in it, which will confuse this
1052 test_util_.ChangeModelToLoadState();
1053 test_util_.SetGoogleBaseURL(GURL("http://google.com/"));
1054 const TemplateURL* t_url = AddKeywordWithDate(
1055 "name", "google.com", "{google:baseURL}?q={searchTerms}", "http://sugg1",
1056 std::string(), "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
1057 ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
1058 EXPECT_EQ("google.com", t_url->url_ref().GetHost());
1059 EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
1061 // Change the Google base url.
1062 test_util_.ResetObserverCount();
1063 test_util_.SetGoogleBaseURL(GURL("http://google.co.uk/"));
1064 VerifyObserverCount(1);
1066 // Make sure the host->TemplateURL map was updated appropriately.
1067 ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.co.uk"));
1068 EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
1069 EXPECT_EQ("google.co.uk", t_url->url_ref().GetHost());
1070 EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
1071 EXPECT_EQ("http://google.co.uk/?q=x", t_url->url_ref().ReplaceSearchTerms(
1072 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x"))));
1074 // Now add a manual entry and then change the Google base URL such that the
1075 // autogenerated Google search keyword would conflict.
1076 TemplateURL* manual = AddKeywordWithDate(
1077 "manual", "google.de", "http://google.de/search?q={searchTerms}",
1078 std::string(), std::string(), std::string(), false, "UTF-8", Time(),
1080 test_util_.SetGoogleBaseURL(GURL("http://google.de"));
1082 // Verify that the manual entry is untouched, and the autogenerated keyword
1085 model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
1086 EXPECT_EQ("google.de", manual->url_ref().GetHost());
1088 model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.co.uk")));
1089 EXPECT_EQ("google.de", t_url->url_ref().GetHost());
1090 EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
1092 // Change the base URL again and verify that the autogenerated keyword follows
1093 // even though it didn't match the base URL, while the manual entry is still
1095 test_util_.SetGoogleBaseURL(GURL("http://google.fr/"));
1096 ASSERT_EQ(manual, model()->GetTemplateURLForHost("google.de"));
1097 EXPECT_EQ("google.de", manual->url_ref().GetHost());
1098 EXPECT_EQ(ASCIIToUTF16("google.de"), manual->keyword());
1099 ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.fr"));
1100 EXPECT_TRUE(model()->GetTemplateURLForHost("google.co.uk") == NULL);
1101 EXPECT_EQ("google.fr", t_url->url_ref().GetHost());
1102 EXPECT_EQ(ASCIIToUTF16("google.fr"), t_url->keyword());
1105 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
1107 TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
1108 test_util_.VerifyLoad();
1109 ASSERT_TRUE(test_util_.profile()->CreateHistoryService(true, false));
1111 // Create a keyword.
1112 TemplateURL* t_url = AddKeywordWithDate(
1113 "keyword", "keyword", "http://foo.com/foo?query={searchTerms}",
1114 "http://sugg1", std::string(), "http://icon1", true, "UTF-8;UTF-16",
1115 base::Time::Now(), base::Time::Now());
1117 // Add a visit that matches the url of the keyword.
1118 HistoryService* history =
1119 HistoryServiceFactory::GetForProfile(test_util_.profile(),
1120 Profile::EXPLICIT_ACCESS);
1122 GURL(t_url->url_ref().ReplaceSearchTerms(
1123 TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah")))),
1124 base::Time::Now(), NULL, 0, GURL(), history::RedirectList(),
1125 content::PAGE_TRANSITION_KEYWORD, history::SOURCE_BROWSED, false);
1127 // Wait for history to finish processing the request.
1128 test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
1130 // Query history for the generated url.
1131 CancelableRequestConsumer consumer;
1132 QueryHistoryCallbackImpl callback;
1133 history->QueryURL(GURL("http://keyword"), true, &consumer,
1134 base::Bind(&QueryHistoryCallbackImpl::Callback,
1135 base::Unretained(&callback)));
1137 // Wait for the request to be processed.
1138 test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
1140 // And make sure the url and visit were added.
1141 EXPECT_TRUE(callback.success);
1142 EXPECT_NE(0, callback.row.id());
1143 ASSERT_EQ(1U, callback.visits.size());
1144 EXPECT_EQ(content::PAGE_TRANSITION_KEYWORD_GENERATED,
1145 content::PageTransitionStripQualifier(callback.visits[0].transition));
1148 // Make sure that the load routine deletes prepopulated engines that no longer
1149 // exist in the prepopulate data.
1150 TEST_F(TemplateURLServiceTest, LoadDeletesUnusedProvider) {
1151 // Create a preloaded template url. Add it to a loaded model and wait for the
1153 TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1154 test_util_.ChangeModelToLoadState();
1155 model()->Add(t_url);
1157 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1158 base::RunLoop().RunUntilIdle();
1160 // Ensure that merging clears this engine.
1161 test_util_.ResetModel(true);
1163 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1165 // Wait for any saves to finish.
1166 base::RunLoop().RunUntilIdle();
1168 // Reload the model to verify that the database was updated as a result of the
1170 test_util_.ResetModel(true);
1172 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
1175 // Make sure that load routine doesn't delete prepopulated engines that no
1176 // longer exist in the prepopulate data if it has been modified by the user.
1177 TEST_F(TemplateURLServiceTest, LoadRetainsModifiedProvider) {
1178 // Create a preloaded template url and add it to a loaded model.
1179 TemplateURL* t_url = CreatePreloadedTemplateURL(false, 999999);
1180 test_util_.ChangeModelToLoadState();
1181 model()->Add(t_url);
1183 // Do the copy after t_url is added so that the id is set.
1184 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
1186 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1188 // Wait for any saves to finish.
1189 base::RunLoop().RunUntilIdle();
1191 // Ensure that merging won't clear it if the user has edited it.
1192 test_util_.ResetModel(true);
1193 const TemplateURL* url_for_unittest =
1194 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1195 ASSERT_TRUE(url_for_unittest != NULL);
1196 AssertEquals(*cloned_url, *url_for_unittest);
1198 // Wait for any saves to finish.
1199 base::RunLoop().RunUntilIdle();
1201 // Reload the model to verify that save/reload retains the item.
1202 test_util_.ResetModel(true);
1204 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
1207 // Make sure that load routine doesn't delete
1208 // prepopulated engines that no longer exist in the prepopulate data if
1209 // it has been modified by the user.
1210 TEST_F(TemplateURLServiceTest, LoadSavesPrepopulatedDefaultSearchProvider) {
1211 test_util_.VerifyLoad();
1212 // Verify that the default search provider is set to something.
1213 TemplateURL* default_search = model()->GetDefaultSearchProvider();
1214 ASSERT_TRUE(default_search != NULL);
1215 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(default_search->profile(),
1216 default_search->data()));
1218 // Wait for any saves to finish.
1219 base::RunLoop().RunUntilIdle();
1221 // Reload the model and check that the default search provider
1222 // was properly saved.
1223 test_util_.ResetModel(true);
1224 default_search = model()->GetDefaultSearchProvider();
1225 ASSERT_TRUE(default_search != NULL);
1226 AssertEquals(*cloned_url, *default_search);
1229 TEST_F(TemplateURLServiceTest, FindNewDefaultSearchProvider) {
1230 // Ensure that if our service is initially empty, we don't initial have a
1232 EXPECT_FALSE(model()->FindNewDefaultSearchProvider());
1234 // Add a few entries with searchTerms, but ensure only the last one is in the
1236 AddKeywordWithDate("name1", "key1", "http://foo1/{searchTerms}",
1237 "http://sugg1", std::string(), "http://icon1", true,
1238 "UTF-8;UTF-16", Time(), Time());
1239 AddKeywordWithDate("name2", "key2", "http://foo2/{searchTerms}",
1240 "http://sugg2", std::string(), "http://icon1", true,
1241 "UTF-8;UTF-16", Time(), Time());
1242 AddKeywordWithDate("name3", "key3", "http://foo1/{searchTerms}",
1243 "http://sugg3", std::string(), "http://icon3", true,
1244 "UTF-8;UTF-16", Time(), Time());
1245 TemplateURLData data;
1246 data.short_name = ASCIIToUTF16("valid");
1247 data.SetKeyword(ASCIIToUTF16("validkeyword"));
1248 data.SetURL("http://valid/{searchTerms}");
1249 data.favicon_url = GURL("http://validicon");
1250 data.show_in_default_list = true;
1251 TemplateURL* valid_turl(new TemplateURL(test_util_.profile(), data));
1252 model()->Add(valid_turl);
1253 EXPECT_EQ(4U, model()->GetTemplateURLs().size());
1255 // Request a new DSP from the service and only expect the valid one.
1256 TemplateURL* new_default = model()->FindNewDefaultSearchProvider();
1257 ASSERT_TRUE(new_default);
1258 EXPECT_EQ(valid_turl, new_default);
1260 // Remove the default we received and ensure that the service returns NULL.
1261 model()->Remove(new_default);
1262 EXPECT_FALSE(model()->FindNewDefaultSearchProvider());
1265 // Make sure that the load routine doesn't delete
1266 // prepopulated engines that no longer exist in the prepopulate data if
1267 // it is the default search provider.
1268 TEST_F(TemplateURLServiceTest, LoadRetainsDefaultProvider) {
1269 // Set the default search provider to a preloaded template url which
1270 // is not in the current set of preloaded template urls and save
1272 TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
1273 test_util_.ChangeModelToLoadState();
1274 model()->Add(t_url);
1275 model()->SetDefaultSearchProvider(t_url);
1276 // Do the copy after t_url is added and set as default so that its
1277 // internal state is correct.
1278 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
1281 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1282 ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
1283 base::RunLoop().RunUntilIdle();
1285 // Ensure that merging won't clear the prepopulated template url
1286 // which is no longer present if it's the default engine.
1287 test_util_.ResetModel(true);
1289 const TemplateURL* keyword_url =
1290 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1291 ASSERT_TRUE(keyword_url != NULL);
1292 AssertEquals(*cloned_url, *keyword_url);
1293 ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1296 // Wait for any saves to finish.
1297 base::RunLoop().RunUntilIdle();
1299 // Reload the model to verify that the update was saved.
1300 test_util_.ResetModel(true);
1302 const TemplateURL* keyword_url =
1303 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1304 ASSERT_TRUE(keyword_url != NULL);
1305 AssertEquals(*cloned_url, *keyword_url);
1306 ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1310 // Make sure that the load routine updates the url of a preexisting
1311 // default search engine provider and that the result is saved correctly.
1312 TEST_F(TemplateURLServiceTest, LoadUpdatesDefaultSearchURL) {
1313 TestLoadUpdatingPreloadedURL(0);
1316 // Make sure that the load routine updates the url of a preexisting
1317 // non-default search engine provider and that the result is saved correctly.
1318 TEST_F(TemplateURLServiceTest, LoadUpdatesSearchURL) {
1319 TestLoadUpdatingPreloadedURL(1);
1322 // Make sure that the load routine sets a default search provider if it was
1323 // missing and not managed.
1324 TEST_F(TemplateURLServiceTest, LoadEnsuresDefaultSearchProviderExists) {
1325 // Force the model to load and make sure we have a default search provider.
1326 test_util_.VerifyLoad();
1327 TemplateURL* old_default = model()->GetDefaultSearchProvider();
1328 EXPECT_TRUE(old_default);
1331 model()->SetDefaultSearchProvider(NULL);
1332 model()->Remove(old_default);
1333 base::RunLoop().RunUntilIdle();
1335 EXPECT_FALSE(model()->GetDefaultSearchProvider());
1337 // Reset the model and load it. There should be a default search provider.
1338 test_util_.ResetModel(true);
1340 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1341 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
1343 // Make default search provider unusable (no search terms).
1344 model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
1345 ASCIIToUTF16("test"), ASCIIToUTF16("test"),
1346 "http://example.com/");
1347 base::RunLoop().RunUntilIdle();
1349 // Reset the model and load it. There should be a usable default search
1351 test_util_.ResetModel(true);
1353 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1354 EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
1357 // Simulates failing to load the webdb and makes sure the default search
1358 // provider is valid.
1359 TEST_F(TemplateURLServiceTest, FailedInit) {
1360 test_util_.VerifyLoad();
1362 test_util_.ClearModel();
1363 scoped_refptr<WebDataService> web_service =
1364 WebDataService::FromBrowserContext(test_util_.profile());
1365 web_service->ShutdownDatabase();
1367 test_util_.ResetModel(false);
1369 base::RunLoop().RunUntilIdle();
1371 ASSERT_TRUE(model()->GetDefaultSearchProvider());
1374 // Verifies that if the default search URL preference is managed, we report
1375 // the default search as managed. Also check that we are getting the right
1377 TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
1378 test_util_.VerifyLoad();
1379 const size_t initial_count = model()->GetTemplateURLs().size();
1380 test_util_.ResetObserverCount();
1382 // Set a regular default search provider.
1383 TemplateURL* regular_default = AddKeywordWithDate(
1384 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
1385 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
1386 VerifyObserverCount(1);
1387 model()->SetDefaultSearchProvider(regular_default);
1388 // Adding the URL and setting the default search provider should have caused
1390 VerifyObserverCount(1);
1391 EXPECT_FALSE(model()->is_default_search_managed());
1392 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1394 // Set a managed preference that establishes a default search provider.
1395 const char kName[] = "test1";
1396 const char kKeyword[] = "test.com";
1397 const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1398 const char kIconURL[] = "http://test.com/icon.jpg";
1399 const char kEncodings[] = "UTF-16;UTF-32";
1400 const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1401 const char kSearchTermsReplacementKey[] = "espv";
1402 test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1403 kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1404 kSearchTermsReplacementKey);
1405 VerifyObserverFired();
1406 EXPECT_TRUE(model()->is_default_search_managed());
1407 EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1409 // Verify that the default manager we are getting is the managed one.
1410 TemplateURLData data;
1411 data.short_name = ASCIIToUTF16(kName);
1412 data.SetKeyword(ASCIIToUTF16(kKeyword));
1413 data.SetURL(kSearchURL);
1414 data.favicon_url = GURL(kIconURL);
1415 data.show_in_default_list = true;
1416 base::SplitString(kEncodings, ';', &data.input_encodings);
1417 data.alternate_urls.push_back(kAlternateURL);
1418 data.search_terms_replacement_key = kSearchTermsReplacementKey;
1419 Profile* profile = test_util_.profile();
1420 scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL(profile,
1422 const TemplateURL* actual_managed_default =
1423 model()->GetDefaultSearchProvider();
1424 ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1425 EXPECT_TRUE(actual_managed_default->show_in_default_list());
1427 // Update the managed preference and check that the model has changed.
1428 const char kNewName[] = "test2";
1429 const char kNewKeyword[] = "other.com";
1430 const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}";
1431 const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}";
1432 test_util_.SetManagedDefaultSearchPreferences(true, kNewName, kNewKeyword,
1433 kNewSearchURL, kNewSuggestURL, std::string(), std::string(),
1434 std::string(), std::string());
1435 VerifyObserverFired();
1436 EXPECT_TRUE(model()->is_default_search_managed());
1437 EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1439 // Verify that the default manager we are now getting is the correct one.
1440 TemplateURLData data2;
1441 data2.short_name = ASCIIToUTF16(kNewName);
1442 data2.SetKeyword(ASCIIToUTF16(kNewKeyword));
1443 data2.SetURL(kNewSearchURL);
1444 data2.suggestions_url = kNewSuggestURL;
1445 data2.show_in_default_list = true;
1446 scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL(profile,
1448 actual_managed_default = model()->GetDefaultSearchProvider();
1449 ExpectSimilar(expected_managed_default2.get(), actual_managed_default);
1450 EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1452 // Remove all the managed prefs and check that we are no longer managed.
1453 test_util_.RemoveManagedDefaultSearchPreferences();
1454 VerifyObserverFired();
1455 EXPECT_FALSE(model()->is_default_search_managed());
1456 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1458 // The default should now be the first URL added
1459 const TemplateURL* actual_final_managed_default =
1460 model()->GetDefaultSearchProvider();
1461 ExpectSimilar(model()->GetTemplateURLs()[0], actual_final_managed_default);
1462 EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true);
1464 // Disable the default search provider through policy.
1465 test_util_.SetManagedDefaultSearchPreferences(false, std::string(),
1466 std::string(), std::string(), std::string(), std::string(),
1467 std::string(), std::string(), std::string());
1468 VerifyObserverFired();
1469 EXPECT_TRUE(model()->is_default_search_managed());
1470 EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider());
1471 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1474 test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
1475 kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1476 kSearchTermsReplacementKey);
1477 VerifyObserverFired();
1478 EXPECT_TRUE(model()->is_default_search_managed());
1479 EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
1481 // Verify that the default manager we are getting is the managed one.
1482 actual_managed_default = model()->GetDefaultSearchProvider();
1483 ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
1484 EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1486 // Clear the model and disable the default search provider through policy.
1487 // Verify that there is no default search provider after loading the model.
1488 // This checks against regressions of http://crbug.com/67180
1490 // First, remove the preferences, reset the model, and set a default.
1491 test_util_.RemoveManagedDefaultSearchPreferences();
1492 test_util_.ResetModel(true);
1493 TemplateURL* new_default =
1494 model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1"));
1495 ASSERT_FALSE(new_default == NULL);
1496 model()->SetDefaultSearchProvider(new_default);
1497 EXPECT_EQ(new_default, model()->GetDefaultSearchProvider());
1499 // Now reset the model again but load it after setting the preferences.
1500 test_util_.ResetModel(false);
1501 test_util_.SetManagedDefaultSearchPreferences(false, std::string(),
1502 std::string(), std::string(), std::string(), std::string(),
1503 std::string(), std::string(), std::string());
1504 test_util_.VerifyLoad();
1505 EXPECT_TRUE(model()->is_default_search_managed());
1506 EXPECT_TRUE(model()->GetDefaultSearchProvider() == NULL);
1509 // Test that if we load a TemplateURL with an empty GUID, the load process
1510 // assigns it a newly generated GUID.
1511 TEST_F(TemplateURLServiceTest, PatchEmptySyncGUID) {
1512 // Add a new TemplateURL.
1513 test_util_.VerifyLoad();
1514 const size_t initial_count = model()->GetTemplateURLs().size();
1516 TemplateURLData data;
1517 data.short_name = ASCIIToUTF16("google");
1518 data.SetKeyword(ASCIIToUTF16("keyword"));
1519 data.SetURL("http://www.google.com/foo/bar");
1520 data.sync_guid.clear();
1521 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
1522 model()->Add(t_url);
1524 VerifyObserverCount(1);
1525 base::RunLoop().RunUntilIdle();
1526 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1528 // Reload the model to verify it was actually saved to the database and
1529 // assigned a new GUID when brought back.
1530 test_util_.ResetModel(true);
1531 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1532 const TemplateURL* loaded_url =
1533 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1534 ASSERT_FALSE(loaded_url == NULL);
1535 ASSERT_FALSE(loaded_url->sync_guid().empty());
1538 // Test that if we load a TemplateURL with duplicate input encodings, the load
1539 // process de-dupes them.
1540 TEST_F(TemplateURLServiceTest, DuplicateInputEncodings) {
1541 // Add a new TemplateURL.
1542 test_util_.VerifyLoad();
1543 const size_t initial_count = model()->GetTemplateURLs().size();
1545 TemplateURLData data;
1546 data.short_name = ASCIIToUTF16("google");
1547 data.SetKeyword(ASCIIToUTF16("keyword"));
1548 data.SetURL("http://www.google.com/foo/bar");
1549 std::vector<std::string> encodings;
1550 data.input_encodings.push_back("UTF-8");
1551 data.input_encodings.push_back("UTF-8");
1552 data.input_encodings.push_back("UTF-16");
1553 data.input_encodings.push_back("UTF-8");
1554 data.input_encodings.push_back("Big5");
1555 data.input_encodings.push_back("UTF-16");
1556 data.input_encodings.push_back("Big5");
1557 data.input_encodings.push_back("Windows-1252");
1558 TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
1559 model()->Add(t_url);
1561 VerifyObserverCount(1);
1562 base::RunLoop().RunUntilIdle();
1563 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1564 const TemplateURL* loaded_url =
1565 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1566 ASSERT_TRUE(loaded_url != NULL);
1567 EXPECT_EQ(8U, loaded_url->input_encodings().size());
1569 // Reload the model to verify it was actually saved to the database and the
1570 // duplicate encodings were removed.
1571 test_util_.ResetModel(true);
1572 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
1573 loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1574 ASSERT_FALSE(loaded_url == NULL);
1575 EXPECT_EQ(4U, loaded_url->input_encodings().size());
1578 TEST_F(TemplateURLServiceTest, DefaultExtensionEngine) {
1579 test_util_.VerifyLoad();
1580 // Add third-party default search engine.
1581 TemplateURL* user_dse = AddKeywordWithDate(
1582 "user", "user", "http://www.goo.com/s?q={searchTerms}",
1583 std::string(), std::string(), std::string(),
1584 true, "UTF-8", Time(), Time());
1585 model()->SetDefaultSearchProvider(user_dse);
1586 EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1588 TemplateURL* ext_dse = CreateKeywordWithDate(
1589 model(), "ext", "ext", "http://www.search.com/s?q={searchTerms}",
1590 std::string(), std::string(), std::string(),
1591 true, "UTF-8", Time(), Time());
1592 scoped_ptr<AssociatedExtensionInfo> extension_info(
1593 new AssociatedExtensionInfo);
1594 extension_info->wants_to_be_default_engine = true;
1595 extension_info->extension_id = "ext";
1596 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1597 EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1599 model()->RemoveExtensionControlledTURL("ext");
1600 ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1603 TEST_F(TemplateURLServiceTest, ExtensionEnginesNotPersist) {
1604 test_util_.VerifyLoad();
1605 // Add third-party default search engine.
1606 TemplateURL* user_dse = AddKeywordWithDate(
1607 "user", "user", "http://www.goo.com/s?q={searchTerms}",
1608 std::string(), std::string(), std::string(),
1609 true, "UTF-8", Time(), Time());
1610 model()->SetDefaultSearchProvider(user_dse);
1611 EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1613 TemplateURL* ext_dse = CreateKeywordWithDate(
1614 model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1615 std::string(), std::string(), std::string(),
1616 true, "UTF-8", Time(), Time());
1617 scoped_ptr<AssociatedExtensionInfo> extension_info(
1618 new AssociatedExtensionInfo);
1619 extension_info->wants_to_be_default_engine = false;
1620 extension_info->extension_id = "ext1";
1621 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1622 EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
1624 ext_dse = CreateKeywordWithDate(
1625 model(), "ext2", "ext2", "http://www.ext2.com/s?q={searchTerms}",
1626 std::string(), std::string(), std::string(),
1627 true, "UTF-8", Time(), Time());
1628 extension_info.reset(new AssociatedExtensionInfo);
1629 extension_info->wants_to_be_default_engine = true;
1630 extension_info->extension_id = "ext2";
1631 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1632 EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
1634 test_util_.ResetModel(true);
1635 user_dse = model()->GetTemplateURLForKeyword(ASCIIToUTF16("user"));
1636 ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
1637 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1638 EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext2")));
1641 TEST_F(TemplateURLServiceTest, ExtensionEngineVsPolicy) {
1642 // Set a managed preference that establishes a default search provider.
1643 const char kName[] = "test";
1644 const char kKeyword[] = "test.com";
1645 const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1646 const char kIconURL[] = "http://test.com/icon.jpg";
1647 const char kEncodings[] = "UTF-16;UTF-32";
1648 const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
1649 const char kSearchTermsReplacementKey[] = "espv";
1650 test_util_.SetManagedDefaultSearchPreferences(
1651 true, kName, kKeyword, kSearchURL, std::string(), kIconURL, kEncodings,
1652 kAlternateURL, kSearchTermsReplacementKey);
1653 test_util_.VerifyLoad();
1654 // Verify that the default manager we are getting is the managed one.
1655 TemplateURLData data;
1656 data.short_name = ASCIIToUTF16(kName);
1657 data.SetKeyword(ASCIIToUTF16(kKeyword));
1658 data.SetURL(kSearchURL);
1659 data.favicon_url = GURL(kIconURL);
1660 data.show_in_default_list = true;
1661 base::SplitString(kEncodings, ';', &data.input_encodings);
1662 data.alternate_urls.push_back(kAlternateURL);
1663 data.search_terms_replacement_key = kSearchTermsReplacementKey;
1664 scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(
1665 test_util_.profile(), data));
1666 EXPECT_TRUE(model()->is_default_search_managed());
1667 const TemplateURL* actual_managed_default =
1668 model()->GetDefaultSearchProvider();
1669 ExpectSimilar(expected_managed_default.get(), actual_managed_default);
1671 TemplateURL* ext_dse = CreateKeywordWithDate(
1672 model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
1673 std::string(), std::string(), std::string(),
1674 true, "UTF-8", Time(), Time());
1675 scoped_ptr<AssociatedExtensionInfo> extension_info(
1676 new AssociatedExtensionInfo);
1677 extension_info->wants_to_be_default_engine = true;
1678 extension_info->extension_id = "ext1";
1679 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
1680 EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
1681 EXPECT_TRUE(model()->is_default_search_managed());
1682 actual_managed_default = model()->GetDefaultSearchProvider();
1683 ExpectSimilar(expected_managed_default.get(), actual_managed_default);