diff options
author | rouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 20:27:03 +0000 |
---|---|---|
committer | rouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-31 20:27:03 +0000 |
commit | 427276eeddc29f2b9d30ed171c5d272c20e3ae69 (patch) | |
tree | 5e350df22370b750b33b9aaefb29ef473fb3f218 | |
parent | e1af3b6b9332143040769bbeb5d12465853be176 (diff) | |
download | chromium_src-427276eeddc29f2b9d30ed171c5d272c20e3ae69.zip chromium_src-427276eeddc29f2b9d30ed171c5d272c20e3ae69.tar.gz chromium_src-427276eeddc29f2b9d30ed171c5d272c20e3ae69.tar.bz2 |
Check for error message from spelling service
When spelling service is not available, it returns HTTP status code 200, but the
JSON response data indicates an error. This CL checks for errors in the JSON
response data to correctly fallback on local spellcheck if needed.
BUG=230245
Review URL: https://chromiumcodereview.appspot.com/16050011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203466 0039d316-1c4b-4281-b951-d872f2087c98
3 files changed, 72 insertions, 38 deletions
diff --git a/chrome/browser/spellchecker/spelling_service_client.cc b/chrome/browser/spellchecker/spelling_service_client.cc index 9eeeb1b..b4fc16f 100644 --- a/chrome/browser/spellchecker/spelling_service_client.cc +++ b/chrome/browser/spellchecker/spelling_service_client.cc @@ -28,6 +28,13 @@ namespace { // The URL for requesting spell checking and sending user feedback. const char kSpellingServiceURL[] = "https://www.googleapis.com/rpc"; +// The location of spellcheck suggestions in JSON response from spelling +// service. +const char kMisspellingsPath[] = "result.spellingCheckResponse.misspellings"; + +// The location of error messages in JSON response from spelling service. +const char kErrorPath[] = "error"; + } // namespace SpellingServiceClient::SpellingServiceClient() { @@ -126,37 +133,6 @@ bool SpellingServiceClient::IsAvailable(Profile* profile, ServiceType type) { } } -SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData( - TextCheckCompleteCallback callback, - string16 text) - : callback(callback), - text(text) { -} - -SpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() { -} - -void SpellingServiceClient::OnURLFetchComplete( - const net::URLFetcher* source) { - DCHECK(spellcheck_fetchers_[source]); - scoped_ptr<const net::URLFetcher> fetcher(source); - scoped_ptr<TextCheckCallbackData> - callback_data(spellcheck_fetchers_[fetcher.get()]); - bool success = false; - std::vector<SpellCheckResult> results; - if (fetcher->GetResponseCode() / 100 == 2) { - std::string data; - fetcher->GetResponseAsString(&data); - success = ParseResponse(data, &results); - } - callback_data->callback.Run(success, callback_data->text, results); - spellcheck_fetchers_.erase(fetcher.get()); -} - -net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) { - return net::URLFetcher::Create(url, net::URLFetcher::POST, this); -} - bool SpellingServiceClient::ParseResponse( const std::string& data, std::vector<SpellCheckResult>* results) { @@ -191,18 +167,31 @@ bool SpellingServiceClient::ParseResponse( // } // } // } + // If the service is not available, the Spelling service returns JSON with an + // error. + // { + // "error": { + // "code": 400, + // "message": "Bad Request", + // "data": [...] + // } + // } scoped_ptr<DictionaryValue> value( static_cast<DictionaryValue*>( base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS))); if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) return false; + // Check for errors from spelling service. + DictionaryValue* error = NULL; + if (value->GetDictionary(kErrorPath, &error)) + return false; + // Retrieve the array of Misspelling objects. When the input text does not // have misspelled words, it returns an empty JSON. (In this case, its HTTP // status is 200.) We just return true for this case. ListValue* misspellings = NULL; - const char kMisspellings[] = "result.spellingCheckResponse.misspellings"; - if (!value->GetList(kMisspellings, &misspellings)) + if (!value->GetList(kMisspellingsPath, &misspellings)) return true; for (size_t i = 0; i < misspellings->GetSize(); ++i) { @@ -234,3 +223,34 @@ bool SpellingServiceClient::ParseResponse( } return true; } + +SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData( + TextCheckCompleteCallback callback, + string16 text) + : callback(callback), + text(text) { +} + +SpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() { +} + +void SpellingServiceClient::OnURLFetchComplete( + const net::URLFetcher* source) { + DCHECK(spellcheck_fetchers_[source]); + scoped_ptr<const net::URLFetcher> fetcher(source); + scoped_ptr<TextCheckCallbackData> + callback_data(spellcheck_fetchers_[fetcher.get()]); + bool success = false; + std::vector<SpellCheckResult> results; + if (fetcher->GetResponseCode() / 100 == 2) { + std::string data; + fetcher->GetResponseAsString(&data); + success = ParseResponse(data, &results); + } + callback_data->callback.Run(success, callback_data->text, results); + spellcheck_fetchers_.erase(fetcher.get()); +} + +net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) { + return net::URLFetcher::Create(url, net::URLFetcher::POST, this); +} diff --git a/chrome/browser/spellchecker/spelling_service_client.h b/chrome/browser/spellchecker/spelling_service_client.h index b0ee720..08ae2e9 100644 --- a/chrome/browser/spellchecker/spelling_service_client.h +++ b/chrome/browser/spellchecker/spelling_service_client.h @@ -87,6 +87,11 @@ class SpellingServiceClient : public net::URLFetcherDelegate { // Returns whether the specified service is available for the given profile. static bool IsAvailable(Profile* profile, ServiceType type); + protected: + // Parses a JSON-RPC response from the Spelling service. + bool ParseResponse(const std::string& data, + std::vector<SpellCheckResult>* results); + private: struct TextCheckCallbackData { TextCheckCallbackData(TextCheckCompleteCallback callback, string16 text); @@ -108,10 +113,6 @@ class SpellingServiceClient : public net::URLFetcherDelegate { // requests to the Spelling service. virtual net::URLFetcher* CreateURLFetcher(const GURL& url); - // Parses a JSON-RPC response from the Spelling service. - bool ParseResponse(const std::string& data, - std::vector<SpellCheckResult>* results); - // The URLFetcher object used for sending a JSON-RPC request. std::map<const net::URLFetcher*, TextCheckCallbackData*> spellcheck_fetchers_; }; diff --git a/chrome/browser/spellchecker/spelling_service_client_unittest.cc b/chrome/browser/spellchecker/spelling_service_client_unittest.cc index 5833fce..2f0921e 100644 --- a/chrome/browser/spellchecker/spelling_service_client_unittest.cc +++ b/chrome/browser/spellchecker/spelling_service_client_unittest.cc @@ -111,7 +111,8 @@ class TestSpellingURLFetcher : public net::TestURLFetcher { // A class derived from the SpellingServiceClient class used by the // SpellingServiceClientTest class. This class overrides CreateURLFetcher so -// this test can use TestSpellingURLFetcher. +// this test can use TestSpellingURLFetcher. This class also lets tests access +// the ParseResponse method. class TestingSpellingServiceClient : public SpellingServiceClient { public: TestingSpellingServiceClient() @@ -160,6 +161,11 @@ class TestingSpellingServiceClient : public SpellingServiceClient { EXPECT_EQ(corrected_text_, text); } + bool ParseResponseSuccess(const std::string& data) { + std::vector<SpellCheckResult> results; + return ParseResponse(data, &results); + } + private: virtual net::URLFetcher* CreateURLFetcher(const GURL& url) OVERRIDE { EXPECT_EQ("https://www.googleapis.com/rpc", url.spec()); @@ -377,3 +383,10 @@ TEST_F(SpellingServiceClientTest, AvailableServices) { EXPECT_FALSE(client_.IsAvailable(&profile_, kSpellcheck)); } } + +// Verify that an error in JSON response from spelling service will result in +// ParseResponse returning false. +TEST_F(SpellingServiceClientTest, ResponseErrorTest) { + EXPECT_TRUE(client_.ParseResponseSuccess("{\"result\": {}}")); + EXPECT_FALSE(client_.ParseResponseSuccess("{\"error\": {}}")); +} |