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