| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/search_engines/template_url_service.h" |
| 6 |
| 5 #include "base/bind.h" | 7 #include "base/bind.h" |
| 6 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 7 #include "base/callback.h" | 9 #include "base/callback.h" |
| 8 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
| 10 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 11 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 12 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/task/cancelable_task_tracker.h" | 17 #include "base/task/cancelable_task_tracker.h" |
| 15 #include "base/test/mock_time_provider.h" | 18 #include "base/test/simple_test_clock.h" |
| 16 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
| 17 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 18 #include "chrome/browser/history/history_service.h" | 21 #include "chrome/browser/history/history_service.h" |
| 19 #include "chrome/browser/history/history_service_factory.h" | 22 #include "chrome/browser/history/history_service_factory.h" |
| 20 #include "chrome/browser/search_engines/template_url_service_test_util.h" | 23 #include "chrome/browser/search_engines/template_url_service_test_util.h" |
| 21 #include "chrome/test/base/testing_profile.h" | 24 #include "chrome/test/base/testing_profile.h" |
| 22 #include "components/search_engines/keyword_web_data_service.h" | 25 #include "components/search_engines/keyword_web_data_service.h" |
| 23 #include "components/search_engines/search_host_to_urls_map.h" | 26 #include "components/search_engines/search_host_to_urls_map.h" |
| 24 #include "components/search_engines/search_terms_data.h" | 27 #include "components/search_engines/search_terms_data.h" |
| 25 #include "components/search_engines/template_url.h" | 28 #include "components/search_engines/template_url.h" |
| 26 #include "components/search_engines/template_url_prepopulate_data.h" | 29 #include "components/search_engines/template_url_prepopulate_data.h" |
| 27 #include "components/search_engines/template_url_service.h" | |
| 28 #include "content/public/test/test_browser_thread_bundle.h" | 30 #include "content/public/test/test_browser_thread_bundle.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
| 30 | 32 |
| 31 using base::ASCIIToUTF16; | 33 using base::ASCIIToUTF16; |
| 32 using base::Time; | 34 using base::Time; |
| 33 using base::TimeDelta; | 35 using base::TimeDelta; |
| 34 using ::testing::Return; | |
| 35 using ::testing::StrictMock; | |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 // QueryHistoryCallbackImpl --------------------------------------------------- | 39 // QueryHistoryCallbackImpl --------------------------------------------------- |
| 40 | 40 |
| 41 struct QueryHistoryCallbackImpl { | 41 struct QueryHistoryCallbackImpl { |
| 42 QueryHistoryCallbackImpl() : success(false) {} | 42 QueryHistoryCallbackImpl() : success(false) {} |
| 43 | 43 |
| 44 void Callback(bool success, | 44 void Callback(bool success, |
| 45 const history::URLRow& row, | 45 const history::URLRow& row, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 const std::string& alternate_url, | 143 const std::string& alternate_url, |
| 144 const std::string& favicon_url, | 144 const std::string& favicon_url, |
| 145 bool safe_for_autoreplace, | 145 bool safe_for_autoreplace, |
| 146 const std::string& encodings, | 146 const std::string& encodings, |
| 147 Time date_created, | 147 Time date_created, |
| 148 Time last_modified); | 148 Time last_modified); |
| 149 | 149 |
| 150 // Verifies the two TemplateURLs are equal. | 150 // Verifies the two TemplateURLs are equal. |
| 151 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual); | 151 void AssertEquals(const TemplateURL& expected, const TemplateURL& actual); |
| 152 | 152 |
| 153 // Verifies the two timestamps are equal, within the expected degree of |
| 154 // precision. |
| 155 void AssertTimesEqual(const base::Time& expected, const base::Time& actual); |
| 156 |
| 153 // Create an URL that appears to have been prepopulated, but won't be in the | 157 // Create an URL that appears to have been prepopulated, but won't be in the |
| 154 // current data. The caller owns the returned TemplateURL*. | 158 // current data. The caller owns the returned TemplateURL*. |
| 155 TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace, | 159 TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace, |
| 156 int prepopulate_id); | 160 int prepopulate_id); |
| 157 | 161 |
| 158 // Helper methods to make calling TemplateURLServiceTestUtil methods less | 162 // Helper methods to make calling TemplateURLServiceTestUtil methods less |
| 159 // visually noisy in the test code. | 163 // visually noisy in the test code. |
| 160 void VerifyObserverCount(int expected_changed_count); | 164 void VerifyObserverCount(int expected_changed_count); |
| 161 void VerifyObserverFired(); | 165 void VerifyObserverFired(); |
| 162 TemplateURLServiceTestUtil* test_util() { return test_util_.get(); } | 166 TemplateURLServiceTestUtil* test_util() { return test_util_.get(); } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 ASSERT_EQ(expected.keyword(), actual.keyword()); | 224 ASSERT_EQ(expected.keyword(), actual.keyword()); |
| 221 ASSERT_EQ(expected.url(), actual.url()); | 225 ASSERT_EQ(expected.url(), actual.url()); |
| 222 ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url()); | 226 ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url()); |
| 223 ASSERT_EQ(expected.favicon_url(), actual.favicon_url()); | 227 ASSERT_EQ(expected.favicon_url(), actual.favicon_url()); |
| 224 ASSERT_EQ(expected.alternate_urls(), actual.alternate_urls()); | 228 ASSERT_EQ(expected.alternate_urls(), actual.alternate_urls()); |
| 225 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list()); | 229 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list()); |
| 226 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace()); | 230 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace()); |
| 227 ASSERT_EQ(expected.input_encodings(), actual.input_encodings()); | 231 ASSERT_EQ(expected.input_encodings(), actual.input_encodings()); |
| 228 ASSERT_EQ(expected.id(), actual.id()); | 232 ASSERT_EQ(expected.id(), actual.id()); |
| 229 ASSERT_EQ(expected.date_created(), actual.date_created()); | 233 ASSERT_EQ(expected.date_created(), actual.date_created()); |
| 230 ASSERT_EQ(expected.last_modified(), actual.last_modified()); | 234 AssertTimesEqual(expected.last_modified(), actual.last_modified()); |
| 231 ASSERT_EQ(expected.sync_guid(), actual.sync_guid()); | 235 ASSERT_EQ(expected.sync_guid(), actual.sync_guid()); |
| 232 ASSERT_EQ(expected.search_terms_replacement_key(), | 236 ASSERT_EQ(expected.search_terms_replacement_key(), |
| 233 actual.search_terms_replacement_key()); | 237 actual.search_terms_replacement_key()); |
| 234 } | 238 } |
| 235 | 239 |
| 240 void TemplateURLServiceTest::AssertTimesEqual(const base::Time& expected, |
| 241 const base::Time& actual) { |
| 242 // Because times are stored with a granularity of one second, there is a loss |
| 243 // of precision when serializing and deserializing the timestamps. Hence, only |
| 244 // expect timestamps to be equal to within one second of one another. |
| 245 ASSERT_LT((expected - actual).magnitude(), base::TimeDelta::FromSeconds(1)); |
| 246 } |
| 247 |
| 236 TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL( | 248 TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL( |
| 237 bool safe_for_autoreplace, | 249 bool safe_for_autoreplace, |
| 238 int prepopulate_id) { | 250 int prepopulate_id) { |
| 239 TemplateURLData data; | 251 TemplateURLData data; |
| 240 data.short_name = ASCIIToUTF16("unittest"); | 252 data.short_name = ASCIIToUTF16("unittest"); |
| 241 data.SetKeyword(ASCIIToUTF16("unittest")); | 253 data.SetKeyword(ASCIIToUTF16("unittest")); |
| 242 data.SetURL("http://www.unittest.com/{searchTerms}"); | 254 data.SetURL("http://www.unittest.com/{searchTerms}"); |
| 243 data.favicon_url = GURL("http://favicon.url"); | 255 data.favicon_url = GURL("http://favicon.url"); |
| 244 data.show_in_default_list = true; | 256 data.show_in_default_list = true; |
| 245 data.safe_for_autoreplace = safe_for_autoreplace; | 257 data.safe_for_autoreplace = safe_for_autoreplace; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 test_util()->ResetModel(true); | 310 test_util()->ResetModel(true); |
| 299 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); | 311 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); |
| 300 TemplateURL* loaded_url = | 312 TemplateURL* loaded_url = |
| 301 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")); | 313 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")); |
| 302 ASSERT_TRUE(loaded_url != NULL); | 314 ASSERT_TRUE(loaded_url != NULL); |
| 303 AssertEquals(*cloned_url, *loaded_url); | 315 AssertEquals(*cloned_url, *loaded_url); |
| 304 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(), | 316 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(), |
| 305 NULL)); | 317 NULL)); |
| 306 | 318 |
| 307 // We expect the last_modified time to be updated to the present time on an | 319 // We expect the last_modified time to be updated to the present time on an |
| 308 // explicit reset. We have to set up the expectation here because ResetModel | 320 // explicit reset. |
| 309 // resets the TimeProvider in the TemplateURLService. | 321 base::Time now = base::Time::Now(); |
| 310 StrictMock<base::MockTimeProvider> mock_time; | 322 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); |
| 311 model()->set_time_provider(&base::MockTimeProvider::StaticNow); | 323 clock->SetNow(now); |
| 312 EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337))); | 324 model()->set_clock(clock.Pass()); |
| 313 | 325 |
| 314 // Mutate an element and verify it succeeded. | 326 // Mutate an element and verify it succeeded. |
| 315 model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"), | 327 model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"), |
| 316 "c"); | 328 "c"); |
| 317 ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name()); | 329 ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name()); |
| 318 ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword()); | 330 ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword()); |
| 319 ASSERT_EQ("c", loaded_url->url()); | 331 ASSERT_EQ("c", loaded_url->url()); |
| 320 ASSERT_FALSE(loaded_url->safe_for_autoreplace()); | 332 ASSERT_FALSE(loaded_url->safe_for_autoreplace()); |
| 321 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(), | 333 ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(), |
| 322 NULL)); | 334 NULL)); |
| 323 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL)); | 335 ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL)); |
| 324 cloned_url.reset(new TemplateURL(loaded_url->data())); | 336 cloned_url.reset(new TemplateURL(loaded_url->data())); |
| 325 base::RunLoop().RunUntilIdle(); | 337 base::RunLoop().RunUntilIdle(); |
| 326 test_util()->ResetModel(true); | 338 test_util()->ResetModel(true); |
| 327 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); | 339 ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); |
| 328 loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")); | 340 loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")); |
| 329 ASSERT_TRUE(loaded_url != NULL); | 341 ASSERT_TRUE(loaded_url != NULL); |
| 330 AssertEquals(*cloned_url, *loaded_url); | 342 AssertEquals(*cloned_url, *loaded_url); |
| 331 // We changed a TemplateURL in the service, so ensure that the time was | 343 // We changed a TemplateURL in the service, so ensure that the time was |
| 332 // updated. | 344 // updated. |
| 333 ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified()); | 345 AssertTimesEqual(now, loaded_url->last_modified()); |
| 334 | 346 |
| 335 // Remove an element and verify it succeeded. | 347 // Remove an element and verify it succeeded. |
| 336 model()->Remove(loaded_url); | 348 model()->Remove(loaded_url); |
| 337 VerifyObserverCount(1); | 349 VerifyObserverCount(1); |
| 338 test_util()->ResetModel(true); | 350 test_util()->ResetModel(true); |
| 339 ASSERT_EQ(initial_count, model()->GetTemplateURLs().size()); | 351 ASSERT_EQ(initial_count, model()->GetTemplateURLs().size()); |
| 340 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL); | 352 EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL); |
| 341 } | 353 } |
| 342 | 354 |
| 343 TEST_F(TemplateURLServiceTest, AddSameKeyword) { | 355 TEST_F(TemplateURLServiceTest, AddSameKeyword) { |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 data.SetURL("http://www.google.com/foo/bar"); | 625 data.SetURL("http://www.google.com/foo/bar"); |
| 614 data.favicon_url = GURL("http://favicon.url"); | 626 data.favicon_url = GURL("http://favicon.url"); |
| 615 data.date_created = Time::FromTimeT(100); | 627 data.date_created = Time::FromTimeT(100); |
| 616 data.last_modified = Time::FromTimeT(100); | 628 data.last_modified = Time::FromTimeT(100); |
| 617 TemplateURL* t_url = new TemplateURL(data); | 629 TemplateURL* t_url = new TemplateURL(data); |
| 618 model()->Add(t_url); | 630 model()->Add(t_url); |
| 619 | 631 |
| 620 VerifyObserverCount(1); | 632 VerifyObserverCount(1); |
| 621 base::RunLoop().RunUntilIdle(); | 633 base::RunLoop().RunUntilIdle(); |
| 622 | 634 |
| 623 StrictMock<base::MockTimeProvider> mock_time; | 635 base::Time now = base::Time::Now(); |
| 624 model()->set_time_provider(&base::MockTimeProvider::StaticNow); | 636 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); |
| 625 EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337))); | 637 clock->SetNow(now); |
| 638 model()->set_clock(clock.Pass()); |
| 626 | 639 |
| 627 // Reset the short name, keyword, url and make sure it takes. | 640 // Reset the short name, keyword, url and make sure it takes. |
| 628 const base::string16 new_short_name(ASCIIToUTF16("a")); | 641 const base::string16 new_short_name(ASCIIToUTF16("a")); |
| 629 const base::string16 new_keyword(ASCIIToUTF16("b")); | 642 const base::string16 new_keyword(ASCIIToUTF16("b")); |
| 630 const std::string new_url("c"); | 643 const std::string new_url("c"); |
| 631 model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url); | 644 model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url); |
| 632 ASSERT_EQ(new_short_name, t_url->short_name()); | 645 ASSERT_EQ(new_short_name, t_url->short_name()); |
| 633 ASSERT_EQ(new_keyword, t_url->keyword()); | 646 ASSERT_EQ(new_keyword, t_url->keyword()); |
| 634 ASSERT_EQ(new_url, t_url->url()); | 647 ASSERT_EQ(new_url, t_url->url()); |
| 635 | 648 |
| 636 // Make sure the mappings in the model were updated. | 649 // Make sure the mappings in the model were updated. |
| 637 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword)); | 650 ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword)); |
| 638 ASSERT_TRUE( | 651 ASSERT_TRUE( |
| 639 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL); | 652 model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL); |
| 640 | 653 |
| 641 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data())); | 654 scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->data())); |
| 642 | 655 |
| 643 // Reload the model from the database and make sure the change took. | 656 // Reload the model from the database and make sure the change took. |
| 644 test_util()->ResetModel(true); | 657 test_util()->ResetModel(true); |
| 645 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); | 658 EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size()); |
| 646 const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword); | 659 const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword); |
| 647 ASSERT_TRUE(read_url); | 660 ASSERT_TRUE(read_url); |
| 648 AssertEquals(*cloned_url, *read_url); | 661 AssertEquals(*cloned_url, *read_url); |
| 649 ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified()); | 662 AssertTimesEqual(now, read_url->last_modified()); |
| 650 } | 663 } |
| 651 | 664 |
| 652 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) { | 665 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) { |
| 653 // Add a new TemplateURL. | 666 // Add a new TemplateURL. |
| 654 test_util()->VerifyLoad(); | 667 test_util()->VerifyLoad(); |
| 655 const size_t initial_count = model()->GetTemplateURLs().size(); | 668 const size_t initial_count = model()->GetTemplateURLs().size(); |
| 656 TemplateURL* t_url = AddKeywordWithDate( | 669 TemplateURL* t_url = AddKeywordWithDate( |
| 657 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1", | 670 "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1", |
| 658 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time()); | 671 std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time()); |
| 659 test_util()->ResetObserverCount(); | 672 test_util()->ResetObserverCount(); |
| (...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1478 scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info( | 1491 scoped_ptr<TemplateURL::AssociatedExtensionInfo> extension_info( |
| 1479 new TemplateURL::AssociatedExtensionInfo( | 1492 new TemplateURL::AssociatedExtensionInfo( |
| 1480 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1")); | 1493 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, "ext1")); |
| 1481 extension_info->wants_to_be_default_engine = true; | 1494 extension_info->wants_to_be_default_engine = true; |
| 1482 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass()); | 1495 model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass()); |
| 1483 EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1"))); | 1496 EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1"))); |
| 1484 EXPECT_TRUE(model()->is_default_search_managed()); | 1497 EXPECT_TRUE(model()->is_default_search_managed()); |
| 1485 actual_managed_default = model()->GetDefaultSearchProvider(); | 1498 actual_managed_default = model()->GetDefaultSearchProvider(); |
| 1486 ExpectSimilar(expected_managed_default.get(), actual_managed_default); | 1499 ExpectSimilar(expected_managed_default.get(), actual_managed_default); |
| 1487 } | 1500 } |
| OLD | NEW |