Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/search_provider.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 | 49 |
| 50 // Returns the first match in |matches| with |allowed_to_be_default_match| | 50 // Returns the first match in |matches| with |allowed_to_be_default_match| |
| 51 // set to true. | 51 // set to true. |
| 52 ACMatches::const_iterator FindDefaultMatch(const ACMatches& matches) { | 52 ACMatches::const_iterator FindDefaultMatch(const ACMatches& matches) { |
| 53 ACMatches::const_iterator it = matches.begin(); | 53 ACMatches::const_iterator it = matches.begin(); |
| 54 while ((it != matches.end()) && !it->allowed_to_be_default_match) | 54 while ((it != matches.end()) && !it->allowed_to_be_default_match) |
| 55 ++it; | 55 ++it; |
| 56 return it; | 56 return it; |
| 57 } | 57 } |
| 58 | 58 |
| 59 class SuggestionDeletionHandler; | |
| 60 class SearchProviderForTest : public SearchProvider { | |
| 61 public: | |
| 62 SearchProviderForTest( | |
| 63 AutocompleteProviderListener* listener, | |
| 64 Profile* profile); | |
| 65 bool is_success() { return is_success_; }; | |
| 66 | |
| 67 protected: | |
| 68 virtual ~SearchProviderForTest(); | |
| 69 | |
| 70 private: | |
| 71 virtual void RecordDeletionResult(bool success) OVERRIDE; | |
| 72 bool is_success_; | |
| 73 FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, TestDeleteMatch_FakeProvider); | |
|
Peter Kasting
2013/12/03 00:33:51
Nit: This declaration seems useless?
Maria
2013/12/03 01:00:26
Done.
| |
| 74 DISALLOW_COPY_AND_ASSIGN(SearchProviderForTest); | |
| 75 }; | |
| 76 | |
| 77 SearchProviderForTest::SearchProviderForTest( | |
| 78 AutocompleteProviderListener* listener, | |
| 79 Profile* profile) : SearchProvider(listener, profile), | |
|
Peter Kasting
2013/12/03 00:33:51
Nit: Wrap ":" and following to next line
Maria
2013/12/03 01:00:26
Done.
| |
| 80 is_success_(false) { | |
| 81 } | |
| 82 | |
| 83 SearchProviderForTest::~SearchProviderForTest() { | |
| 84 } | |
| 85 | |
| 86 void SearchProviderForTest::RecordDeletionResult(bool success) { | |
| 87 is_success_ = success; | |
| 88 } | |
| 89 | |
| 59 } // namespace | 90 } // namespace |
| 60 | 91 |
| 61 // SearchProviderTest --------------------------------------------------------- | 92 // SearchProviderTest --------------------------------------------------------- |
| 62 | 93 |
| 63 // The following environment is configured for these tests: | 94 // The following environment is configured for these tests: |
| 64 // . The TemplateURL default_t_url_ is set as the default provider. | 95 // . The TemplateURL default_t_url_ is set as the default provider. |
| 65 // . The TemplateURL keyword_t_url_ is added to the TemplateURLService. This | 96 // . The TemplateURL keyword_t_url_ is added to the TemplateURLService. This |
| 66 // TemplateURL has a valid suggest and search URL. | 97 // TemplateURL has a valid suggest and search URL. |
| 67 // . The URL created by using the search term term1_ with default_t_url_ is | 98 // . The URL created by using the search term term1_ with default_t_url_ is |
| 68 // added to history. | 99 // added to history. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 | 211 |
| 181 content::TestBrowserThreadBundle thread_bundle_; | 212 content::TestBrowserThreadBundle thread_bundle_; |
| 182 | 213 |
| 183 // URLFetcherFactory implementation registered. | 214 // URLFetcherFactory implementation registered. |
| 184 net::TestURLFetcherFactory test_factory_; | 215 net::TestURLFetcherFactory test_factory_; |
| 185 | 216 |
| 186 // Profile we use. | 217 // Profile we use. |
| 187 TestingProfile profile_; | 218 TestingProfile profile_; |
| 188 | 219 |
| 189 // The provider. | 220 // The provider. |
| 190 scoped_refptr<SearchProvider> provider_; | 221 scoped_refptr<SearchProviderForTest> provider_; |
| 191 | 222 |
| 192 // If non-NULL, OnProviderUpdate quits the current |run_loop_|. | 223 // If non-NULL, OnProviderUpdate quits the current |run_loop_|. |
| 193 base::RunLoop* run_loop_; | 224 base::RunLoop* run_loop_; |
| 194 | 225 |
| 195 DISALLOW_COPY_AND_ASSIGN(SearchProviderTest); | 226 DISALLOW_COPY_AND_ASSIGN(SearchProviderTest); |
| 196 }; | 227 }; |
| 197 | 228 |
| 198 // static | 229 // static |
| 199 const std::string SearchProviderTest::kNotApplicable = "Not Applicable"; | 230 const std::string SearchProviderTest::kNotApplicable = "Not Applicable"; |
| 200 | 231 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 ASSERT_NE(0, keyword_t_url_->id()); | 269 ASSERT_NE(0, keyword_t_url_->id()); |
| 239 | 270 |
| 240 // Add a page and search term for keyword_t_url_. | 271 // Add a page and search term for keyword_t_url_. |
| 241 keyword_url_ = AddSearchToHistory(keyword_t_url_, keyword_term_, 1); | 272 keyword_url_ = AddSearchToHistory(keyword_t_url_, keyword_term_, 1); |
| 242 | 273 |
| 243 // Keywords are updated by the InMemoryHistoryBackend only after the message | 274 // Keywords are updated by the InMemoryHistoryBackend only after the message |
| 244 // has been processed on the history thread. Block until history processes all | 275 // has been processed on the history thread. Block until history processes all |
| 245 // requests to ensure the InMemoryDatabase is the state we expect it. | 276 // requests to ensure the InMemoryDatabase is the state we expect it. |
| 246 profile_.BlockUntilHistoryProcessesPendingRequests(); | 277 profile_.BlockUntilHistoryProcessesPendingRequests(); |
| 247 | 278 |
| 248 provider_ = new SearchProvider(this, &profile_); | 279 provider_ = new SearchProviderForTest(this, &profile_); |
| 249 provider_->kMinimumTimeBetweenSuggestQueriesMs = 0; | 280 provider_->kMinimumTimeBetweenSuggestQueriesMs = 0; |
| 250 } | 281 } |
| 251 | 282 |
| 252 void SearchProviderTest::TearDown() { | 283 void SearchProviderTest::TearDown() { |
| 253 base::RunLoop().RunUntilIdle(); | 284 base::RunLoop().RunUntilIdle(); |
| 254 | 285 |
| 255 // Shutdown the provider before the profile. | 286 // Shutdown the provider before the profile. |
| 256 provider_ = NULL; | 287 provider_ = NULL; |
| 257 } | 288 } |
| 258 | 289 |
| (...skipping 3088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3347 if (suggestion == kNotApplicable) | 3378 if (suggestion == kNotApplicable) |
| 3348 break; | 3379 break; |
| 3349 if (cases[i].results[j].is_navigation_result) { | 3380 if (cases[i].results[j].is_navigation_result) { |
| 3350 provider_->default_results_.navigation_results.push_back( | 3381 provider_->default_results_.navigation_results.push_back( |
| 3351 SearchProvider::NavigationResult( | 3382 SearchProvider::NavigationResult( |
| 3352 *provider_.get(), GURL(suggestion), string16(), false, | 3383 *provider_.get(), GURL(suggestion), string16(), false, |
| 3353 cases[i].results[j].relevance, false)); | 3384 cases[i].results[j].relevance, false)); |
| 3354 } else { | 3385 } else { |
| 3355 provider_->default_results_.suggest_results.push_back( | 3386 provider_->default_results_.suggest_results.push_back( |
| 3356 SearchProvider::SuggestResult(ASCIIToUTF16(suggestion), string16(), | 3387 SearchProvider::SuggestResult(ASCIIToUTF16(suggestion), string16(), |
| 3357 string16(), std::string(), false, | 3388 string16(), std::string(), |
| 3389 std::string(), false, | |
| 3358 cases[i].results[j].relevance, | 3390 cases[i].results[j].relevance, |
| 3359 false, false)); | 3391 false, false)); |
| 3360 } | 3392 } |
| 3361 } | 3393 } |
| 3362 | 3394 |
| 3363 provider_->input_ = AutocompleteInput( | 3395 provider_->input_ = AutocompleteInput( |
| 3364 ASCIIToUTF16(cases[i].omnibox_input), string16::npos, string16(), | 3396 ASCIIToUTF16(cases[i].omnibox_input), string16::npos, string16(), |
| 3365 GURL(), AutocompleteInput::INVALID_SPEC, false, false, true, | 3397 GURL(), AutocompleteInput::INVALID_SPEC, false, false, true, |
| 3366 AutocompleteInput::ALL_MATCHES); | 3398 AutocompleteInput::ALL_MATCHES); |
| 3367 provider_->RemoveAllStaleResults(); | 3399 provider_->RemoveAllStaleResults(); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3749 } | 3781 } |
| 3750 | 3782 |
| 3751 // A basic test that verifies that the XSSI guarded JSON response is parsed | 3783 // A basic test that verifies that the XSSI guarded JSON response is parsed |
| 3752 // correctly. | 3784 // correctly. |
| 3753 TEST_F(SearchProviderTest, XSSIGuardedJSONParsing) { | 3785 TEST_F(SearchProviderTest, XSSIGuardedJSONParsing) { |
| 3754 struct Match { | 3786 struct Match { |
| 3755 std::string contents; | 3787 std::string contents; |
| 3756 AutocompleteMatchType::Type type; | 3788 AutocompleteMatchType::Type type; |
| 3757 }; | 3789 }; |
| 3758 const Match kEmptyMatch = { kNotApplicable, | 3790 const Match kEmptyMatch = { kNotApplicable, |
| 3759 AutocompleteMatchType::NUM_TYPES}; | 3791 AutocompleteMatchType::NUM_TYPES |
| 3792 }; | |
|
Peter Kasting
2013/12/03 00:33:51
Nit: Wrapping the } is fine, but in that case, als
Maria
2013/12/03 01:00:26
Done.
| |
| 3760 | 3793 |
| 3761 struct { | 3794 struct { |
| 3762 const std::string input_text; | 3795 const std::string input_text; |
| 3763 const std::string default_provider_response_json; | 3796 const std::string default_provider_response_json; |
| 3764 const Match matches[4]; | 3797 const Match matches[4]; |
| 3765 } cases[] = { | 3798 } cases[] = { |
| 3766 // No XSSI guard. | 3799 // No XSSI guard. |
| 3767 { "a", | 3800 { "a", |
| 3768 "[\"a\",[\"b\", \"c\"],[],[]," | 3801 "[\"a\",[\"b\", \"c\"],[],[]," |
| 3769 "{\"google:suggesttype\":[\"QUERY\",\"QUERY\"]," | 3802 "{\"google:suggesttype\":[\"QUERY\",\"QUERY\"]," |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3828 EXPECT_EQ(cases[i].matches[j].type, matches[j].type); | 3861 EXPECT_EQ(cases[i].matches[j].type, matches[j].type); |
| 3829 } | 3862 } |
| 3830 for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) { | 3863 for (; j < ARRAYSIZE_UNSAFE(cases[i].matches); ++j) { |
| 3831 SCOPED_TRACE("and match: " + base::IntToString(j)); | 3864 SCOPED_TRACE("and match: " + base::IntToString(j)); |
| 3832 EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable); | 3865 EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable); |
| 3833 EXPECT_EQ(cases[i].matches[j].type, AutocompleteMatchType::NUM_TYPES); | 3866 EXPECT_EQ(cases[i].matches[j].type, AutocompleteMatchType::NUM_TYPES); |
| 3834 } | 3867 } |
| 3835 } | 3868 } |
| 3836 } | 3869 } |
| 3837 | 3870 |
| 3871 // Test that deletion url gets set on an AutocompleteMatch when available for a | |
| 3872 // personalized query. | |
| 3873 TEST_F(SearchProviderTest, ParseDeletionUrl) { | |
| 3874 struct Match { | |
| 3875 std::string contents; | |
| 3876 std::string deletion_url; | |
| 3877 AutocompleteMatchType::Type type; | |
| 3878 }; | |
| 3879 | |
| 3880 const Match kEmptyMatch = { | |
| 3881 kNotApplicable, "", AutocompleteMatchType::NUM_TYPES | |
| 3882 }; | |
| 3883 | |
| 3884 const char url[] = "https://www.google.com/complete/deleteitems" | |
| 3885 "?delq=ab&client=chrome&deltok=xsrf123"; | |
| 3886 | |
| 3887 struct { | |
| 3888 const std::string input_text; | |
| 3889 const std::string response_json; | |
| 3890 const Match matches[4]; | |
| 3891 } cases[] = { | |
| 3892 // A deletion URL on a personalized query should be reflected in the | |
| 3893 // resulting AutocompleteMatch. | |
| 3894 { "a", | |
| 3895 "[\"a\",[\"ab\", \"ac\"],[],[]," | |
| 3896 "{\"google:suggesttype\":[\"PERSONALIZED_QUERY\",\"QUERY\"]," | |
| 3897 "\"google:suggestrelevance\":[1, 2]," | |
| 3898 "\"google:suggestdetail\":[{\"du\":" | |
| 3899 "\"https://www.google.com/complete/deleteitems?delq=ab&client=chrome" | |
| 3900 "&deltok=xsrf123\"}, {}]}]", | |
| 3901 { { "a", "", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED }, | |
| 3902 { "ac", "", AutocompleteMatchType::SEARCH_SUGGEST }, | |
| 3903 { "ab", url, AutocompleteMatchType::SEARCH_SUGGEST }, | |
| 3904 kEmptyMatch, | |
| 3905 }, | |
| 3906 }, | |
| 3907 // Personalized queries without deletion URLs shouldn't cause errors. | |
| 3908 { "a", | |
| 3909 "[\"a\",[\"ab\", \"ac\"],[],[]," | |
| 3910 "{\"google:suggesttype\":[\"PERSONALIZED_QUERY\",\"QUERY\"]," | |
| 3911 "\"google:suggestrelevance\":[1, 2]," | |
| 3912 "\"google:suggestdetail\":[{}, {}]}]", | |
| 3913 { { "a", "", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED }, | |
| 3914 { "ac", "", AutocompleteMatchType::SEARCH_SUGGEST }, | |
| 3915 { "ab", "", AutocompleteMatchType::SEARCH_SUGGEST }, | |
| 3916 kEmptyMatch, | |
| 3917 }, | |
| 3918 }, | |
| 3919 }; | |
| 3920 | |
| 3921 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { | |
| 3922 QueryForInput(ASCIIToUTF16(cases[i].input_text), false, false); | |
| 3923 | |
| 3924 net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID( | |
| 3925 SearchProvider::kDefaultProviderURLFetcherID); | |
| 3926 ASSERT_TRUE(fetcher); | |
| 3927 fetcher->set_response_code(200); | |
| 3928 fetcher->SetResponseString(cases[i].response_json); | |
| 3929 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
| 3930 | |
| 3931 RunTillProviderDone(); | |
| 3932 | |
| 3933 const ACMatches& matches = provider_->matches(); | |
| 3934 ASSERT_FALSE(matches.empty()); | |
| 3935 | |
| 3936 SCOPED_TRACE("for input with json = " + cases[i].response_json); | |
| 3937 | |
| 3938 for (size_t j = 0; j < matches.size(); ++j) { | |
| 3939 const Match& match = cases[i].matches[j]; | |
| 3940 SCOPED_TRACE(" and match index: " + base::IntToString(j)); | |
| 3941 EXPECT_EQ(match.contents, UTF16ToUTF8(matches[j].contents)); | |
| 3942 EXPECT_EQ(match.deletion_url, matches[j].GetAdditionalInfo( | |
| 3943 "deletion_url")); | |
| 3944 } | |
| 3945 } | |
| 3946 } | |
| 3838 | 3947 |
| 3839 TEST_F(SearchProviderTest, ReflectsBookmarkBarState) { | 3948 TEST_F(SearchProviderTest, ReflectsBookmarkBarState) { |
| 3840 profile_.GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false); | 3949 profile_.GetPrefs()->SetBoolean(prefs::kShowBookmarkBar, false); |
| 3841 string16 term = term1_.substr(0, term1_.length() - 1); | 3950 string16 term = term1_.substr(0, term1_.length() - 1); |
| 3842 QueryForInput(term, true, false); | 3951 QueryForInput(term, true, false); |
| 3843 ASSERT_FALSE(provider_->matches().empty()); | 3952 ASSERT_FALSE(provider_->matches().empty()); |
| 3844 EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, | 3953 EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
| 3845 provider_->matches()[0].type); | 3954 provider_->matches()[0].type); |
| 3846 ASSERT_TRUE(provider_->matches()[0].search_terms_args != NULL); | 3955 ASSERT_TRUE(provider_->matches()[0].search_terms_args != NULL); |
| 3847 EXPECT_FALSE(provider_->matches()[0].search_terms_args->bookmark_bar_pinned); | 3956 EXPECT_FALSE(provider_->matches()[0].search_terms_args->bookmark_bar_pinned); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3974 AutocompleteInput::OTHER, &profile_)); | 4083 AutocompleteInput::OTHER, &profile_)); |
| 3975 encrypted_types.Remove(syncer::SESSIONS); | 4084 encrypted_types.Remove(syncer::SESSIONS); |
| 3976 service->OnEncryptedTypesChanged(encrypted_types, false); | 4085 service->OnEncryptedTypesChanged(encrypted_types, false); |
| 3977 | 4086 |
| 3978 // Check that there were no side effects from previous tests. | 4087 // Check that there were no side effects from previous tests. |
| 3979 EXPECT_TRUE(SearchProvider::CanSendURL( | 4088 EXPECT_TRUE(SearchProvider::CanSendURL( |
| 3980 GURL("http://www.google.com/search"), | 4089 GURL("http://www.google.com/search"), |
| 3981 GURL("https://www.google.com/complete/search"), &google_template_url, | 4090 GURL("https://www.google.com/complete/search"), &google_template_url, |
| 3982 AutocompleteInput::OTHER, &profile_)); | 4091 AutocompleteInput::OTHER, &profile_)); |
| 3983 } | 4092 } |
| 4093 | |
| 4094 TEST_F(SearchProviderTest, TestDeleteMatch_HasDeletionUrlSuccess) { | |
|
Anuj
2013/12/03 01:25:47
I think TestDeleteMatch_Success is sufficient. Has
| |
| 4095 AutocompleteMatch match(provider_, 0, true, | |
| 4096 AutocompleteMatchType::SEARCH_SUGGEST); | |
| 4097 match.RecordAdditionalInfo( | |
| 4098 SearchProvider::kDeletionUrlKey, | |
| 4099 "https://www.google.com/complete/deleteitem?q=foo"); | |
| 4100 provider_->matches_.push_back(match); | |
| 4101 provider_->DeleteMatch(match); | |
|
Anuj
2013/12/03 01:25:47
An empty line before this to create separation bet
Maria
2013/12/03 01:40:15
Done.
| |
| 4102 ASSERT_FALSE(provider_->deletion_handlers_.empty()); | |
| 4103 ASSERT_TRUE(provider_->matches_.empty()); | |
| 4104 // Set up a default fetcher with provided results. | |
| 4105 net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID( | |
| 4106 SearchProvider::kDeletionURLFetcherID); | |
| 4107 ASSERT_TRUE(fetcher); | |
|
Anuj
2013/12/03 01:25:47
Omit this? It doesn't seem particularly useful.
Maria
2013/12/03 01:40:15
All the other tests in this class do it. It's usef
| |
| 4108 fetcher->set_response_code(200); | |
|
Anuj
2013/12/03 01:25:47
Move the fetcher set up code before the call to De
Maria
2013/12/03 01:40:15
That's not possible because GetFetcherByID relies
| |
| 4109 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
| 4110 ASSERT_TRUE(provider_->deletion_handlers_.empty()); | |
| 4111 ASSERT_TRUE(provider_->is_success()); | |
| 4112 } | |
| 4113 | |
| 4114 TEST_F(SearchProviderTest, TestDeleteMatch_HasDeletionUrlFailure) { | |
| 4115 AutocompleteMatch match(provider_, 0, true, | |
| 4116 AutocompleteMatchType::SEARCH_SUGGEST); | |
| 4117 match.RecordAdditionalInfo( | |
| 4118 SearchProvider::kDeletionUrlKey, | |
| 4119 "https://www.google.com/complete/deleteitem?q=foo"); | |
|
Peter Kasting
2013/12/03 00:33:51
Nit: If we combine these two tests into one, we ca
Maria
2013/12/03 01:00:26
We could, but I'd rather have two separate test ca
Peter Kasting
2013/12/03 01:03:22
They shouldn't depend on each other's passing. Wh
Anuj
2013/12/03 01:25:47
I have been told that the assert/expects should no
| |
| 4120 provider_->matches_.push_back(match); | |
| 4121 provider_->DeleteMatch(match); | |
| 4122 ASSERT_FALSE(provider_->deletion_handlers_.empty()); | |
| 4123 ASSERT_TRUE(provider_->matches_.empty()); | |
| 4124 // Set up a default fetcher with provided results. | |
| 4125 net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID( | |
| 4126 SearchProvider::kDeletionURLFetcherID); | |
| 4127 ASSERT_TRUE(fetcher); | |
| 4128 fetcher->set_response_code(500); | |
| 4129 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
| 4130 ASSERT_TRUE(provider_->deletion_handlers_.empty()); | |
| 4131 ASSERT_FALSE(provider_->is_success()); | |
| 4132 } | |
| OLD | NEW |