// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/spellcheck/browser/spelling_service_client.h"

#include <stddef.h>

#include <algorithm>

#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/memory/ptr_util.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 "components/data_use_measurement/core/data_use_user_data.h"
#include "components/prefs/pref_service.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.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 {

// 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";

// Languages currently supported by SPELLCHECK.
const char* const kValidLanguages[] = {"en", "es", "fi", "da"};

}  // namespace

SpellingServiceClient::SpellingServiceClient() {}

SpellingServiceClient::~SpellingServiceClient() {}

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 dictionary;
  pref->GetList(spellcheck::prefs::kSpellCheckDictionaries)
      ->GetString(0, &dictionary);

  std::string language_code;
  std::string country_code;
  spellcheck::GetISOLanguageCountryCodeFromLocale(dictionary, &language_code,
                                                  &country_code);

  // Replace typographical apostrophes with typewriter apostrophes, so that
  // server word breaker behaves correctly.
  const base::char16 kApostrophe = 0x27;
  const base::char16 kRightSingleQuotationMark = 0x2019;
  base::string16 text_copy = text;
  std::replace(text_copy.begin(), text_copy.end(), kRightSingleQuotationMark,
               kApostrophe);

  // Format the JSON request to be sent to the Spelling service.
  std::string encoded_text = base::GetQuotedJSONString(text_copy);

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

  // Create traffic annotation tag.
  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("spellcheck_lookup", R"(
        semantics {
          sender: "Online Spellcheck"
          description:
            "Chromium can provide smarter spell-checking, by sending the text "
            "that the users type into the browser, to Google's servers. This"
            "allows users to use the same spell-checking technology used by "
            "Google products, such as Docs. If the feature is enabled, "
            "Chromium will send the entire contents of text fields as user "
            "types them to Google, along with the browser’s default language. "
            "Google returns a list of suggested spellings, which will be "
            "displayed in the context menu."
          trigger: "User types text into a text field or asks to correct a "
                   "misspelled word."
          data: "Text a user has typed into a text field. No user identifier "
                "is sent along with the text."
          destination: GOOGLE_OWNED_SERVICE
        }
        policy {
          cookies_allowed: NO
          setting:
            "Users can enable or disable this feature via 'Use a web service "
            "to help resolve spelling errors.' in Chromium's settings under "
            "Advanced. The feature is disabled by default."
          chrome_policy {
            SpellCheckServiceEnabled {
                policy_options {mode: MANDATORY}
                SpellCheckServiceEnabled: false
            }
          }
        })");

  net::URLFetcher* fetcher =
      CreateURLFetcher(url, traffic_annotation).release();
  data_use_measurement::DataUseUserData::AttachToFetcher(
      fetcher, data_use_measurement::DataUseUserData::SPELL_CHECKER);
  fetcher->SetRequestContext(
      content::BrowserContext::GetDefaultStoragePartition(context)
          ->GetURLRequestContext());
  fetcher->SetUploadData("application/json", request);
  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                        net::LOAD_DO_NOT_SAVE_COOKIES);
  spellcheck_fetchers_[fetcher] = base::MakeUnique<TextCheckCallbackData>(
      base::WrapUnique(fetcher), 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 prefs don't allow spellchecking, if the context is off the record, or if
  // multilingual spellchecking is enabled the spelling service should be
  // unavailable.
  if (!pref->GetBoolean(spellcheck::prefs::kEnableSpellcheck) ||
      !pref->GetBoolean(spellcheck::prefs::kSpellCheckUseSpellingService) ||
      context->IsOffTheRecord())
    return false;

  // If the locale for spelling has not been set, the user has not decided to
  // use spellcheck so we don't do anything remote (suggest or spelling).
  std::string locale;
  pref->GetList(spellcheck::prefs::kSpellCheckDictionaries)
      ->GetString(0, &locale);
  if (locale.empty())
    return false;

  // Finally, if all options are available, we only enable only SUGGEST
  // if SPELLCHECK is not available for our language because SPELLCHECK results
  // are a superset of SUGGEST results.
  for (const char* language : kValidLanguages) {
    if (!locale.compare(0, 2, language))
      return type == SPELLCHECK;
  }

  // Only SUGGEST is allowed.
  return type == SUGGEST;
}

bool SpellingServiceClient::ParseResponse(
    const std::string& data,
    std::vector<SpellCheckResult>* results) {
  // When this JSON-RPC call finishes successfully, the Spelling service returns
  // an JSON object listed below.
  // * result - an envelope object representing the result from the APIARY
  //   server, which is the JSON-API front-end for the Spelling service. This
  //   object consists of the following variable:
  //   - spellingCheckResponse (SpellingCheckResponse).
  // * SpellingCheckResponse - an object representing the result from the
  //   Spelling service. This object consists of the following variable:
  //   - misspellings (optional array of Misspelling)
  // * Misspelling - an object representing a misspelling region and its
  //   suggestions. This object consists of the following variables:
  //   - charStart (number) - the beginning of the misspelled region;
  //   - charLength (number) - the length of the misspelled region;
  //   - suggestions (array of string) - the suggestions for the misspelling
  //     text, and;
  //   - canAutoCorrect (optional boolean) - whether we can use the first
  //     suggestion for auto-correction.
  // For example, the Spelling service returns the following JSON when we send a
  // spelling request for "duck goes quisk" as of 16 August, 2011.
  // {
  //   "result": {
  //     "spellingCheckResponse": {
  //       "misspellings": [{
  //           "charStart": 10,
  //           "charLength": 5,
  //           "suggestions": [{ "suggestion": "quack" }],
  //           "canAutoCorrect": false
  //       }]
  //     }
  //   }
  // }
  // If the service is not available, the Spelling service returns JSON with an
  // error.
  // {
  //   "error": {
  //     "code": 400,
  //     "message": "Bad Request",
  //     "data": [...]
  //   }
  // }
  std::unique_ptr<base::DictionaryValue> value(
      static_cast<base::DictionaryValue*>(
          base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS)
              .release()));
  if (!value.get() || !value->is_dict())
    return false;

  // Check for errors from spelling service.
  base::DictionaryValue* error = nullptr;
  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.
  base::ListValue* misspellings = nullptr;
  if (!value->GetList(kMisspellingsPath, &misspellings))
    return true;

  for (size_t i = 0; i < misspellings->GetSize(); ++i) {
    // Retrieve the i-th misspelling region and put it to the given vector. When
    // the Spelling service sends two or more suggestions, we read only the
    // first one because SpellCheckResult can store only one suggestion.
    base::DictionaryValue* misspelling = nullptr;
    if (!misspellings->GetDictionary(i, &misspelling))
      return false;

    int start = 0;
    int length = 0;
    base::ListValue* suggestions = nullptr;
    if (!misspelling->GetInteger("charStart", &start) ||
        !misspelling->GetInteger("charLength", &length) ||
        !misspelling->GetList("suggestions", &suggestions)) {
      return false;
    }

    base::DictionaryValue* suggestion = nullptr;
    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(
    std::unique_ptr<net::URLFetcher> fetcher,
    TextCheckCompleteCallback callback,
    base::string16 text)
    : fetcher(std::move(fetcher)), callback(callback), text(text) {}

SpellingServiceClient::TextCheckCallbackData::~TextCheckCallbackData() {}

void SpellingServiceClient::OnURLFetchComplete(const net::URLFetcher* source) {
  DCHECK(base::ContainsKey(spellcheck_fetchers_, source));
  std::unique_ptr<TextCheckCallbackData> callback_data =
      std::move(spellcheck_fetchers_[source]);
  spellcheck_fetchers_.erase(source);

  bool success = false;
  std::vector<SpellCheckResult> results;
  if (source->GetResponseCode() / 100 == 2) {
    std::string data;
    source->GetResponseAsString(&data);
    success = ParseResponse(data, &results);
  }

  // The callback may release the last (transitive) dependency on |this|. It
  // MUST be the last function called.
  callback_data->callback.Run(success, callback_data->text, results);
}

std::unique_ptr<net::URLFetcher> SpellingServiceClient::CreateURLFetcher(
    const GURL& url,
    net::NetworkTrafficAnnotationTag traffic_annotation) {
  return net::URLFetcher::Create(url, net::URLFetcher::POST, this,
                                 traffic_annotation);
}
