1 // Copyright (c) 2011 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/callback.h" 6 #include "base/memory/ref_counted.h" 7 #include "base/memory/scoped_vector.h" 8 #include "base/string_split.h" 9 #include "base/string_util.h" 10 #include "base/threading/thread.h" 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/history/history.h" 13 #include "chrome/browser/history/history_notifications.h" 14 #include "chrome/browser/search_engines/search_host_to_urls_map.h" 15 #include "chrome/browser/search_engines/search_terms_data.h" 16 #include "chrome/browser/search_engines/template_url.h" 17 #include "chrome/browser/search_engines/template_url_model.h" 18 #include "chrome/browser/search_engines/template_url_model_test_util.h" 19 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" 20 #include "chrome/browser/webdata/web_database.h" 21 #include "chrome/common/pref_names.h" 22 #include "chrome/test/testing_pref_service.h" 23 #include "chrome/test/testing_profile.h" 24 #include "content/browser/browser_thread.h" 25 #include "content/common/notification_details.h" 26 #include "content/common/notification_source.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 using base::Time; 30 using base::TimeDelta; 31 32 #if defined(OS_LINUX) 33 // Timed out on Chromium Linux. http://crbug.com/53607 34 #define MAYBE_Load DISABLED_Load 35 #else 36 #define MAYBE_Load Load 37 #endif 38 39 // Test the GenerateSearchURL on a thread or the main thread. 40 class TestGenerateSearchURL 41 : public base::RefCountedThreadSafe<TestGenerateSearchURL> { 42 public: 43 explicit TestGenerateSearchURL(SearchTermsData* search_terms_data) 44 : search_terms_data_(search_terms_data), 45 passed_(false) { 46 } 47 48 // Run the test cases for GenerateSearchURL. 49 void RunTest(); 50 51 // Did the test pass? 52 bool passed() const { return passed_; } 53 54 private: 55 friend class base::RefCountedThreadSafe<TestGenerateSearchURL>; 56 ~TestGenerateSearchURL() {} 57 58 SearchTermsData* search_terms_data_; 59 bool passed_; 60 61 DISALLOW_COPY_AND_ASSIGN(TestGenerateSearchURL); 62 }; 63 64 // Simple implementation of SearchTermsData. 65 class TestSearchTermsData : public SearchTermsData { 66 public: 67 explicit TestSearchTermsData(const char* google_base_url) 68 : google_base_url_(google_base_url) { 69 } 70 71 virtual std::string GoogleBaseURLValue() const { 72 return google_base_url_; 73 } 74 75 virtual std::string GetApplicationLocale() const { 76 return "yy"; 77 } 78 79 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) 80 // Returns the value for the Chrome Omnibox rlz. 81 virtual string16 GetRlzParameterValue() const { 82 return string16(); 83 } 84 #endif 85 86 private: 87 std::string google_base_url_; 88 89 DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData); 90 }; 91 92 // Create an URL that appears to have been prepopulated, but won't be in the 93 // current data. The caller owns the returned TemplateURL*. 94 static TemplateURL* CreatePreloadedTemplateURL() { 95 TemplateURL* t_url = new TemplateURL(); 96 t_url->SetURL("http://www.unittest.com/", 0, 0); 97 t_url->set_keyword(ASCIIToUTF16("unittest")); 98 t_url->set_short_name(ASCIIToUTF16("unittest")); 99 t_url->set_safe_for_autoreplace(true); 100 GURL favicon_url("http://favicon.url"); 101 t_url->SetFaviconURL(favicon_url); 102 t_url->set_date_created(Time::FromTimeT(100)); 103 t_url->set_prepopulate_id(999999); 104 return t_url; 105 } 106 107 class TemplateURLModelTest : public testing::Test { 108 public: 109 TemplateURLModelTest() {} 110 111 virtual void SetUp() { 112 test_util_.SetUp(); 113 } 114 115 virtual void TearDown() { 116 test_util_.TearDown(); 117 } 118 119 TemplateURL* AddKeywordWithDate(const std::string& keyword, 120 bool autogenerate_keyword, 121 const std::string& url, 122 const std::string& suggest_url, 123 const std::string& favicon_url, 124 const std::string& encodings, 125 const std::string& short_name, 126 bool safe_for_autoreplace, 127 Time created_date) { 128 TemplateURL* template_url = new TemplateURL(); 129 template_url->SetURL(url, 0, 0); 130 template_url->SetSuggestionsURL(suggest_url, 0, 0); 131 template_url->SetFaviconURL(GURL(favicon_url)); 132 template_url->set_keyword(UTF8ToUTF16(keyword)); 133 template_url->set_autogenerate_keyword(autogenerate_keyword); 134 template_url->set_short_name(UTF8ToUTF16(short_name)); 135 std::vector<std::string> encodings_vector; 136 base::SplitString(encodings, ';', &encodings_vector); 137 template_url->set_input_encodings(encodings_vector); 138 template_url->set_date_created(created_date); 139 template_url->set_safe_for_autoreplace(safe_for_autoreplace); 140 model()->Add(template_url); 141 EXPECT_NE(0, template_url->id()); 142 return template_url; 143 } 144 145 // Simulate firing by the prefs service specifying that the managed 146 // preferences have changed. 147 void NotifyManagedPrefsHaveChanged() { 148 model()->Observe( 149 NotificationType::PREF_CHANGED, 150 Source<PrefService>(profile()->GetTestingPrefService()), 151 Details<std::string>(NULL)); 152 } 153 154 // Verifies the two TemplateURLs are equal. 155 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual) { 156 ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.url(), actual.url())); 157 ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.suggestions_url(), 158 actual.suggestions_url())); 159 ASSERT_EQ(expected.keyword(), actual.keyword()); 160 ASSERT_EQ(expected.short_name(), actual.short_name()); 161 ASSERT_EQ(JoinString(expected.input_encodings(), ';'), 162 JoinString(actual.input_encodings(), ';')); 163 ASSERT_TRUE(expected.GetFaviconURL() == actual.GetFaviconURL()); 164 ASSERT_EQ(expected.id(), actual.id()); 165 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace()); 166 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list()); 167 ASSERT_TRUE(expected.date_created() == actual.date_created()); 168 } 169 170 // Checks that the two TemplateURLs are similar. It does not check the id 171 // and the date_created. Neither pointer should be NULL. 172 void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) { 173 ASSERT_TRUE(expected != NULL); 174 ASSERT_TRUE(actual != NULL); 175 EXPECT_TRUE(TemplateURLRef::SameUrlRefs(expected->url(), actual->url())); 176 EXPECT_TRUE(TemplateURLRef::SameUrlRefs(expected->suggestions_url(), 177 actual->suggestions_url())); 178 EXPECT_EQ(expected->keyword(), actual->keyword()); 179 EXPECT_EQ(expected->short_name(), actual->short_name()); 180 EXPECT_EQ(JoinString(expected->input_encodings(), ';'), 181 JoinString(actual->input_encodings(), ';')); 182 EXPECT_TRUE(expected->GetFaviconURL() == actual->GetFaviconURL()); 183 EXPECT_EQ(expected->safe_for_autoreplace(), actual->safe_for_autoreplace()); 184 EXPECT_EQ(expected->show_in_default_list(), actual->show_in_default_list()); 185 } 186 187 // Set the managed preferences for the default search provider and trigger 188 // notification. 189 void SetManagedDefaultSearchPreferences(bool enabled, 190 const char* name, 191 const char* search_url, 192 const char* suggest_url, 193 const char* icon_url, 194 const char* encodings, 195 const char* keyword) { 196 TestingPrefService* service = profile()->GetTestingPrefService(); 197 service->SetManagedPref( 198 prefs::kDefaultSearchProviderEnabled, 199 Value::CreateBooleanValue(enabled)); 200 service->SetManagedPref( 201 prefs::kDefaultSearchProviderName, 202 Value::CreateStringValue(name)); 203 service->SetManagedPref( 204 prefs::kDefaultSearchProviderSearchURL, 205 Value::CreateStringValue(search_url)); 206 service->SetManagedPref( 207 prefs::kDefaultSearchProviderSuggestURL, 208 Value::CreateStringValue(suggest_url)); 209 service->SetManagedPref( 210 prefs::kDefaultSearchProviderIconURL, 211 Value::CreateStringValue(icon_url)); 212 service->SetManagedPref( 213 prefs::kDefaultSearchProviderEncodings, 214 Value::CreateStringValue(encodings)); 215 service->SetManagedPref( 216 prefs::kDefaultSearchProviderKeyword, 217 Value::CreateStringValue(keyword)); 218 } 219 220 // Remove all the managed preferences for the default search provider and 221 // trigger notification. 222 void RemoveManagedDefaultSearchPreferences() { 223 TestingPrefService* service = profile()->GetTestingPrefService(); 224 service->RemoveManagedPref( 225 prefs::kDefaultSearchProviderSearchURL); 226 service->RemoveManagedPref( 227 prefs::kDefaultSearchProviderEnabled); 228 service->RemoveManagedPref( 229 prefs::kDefaultSearchProviderName); 230 service->RemoveManagedPref( 231 prefs::kDefaultSearchProviderSuggestURL); 232 service->RemoveManagedPref( 233 prefs::kDefaultSearchProviderIconURL); 234 service->RemoveManagedPref( 235 prefs::kDefaultSearchProviderEncodings); 236 service->RemoveManagedPref( 237 prefs::kDefaultSearchProviderKeyword); 238 service->RemoveManagedPref( 239 prefs::kDefaultSearchProviderID); 240 service->RemoveManagedPref( 241 prefs::kDefaultSearchProviderPrepopulateID); 242 } 243 244 // Creates a TemplateURL with the same prepopulated id as a real prepopulated 245 // item. The input number determines which prepopulated item. The caller is 246 // responsible for owning the returned TemplateURL*. 247 TemplateURL* CreateReplaceablePreloadedTemplateURL( 248 size_t index_offset_from_default, 249 string16* prepopulated_display_url); 250 251 // Verifies the behavior of when a preloaded url later gets changed. 252 // Since the input is the offset from the default, when one passes in 253 // 0, it tests the default. Passing in a number > 0 will verify what 254 // happens when a preloaded url that is not the default gets updated. 255 void TestLoadUpdatingPreloadedURL(size_t index_offset_from_default); 256 257 // Helper methods to make calling TemplateURLModelTestUtil methods less 258 // visually noisy in the test code. 259 void VerifyObserverCount(int expected_changed_count) { 260 EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount()); 261 test_util_.ResetObserverCount(); 262 } 263 void VerifyObserverFired() { 264 EXPECT_LE(1, test_util_.GetObserverCount()); 265 test_util_.ResetObserverCount(); 266 } 267 void BlockTillServiceProcessesRequests() { 268 TemplateURLModelTestUtil::BlockTillServiceProcessesRequests(); 269 } 270 void VerifyLoad() { test_util_.VerifyLoad(); } 271 void ChangeModelToLoadState() { test_util_.ChangeModelToLoadState(); } 272 void ResetModel(bool verify_load) { test_util_.ResetModel(verify_load); } 273 string16 GetAndClearSearchTerm() { 274 return test_util_.GetAndClearSearchTerm(); 275 } 276 void SetGoogleBaseURL(const std::string& base_url) const { 277 test_util_.SetGoogleBaseURL(base_url); 278 } 279 WebDataService* GetWebDataService() { return test_util_.GetWebDataService(); } 280 TemplateURLModel* model() { return test_util_.model(); } 281 TestingProfile* profile() { return test_util_.profile(); } 282 283 protected: 284 TemplateURLModelTestUtil test_util_; 285 286 DISALLOW_COPY_AND_ASSIGN(TemplateURLModelTest); 287 }; 288 289 void TestGenerateSearchURL::RunTest() { 290 struct GenerateSearchURLCase { 291 const char* test_name; 292 const char* url; 293 const char* expected; 294 } generate_url_cases[] = { 295 { "empty TemplateURLRef", NULL, "" }, 296 { "invalid URL", "foo{searchTerms}", "" }, 297 { "URL with no replacements", "http://foo/", "http://foo/" }, 298 { "basic functionality", "http://foo/{searchTerms}", 299 "http://foo/blah.blah.blah.blah.blah" } 300 }; 301 302 // Don't use ASSERT/EXPECT since this is run on a thread in one test 303 // and those macros aren't meant for threads at this time according to 304 // gtest documentation. 305 bool everything_passed = true; 306 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) { 307 TemplateURL t_url; 308 if (generate_url_cases[i].url) 309 t_url.SetURL(generate_url_cases[i].url, 0, 0); 310 311 std::string result = search_terms_data_ ? 312 TemplateURLModel::GenerateSearchURLUsingTermsData( 313 &t_url, *search_terms_data_).spec() : 314 TemplateURLModel::GenerateSearchURL(&t_url).spec(); 315 if (strcmp(generate_url_cases[i].expected, result.c_str())) { 316 LOG(ERROR) << generate_url_cases[i].test_name << " failed. Expected " << 317 generate_url_cases[i].expected << " Actual " << result; 318 319 everything_passed = false; 320 } 321 } 322 passed_ = everything_passed; 323 } 324 325 TemplateURL* TemplateURLModelTest::CreateReplaceablePreloadedTemplateURL( 326 size_t index_offset_from_default, 327 string16* prepopulated_display_url) { 328 TemplateURL* t_url = CreatePreloadedTemplateURL(); 329 ScopedVector<TemplateURL> prepopulated_urls; 330 size_t default_search_provider_index = 0; 331 TemplateURLPrepopulateData::GetPrepopulatedEngines( 332 profile()->GetPrefs(), 333 &prepopulated_urls.get(), 334 &default_search_provider_index); 335 EXPECT_LT(index_offset_from_default, prepopulated_urls.size()); 336 size_t prepopulated_index = 337 (default_search_provider_index + index_offset_from_default) % 338 prepopulated_urls.size(); 339 t_url->set_prepopulate_id( 340 prepopulated_urls[prepopulated_index]->prepopulate_id()); 341 *prepopulated_display_url = 342 prepopulated_urls[prepopulated_index]->url()->DisplayURL(); 343 return t_url; 344 } 345 346 void TemplateURLModelTest::TestLoadUpdatingPreloadedURL( 347 size_t index_offset_from_default) { 348 string16 prepopulated_url; 349 TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL( 350 index_offset_from_default, &prepopulated_url); 351 t_url->set_safe_for_autoreplace(false); 352 353 string16 original_url = t_url->url()->DisplayURL(); 354 ASSERT_NE(prepopulated_url, original_url); 355 356 // Then add it to the model and save it all. 357 ChangeModelToLoadState(); 358 model()->Add(t_url); 359 const TemplateURL* keyword_url = 360 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 361 ASSERT_EQ(t_url, keyword_url); 362 ASSERT_EQ(original_url, keyword_url->url()->DisplayURL()); 363 BlockTillServiceProcessesRequests(); 364 365 // Now reload the model and verify that the merge updates the url. 366 ResetModel(true); 367 keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 368 ASSERT_TRUE(keyword_url != NULL); 369 ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL()); 370 371 // Wait for any saves to finish. 372 BlockTillServiceProcessesRequests(); 373 374 // Reload the model to verify that change was saved correctly. 375 ResetModel(true); 376 keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 377 ASSERT_TRUE(keyword_url != NULL); 378 ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL()); 379 } 380 381 TEST_F(TemplateURLModelTest, MAYBE_Load) { 382 VerifyLoad(); 383 } 384 385 TEST_F(TemplateURLModelTest, AddUpdateRemove) { 386 // Add a new TemplateURL. 387 VerifyLoad(); 388 const size_t initial_count = model()->GetTemplateURLs().size(); 389 390 TemplateURL* t_url = new TemplateURL(); 391 t_url->SetURL("http://www.google.com/foo/bar", 0, 0); 392 t_url->set_keyword(ASCIIToUTF16("keyword")); 393 t_url->set_short_name(ASCIIToUTF16("google")); 394 GURL favicon_url("http://favicon.url"); 395 t_url->SetFaviconURL(favicon_url); 396 t_url->set_date_created(Time::FromTimeT(100)); 397 t_url->set_safe_for_autoreplace(true); 398 model()->Add(t_url); 399 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), 400 GURL(), NULL)); 401 VerifyObserverCount(1); 402 BlockTillServiceProcessesRequests(); 403 // We need to clone as model takes ownership of TemplateURL and will 404 // delete it. 405 TemplateURL cloned_url(*t_url); 406 ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 407 ASSERT_TRUE(model()->GetTemplateURLForKeyword(t_url->keyword()) == t_url); 408 ASSERT_TRUE(t_url->date_created() == cloned_url.date_created()); 409 410 // Reload the model to verify it was actually saved to the database. 411 ResetModel(true); 412 ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 413 const TemplateURL* loaded_url = 414 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")); 415 ASSERT_TRUE(loaded_url != NULL); 416 AssertEquals(cloned_url, *loaded_url); 417 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), 418 GURL(), NULL)); 419 420 // Mutate an element and verify it succeeded. 421 model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), 422 ASCIIToUTF16("b"), "c"); 423 ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name()); 424 ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword()); 425 ASSERT_EQ("c", loaded_url->url()->url()); 426 ASSERT_FALSE(loaded_url->safe_for_autoreplace()); 427 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), 428 GURL(), NULL)); 429 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL)); 430 cloned_url = *loaded_url; 431 BlockTillServiceProcessesRequests(); 432 ResetModel(true); 433 ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 434 loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")); 435 ASSERT_TRUE(loaded_url != NULL); 436 AssertEquals(cloned_url, *loaded_url); 437 438 // Remove an element and verify it succeeded. 439 model()->Remove(loaded_url); 440 VerifyObserverCount(1); 441 ResetModel(true); 442 ASSERT_EQ(initial_count, model()->GetTemplateURLs().size()); 443 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL); 444 } 445 446 TEST_F(TemplateURLModelTest, GenerateKeyword) { 447 ASSERT_EQ(string16(), TemplateURLModel::GenerateKeyword(GURL(), true)); 448 // Shouldn't generate keywords for https. 449 ASSERT_EQ(string16(), 450 TemplateURLModel::GenerateKeyword(GURL("https://blah"), true)); 451 ASSERT_EQ(ASCIIToUTF16("foo"), 452 TemplateURLModel::GenerateKeyword(GURL("http://foo"), true)); 453 // www. should be stripped. 454 ASSERT_EQ(ASCIIToUTF16("foo"), 455 TemplateURLModel::GenerateKeyword(GURL("http://www.foo"), true)); 456 // Shouldn't generate keywords with paths, if autodetected. 457 ASSERT_EQ(string16(), 458 TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), true)); 459 ASSERT_EQ(ASCIIToUTF16("blah"), 460 TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), false)); 461 // FTP shouldn't generate a keyword. 462 ASSERT_EQ(string16(), 463 TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true)); 464 // Make sure we don't get a trailing / 465 ASSERT_EQ(ASCIIToUTF16("blah"), 466 TemplateURLModel::GenerateKeyword(GURL("http://blah/"), true)); 467 } 468 469 TEST_F(TemplateURLModelTest, GenerateSearchURL) { 470 scoped_refptr<TestGenerateSearchURL> test_generate_search_url( 471 new TestGenerateSearchURL(NULL)); 472 test_generate_search_url->RunTest(); 473 EXPECT_TRUE(test_generate_search_url->passed()); 474 } 475 476 TEST_F(TemplateURLModelTest, GenerateSearchURLUsingTermsData) { 477 // Run the test for GenerateSearchURLUsingTermsData on the "IO" thread and 478 // wait for it to finish. 479 TestSearchTermsData search_terms_data("http://google.com/"); 480 scoped_refptr<TestGenerateSearchURL> test_generate_search_url( 481 new TestGenerateSearchURL(&search_terms_data)); 482 483 test_util_.StartIOThread(); 484 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask( 485 FROM_HERE, 486 NewRunnableMethod(test_generate_search_url.get(), 487 &TestGenerateSearchURL::RunTest)); 488 TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests(); 489 EXPECT_TRUE(test_generate_search_url->passed()); 490 } 491 492 TEST_F(TemplateURLModelTest, ClearBrowsingData_Keywords) { 493 Time now = Time::Now(); 494 TimeDelta one_day = TimeDelta::FromDays(1); 495 Time month_ago = now - TimeDelta::FromDays(30); 496 497 // Nothing has been added. 498 EXPECT_EQ(0U, model()->GetTemplateURLs().size()); 499 500 // Create one with a 0 time. 501 AddKeywordWithDate("key1", false, "http://foo1", "http://suggest1", 502 "http://icon1", "UTF-8;UTF-16", "name1", true, Time()); 503 // Create one for now and +/- 1 day. 504 AddKeywordWithDate("key2", false, "http://foo2", "http://suggest2", 505 "http://icon2", "UTF-8;UTF-16", "name2", true, 506 now - one_day); 507 AddKeywordWithDate("key3", false, "http://foo3", "", "", "", "name3", 508 true, now); 509 AddKeywordWithDate("key4", false, "http://foo4", "", "", "", "name4", 510 true, now + one_day); 511 // Try the other three states. 512 AddKeywordWithDate("key5", false, "http://foo5", "http://suggest5", 513 "http://icon5", "UTF-8;UTF-16", "name5", false, now); 514 AddKeywordWithDate("key6", false, "http://foo6", "http://suggest6", 515 "http://icon6", "UTF-8;UTF-16", "name6", false, 516 month_ago); 517 518 // We just added a few items, validate them. 519 EXPECT_EQ(6U, model()->GetTemplateURLs().size()); 520 521 // Try removing from current timestamp. This should delete the one in the 522 // future and one very recent one. 523 model()->RemoveAutoGeneratedSince(now); 524 EXPECT_EQ(4U, model()->GetTemplateURLs().size()); 525 526 // Try removing from two months ago. This should only delete items that are 527 // auto-generated. 528 model()->RemoveAutoGeneratedSince(now - TimeDelta::FromDays(60)); 529 EXPECT_EQ(3U, model()->GetTemplateURLs().size()); 530 531 // Make sure the right values remain. 532 EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword()); 533 EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace()); 534 EXPECT_EQ(0U, 535 model()->GetTemplateURLs()[0]->date_created().ToInternalValue()); 536 537 EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword()); 538 EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace()); 539 EXPECT_EQ(now.ToInternalValue(), 540 model()->GetTemplateURLs()[1]->date_created().ToInternalValue()); 541 542 EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword()); 543 EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace()); 544 EXPECT_EQ(month_ago.ToInternalValue(), 545 model()->GetTemplateURLs()[2]->date_created().ToInternalValue()); 546 547 // Try removing from Time=0. This should delete one more. 548 model()->RemoveAutoGeneratedSince(Time()); 549 EXPECT_EQ(2U, model()->GetTemplateURLs().size()); 550 } 551 552 TEST_F(TemplateURLModelTest, Reset) { 553 // Add a new TemplateURL. 554 VerifyLoad(); 555 const size_t initial_count = model()->GetTemplateURLs().size(); 556 TemplateURL* t_url = new TemplateURL(); 557 t_url->SetURL("http://www.google.com/foo/bar", 0, 0); 558 t_url->set_keyword(ASCIIToUTF16("keyword")); 559 t_url->set_short_name(ASCIIToUTF16("google")); 560 GURL favicon_url("http://favicon.url"); 561 t_url->SetFaviconURL(favicon_url); 562 t_url->set_date_created(Time::FromTimeT(100)); 563 model()->Add(t_url); 564 565 VerifyObserverCount(1); 566 BlockTillServiceProcessesRequests(); 567 568 // Reset the short name, keyword, url and make sure it takes. 569 const string16 new_short_name(ASCIIToUTF16("a")); 570 const string16 new_keyword(ASCIIToUTF16("b")); 571 const std::string new_url("c"); 572 model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url); 573 ASSERT_EQ(new_short_name, t_url->short_name()); 574 ASSERT_EQ(new_keyword, t_url->keyword()); 575 ASSERT_EQ(new_url, t_url->url()->url()); 576 577 // Make sure the mappings in the model were updated. 578 ASSERT_TRUE(model()->GetTemplateURLForKeyword(new_keyword) == t_url); 579 ASSERT_TRUE( 580 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL); 581 582 TemplateURL last_url = *t_url; 583 584 // Reload the model from the database and make sure the change took. 585 ResetModel(true); 586 t_url = NULL; 587 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); 588 const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword); 589 ASSERT_TRUE(read_url); 590 AssertEquals(last_url, *read_url); 591 } 592 593 TEST_F(TemplateURLModelTest, DefaultSearchProvider) { 594 // Add a new TemplateURL. 595 VerifyLoad(); 596 const size_t initial_count = model()->GetTemplateURLs().size(); 597 TemplateURL* t_url = AddKeywordWithDate("key1", false, "http://foo1", 598 "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time()); 599 600 test_util_.ResetObserverCount(); 601 model()->SetDefaultSearchProvider(t_url); 602 603 ASSERT_EQ(t_url, model()->GetDefaultSearchProvider()); 604 605 ASSERT_TRUE(t_url->safe_for_autoreplace()); 606 ASSERT_TRUE(t_url->show_in_default_list()); 607 608 // Setting the default search provider should have caused notification. 609 VerifyObserverCount(1); 610 611 BlockTillServiceProcessesRequests(); 612 613 TemplateURL cloned_url = *t_url; 614 615 ResetModel(true); 616 t_url = NULL; 617 618 // Make sure when we reload we get a default search provider. 619 EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 620 ASSERT_TRUE(model()->GetDefaultSearchProvider()); 621 AssertEquals(cloned_url, *model()->GetDefaultSearchProvider()); 622 } 623 624 TEST_F(TemplateURLModelTest, TemplateURLWithNoKeyword) { 625 VerifyLoad(); 626 627 const size_t initial_count = model()->GetTemplateURLs().size(); 628 629 AddKeywordWithDate("", false, "http://foo1", "http://sugg1", 630 "http://icon1", "UTF-8;UTF-16", "name1", true, Time()); 631 632 // We just added a few items, validate them. 633 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); 634 635 // Reload the model from the database and make sure we get the url back. 636 ResetModel(true); 637 638 ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 639 640 bool found_keyword = false; 641 for (size_t i = 0; i < initial_count + 1; ++i) { 642 if (model()->GetTemplateURLs()[i]->keyword().empty()) { 643 found_keyword = true; 644 break; 645 } 646 } 647 ASSERT_TRUE(found_keyword); 648 } 649 650 TEST_F(TemplateURLModelTest, CantReplaceWithSameKeyword) { 651 ChangeModelToLoadState(); 652 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL)); 653 TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo1", 654 "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time()); 655 656 // Can still replace, newly added template url is marked safe to replace. 657 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), 658 GURL("http://foo2"), NULL)); 659 660 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should 661 // no longer be replaceable. 662 model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(), 663 t_url->url()->url()); 664 665 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), 666 GURL("http://foo2"), NULL)); 667 } 668 669 TEST_F(TemplateURLModelTest, CantReplaceWithSameHosts) { 670 ChangeModelToLoadState(); 671 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), 672 GURL("http://foo.com"), NULL)); 673 TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo.com", 674 "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time()); 675 676 // Can still replace, newly added template url is marked safe to replace. 677 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"), 678 GURL("http://foo.com"), NULL)); 679 680 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should 681 // no longer be replaceable. 682 model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(), 683 t_url->url()->url()); 684 685 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"), 686 GURL("http://foo.com"), NULL)); 687 } 688 689 TEST_F(TemplateURLModelTest, HasDefaultSearchProvider) { 690 // We should have a default search provider even if we haven't loaded. 691 ASSERT_TRUE(model()->GetDefaultSearchProvider()); 692 693 // Now force the model to load and make sure we still have a default. 694 VerifyLoad(); 695 696 ASSERT_TRUE(model()->GetDefaultSearchProvider()); 697 } 698 699 TEST_F(TemplateURLModelTest, DefaultSearchProviderLoadedFromPrefs) { 700 VerifyLoad(); 701 702 TemplateURL* template_url = new TemplateURL(); 703 template_url->SetURL("http://url", 0, 0); 704 template_url->SetSuggestionsURL("http://url2", 0, 0); 705 template_url->SetInstantURL("http://instant", 0, 0); 706 template_url->set_short_name(ASCIIToUTF16("a")); 707 template_url->set_safe_for_autoreplace(true); 708 template_url->set_date_created(Time::FromTimeT(100)); 709 710 model()->Add(template_url); 711 712 const TemplateURLID id = template_url->id(); 713 714 model()->SetDefaultSearchProvider(template_url); 715 716 BlockTillServiceProcessesRequests(); 717 718 TemplateURL first_default_search_provider = *template_url; 719 720 template_url = NULL; 721 722 // Reset the model and don't load it. The template url we set as the default 723 // should be pulled from prefs now. 724 ResetModel(false); 725 726 // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs 727 // value are persisted to prefs. 728 const TemplateURL* default_turl = model()->GetDefaultSearchProvider(); 729 ASSERT_TRUE(default_turl); 730 ASSERT_TRUE(default_turl->url()); 731 ASSERT_EQ("http://url", default_turl->url()->url()); 732 ASSERT_TRUE(default_turl->suggestions_url()); 733 ASSERT_EQ("http://url2", default_turl->suggestions_url()->url()); 734 ASSERT_TRUE(default_turl->instant_url()); 735 EXPECT_EQ("http://instant", default_turl->instant_url()->url()); 736 ASSERT_EQ(ASCIIToUTF16("a"), default_turl->short_name()); 737 ASSERT_EQ(id, default_turl->id()); 738 739 // Now do a load and make sure the default search provider really takes. 740 VerifyLoad(); 741 742 ASSERT_TRUE(model()->GetDefaultSearchProvider()); 743 AssertEquals(first_default_search_provider, 744 *model()->GetDefaultSearchProvider()); 745 } 746 747 TEST_F(TemplateURLModelTest, BuildQueryTerms) { 748 struct TestData { 749 const std::string url; 750 const bool result; 751 // Keys and values are a semicolon separated list of expected values in the 752 // map. 753 const std::string keys; 754 const std::string values; 755 } data[] = { 756 // No query should return false. 757 { "http://blah/", false, "", "" }, 758 759 // Query with empty key should return false. 760 { "http://blah/foo?=y", false, "", "" }, 761 762 // Query with key occurring multiple times should return false. 763 { "http://blah/foo?x=y&x=z", false, "", "" }, 764 765 { "http://blah/foo?x=y", true, "x", "y" }, 766 { "http://blah/foo?x=y&y=z", true, "x;y", "y;z" }, 767 768 // Key occurring multiple times should get an empty string. 769 { "http://blah/foo?x=y&x=z&y=z", true, "x;y", ";z" }, 770 }; 771 772 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { 773 TemplateURLModel::QueryTerms terms; 774 ASSERT_EQ(data[i].result, 775 TemplateURLModel::BuildQueryTerms(GURL(data[i].url), &terms)); 776 if (data[i].result) { 777 std::vector<std::string> keys; 778 std::vector<std::string> values; 779 base::SplitString(data[i].keys, ';', &keys); 780 base::SplitString(data[i].values, ';', &values); 781 ASSERT_TRUE(keys.size() == values.size()); 782 ASSERT_EQ(keys.size(), terms.size()); 783 for (size_t j = 0; j < keys.size(); ++j) { 784 TemplateURLModel::QueryTerms::iterator term_iterator = 785 terms.find(keys[j]); 786 ASSERT_TRUE(term_iterator != terms.end()); 787 ASSERT_EQ(values[j], term_iterator->second); 788 } 789 } 790 } 791 } 792 793 TEST_F(TemplateURLModelTest, UpdateKeywordSearchTermsForURL) { 794 struct TestData { 795 const std::string url; 796 const string16 term; 797 } data[] = { 798 { "http://foo/", string16() }, 799 { "http://foo/foo?q=xx", string16() }, 800 { "http://x/bar?q=xx", string16() }, 801 { "http://x/foo?y=xx", string16() }, 802 { "http://x/foo?q=xx", ASCIIToUTF16("xx") }, 803 { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") }, 804 { "http://x/foo?q=b&q=xx", string16() }, 805 }; 806 807 ChangeModelToLoadState(); 808 AddKeywordWithDate("x", false, "http://x/foo?q={searchTerms}", 809 "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name", false, Time()); 810 811 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { 812 history::URLVisitedDetails details; 813 details.row = history::URLRow(GURL(data[i].url)); 814 details.transition = 0; 815 model()->UpdateKeywordSearchTermsForURL(details); 816 EXPECT_EQ(data[i].term, GetAndClearSearchTerm()); 817 } 818 } 819 820 TEST_F(TemplateURLModelTest, DontUpdateKeywordSearchForNonReplaceable) { 821 struct TestData { 822 const std::string url; 823 } data[] = { 824 { "http://foo/" }, 825 { "http://x/bar?q=xx" }, 826 { "http://x/foo?y=xx" }, 827 }; 828 829 ChangeModelToLoadState(); 830 AddKeywordWithDate("x", false, "http://x/foo", "http://sugg1", 831 "http://icon1", "UTF-8;UTF-16", "name", false, Time()); 832 833 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { 834 history::URLVisitedDetails details; 835 details.row = history::URLRow(GURL(data[i].url)); 836 details.transition = 0; 837 model()->UpdateKeywordSearchTermsForURL(details); 838 ASSERT_EQ(string16(), GetAndClearSearchTerm()); 839 } 840 } 841 842 TEST_F(TemplateURLModelTest, ChangeGoogleBaseValue) { 843 // NOTE: Do not do a VerifyLoad() here as it will load the prepopulate data, 844 // which also has a {google:baseURL} keyword in it, which will confuse this 845 // test. 846 ChangeModelToLoadState(); 847 SetGoogleBaseURL("http://google.com/"); 848 const TemplateURL* t_url = AddKeywordWithDate("", true, 849 "{google:baseURL}?q={searchTerms}", "http://sugg1", "http://icon1", 850 "UTF-8;UTF-16", "name", false, Time()); 851 ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com")); 852 EXPECT_EQ("google.com", t_url->url()->GetHost()); 853 EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword()); 854 855 // Change the Google base url. 856 test_util_.ResetObserverCount(); 857 SetGoogleBaseURL("http://foo.com/"); 858 VerifyObserverCount(1); 859 860 // Make sure the host->TemplateURL map was updated appropriately. 861 ASSERT_EQ(t_url, model()->GetTemplateURLForHost("foo.com")); 862 EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL); 863 EXPECT_EQ("foo.com", t_url->url()->GetHost()); 864 EXPECT_EQ(ASCIIToUTF16("foo.com"), t_url->keyword()); 865 EXPECT_EQ("http://foo.com/?q=x", t_url->url()->ReplaceSearchTerms(*t_url, 866 ASCIIToUTF16("x"), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())); 867 } 868 869 struct QueryHistoryCallbackImpl { 870 QueryHistoryCallbackImpl() : success(false) {} 871 872 void Callback(HistoryService::Handle handle, 873 bool success, const history::URLRow* row, 874 history::VisitVector* visits) { 875 this->success = success; 876 if (row) 877 this->row = *row; 878 if (visits) 879 this->visits = *visits; 880 } 881 882 bool success; 883 history::URLRow row; 884 history::VisitVector visits; 885 }; 886 887 // Make sure TemplateURLModel generates a KEYWORD_GENERATED visit for 888 // KEYWORD visits. 889 TEST_F(TemplateURLModelTest, GenerateVisitOnKeyword) { 890 VerifyLoad(); 891 profile()->CreateHistoryService(true, false); 892 893 // Create a keyword. 894 TemplateURL* t_url = AddKeywordWithDate( 895 "keyword", false, "http://foo.com/foo?query={searchTerms}", 896 "http://sugg1", "http://icon1", "UTF-8;UTF-16", "keyword", 897 true, base::Time::Now()); 898 899 // Add a visit that matches the url of the keyword. 900 HistoryService* history = 901 profile()->GetHistoryService(Profile::EXPLICIT_ACCESS); 902 history->AddPage( 903 GURL(t_url->url()->ReplaceSearchTerms(*t_url, ASCIIToUTF16("blah"), 0, 904 string16())), 905 NULL, 0, GURL(), PageTransition::KEYWORD, history::RedirectList(), 906 history::SOURCE_BROWSED, false); 907 908 // Wait for history to finish processing the request. 909 profile()->BlockUntilHistoryProcessesPendingRequests(); 910 911 // Query history for the generated url. 912 CancelableRequestConsumer consumer; 913 QueryHistoryCallbackImpl callback; 914 history->QueryURL(GURL("http://keyword"), true, &consumer, 915 NewCallback(&callback, &QueryHistoryCallbackImpl::Callback)); 916 917 // Wait for the request to be processed. 918 profile()->BlockUntilHistoryProcessesPendingRequests(); 919 920 // And make sure the url and visit were added. 921 EXPECT_TRUE(callback.success); 922 EXPECT_NE(0, callback.row.id()); 923 ASSERT_EQ(1U, callback.visits.size()); 924 EXPECT_EQ(PageTransition::KEYWORD_GENERATED, 925 PageTransition::StripQualifier(callback.visits[0].transition)); 926 } 927 928 // Make sure that the load routine deletes prepopulated engines that no longer 929 // exist in the prepopulate data. 930 TEST_F(TemplateURLModelTest, LoadDeletesUnusedProvider) { 931 // Create a preloaded template url. Add it to a loaded model and wait for the 932 // saves to finish. 933 TemplateURL* t_url = CreatePreloadedTemplateURL(); 934 ChangeModelToLoadState(); 935 model()->Add(t_url); 936 ASSERT_TRUE( 937 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL); 938 BlockTillServiceProcessesRequests(); 939 940 // Ensure that merging clears this engine. 941 ResetModel(true); 942 ASSERT_TRUE( 943 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL); 944 945 // Wait for any saves to finish. 946 BlockTillServiceProcessesRequests(); 947 948 // Reload the model to verify that the database was updated as a result of the 949 // merge. 950 ResetModel(true); 951 ASSERT_TRUE( 952 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL); 953 } 954 955 // Make sure that load routine doesn't delete prepopulated engines that no 956 // longer exist in the prepopulate data if it has been modified by the user. 957 TEST_F(TemplateURLModelTest, LoadRetainsModifiedProvider) { 958 // Create a preloaded template url and add it to a loaded model. 959 TemplateURL* t_url = CreatePreloadedTemplateURL(); 960 t_url->set_safe_for_autoreplace(false); 961 ChangeModelToLoadState(); 962 model()->Add(t_url); 963 964 // Do the copy after t_url is added so that the id is set. 965 TemplateURL copy_t_url = *t_url; 966 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"))); 967 968 // Wait for any saves to finish. 969 BlockTillServiceProcessesRequests(); 970 971 // Ensure that merging won't clear it if the user has edited it. 972 ResetModel(true); 973 const TemplateURL* url_for_unittest = 974 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 975 ASSERT_TRUE(url_for_unittest != NULL); 976 AssertEquals(copy_t_url, *url_for_unittest); 977 978 // Wait for any saves to finish. 979 BlockTillServiceProcessesRequests(); 980 981 // Reload the model to verify that save/reload retains the item. 982 ResetModel(true); 983 ASSERT_TRUE( 984 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL); 985 } 986 987 // Make sure that load routine doesn't delete 988 // prepopulated engines that no longer exist in the prepopulate data if 989 // it has been modified by the user. 990 TEST_F(TemplateURLModelTest, LoadSavesPrepopulatedDefaultSearchProvider) { 991 VerifyLoad(); 992 // Verify that the default search provider is set to something. 993 ASSERT_TRUE(model()->GetDefaultSearchProvider() != NULL); 994 TemplateURL default_url = *model()->GetDefaultSearchProvider(); 995 996 // Wait for any saves to finish. 997 BlockTillServiceProcessesRequests(); 998 999 // Reload the model and check that the default search provider 1000 // was properly saved. 1001 ResetModel(true); 1002 ASSERT_TRUE(model()->GetDefaultSearchProvider() != NULL); 1003 AssertEquals(default_url, *model()->GetDefaultSearchProvider()); 1004 } 1005 1006 // Make sure that the load routine doesn't delete 1007 // prepopulated engines that no longer exist in the prepopulate data if 1008 // it is the default search provider. 1009 TEST_F(TemplateURLModelTest, LoadRetainsDefaultProvider) { 1010 // Set the default search provider to a preloaded template url which 1011 // is not in the current set of preloaded template urls and save 1012 // the result. 1013 TemplateURL* t_url = CreatePreloadedTemplateURL(); 1014 ChangeModelToLoadState(); 1015 model()->Add(t_url); 1016 model()->SetDefaultSearchProvider(t_url); 1017 // Do the copy after t_url is added and set as default so that its 1018 // internal state is correct. 1019 TemplateURL copy_t_url = *t_url; 1020 1021 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"))); 1022 ASSERT_EQ(t_url, model()->GetDefaultSearchProvider()); 1023 BlockTillServiceProcessesRequests(); 1024 1025 // Ensure that merging won't clear the prepopulated template url 1026 // which is no longer present if it's the default engine. 1027 ResetModel(true); 1028 { 1029 const TemplateURL* keyword_url = 1030 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 1031 ASSERT_TRUE(keyword_url != NULL); 1032 AssertEquals(copy_t_url, *keyword_url); 1033 ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider()); 1034 } 1035 1036 // Wait for any saves to finish. 1037 BlockTillServiceProcessesRequests(); 1038 1039 // Reload the model to verify that the update was saved. 1040 ResetModel(true); 1041 { 1042 const TemplateURL* keyword_url = 1043 model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")); 1044 ASSERT_TRUE(keyword_url != NULL); 1045 AssertEquals(copy_t_url, *keyword_url); 1046 ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider()); 1047 } 1048 } 1049 1050 // Make sure that the load routine updates the url of a preexisting 1051 // default search engine provider and that the result is saved correctly. 1052 TEST_F(TemplateURLModelTest, LoadUpdatesDefaultSearchURL) { 1053 TestLoadUpdatingPreloadedURL(0); 1054 } 1055 1056 // Make sure that the load routine updates the url of a preexisting 1057 // non-default search engine provider and that the result is saved correctly. 1058 TEST_F(TemplateURLModelTest, LoadUpdatesSearchURL) { 1059 TestLoadUpdatingPreloadedURL(1); 1060 } 1061 1062 // Make sure that the load does update of auto-keywords correctly. 1063 // This test basically verifies that no asserts or crashes occur 1064 // during this operation. 1065 TEST_F(TemplateURLModelTest, LoadDoesAutoKeywordUpdate) { 1066 string16 prepopulated_url; 1067 TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL( 1068 0, &prepopulated_url); 1069 t_url->set_safe_for_autoreplace(false); 1070 t_url->SetURL("{google:baseURL}?q={searchTerms}", 0, 0); 1071 t_url->set_autogenerate_keyword(true); 1072 1073 // Then add it to the model and save it all. 1074 ChangeModelToLoadState(); 1075 model()->Add(t_url); 1076 BlockTillServiceProcessesRequests(); 1077 1078 // Now reload the model and verify that the merge updates the url. 1079 ResetModel(true); 1080 1081 // Wait for any saves to finish. 1082 BlockTillServiceProcessesRequests(); 1083 } 1084 1085 // Simulates failing to load the webdb and makes sure the default search 1086 // provider is valid. 1087 TEST_F(TemplateURLModelTest, FailedInit) { 1088 VerifyLoad(); 1089 1090 test_util_.ClearModel(); 1091 test_util_.GetWebDataService()->UnloadDatabase(); 1092 test_util_.GetWebDataService()->set_failed_init(true); 1093 1094 ResetModel(false); 1095 model()->Load(); 1096 BlockTillServiceProcessesRequests(); 1097 1098 ASSERT_TRUE(model()->GetDefaultSearchProvider()); 1099 } 1100 1101 // Verifies that if the default search URL preference is managed, we report 1102 // the default search as managed. Also check that we are getting the right 1103 // values. 1104 TEST_F(TemplateURLModelTest, TestManagedDefaultSearch) { 1105 VerifyLoad(); 1106 const size_t initial_count = model()->GetTemplateURLs().size(); 1107 test_util_.ResetObserverCount(); 1108 1109 // Set a regular default search provider. 1110 TemplateURL* regular_default = AddKeywordWithDate("key1", false, 1111 "http://foo1", "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", 1112 true, Time()); 1113 VerifyObserverCount(1); 1114 model()->SetDefaultSearchProvider(regular_default); 1115 // Adding the URL and setting the default search provider should have caused 1116 // notifications. 1117 VerifyObserverCount(1); 1118 EXPECT_FALSE(model()->is_default_search_managed()); 1119 EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 1120 1121 // Set a managed preference that establishes a default search provider. 1122 const char kName[] = "test1"; 1123 const char kSearchURL[] = "http://test.com/search?t={searchTerms}"; 1124 const char kIconURL[] = "http://test.com/icon.jpg"; 1125 const char kEncodings[] = "UTF-16;UTF-32"; 1126 SetManagedDefaultSearchPreferences(true, kName, kSearchURL, "", kIconURL, 1127 kEncodings, ""); 1128 VerifyObserverFired(); 1129 EXPECT_TRUE(model()->is_default_search_managed()); 1130 EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size()); 1131 1132 // Verify that the default manager we are getting is the managed one. 1133 scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL()); 1134 expected_managed_default1->SetURL(kSearchURL, 0, 0); 1135 expected_managed_default1->SetFaviconURL(GURL(kIconURL)); 1136 expected_managed_default1->set_short_name(ASCIIToUTF16("test1")); 1137 std::vector<std::string> encodings_vector; 1138 base::SplitString(kEncodings, ';', &encodings_vector); 1139 expected_managed_default1->set_input_encodings(encodings_vector); 1140 expected_managed_default1->set_show_in_default_list(true); 1141 const TemplateURL* actual_managed_default = 1142 model()->GetDefaultSearchProvider(); 1143 ExpectSimilar(actual_managed_default, expected_managed_default1.get()); 1144 EXPECT_EQ(actual_managed_default->show_in_default_list(), true); 1145 1146 // Update the managed preference and check that the model has changed. 1147 const char kNewName[] = "test2"; 1148 const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}"; 1149 const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}"; 1150 SetManagedDefaultSearchPreferences(true, kNewName, kNewSearchURL, 1151 kNewSuggestURL, "", "", ""); 1152 VerifyObserverFired(); 1153 EXPECT_TRUE(model()->is_default_search_managed()); 1154 EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size()); 1155 1156 // Verify that the default manager we are now getting is the correct one. 1157 scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL()); 1158 expected_managed_default2->SetURL(kNewSearchURL, 0, 0); 1159 expected_managed_default2->SetSuggestionsURL(kNewSuggestURL, 0, 0); 1160 expected_managed_default2->set_short_name(ASCIIToUTF16("test2")); 1161 expected_managed_default2->set_show_in_default_list(true); 1162 actual_managed_default = model()->GetDefaultSearchProvider(); 1163 ExpectSimilar(actual_managed_default, expected_managed_default2.get()); 1164 EXPECT_EQ(actual_managed_default->show_in_default_list(), true); 1165 1166 // Remove all the managed prefs and check that we are no longer managed. 1167 RemoveManagedDefaultSearchPreferences(); 1168 VerifyObserverFired(); 1169 EXPECT_FALSE(model()->is_default_search_managed()); 1170 EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 1171 1172 // The default should now be the first URL added 1173 const TemplateURL* actual_final_managed_default = 1174 model()->GetDefaultSearchProvider(); 1175 ExpectSimilar(actual_final_managed_default, 1176 model()->GetTemplateURLs()[0]); 1177 EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true); 1178 1179 // Disable the default search provider through policy. 1180 SetManagedDefaultSearchPreferences(false, "", "", "", "", "", ""); 1181 VerifyObserverFired(); 1182 EXPECT_TRUE(model()->is_default_search_managed()); 1183 EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider()); 1184 EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size()); 1185 1186 // Re-enable it. 1187 SetManagedDefaultSearchPreferences(true, kName, kSearchURL, "", kIconURL, 1188 kEncodings, ""); 1189 VerifyObserverFired(); 1190 EXPECT_TRUE(model()->is_default_search_managed()); 1191 EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size()); 1192 1193 // Verify that the default manager we are getting is the managed one. 1194 actual_managed_default = model()->GetDefaultSearchProvider(); 1195 ExpectSimilar(actual_managed_default, expected_managed_default1.get()); 1196 EXPECT_EQ(actual_managed_default->show_in_default_list(), true); 1197 } 1198