| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 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/file_util.h" | |
| 6 #include "base/logging.h" | |
| 7 #include "base/path_service.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "chrome/browser/template_url.h" | |
| 10 #include "chrome/browser/template_url_model.h" | |
| 11 #include "chrome/common/pref_service.h" | |
| 12 #include "chrome/test/testing_profile.h" | |
| 13 #include "googleurl/src/gurl.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 | |
| 16 using base::Time; | |
| 17 using base::TimeDelta; | |
| 18 | |
| 19 // A Task used to coordinate when the database has finished processing | |
| 20 // requests. See note in BlockTillServiceProcessesRequests for details. | |
| 21 // | |
| 22 // When Run() schedules a QuitTask on the message loop it was created with. | |
| 23 class QuitTask2 : public Task { | |
| 24 public: | |
| 25 QuitTask2() : main_loop_(MessageLoop::current()) {} | |
| 26 | |
| 27 virtual void Run() { | |
| 28 main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | |
| 29 } | |
| 30 | |
| 31 private: | |
| 32 MessageLoop* main_loop_; | |
| 33 }; | |
| 34 | |
| 35 // Subclass the TestingProfile so that it can return a WebDataService. | |
| 36 class TemplateURLModelTestingProfile : public TestingProfile { | |
| 37 public: | |
| 38 TemplateURLModelTestingProfile() : TestingProfile() { } | |
| 39 | |
| 40 void SetUp() { | |
| 41 // Name a subdirectory of the temp directory. | |
| 42 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_)); | |
| 43 file_util::AppendToPath(&test_dir_, L"TemplateURLModelTest"); | |
| 44 | |
| 45 // Create a fresh, empty copy of this directory. | |
| 46 file_util::Delete(test_dir_, true); | |
| 47 file_util::CreateDirectory(test_dir_); | |
| 48 | |
| 49 std::wstring path = test_dir_; | |
| 50 file_util::AppendToPath(&path, L"TestDataService.db"); | |
| 51 service_ = new WebDataService; | |
| 52 EXPECT_TRUE(service_->InitWithPath(path)); | |
| 53 } | |
| 54 | |
| 55 void TearDown() { | |
| 56 // Clean up the test directory. | |
| 57 service_->Shutdown(); | |
| 58 ASSERT_TRUE(file_util::Delete(test_dir_, true)); | |
| 59 ASSERT_FALSE(file_util::PathExists(test_dir_)); | |
| 60 } | |
| 61 | |
| 62 virtual WebDataService* GetWebDataService(ServiceAccessType access) { | |
| 63 return service_.get(); | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 scoped_refptr<WebDataService> service_; | |
| 68 std::wstring test_dir_; | |
| 69 }; | |
| 70 | |
| 71 // Trivial subclass of TemplateURLModel that records the last invocation of | |
| 72 // SetKeywordSearchTermsForURL. | |
| 73 class TestingTemplateURLModel : public TemplateURLModel { | |
| 74 public: | |
| 75 explicit TestingTemplateURLModel(Profile* profile) | |
| 76 : TemplateURLModel(profile) { | |
| 77 } | |
| 78 | |
| 79 std::wstring GetAndClearSearchTerm() { | |
| 80 std::wstring search_term; | |
| 81 search_term.swap(search_term_); | |
| 82 return search_term; | |
| 83 } | |
| 84 | |
| 85 protected: | |
| 86 virtual void SetKeywordSearchTermsForURL(const TemplateURL* t_url, | |
| 87 const GURL& url, | |
| 88 const std::wstring& term) { | |
| 89 search_term_ = term; | |
| 90 } | |
| 91 | |
| 92 private: | |
| 93 std::wstring search_term_; | |
| 94 | |
| 95 DISALLOW_EVIL_CONSTRUCTORS(TestingTemplateURLModel); | |
| 96 }; | |
| 97 | |
| 98 class TemplateURLModelTest : public testing::Test, | |
| 99 public TemplateURLModelObserver { | |
| 100 public: | |
| 101 TemplateURLModelTest() : changed_count_(0) { | |
| 102 } | |
| 103 | |
| 104 virtual void SetUp() { | |
| 105 profile_.reset(new TemplateURLModelTestingProfile()); | |
| 106 profile_->SetUp(); | |
| 107 model_.reset(new TestingTemplateURLModel(profile_.get())); | |
| 108 model_->AddObserver(this); | |
| 109 } | |
| 110 | |
| 111 virtual void TearDown() { | |
| 112 profile_->TearDown(); | |
| 113 delete TemplateURLRef::google_base_url_; | |
| 114 TemplateURLRef::google_base_url_ = NULL; | |
| 115 | |
| 116 // Flush the message loop to make Purify happy. | |
| 117 message_loop_.RunAllPending(); | |
| 118 } | |
| 119 | |
| 120 TemplateURL* AddKeywordWithDate(const std::wstring& keyword, | |
| 121 bool autogenerate_keyword, | |
| 122 const std::wstring& url, | |
| 123 const std::wstring& short_name, | |
| 124 bool safe_for_autoreplace, | |
| 125 Time created_date) { | |
| 126 TemplateURL* template_url = new TemplateURL(); | |
| 127 template_url->SetURL(url, 0, 0); | |
| 128 template_url->set_keyword(keyword); | |
| 129 template_url->set_autogenerate_keyword(autogenerate_keyword); | |
| 130 template_url->set_short_name(short_name); | |
| 131 template_url->set_date_created(created_date); | |
| 132 template_url->set_safe_for_autoreplace(safe_for_autoreplace); | |
| 133 model_->Add(template_url); | |
| 134 EXPECT_NE(0, template_url->id()); | |
| 135 return template_url; | |
| 136 } | |
| 137 | |
| 138 virtual void OnTemplateURLModelChanged() { | |
| 139 changed_count_++; | |
| 140 } | |
| 141 | |
| 142 void VerifyObserverCount(int expected_changed_count) { | |
| 143 ASSERT_EQ(expected_changed_count, changed_count_); | |
| 144 changed_count_ = 0; | |
| 145 } | |
| 146 | |
| 147 // Blocks the caller until the service has finished servicing all pending | |
| 148 // requests. | |
| 149 void BlockTillServiceProcessesRequests() { | |
| 150 // Schedule a task on the background thread that is processed after all | |
| 151 // pending requests on the background thread. | |
| 152 profile_->GetWebDataService(Profile::EXPLICIT_ACCESS)->thread()-> | |
| 153 message_loop()->PostTask(FROM_HERE, new QuitTask2()); | |
| 154 // Run the current message loop. QuitTask2, when run, invokes Quit, | |
| 155 // which unblocks this. | |
| 156 MessageLoop::current()->Run(); | |
| 157 } | |
| 158 | |
| 159 // Makes sure the load was successful and sent the correct notification. | |
| 160 void VerifyLoad() { | |
| 161 ASSERT_FALSE(model_->loaded()); | |
| 162 model_->Load(); | |
| 163 BlockTillServiceProcessesRequests(); | |
| 164 VerifyObserverCount(1); | |
| 165 changed_count_ = 0; | |
| 166 } | |
| 167 | |
| 168 // Creates a new TemplateURLModel. | |
| 169 void ResetModel(bool verify_load) { | |
| 170 model_.reset(new TestingTemplateURLModel(profile_.get())); | |
| 171 model_->AddObserver(this); | |
| 172 changed_count_ = 0; | |
| 173 if (verify_load) | |
| 174 VerifyLoad(); | |
| 175 } | |
| 176 | |
| 177 // Verifies the two TemplateURLs are equal. | |
| 178 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual) { | |
| 179 ASSERT_EQ(expected.url()->url(), actual.url()->url()); | |
| 180 ASSERT_EQ(expected.keyword(), actual.keyword()); | |
| 181 ASSERT_EQ(expected.short_name(), actual.short_name()); | |
| 182 ASSERT_TRUE(expected.GetFavIconURL() == actual.GetFavIconURL()); | |
| 183 ASSERT_EQ(expected.id(), actual.id()); | |
| 184 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace()); | |
| 185 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list()); | |
| 186 ASSERT_TRUE(expected.date_created() == actual.date_created()); | |
| 187 } | |
| 188 | |
| 189 std::wstring GetAndClearSearchTerm() { | |
| 190 return model_->GetAndClearSearchTerm(); | |
| 191 } | |
| 192 | |
| 193 void SetGoogleBaseURL(const std::wstring& base_url) const { | |
| 194 delete TemplateURLRef::google_base_url_; | |
| 195 TemplateURLRef::google_base_url_ = new std::wstring(base_url); | |
| 196 } | |
| 197 | |
| 198 MessageLoopForUI message_loop_; | |
| 199 scoped_ptr<TemplateURLModelTestingProfile> profile_; | |
| 200 scoped_ptr<TestingTemplateURLModel> model_; | |
| 201 int changed_count_; | |
| 202 }; | |
| 203 | |
| 204 TEST_F(TemplateURLModelTest, Load) { | |
| 205 VerifyLoad(); | |
| 206 } | |
| 207 | |
| 208 TEST_F(TemplateURLModelTest, AddUpdateRemove) { | |
| 209 // Add a new TemplateURL. | |
| 210 VerifyLoad(); | |
| 211 const size_t initial_count = model_->GetTemplateURLs().size(); | |
| 212 | |
| 213 TemplateURL* t_url = new TemplateURL(); | |
| 214 t_url->SetURL(L"http://www.google.com/foo/bar", 0, 0); | |
| 215 t_url->set_keyword(L"keyword"); | |
| 216 t_url->set_short_name(L"google"); | |
| 217 GURL favicon_url("http://favicon.url"); | |
| 218 t_url->SetFavIconURL(favicon_url); | |
| 219 t_url->set_date_created(Time::FromTimeT(100)); | |
| 220 t_url->set_safe_for_autoreplace(true); | |
| 221 model_->Add(t_url); | |
| 222 ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL)); | |
| 223 VerifyObserverCount(1); | |
| 224 BlockTillServiceProcessesRequests(); | |
| 225 // We need to clone as model takes ownership of TemplateURL and will | |
| 226 // delete it. | |
| 227 TemplateURL cloned_url(*t_url); | |
| 228 ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size()); | |
| 229 ASSERT_TRUE(model_->GetTemplateURLForKeyword(t_url->keyword()) == t_url); | |
| 230 ASSERT_TRUE(t_url->date_created() == cloned_url.date_created()); | |
| 231 | |
| 232 // Reload the model to verify it was actually saved to the database. | |
| 233 ResetModel(true); | |
| 234 ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size()); | |
| 235 const TemplateURL* loaded_url = model_->GetTemplateURLForKeyword(L"keyword"); | |
| 236 ASSERT_TRUE(loaded_url != NULL); | |
| 237 AssertEquals(cloned_url, *loaded_url); | |
| 238 ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL)); | |
| 239 | |
| 240 // Mutate an element and verify it succeeded. | |
| 241 model_->ResetTemplateURL(loaded_url, L"a", L"b", L"c"); | |
| 242 ASSERT_EQ(L"a", loaded_url->short_name()); | |
| 243 ASSERT_EQ(L"b", loaded_url->keyword()); | |
| 244 ASSERT_EQ(L"c", loaded_url->url()->url()); | |
| 245 ASSERT_FALSE(loaded_url->safe_for_autoreplace()); | |
| 246 ASSERT_TRUE(model_->CanReplaceKeyword(L"keyword", std::wstring(), NULL)); | |
| 247 ASSERT_FALSE(model_->CanReplaceKeyword(L"b", std::wstring(), NULL)); | |
| 248 cloned_url = *loaded_url; | |
| 249 BlockTillServiceProcessesRequests(); | |
| 250 ResetModel(true); | |
| 251 ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size()); | |
| 252 loaded_url = model_->GetTemplateURLForKeyword(L"b"); | |
| 253 ASSERT_TRUE(loaded_url != NULL); | |
| 254 AssertEquals(cloned_url, *loaded_url); | |
| 255 | |
| 256 // Remove an element and verify it succeeded. | |
| 257 model_->Remove(loaded_url); | |
| 258 VerifyObserverCount(1); | |
| 259 ResetModel(true); | |
| 260 ASSERT_EQ(initial_count, model_->GetTemplateURLs().size()); | |
| 261 EXPECT_TRUE(model_->GetTemplateURLForKeyword(L"b") == NULL); | |
| 262 } | |
| 263 | |
| 264 TEST_F(TemplateURLModelTest, GenerateKeyword) { | |
| 265 ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL(), true)); | |
| 266 // Shouldn't generate keywords for https. | |
| 267 ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("https://blah"), true)); | |
| 268 ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://foo"), | |
| 269 true)); | |
| 270 // www. should be stripped. | |
| 271 ASSERT_EQ(L"foo", TemplateURLModel::GenerateKeyword(GURL("http://www.foo"), | |
| 272 true)); | |
| 273 // Shouldn't generate keywords with paths, if autodetected. | |
| 274 ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), | |
| 275 true)); | |
| 276 ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), | |
| 277 false)); | |
| 278 // FTP shouldn't generate a keyword. | |
| 279 ASSERT_EQ(L"", TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true)); | |
| 280 // Make sure we don't get a trailing / | |
| 281 ASSERT_EQ(L"blah", TemplateURLModel::GenerateKeyword(GURL("http://blah/"), | |
| 282 true)); | |
| 283 } | |
| 284 | |
| 285 TEST_F(TemplateURLModelTest, ClearBrowsingData_Keywords) { | |
| 286 Time now = Time::Now(); | |
| 287 TimeDelta one_day = TimeDelta::FromDays(1); | |
| 288 Time month_ago = now - TimeDelta::FromDays(30); | |
| 289 | |
| 290 // Nothing has been added. | |
| 291 EXPECT_EQ(0U, model_->GetTemplateURLs().size()); | |
| 292 | |
| 293 // Create one with a 0 time. | |
| 294 AddKeywordWithDate(L"key1", false, L"http://foo1", L"name1", true, Time()); | |
| 295 // Create one for now and +/- 1 day. | |
| 296 AddKeywordWithDate(L"key2", false, L"http://foo2", L"name2", true, | |
| 297 now - one_day); | |
| 298 AddKeywordWithDate(L"key3", false, L"http://foo3", L"name3", true, now); | |
| 299 AddKeywordWithDate(L"key4", false, L"http://foo4", L"name4", true, | |
| 300 now + one_day); | |
| 301 // Try the other three states. | |
| 302 AddKeywordWithDate(L"key5", false, L"http://foo5", L"name5", false, now); | |
| 303 AddKeywordWithDate(L"key6", false, L"http://foo6", L"name6", false, month_ago)
; | |
| 304 | |
| 305 // We just added a few items, validate them. | |
| 306 EXPECT_EQ(6U, model_->GetTemplateURLs().size()); | |
| 307 | |
| 308 // Try removing from current timestamp. This should delete the one in the | |
| 309 // future and one very recent one. | |
| 310 model_->RemoveAutoGeneratedSince(now); | |
| 311 EXPECT_EQ(4U, model_->GetTemplateURLs().size()); | |
| 312 | |
| 313 // Try removing from two months ago. This should only delete items that are | |
| 314 // auto-generated. | |
| 315 model_->RemoveAutoGeneratedSince(now - TimeDelta::FromDays(60)); | |
| 316 EXPECT_EQ(3U, model_->GetTemplateURLs().size()); | |
| 317 | |
| 318 // Make sure the right values remain. | |
| 319 EXPECT_EQ(L"key1", model_->GetTemplateURLs()[0]->keyword()); | |
| 320 EXPECT_TRUE(model_->GetTemplateURLs()[0]->safe_for_autoreplace()); | |
| 321 EXPECT_EQ(0U, model_->GetTemplateURLs()[0]->date_created().ToInternalValue()); | |
| 322 | |
| 323 EXPECT_EQ(L"key5", model_->GetTemplateURLs()[1]->keyword()); | |
| 324 EXPECT_FALSE(model_->GetTemplateURLs()[1]->safe_for_autoreplace()); | |
| 325 EXPECT_EQ(now.ToInternalValue(), | |
| 326 model_->GetTemplateURLs()[1]->date_created().ToInternalValue()); | |
| 327 | |
| 328 EXPECT_EQ(L"key6", model_->GetTemplateURLs()[2]->keyword()); | |
| 329 EXPECT_FALSE(model_->GetTemplateURLs()[2]->safe_for_autoreplace()); | |
| 330 EXPECT_EQ(month_ago.ToInternalValue(), | |
| 331 model_->GetTemplateURLs()[2]->date_created().ToInternalValue()); | |
| 332 | |
| 333 // Try removing from Time=0. This should delete one more. | |
| 334 model_->RemoveAutoGeneratedSince(Time()); | |
| 335 EXPECT_EQ(2U, model_->GetTemplateURLs().size()); | |
| 336 } | |
| 337 | |
| 338 TEST_F(TemplateURLModelTest, Reset) { | |
| 339 // Add a new TemplateURL. | |
| 340 VerifyLoad(); | |
| 341 const size_t initial_count = model_->GetTemplateURLs().size(); | |
| 342 TemplateURL* t_url = new TemplateURL(); | |
| 343 t_url->SetURL(L"http://www.google.com/foo/bar", 0, 0); | |
| 344 t_url->set_keyword(L"keyword"); | |
| 345 t_url->set_short_name(L"google"); | |
| 346 GURL favicon_url("http://favicon.url"); | |
| 347 t_url->SetFavIconURL(favicon_url); | |
| 348 t_url->set_date_created(Time::FromTimeT(100)); | |
| 349 model_->Add(t_url); | |
| 350 | |
| 351 VerifyObserverCount(1); | |
| 352 BlockTillServiceProcessesRequests(); | |
| 353 | |
| 354 // Reset the short name, keyword, url and make sure it takes. | |
| 355 const std::wstring new_short_name(L"a"); | |
| 356 const std::wstring new_keyword(L"b"); | |
| 357 const std::wstring new_url(L"c"); | |
| 358 model_->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url); | |
| 359 ASSERT_EQ(new_short_name, t_url->short_name()); | |
| 360 ASSERT_EQ(new_keyword, t_url->keyword()); | |
| 361 ASSERT_EQ(new_url, t_url->url()->url()); | |
| 362 | |
| 363 // Make sure the mappings in the model were updated. | |
| 364 ASSERT_TRUE(model_->GetTemplateURLForKeyword(new_keyword) == t_url); | |
| 365 ASSERT_TRUE(model_->GetTemplateURLForKeyword(L"keyword") == NULL); | |
| 366 | |
| 367 TemplateURL last_url = *t_url; | |
| 368 | |
| 369 // Reload the model from the database and make sure the change took. | |
| 370 ResetModel(true); | |
| 371 t_url = NULL; | |
| 372 EXPECT_EQ(initial_count + 1, model_->GetTemplateURLs().size()); | |
| 373 const TemplateURL* read_url = model_->GetTemplateURLForKeyword(new_keyword); | |
| 374 ASSERT_TRUE(read_url); | |
| 375 AssertEquals(last_url, *read_url); | |
| 376 } | |
| 377 | |
| 378 TEST_F(TemplateURLModelTest, DefaultSearchProvider) { | |
| 379 // Add a new TemplateURL. | |
| 380 VerifyLoad(); | |
| 381 const size_t initial_count = model_->GetTemplateURLs().size(); | |
| 382 TemplateURL* t_url = AddKeywordWithDate(L"key1", false, L"http://foo1", | |
| 383 L"name1", true, Time()); | |
| 384 | |
| 385 changed_count_ = 0; | |
| 386 model_->SetDefaultSearchProvider(t_url); | |
| 387 | |
| 388 ASSERT_EQ(t_url, model_->GetDefaultSearchProvider()); | |
| 389 | |
| 390 ASSERT_TRUE(t_url->safe_for_autoreplace()); | |
| 391 ASSERT_TRUE(t_url->show_in_default_list()); | |
| 392 | |
| 393 // Setting the default search provider should have caused notification. | |
| 394 VerifyObserverCount(1); | |
| 395 | |
| 396 BlockTillServiceProcessesRequests(); | |
| 397 | |
| 398 TemplateURL cloned_url = *t_url; | |
| 399 | |
| 400 ResetModel(true); | |
| 401 t_url = NULL; | |
| 402 | |
| 403 // Make sure when we reload we get a default search provider. | |
| 404 EXPECT_EQ(1 + initial_count, model_->GetTemplateURLs().size()); | |
| 405 ASSERT_TRUE(model_->GetDefaultSearchProvider()); | |
| 406 AssertEquals(cloned_url, *model_->GetDefaultSearchProvider()); | |
| 407 } | |
| 408 | |
| 409 TEST_F(TemplateURLModelTest, TemplateURLWithNoKeyword) { | |
| 410 VerifyLoad(); | |
| 411 | |
| 412 const size_t initial_count = model_->GetTemplateURLs().size(); | |
| 413 | |
| 414 AddKeywordWithDate(std::wstring(), false, L"http://foo1", L"name1", true, | |
| 415 Time()); | |
| 416 | |
| 417 // We just added a few items, validate them. | |
| 418 ASSERT_EQ(initial_count + 1, model_->GetTemplateURLs().size()); | |
| 419 | |
| 420 // Reload the model from the database and make sure we get the url back. | |
| 421 ResetModel(true); | |
| 422 | |
| 423 ASSERT_EQ(1 + initial_count, model_->GetTemplateURLs().size()); | |
| 424 | |
| 425 bool found_keyword = false; | |
| 426 for (size_t i = 0; i < initial_count + 1; ++i) { | |
| 427 if (model_->GetTemplateURLs()[i]->keyword().empty()) { | |
| 428 found_keyword = true; | |
| 429 break; | |
| 430 } | |
| 431 } | |
| 432 ASSERT_TRUE(found_keyword); | |
| 433 } | |
| 434 | |
| 435 TEST_F(TemplateURLModelTest, CantReplaceWithSameKeyword) { | |
| 436 ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", std::wstring(), NULL)); | |
| 437 TemplateURL* t_url = AddKeywordWithDate(L"foo", false, L"http://foo1", | |
| 438 L"name1", true, Time()); | |
| 439 | |
| 440 // Can still replace, newly added template url is marked safe to replace. | |
| 441 ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", L"http://foo2", NULL)); | |
| 442 | |
| 443 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should | |
| 444 // no longer be replaceable. | |
| 445 model_->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(), | |
| 446 t_url->url()->url()); | |
| 447 | |
| 448 ASSERT_FALSE(model_->CanReplaceKeyword(L"foo", L"http://foo2", NULL)); | |
| 449 } | |
| 450 | |
| 451 TEST_F(TemplateURLModelTest, CantReplaceWithSameHosts) { | |
| 452 ASSERT_TRUE(model_->CanReplaceKeyword(L"foo", L"http://foo.com", NULL)); | |
| 453 TemplateURL* t_url = AddKeywordWithDate(L"foo", false, L"http://foo.com", | |
| 454 L"name1", true, Time()); | |
| 455 | |
| 456 // Can still replace, newly added template url is marked safe to replace. | |
| 457 ASSERT_TRUE(model_->CanReplaceKeyword(L"bar", L"http://foo.com", NULL)); | |
| 458 | |
| 459 // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should | |
| 460 // no longer be replaceable. | |
| 461 model_->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(), | |
| 462 t_url->url()->url()); | |
| 463 | |
| 464 ASSERT_FALSE(model_->CanReplaceKeyword(L"bar", L"http://foo.com", NULL)); | |
| 465 } | |
| 466 | |
| 467 TEST_F(TemplateURLModelTest, HasDefaultSearchProvider) { | |
| 468 // We should have a default search provider even if we haven't loaded. | |
| 469 ASSERT_TRUE(model_->GetDefaultSearchProvider()); | |
| 470 | |
| 471 // Now force the model to load and make sure we still have a default. | |
| 472 VerifyLoad(); | |
| 473 | |
| 474 ASSERT_TRUE(model_->GetDefaultSearchProvider()); | |
| 475 } | |
| 476 | |
| 477 TEST_F(TemplateURLModelTest, DefaultSearchProviderLoadedFromPrefs) { | |
| 478 VerifyLoad(); | |
| 479 | |
| 480 TemplateURL* template_url = new TemplateURL(); | |
| 481 template_url->SetURL(L"http://url", 0, 0); | |
| 482 template_url->SetSuggestionsURL(L"http://url2", 0, 0); | |
| 483 template_url->set_short_name(L"a"); | |
| 484 template_url->set_safe_for_autoreplace(true); | |
| 485 template_url->set_date_created(Time::FromTimeT(100)); | |
| 486 | |
| 487 model_->Add(template_url); | |
| 488 | |
| 489 const TemplateURL::IDType id = template_url->id(); | |
| 490 | |
| 491 model_->SetDefaultSearchProvider(template_url); | |
| 492 | |
| 493 BlockTillServiceProcessesRequests(); | |
| 494 | |
| 495 TemplateURL first_default_search_provider = *template_url; | |
| 496 | |
| 497 template_url = NULL; | |
| 498 | |
| 499 // Reset the model and don't load it. The template url we set as the default | |
| 500 // should be pulled from prefs now. | |
| 501 ResetModel(false); | |
| 502 | |
| 503 // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs | |
| 504 // value are persisted to prefs. | |
| 505 const TemplateURL* default_turl = model_->GetDefaultSearchProvider(); | |
| 506 ASSERT_TRUE(default_turl); | |
| 507 ASSERT_TRUE(default_turl->url()); | |
| 508 ASSERT_EQ(L"http://url", default_turl->url()->url()); | |
| 509 ASSERT_TRUE(default_turl->suggestions_url()); | |
| 510 ASSERT_EQ(L"http://url2", default_turl->suggestions_url()->url()); | |
| 511 ASSERT_EQ(L"a", default_turl->short_name()); | |
| 512 ASSERT_EQ(id, default_turl->id()); | |
| 513 | |
| 514 // Now do a load and make sure the default search provider really takes. | |
| 515 VerifyLoad(); | |
| 516 | |
| 517 ASSERT_TRUE(model_->GetDefaultSearchProvider()); | |
| 518 AssertEquals(first_default_search_provider, | |
| 519 *model_->GetDefaultSearchProvider()); | |
| 520 } | |
| 521 | |
| 522 TEST_F(TemplateURLModelTest, BuildQueryTerms) { | |
| 523 struct TestData { | |
| 524 const std::string url; | |
| 525 const bool result; | |
| 526 // Keys and values are a semicolon separated list of expected values in the | |
| 527 // map. | |
| 528 const std::string keys; | |
| 529 const std::string values; | |
| 530 } data[] = { | |
| 531 // No query should return false. | |
| 532 { "http://blah/", false, "", "" }, | |
| 533 | |
| 534 // Query with empty key should return false. | |
| 535 { "http://blah/foo?=y", false, "", "" }, | |
| 536 | |
| 537 // Query with key occurring multiple times should return false. | |
| 538 { "http://blah/foo?x=y&x=z", false, "", "" }, | |
| 539 | |
| 540 { "http://blah/foo?x=y", true, "x", "y" }, | |
| 541 { "http://blah/foo?x=y&y=z", true, "x;y", "y;z" }, | |
| 542 | |
| 543 // Key occurring multiple times should get an empty string. | |
| 544 { "http://blah/foo?x=y&x=z&y=z", true, "x;y", ";z" }, | |
| 545 }; | |
| 546 | |
| 547 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | |
| 548 TemplateURLModel::QueryTerms terms; | |
| 549 ASSERT_EQ(data[i].result, | |
| 550 TemplateURLModel::BuildQueryTerms(GURL(data[i].url), &terms)); | |
| 551 if (data[i].result) { | |
| 552 std::vector<std::string> keys; | |
| 553 std::vector<std::string> values; | |
| 554 SplitString(data[i].keys, ';', &keys); | |
| 555 SplitString(data[i].values, ';', &values); | |
| 556 ASSERT_TRUE(keys.size() == values.size()); | |
| 557 ASSERT_EQ(keys.size(), terms.size()); | |
| 558 for (size_t j = 0; j < keys.size(); ++j) { | |
| 559 TemplateURLModel::QueryTerms::iterator term_iterator = | |
| 560 terms.find(keys[j]); | |
| 561 ASSERT_TRUE(term_iterator != terms.end()); | |
| 562 ASSERT_EQ(values[j], term_iterator->second); | |
| 563 } | |
| 564 } | |
| 565 } | |
| 566 } | |
| 567 | |
| 568 TEST_F(TemplateURLModelTest, UpdateKeywordSearchTermsForURL) { | |
| 569 struct TestData { | |
| 570 const std::string url; | |
| 571 const std::wstring term; | |
| 572 } data[] = { | |
| 573 { "http://foo/", L"" }, | |
| 574 { "http://foo/foo?q=xx", L"" }, | |
| 575 { "http://x/bar?q=xx", L"" }, | |
| 576 { "http://x/foo?y=xx", L"" }, | |
| 577 { "http://x/foo?q=xx", L"xx" }, | |
| 578 { "http://x/foo?a=b&q=xx", L"xx" }, | |
| 579 { "http://x/foo?q=b&q=xx", L"" }, | |
| 580 }; | |
| 581 | |
| 582 AddKeywordWithDate(L"x", false, L"http://x/foo?q={searchTerms}", L"name", | |
| 583 false, Time()); | |
| 584 | |
| 585 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | |
| 586 model_->UpdateKeywordSearchTermsForURL(history::URLRow(GURL(data[i].url))); | |
| 587 EXPECT_EQ(data[i].term, GetAndClearSearchTerm()); | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 TEST_F(TemplateURLModelTest, DontUpdateKeywordSearchForNonReplaceable) { | |
| 592 struct TestData { | |
| 593 const std::string url; | |
| 594 } data[] = { | |
| 595 { "http://foo/" }, | |
| 596 { "http://x/bar?q=xx" }, | |
| 597 { "http://x/foo?y=xx" }, | |
| 598 }; | |
| 599 | |
| 600 AddKeywordWithDate(L"x", false, L"http://x/foo", L"name", false, Time()); | |
| 601 | |
| 602 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { | |
| 603 model_->UpdateKeywordSearchTermsForURL(history::URLRow(GURL(data[i].url))); | |
| 604 ASSERT_EQ(std::wstring(), GetAndClearSearchTerm()); | |
| 605 } | |
| 606 } | |
| 607 | |
| 608 TEST_F(TemplateURLModelTest, ChangeGoogleBaseValue) { | |
| 609 // NOTE: Do not do a VerifyLoad() here as it will load the prepopulate data, | |
| 610 // which also has a {google:baseURL} keyword in it, which will confuse this | |
| 611 // test. | |
| 612 SetGoogleBaseURL(L"http://google.com/"); | |
| 613 const TemplateURL* t_url = AddKeywordWithDate(std::wstring(), true, | |
| 614 L"{google:baseURL}?q={searchTerms}", L"name", false, Time()); | |
| 615 ASSERT_EQ(t_url, model_->GetTemplateURLForHost("google.com")); | |
| 616 EXPECT_EQ("google.com", t_url->url()->GetHost()); | |
| 617 EXPECT_EQ(L"google.com", t_url->keyword()); | |
| 618 | |
| 619 // Change the Google base url. | |
| 620 model_->loaded_ = true; // Hack to make sure we get notified of the base URL | |
| 621 // changing. | |
| 622 SetGoogleBaseURL(L"http://foo.com/"); | |
| 623 model_->GoogleBaseURLChanged(); | |
| 624 VerifyObserverCount(1); | |
| 625 | |
| 626 // Make sure the host->TemplateURL map was updated appropriately. | |
| 627 ASSERT_EQ(t_url, model_->GetTemplateURLForHost("foo.com")); | |
| 628 EXPECT_TRUE(model_->GetTemplateURLForHost("google.com") == NULL); | |
| 629 EXPECT_EQ("foo.com", t_url->url()->GetHost()); | |
| 630 EXPECT_EQ(L"foo.com", t_url->keyword()); | |
| 631 EXPECT_EQ("http://foo.com/?q=x", t_url->url()->ReplaceSearchTerms(*t_url, | |
| 632 L"x", TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, std::wstring()).spec()); | |
| 633 } | |
| OLD | NEW |