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);
}