blob: 03b186954309c9fc9f2212af8bcf5a12635cbeab [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/components/quick_answers/translation_result_loader.h"
#include <utility>
#include "base/json/json_writer.h"
#include "base/strings/escape.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/components/quick_answers/quick_answers_model.h"
#include "chromeos/components/quick_answers/utils/quick_answers_utils.h"
#include "chromeos/services/assistant/public/shared/constants.h"
#include "google_apis/google_api_keys.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/gurl.h"
namespace quick_answers {
namespace {
using base::Value;
// The JSON we generate looks like this:
// {
// "q": [
// "test input"
// ],
// "source": "en",
// "target": "zh"
// }
constexpr char kTranslationAPIUrl[] =
"https://translation.googleapis.com/language/translate/v2";
constexpr char kApiKeyName[] = "key";
constexpr base::StringPiece kQueryKey = "q";
constexpr base::StringPiece kSourceLanguageKey = "source";
constexpr base::StringPiece kTargetLanguageKey = "target";
std::string BuildTranslationRequestBody(const IntentInfo& intent_info) {
Value::Dict payload;
Value::List query;
query.Append(intent_info.intent_text);
payload.Set(kQueryKey, std::move(query));
payload.Set(kSourceLanguageKey, intent_info.source_language);
payload.Set(kTargetLanguageKey, intent_info.device_language);
std::string request_payload_str;
base::JSONWriter::Write(payload, &request_payload_str);
return request_payload_str;
}
} // namespace
TranslationResultLoader::TranslationResultLoader(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
ResultLoaderDelegate* delegate)
: ResultLoader(url_loader_factory, delegate) {}
TranslationResultLoader::~TranslationResultLoader() = default;
void TranslationResultLoader::BuildRequest(
const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback) const {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = net::AppendQueryParameter(
GURL(kTranslationAPIUrl), kApiKeyName, google_apis::GetAPIKey());
resource_request->method = net::HttpRequestHeaders::kPostMethod;
resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept,
"application/json");
std::move(callback).Run(
std::move(resource_request),
BuildTranslationRequestBody(preprocessed_output.intent_info));
}
void TranslationResultLoader::ProcessResponse(
const PreprocessedOutput& preprocessed_output,
std::unique_ptr<std::string> response_body,
ResponseParserCallback complete_callback) {
if (translation_response_parser_) {
DCHECK(false) << "translation_response_parser_ must be nullptr";
std::move(complete_callback).Run(nullptr);
return;
}
translation_response_parser_ =
std::make_unique<TranslationResponseParser>(base::BindOnce(
&TranslationResultLoader::ProcessParsedResponse,
weak_ptr_factory_.GetWeakPtr(), preprocessed_output.intent_info,
std::move(complete_callback)));
translation_response_parser_->ProcessResponse(std::move(response_body));
}
void TranslationResultLoader::ProcessParsedResponse(
IntentInfo intent_info,
ResponseParserCallback complete_callback,
std::unique_ptr<TranslationResult> translation_result) {
translation_response_parser_.reset();
if (!translation_result || translation_result->translated_text.empty()) {
std::move(complete_callback).Run(nullptr);
return;
}
translation_result->text_to_translate =
base::UTF8ToUTF16(intent_info.intent_text);
translation_result->source_locale = intent_info.source_language;
translation_result->target_locale = intent_info.device_language;
std::unique_ptr<QuickAnswer> quick_answer = std::make_unique<QuickAnswer>();
quick_answer->result_type = ResultType::kTranslationResult;
quick_answer->title.push_back(std::make_unique<QuickAnswerText>(
BuildTranslationTitleText(intent_info)));
quick_answer->first_answer_row.push_back(
std::make_unique<QuickAnswerResultText>(
base::UTF16ToUTF8(translation_result->translated_text)));
std::unique_ptr<QuickAnswersSession> session =
std::make_unique<QuickAnswersSession>();
session->structured_result = std::make_unique<StructuredResult>();
session->structured_result->translation_result =
std::move(translation_result);
session->quick_answer = std::move(quick_answer);
std::move(complete_callback).Run(std::move(session));
}
} // namespace quick_answers