spelling_service_client.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// Copyright (c) 2012 The Chromium Authors. All rights reserved. 294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// Use of this source code is governed by a BSD-style license that can be 394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// found in the LICENSE file. 494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "chrome/browser/spellchecker/spelling_service_client.h" 694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/command_line.h" 894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/json/json_reader.h" 994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/json/string_escape.h" 1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/logging.h" 1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/prefs/pref_service.h" 1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/stl_util.h" 1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/strings/string_util.h" 1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/strings/stringprintf.h" 1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/strings/utf_string_conversions.h" 1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "base/values.h" 17d747129e1e8876f5a50f47156ec50b6969a638e4Nick Kralevich#include "chrome/common/chrome_switches.h" 1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "chrome/common/pref_names.h" 1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "chrome/common/spellcheck_common.h" 2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "chrome/common/spellcheck_result.h" 2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "components/user_prefs/user_prefs.h" 2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "content/public/browser/browser_context.h" 2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "google_apis/google_api_keys.h" 2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "net/base/load_flags.h" 2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "net/url_request/url_fetcher.h" 2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include "url/gurl.h" 2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodnamespace { 2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// The URL for requesting spell checking and sending user feedback. 31a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevichconst char kSpellingServiceURL[] = "https://www.googleapis.com/rpc"; 3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// The location of spellcheck suggestions in JSON response from spelling 3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// service. 3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodconst char kMisspellingsPath[] = "result.spellingCheckResponse.misspellings"; 3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood// The location of error messages in JSON response from spelling service. 3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodconst char kErrorPath[] = "error"; 3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} // namespace 4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike LockwoodSpellingServiceClient::SpellingServiceClient() { 4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike LockwoodSpellingServiceClient::~SpellingServiceClient() { 4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood STLDeleteContainerPairPointers(spellcheck_fetchers_.begin(), 4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood spellcheck_fetchers_.end()); 4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 4994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodbool SpellingServiceClient::RequestTextCheck( 5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood content::BrowserContext* context, 5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ServiceType type, 5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const base::string16& text, 5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const TextCheckCompleteCallback& callback) { 5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DCHECK(type == SUGGEST || type == SPELLCHECK); 5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!context || !IsAvailable(context, type)) { 5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood callback.Run(false, text, std::vector<SpellCheckResult>()); 58a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich return false; 5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const PrefService* pref = user_prefs::UserPrefs::Get(context); 62a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich DCHECK(pref); 6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string language_code; 6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string country_code; 6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood chrome::spellcheck_common::GetISOLanguageCountryCodeFromLocale( 6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood pref->GetString(prefs::kSpellCheckDictionary), 6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood &language_code, 6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood &country_code); 7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Format the JSON request to be sent to the Spelling service. 7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string encoded_text; 7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood base::JsonDoubleQuote(text, false, &encoded_text); 7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood static const char kSpellingRequest[] = 7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "{" 7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"method\":\"spelling.check\"," 7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"apiVersion\":\"v%d\"," 7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"params\":{" 8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"text\":\"%s\"," 8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"language\":\"%s\"," 8294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"originCountry\":\"%s\"," 8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "\"key\":%s" 8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "}" 8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood "}"; 8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string api_key = base::GetDoubleQuotedJson(google_apis::GetAPIKey()); 8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string request = base::StringPrintf( 8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood kSpellingRequest, 8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood type, 9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood encoded_text.c_str(), 9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood language_code.c_str(), 9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood country_code.c_str(), 9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood api_key.c_str()); 9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood GURL url = GURL(kSpellingServiceURL); 9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood net::URLFetcher* fetcher = CreateURLFetcher(url); 9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fetcher->SetRequestContext(context->GetRequestContext()); 9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fetcher->SetUploadData("application/json", request); 9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fetcher->SetLoadFlags( 10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); 10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood spellcheck_fetchers_[fetcher] = new TextCheckCallbackData(callback, text); 10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fetcher->Start(); 10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return true; 10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodbool SpellingServiceClient::IsAvailable( 10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood content::BrowserContext* context, 10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ServiceType type) { 10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const PrefService* pref = user_prefs::UserPrefs::Get(context); 11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DCHECK(pref); 11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // If prefs don't allow spellchecking or if the context is off the record, 11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // the spelling service should be unavailable. 11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!pref->GetBoolean(prefs::kEnableContinuousSpellcheck) || 11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood !pref->GetBoolean(prefs::kSpellCheckUseSpellingService) || 11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood context->IsOffTheRecord()) 11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // If the locale for spelling has not been set, the user has not decided to 11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // use spellcheck so we don't do anything remote (suggest or spelling). 12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string locale = pref->GetString(prefs::kSpellCheckDictionary); 12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (locale.empty()) 12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 12394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // If we do not have the spelling service enabled, then we are only available 12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // for SUGGEST. 12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const CommandLine* command_line = CommandLine::ForCurrentProcess(); 12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (command_line->HasSwitch(switches::kUseSpellingSuggestions)) 12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return type == SUGGEST; 12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Finally, if all options are available, we only enable only SUGGEST 13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // if SPELLCHECK is not available for our language because SPELLCHECK results 13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // are a superset of SUGGEST results. 13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // TODO(rlp): Only available for English right now. Fix this line to include 13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // all languages SPELLCHECK covers. 13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bool language_available = !locale.compare(0, 2, "en"); 13694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (language_available) { 13794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return type == SPELLCHECK; 13894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 13994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Only SUGGEST is allowed. 14094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return type == SUGGEST; 14194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 14294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 14394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 14494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodbool SpellingServiceClient::ParseResponse( 14594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const std::string& data, 14694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::vector<SpellCheckResult>* results) { 14794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // When this JSON-RPC call finishes successfully, the Spelling service returns 14894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // an JSON object listed below. 14994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // * result - an envelope object representing the result from the APIARY 15094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // server, which is the JSON-API front-end for the Spelling service. This 15194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // object consists of the following variable: 15294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - spellingCheckResponse (SpellingCheckResponse). 15394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // * SpellingCheckResponse - an object representing the result from the 15494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Spelling service. This object consists of the following variable: 15594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - misspellings (optional array of Misspelling) 15694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // * Misspelling - an object representing a misspelling region and its 15794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // suggestions. This object consists of the following variables: 15894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - charStart (number) - the beginning of the misspelled region; 15994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - charLength (number) - the length of the misspelled region; 16094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - suggestions (array of string) - the suggestions for the misspelling 16194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // text, and; 16294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // - canAutoCorrect (optional boolean) - whether we can use the first 16394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // suggestion for auto-correction. 16494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // For example, the Spelling service returns the following JSON when we send a 16594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // spelling request for "duck goes quisk" as of 16 August, 2011. 16694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // { 16794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "result": { 16894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "spellingCheckResponse": { 16994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "misspellings": [{ 17094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "charStart": 10, 17194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "charLength": 5, 17294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "suggestions": [{ "suggestion": "quack" }], 17394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "canAutoCorrect": false 17494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // }] 17594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // } 17694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // } 17794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // } 17894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // If the service is not available, the Spelling service returns JSON with an 17994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // error. 18094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // { 18194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "error": { 18294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "code": 400, 18394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "message": "Bad Request", 18494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // "data": [...] 18594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // } 18694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // } 187a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich scoped_ptr<DictionaryValue> value( 18894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood static_cast<DictionaryValue*>( 18994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS))); 19094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) 19194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 19294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 19394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Check for errors from spelling service. 19494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DictionaryValue* error = NULL; 19594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (value->GetDictionary(kErrorPath, &error)) 19694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 19794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 19894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Retrieve the array of Misspelling objects. When the input text does not 19994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // have misspelled words, it returns an empty JSON. (In this case, its HTTP 20094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // status is 200.) We just return true for this case. 20194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ListValue* misspellings = NULL; 20294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!value->GetList(kMisspellingsPath, &misspellings)) 20394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return true; 20494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 20594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood for (size_t i = 0; i < misspellings->GetSize(); ++i) { 20694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // Retrieve the i-th misspelling region and put it to the given vector. When 207a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich // the Spelling service sends two or more suggestions, we read only the 20894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // first one because SpellCheckResult can store only one suggestion. 20994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DictionaryValue* misspelling = NULL; 21094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!misspellings->GetDictionary(i, &misspelling)) 211a2d838a542c34d2887a0ec1fafa5f47566d595e9Nick Kralevich return false; 21294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 21394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int start = 0; 21494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int length = 0; 21594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ListValue* suggestions = NULL; 21694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!misspelling->GetInteger("charStart", &start) || 21794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood !misspelling->GetInteger("charLength", &length) || 21894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood !misspelling->GetList("suggestions", &suggestions)) { 21994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 22094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 22194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 22294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DictionaryValue* suggestion = NULL; 22394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood base::string16 replacement; 22494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!suggestions->GetDictionary(0, &suggestion) || 22594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood !suggestion->GetString("suggestion", &replacement)) { 22694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return false; 22794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 22894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood SpellCheckResult result( 22994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood SpellCheckResult::SPELLING, start, length, replacement); 23094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood results->push_back(result); 23194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 23294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return true; 23394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 23494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 23594afecf4b6f437b3ee9a076242402e421c6c07a6Mike LockwoodSpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData( 23694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood TextCheckCompleteCallback callback, 23794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood base::string16 text) 23894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood : callback(callback), 23994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood text(text) { 24094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 24194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 24294afecf4b6f437b3ee9a076242402e421c6c07a6Mike LockwoodSpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() { 24394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 24494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 24594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodvoid SpellingServiceClient::OnURLFetchComplete( 24694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const net::URLFetcher* source) { 24794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood DCHECK(spellcheck_fetchers_[source]); 24894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood scoped_ptr<const net::URLFetcher> fetcher(source); 24994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood scoped_ptr<TextCheckCallbackData> 25094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood callback_data(spellcheck_fetchers_[fetcher.get()]); 25194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood bool success = false; 25294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::vector<SpellCheckResult> results; 25394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (fetcher->GetResponseCode() / 100 == 2) { 25494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood std::string data; 25594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fetcher->GetResponseAsString(&data); 25694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood success = ParseResponse(data, &results); 25794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 25894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood callback_data->callback.Run(success, callback_data->text, results); 25994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood spellcheck_fetchers_.erase(fetcher.get()); 26094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 26194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 26294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodnet::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) { 26394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return net::URLFetcher::Create(url, net::URLFetcher::POST, this); 26494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 26594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood