This source file includes following definitions.
- RequestTextCheck
- IsAvailable
- ParseResponse
- text
- OnURLFetchComplete
- CreateURLFetcher
#include "chrome/browser/spellchecker/spelling_service_client.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/spellcheck_common.h"
#include "chrome/common/spellcheck_result.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "google_apis/google_api_keys.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "url/gurl.h"
namespace {
const char kSpellingServiceURL[] = "https://www.googleapis.com/rpc";
const char kMisspellingsPath[] = "result.spellingCheckResponse.misspellings";
const char kErrorPath[] = "error";
}
SpellingServiceClient::SpellingServiceClient() {
}
SpellingServiceClient::~SpellingServiceClient() {
STLDeleteContainerPairPointers(spellcheck_fetchers_.begin(),
spellcheck_fetchers_.end());
}
bool SpellingServiceClient::RequestTextCheck(
content::BrowserContext* context,
ServiceType type,
const base::string16& text,
const TextCheckCompleteCallback& callback) {
DCHECK(type == SUGGEST || type == SPELLCHECK);
if (!context || !IsAvailable(context, type)) {
callback.Run(false, text, std::vector<SpellCheckResult>());
return false;
}
const PrefService* pref = user_prefs::UserPrefs::Get(context);
DCHECK(pref);
std::string language_code;
std::string country_code;
chrome::spellcheck_common::GetISOLanguageCountryCodeFromLocale(
pref->GetString(prefs::kSpellCheckDictionary),
&language_code,
&country_code);
std::string encoded_text = base::GetQuotedJSONString(text);
static const char kSpellingRequest[] =
"{"
"\"method\":\"spelling.check\","
"\"apiVersion\":\"v%d\","
"\"params\":{"
"\"text\":%s,"
"\"language\":\"%s\","
"\"originCountry\":\"%s\","
"\"key\":%s"
"}"
"}";
std::string api_key = base::GetQuotedJSONString(google_apis::GetAPIKey());
std::string request = base::StringPrintf(
kSpellingRequest,
type,
encoded_text.c_str(),
language_code.c_str(),
country_code.c_str(),
api_key.c_str());
GURL url = GURL(kSpellingServiceURL);
net::URLFetcher* fetcher = CreateURLFetcher(url);
fetcher->SetRequestContext(context->GetRequestContext());
fetcher->SetUploadData("application/json", request);
fetcher->SetLoadFlags(
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
spellcheck_fetchers_[fetcher] = new TextCheckCallbackData(callback, text);
fetcher->Start();
return true;
}
bool SpellingServiceClient::IsAvailable(
content::BrowserContext* context,
ServiceType type) {
const PrefService* pref = user_prefs::UserPrefs::Get(context);
DCHECK(pref);
if (!pref->GetBoolean(prefs::kEnableContinuousSpellcheck) ||
!pref->GetBoolean(prefs::kSpellCheckUseSpellingService) ||
context->IsOffTheRecord())
return false;
std::string locale = pref->GetString(prefs::kSpellCheckDictionary);
if (locale.empty())
return false;
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUseSpellingSuggestions))
return type == SUGGEST;
bool language_available = !locale.compare(0, 2, "en");
if (language_available) {
return type == SPELLCHECK;
} else {
return type == SUGGEST;
}
}
bool SpellingServiceClient::ParseResponse(
const std::string& data,
std::vector<SpellCheckResult>* results) {
scoped_ptr<base::DictionaryValue> value(
static_cast<base::DictionaryValue*>(
base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS)));
if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY))
return false;
base::DictionaryValue* error = NULL;
if (value->GetDictionary(kErrorPath, &error))
return false;
base::ListValue* misspellings = NULL;
if (!value->GetList(kMisspellingsPath, &misspellings))
return true;
for (size_t i = 0; i < misspellings->GetSize(); ++i) {
base::DictionaryValue* misspelling = NULL;
if (!misspellings->GetDictionary(i, &misspelling))
return false;
int start = 0;
int length = 0;
base::ListValue* suggestions = NULL;
if (!misspelling->GetInteger("charStart", &start) ||
!misspelling->GetInteger("charLength", &length) ||
!misspelling->GetList("suggestions", &suggestions)) {
return false;
}
base::DictionaryValue* suggestion = NULL;
base::string16 replacement;
if (!suggestions->GetDictionary(0, &suggestion) ||
!suggestion->GetString("suggestion", &replacement)) {
return false;
}
SpellCheckResult result(
SpellCheckResult::SPELLING, start, length, replacement);
results->push_back(result);
}
return true;
}
SpellingServiceClient::TextCheckCallbackData::TextCheckCallbackData(
TextCheckCompleteCallback callback,
base::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);
}
spellcheck_fetchers_.erase(fetcher.get());
callback_data->callback.Run(success, callback_data->text, results);
}
net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) {
return net::URLFetcher::Create(url, net::URLFetcher::POST, this);
}