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