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