diff options
author | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-03 12:00:01 +0000 |
---|---|---|
committer | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-03 12:00:01 +0000 |
commit | 2e8c601f54f7ac7ac786c99f5a3b0bb8246d16bf (patch) | |
tree | 247cac8f7ba11f69bfc5499ddf6183b3fbc355ce /chrome/browser/autocomplete | |
parent | 31d6d17ee26de3b4007689ab01d5e8842f2f2c53 (diff) | |
download | chromium_src-2e8c601f54f7ac7ac786c99f5a3b0bb8246d16bf.zip chromium_src-2e8c601f54f7ac7ac786c99f5a3b0bb8246d16bf.tar.gz chromium_src-2e8c601f54f7ac7ac786c99f5a3b0bb8246d16bf.tar.bz2 |
Ensure zero suggest can handle XSSI-escaped output.
Zero suggest request re-uses the same URL as regular suggest and
therefore will be requesting xssi=t by default. We should make sure the
output is then correctly parsed.
BUG=
Review URL: https://codereview.chromium.org/96753004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238360 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
4 files changed, 54 insertions, 22 deletions
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index 8fefaf3..a606d97 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -653,24 +653,8 @@ void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { } } - // The JSON response should be an array. - for (size_t response_start_index = json_data.find("["), i = 0; - response_start_index != std::string::npos && i < 5; - response_start_index = json_data.find("[", 1), i++) { - // Remove any XSSI guards to allow for JSON parsing. - if (response_start_index > 0) - json_data.erase(0, response_start_index); - - JSONStringValueSerializer deserializer(json_data); - deserializer.set_allow_trailing_comma(true); - int error_code = 0; - scoped_ptr<Value> data(deserializer.Deserialize(&error_code, NULL)); - if (error_code == 0) { - results_updated = data.get() && - ParseSuggestResults(data.get(), is_keyword); - break; - } - } + scoped_ptr<Value> data(DeserializeJsonData(json_data)); + results_updated = data.get() && ParseSuggestResults(data.get(), is_keyword); } UpdateMatches(); @@ -1040,6 +1024,25 @@ net::URLFetcher* SearchProvider::CreateSuggestFetcher( return fetcher; } +scoped_ptr<Value> SearchProvider::DeserializeJsonData(std::string json_data) { + // The JSON response should be an array. + for (size_t response_start_index = json_data.find("["), i = 0; + response_start_index != std::string::npos && i < 5; + response_start_index = json_data.find("[", 1), i++) { + // Remove any XSSI guards to allow for JSON parsing. + if (response_start_index > 0) + json_data.erase(0, response_start_index); + + JSONStringValueSerializer deserializer(json_data); + deserializer.set_allow_trailing_comma(true); + int error_code = 0; + scoped_ptr<Value> data(deserializer.Deserialize(&error_code, NULL)); + if (error_code == 0) + return data.Pass(); + } + return scoped_ptr<Value>(); +} + bool SearchProvider::ParseSuggestResults(Value* root_val, bool is_keyword) { string16 query; ListValue* root_list = NULL; diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h index e8c07d5..cfff8a3 100644 --- a/chrome/browser/autocomplete/search_provider.h +++ b/chrome/browser/autocomplete/search_provider.h @@ -410,6 +410,11 @@ class SearchProvider : public AutocompleteProvider, const TemplateURL* template_url, const AutocompleteInput& input); + // Parses JSON response received from the provider, stripping XSSI + // protection if needed. Returns the parsed data if successful, NULL + // otherwise. + static scoped_ptr<base::Value> DeserializeJsonData(std::string json_data); + // Parses results from the suggest server and updates the appropriate suggest // and navigation result lists, depending on whether |is_keyword| is true. // Returns whether the appropriate result list members were updated. diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc index bae74a7..6ae49e0 100644 --- a/chrome/browser/autocomplete/search_provider_unittest.cc +++ b/chrome/browser/autocomplete/search_provider_unittest.cc @@ -3748,9 +3748,35 @@ TEST_F(SearchProviderTest, PrefetchMetadataParsing) { } } +TEST_F(SearchProviderTest, XSSIGuardedJSONParsing_InvalidResponse) { + ClearAllResults(); + + std::string input_str("abc"); + QueryForInput(ASCIIToUTF16(input_str), false, false); + + // Set up a default fetcher with provided results. + net::TestURLFetcher* fetcher = + test_factory_.GetFetcherByID( + SearchProvider::kDefaultProviderURLFetcherID); + ASSERT_TRUE(fetcher); + fetcher->set_response_code(200); + fetcher->SetResponseString("this is a bad non-json response"); + fetcher->delegate()->OnURLFetchComplete(fetcher); + + RunTillProviderDone(); + + const ACMatches& matches = provider_->matches(); + + // Should have exactly one "search what you typed" match + ASSERT_TRUE(matches.size() == 1); + EXPECT_EQ(input_str, UTF16ToUTF8(matches[0].contents)); + EXPECT_EQ(AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, + matches[0].type); +} + // A basic test that verifies that the XSSI guarded JSON response is parsed // correctly. -TEST_F(SearchProviderTest, XSSIGuardedJSONParsing) { +TEST_F(SearchProviderTest, XSSIGuardedJSONParsing_ValidResponses) { struct Match { std::string contents; AutocompleteMatchType::Type type; diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc index 07d7c2c..7207fd8 100644 --- a/chrome/browser/autocomplete/zero_suggest_provider.cc +++ b/chrome/browser/autocomplete/zero_suggest_provider.cc @@ -133,9 +133,7 @@ void ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) { source->GetStatus().is_success() && source->GetResponseCode() == 200; if (request_succeeded) { - JSONStringValueSerializer deserializer(json_data); - deserializer.set_allow_trailing_comma(true); - scoped_ptr<Value> data(deserializer.Deserialize(NULL, NULL)); + scoped_ptr<Value> data(SearchProvider::DeserializeJsonData(json_data)); if (data.get()) ParseSuggestResults(*data.get()); } |