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