Commit d73bde35 authored by Yue Li's avatar Yue Li Committed by Commit Bot

Quick Answers: Add cloud API integration for translation

Bug: b/150034512
Test: Run existing tests
Change-Id: I1a0349a96fe1c640d0611e174410861ab4864e69
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2431792Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Yue Li <updowndota@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811751}
parent 6d66bf13
...@@ -26,6 +26,10 @@ source_set("quick_answers") { ...@@ -26,6 +26,10 @@ source_set("quick_answers") {
"search_result_parsers/translation_result_parser.h", "search_result_parsers/translation_result_parser.h",
"search_result_parsers/unit_conversion_result_parser.cc", "search_result_parsers/unit_conversion_result_parser.cc",
"search_result_parsers/unit_conversion_result_parser.h", "search_result_parsers/unit_conversion_result_parser.h",
"translation_response_parser.cc",
"translation_response_parser.h",
"translation_result_loader.cc",
"translation_result_loader.h",
"understanding/intent_generator.cc", "understanding/intent_generator.cc",
"understanding/intent_generator.h", "understanding/intent_generator.h",
"utils/language_detector.cc", "utils/language_detector.cc",
......
...@@ -110,7 +110,7 @@ void QuickAnswersClient::FetchQuickAnswers( ...@@ -110,7 +110,7 @@ void QuickAnswersClient::FetchQuickAnswers(
result_loader_ = CreateResultLoader( result_loader_ = CreateResultLoader(
preprocessed_request.preprocessed_output.intent_info.intent_type); preprocessed_request.preprocessed_output.intent_info.intent_type);
// Load and parse search result. // Load and parse search result.
result_loader_->Fetch(preprocessed_request.preprocessed_output.query); result_loader_->Fetch(preprocessed_request.preprocessed_output);
} }
void QuickAnswersClient::SendRequest( void QuickAnswersClient::SendRequest(
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "chromeos/components/quick_answers/utils/quick_answers_utils.h" #include "chromeos/components/quick_answers/utils/quick_answers_utils.h"
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -31,8 +32,10 @@ class TestResultLoader : public ResultLoader { ...@@ -31,8 +32,10 @@ class TestResultLoader : public ResultLoader {
ResultLoaderDelegate* delegate) ResultLoaderDelegate* delegate)
: ResultLoader(url_loader_factory, delegate) {} : ResultLoader(url_loader_factory, delegate) {}
// ResultLoader: // ResultLoader:
GURL BuildRequestUrl(const std::string& selected_text) const override { void BuildRequest(const PreprocessedOutput& preprocessed_output,
return GURL(); BuildRequestCallback callback) const override {
return std::move(callback).Run(
std::make_unique<network::ResourceRequest>());
} }
void ProcessResponse(std::unique_ptr<std::string> response_body, void ProcessResponse(std::unique_ptr<std::string> response_body,
ResponseParserCallback complete_callback) override {} ResponseParserCallback complete_callback) override {}
...@@ -48,7 +51,7 @@ class MockResultLoader : public TestResultLoader { ...@@ -48,7 +51,7 @@ class MockResultLoader : public TestResultLoader {
MockResultLoader& operator=(const MockResultLoader&) = delete; MockResultLoader& operator=(const MockResultLoader&) = delete;
// TestResultLoader: // TestResultLoader:
MOCK_METHOD1(Fetch, void(const std::string&)); MOCK_METHOD1(Fetch, void(const PreprocessedOutput&));
}; };
MATCHER_P(QuickAnswersRequestWithOutputEqual, quick_answers_request, "") { MATCHER_P(QuickAnswersRequestWithOutputEqual, quick_answers_request, "") {
...@@ -305,7 +308,9 @@ TEST_F(QuickAnswersClientTest, SendRequest) { ...@@ -305,7 +308,9 @@ TEST_F(QuickAnswersClientTest, SendRequest) {
mock_result_loader_ = mock_result_loader_ =
std::make_unique<MockResultLoader>(&test_url_loader_factory_, nullptr); std::make_unique<MockResultLoader>(&test_url_loader_factory_, nullptr);
EXPECT_CALL(*mock_result_loader_, Fetch(::testing::Eq("Define:sel"))); EXPECT_CALL(*mock_result_loader_,
Fetch(PreprocessedOutputEqual(PreprocessRequest(
IntentInfo("sel", IntentType::kDictionary)))));
QuickAnswersClient::SetResultLoaderFactoryForTesting( QuickAnswersClient::SetResultLoaderFactoryForTesting(
&result_loader_factory_callback_); &result_loader_factory_callback_);
...@@ -347,7 +352,9 @@ TEST_F(QuickAnswersClientTest, FetchQuickAnswers) { ...@@ -347,7 +352,9 @@ TEST_F(QuickAnswersClientTest, FetchQuickAnswers) {
mock_result_loader_ = mock_result_loader_ =
std::make_unique<MockResultLoader>(&test_url_loader_factory_, nullptr); std::make_unique<MockResultLoader>(&test_url_loader_factory_, nullptr);
EXPECT_CALL(*mock_result_loader_, Fetch(::testing::Eq("Define:sel"))); EXPECT_CALL(*mock_result_loader_,
Fetch(PreprocessedOutputEqual(
quick_answers_request->preprocessed_output)));
QuickAnswersClient::SetResultLoaderFactoryForTesting( QuickAnswersClient::SetResultLoaderFactoryForTesting(
&result_loader_factory_callback_); &result_loader_factory_callback_);
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
#include "base/bind.h" #include "base/bind.h"
#include "chromeos/components/quick_answers/quick_answers_model.h" #include "chromeos/components/quick_answers/quick_answers_model.h"
#include "chromeos/components/quick_answers/search_result_loader.h" #include "chromeos/components/quick_answers/search_result_loader.h"
#include "chromeos/components/quick_answers/translation_result_loader.h"
#include "chromeos/components/quick_answers/utils/quick_answers_metrics.h" #include "chromeos/components/quick_answers/utils/quick_answers_metrics.h"
#include "chromeos/constants/chromeos_features.h"
#include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/simple_url_loader.h"
...@@ -50,17 +52,25 @@ std::unique_ptr<ResultLoader> ResultLoader::Create( ...@@ -50,17 +52,25 @@ std::unique_ptr<ResultLoader> ResultLoader::Create(
IntentType intent_type, IntentType intent_type,
URLLoaderFactory* url_loader_factory, URLLoaderFactory* url_loader_factory,
ResultLoader::ResultLoaderDelegate* delegate) { ResultLoader::ResultLoaderDelegate* delegate) {
// TODO(llin): Add TranslationResultLoader if the intent type is translation. if (features::IsQuickAnswersTranslationCloudAPIEnabled() &&
intent_type == IntentType::kTranslation)
return std::make_unique<TranslationResultLoader>(url_loader_factory,
delegate);
return std::make_unique<SearchResultLoader>(url_loader_factory, delegate); return std::make_unique<SearchResultLoader>(url_loader_factory, delegate);
} }
void ResultLoader::Fetch(const std::string& selected_text) { void ResultLoader::Fetch(const PreprocessedOutput& preprocessed_output) {
DCHECK(network_loader_factory_); DCHECK(network_loader_factory_);
DCHECK(!selected_text.empty()); DCHECK(!preprocessed_output.query.empty());
// Load the resource. // Load the resource.
auto resource_request = std::make_unique<network::ResourceRequest>(); BuildRequest(preprocessed_output,
resource_request->url = BuildRequestUrl(selected_text); base::BindOnce(&ResultLoader::OnBuildRequestComplete,
weak_factory_.GetWeakPtr()));
}
void ResultLoader::OnBuildRequestComplete(
std::unique_ptr<network::ResourceRequest> resource_request) {
loader_ = network::SimpleURLLoader::Create(std::move(resource_request), loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
kNetworkTrafficAnnotationTag); kNetworkTrafficAnnotationTag);
...@@ -68,7 +78,7 @@ void ResultLoader::Fetch(const std::string& selected_text) { ...@@ -68,7 +78,7 @@ void ResultLoader::Fetch(const std::string& selected_text) {
loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
network_loader_factory_, network_loader_factory_,
base::BindOnce(&ResultLoader::OnSimpleURLLoaderComplete, base::BindOnce(&ResultLoader::OnSimpleURLLoaderComplete,
base::Unretained(this))); weak_factory_.GetWeakPtr()));
} }
void ResultLoader::OnSimpleURLLoaderComplete( void ResultLoader::OnSimpleURLLoaderComplete(
...@@ -84,7 +94,7 @@ void ResultLoader::OnSimpleURLLoaderComplete( ...@@ -84,7 +94,7 @@ void ResultLoader::OnSimpleURLLoaderComplete(
ProcessResponse(std::move(response_body), ProcessResponse(std::move(response_body),
base::BindOnce(&ResultLoader::OnResultParserComplete, base::BindOnce(&ResultLoader::OnResultParserComplete,
base::Unretained(this))); weak_factory_.GetWeakPtr()));
} }
void ResultLoader::OnResultParserComplete( void ResultLoader::OnResultParserComplete(
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/memory/weak_ptr.h"
#include "chromeos/components/quick_answers/search_result_parsers/search_response_parser.h" #include "chromeos/components/quick_answers/search_result_parsers/search_response_parser.h"
class GURL;
namespace network { namespace network {
class SimpleURLLoader; class SimpleURLLoader;
struct ResourceRequest;
namespace mojom { namespace mojom {
class URLLoaderFactory; class URLLoaderFactory;
...@@ -24,6 +24,7 @@ namespace chromeos { ...@@ -24,6 +24,7 @@ namespace chromeos {
namespace quick_answers { namespace quick_answers {
enum class IntentType; enum class IntentType;
struct PreprocessedOutput;
class ResultLoader { class ResultLoader {
public: public:
...@@ -51,6 +52,9 @@ class ResultLoader { ...@@ -51,6 +52,9 @@ class ResultLoader {
using ResponseParserCallback = using ResponseParserCallback =
base::OnceCallback<void(std::unique_ptr<QuickAnswer> quick_answer)>; base::OnceCallback<void(std::unique_ptr<QuickAnswer> quick_answer)>;
using BuildRequestCallback = base::OnceCallback<void(
std::unique_ptr<network::ResourceRequest> resource_request)>;
ResultLoader(network::mojom::URLLoaderFactory* url_loader_factory, ResultLoader(network::mojom::URLLoaderFactory* url_loader_factory,
ResultLoaderDelegate* delegate); ResultLoaderDelegate* delegate);
...@@ -70,11 +74,12 @@ class ResultLoader { ...@@ -70,11 +74,12 @@ class ResultLoader {
// calling |ResultLoaderDelegate| methods when finished. // calling |ResultLoaderDelegate| methods when finished.
// Note that delegate methods should be called only once per // Note that delegate methods should be called only once per
// ResultLoader instance. Virtual for testing. // ResultLoader instance. Virtual for testing.
virtual void Fetch(const std::string& selected_text); virtual void Fetch(const PreprocessedOutput& preprocessed_output);
protected: protected:
// Builds the request URL from |selected_text|. // Builds the request URL from |selected_text|.
virtual GURL BuildRequestUrl(const std::string& selected_text) const = 0; virtual void BuildRequest(const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback) const = 0;
// Process the |response_body| and invoked the callback with |QuickAnswer|. // Process the |response_body| and invoked the callback with |QuickAnswer|.
virtual void ProcessResponse(std::unique_ptr<std::string> response_body, virtual void ProcessResponse(std::unique_ptr<std::string> response_body,
...@@ -85,11 +90,15 @@ class ResultLoader { ...@@ -85,11 +90,15 @@ class ResultLoader {
std::unique_ptr<network::SimpleURLLoader> loader_; std::unique_ptr<network::SimpleURLLoader> loader_;
ResultLoaderDelegate* const delegate_; ResultLoaderDelegate* const delegate_;
void OnBuildRequestComplete(
std::unique_ptr<network::ResourceRequest> resource_request);
void OnSimpleURLLoaderComplete(std::unique_ptr<std::string> response_body); void OnSimpleURLLoaderComplete(std::unique_ptr<std::string> response_body);
void OnResultParserComplete(std::unique_ptr<QuickAnswer> quick_answer); void OnResultParserComplete(std::unique_ptr<QuickAnswer> quick_answer);
// Time when the query is issued. // Time when the query is issued.
base::TimeTicks fetch_start_time_; base::TimeTicks fetch_start_time_;
base::WeakPtrFactory<ResultLoader> weak_factory_{this};
}; };
} // namespace quick_answers } // namespace quick_answers
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chromeos/services/assistant/public/shared/constants.h" #include "chromeos/services/assistant/public/shared/constants.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -70,15 +71,19 @@ SearchResultLoader::SearchResultLoader(URLLoaderFactory* url_loader_factory, ...@@ -70,15 +71,19 @@ SearchResultLoader::SearchResultLoader(URLLoaderFactory* url_loader_factory,
SearchResultLoader::~SearchResultLoader() = default; SearchResultLoader::~SearchResultLoader() = default;
GURL SearchResultLoader::BuildRequestUrl( void SearchResultLoader::BuildRequest(
const std::string& selected_text) const { const PreprocessedOutput& preprocessed_output,
GURL result = GURL(assistant::kKnowledgeApiEndpoint); BuildRequestCallback callback) const {
GURL url = GURL(assistant::kKnowledgeApiEndpoint);
// Add encoded request payload. // Add encoded request payload.
result = net::AppendOrReplaceQueryParameter( url = net::AppendOrReplaceQueryParameter(
result, assistant::kPayloadParamName, url, assistant::kPayloadParamName,
BuildSearchRequestPayload(selected_text)); BuildSearchRequestPayload(preprocessed_output.query));
return result;
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
std::move(callback).Run(std::move(resource_request));
} }
void SearchResultLoader::ProcessResponse( void SearchResultLoader::ProcessResponse(
......
...@@ -31,7 +31,8 @@ class SearchResultLoader : public ResultLoader { ...@@ -31,7 +31,8 @@ class SearchResultLoader : public ResultLoader {
~SearchResultLoader() override; ~SearchResultLoader() override;
// ResultLoader: // ResultLoader:
GURL BuildRequestUrl(const std::string& selected_text) const override; void BuildRequest(const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback) const override;
void ProcessResponse(std::unique_ptr<std::string> response_body, void ProcessResponse(std::unique_ptr<std::string> response_body,
ResponseParserCallback complete_callback) override; ResponseParserCallback complete_callback) override;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "chromeos/components/quick_answers/quick_answers_model.h" #include "chromeos/components/quick_answers/quick_answers_model.h"
#include "chromeos/components/quick_answers/test/test_helpers.h" #include "chromeos/components/quick_answers/test/test_helpers.h"
#include "chromeos/components/quick_answers/utils/quick_answers_utils.h"
#include "chromeos/services/assistant/public/shared/constants.h" #include "chromeos/services/assistant/public/shared/constants.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
...@@ -78,7 +79,7 @@ TEST_F(SearchResultLoaderTest, Success) { ...@@ -78,7 +79,7 @@ TEST_F(SearchResultLoaderTest, Success) {
*mock_delegate_, *mock_delegate_,
OnQuickAnswerReceived(QuickAnswerEqual(&(*expected_quick_answer)))); OnQuickAnswerReceived(QuickAnswerEqual(&(*expected_quick_answer))));
EXPECT_CALL(*mock_delegate_, OnNetworkError()).Times(0); EXPECT_CALL(*mock_delegate_, OnNetworkError()).Times(0);
loader_->Fetch("23cm"); loader_->Fetch(PreprocessRequest(IntentInfo("23cm", IntentType::kUnknown)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
...@@ -89,7 +90,7 @@ TEST_F(SearchResultLoaderTest, NetworkError) { ...@@ -89,7 +90,7 @@ TEST_F(SearchResultLoaderTest, NetworkError) {
network::URLLoaderCompletionStatus(net::HTTP_NOT_FOUND)); network::URLLoaderCompletionStatus(net::HTTP_NOT_FOUND));
EXPECT_CALL(*mock_delegate_, OnNetworkError()); EXPECT_CALL(*mock_delegate_, OnNetworkError());
EXPECT_CALL(*mock_delegate_, OnQuickAnswerReceived(testing::_)).Times(0); EXPECT_CALL(*mock_delegate_, OnQuickAnswerReceived(testing::_)).Times(0);
loader_->Fetch("23cm"); loader_->Fetch(PreprocessRequest(IntentInfo("23cm", IntentType::kUnknown)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
...@@ -98,7 +99,7 @@ TEST_F(SearchResultLoaderTest, EmptyResponse) { ...@@ -98,7 +99,7 @@ TEST_F(SearchResultLoaderTest, EmptyResponse) {
std::string()); std::string());
EXPECT_CALL(*mock_delegate_, OnQuickAnswerReceived(testing::Eq(nullptr))); EXPECT_CALL(*mock_delegate_, OnQuickAnswerReceived(testing::Eq(nullptr)));
EXPECT_CALL(*mock_delegate_, OnNetworkError()).Times(0); EXPECT_CALL(*mock_delegate_, OnNetworkError()).Times(0);
loader_->Fetch("23cm"); loader_->Fetch(PreprocessRequest(IntentInfo("23cm", IntentType::kUnknown)));
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
......
...@@ -50,6 +50,10 @@ MATCHER_P(QuickAnswersRequestEqual, quick_answers_request, "") { ...@@ -50,6 +50,10 @@ MATCHER_P(QuickAnswersRequestEqual, quick_answers_request, "") {
return (arg.selected_text == quick_answers_request.selected_text); return (arg.selected_text == quick_answers_request.selected_text);
} }
MATCHER_P(PreprocessedOutputEqual, preprocessed_output, "") {
return (arg.query == preprocessed_output.query);
}
} // namespace quick_answers } // namespace quick_answers
} // namespace chromeos } // namespace chromeos
......
// Copyright 2020 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 "chromeos/components/quick_answers/translation_response_parser.h"
#include <utility>
#include "base/bind.h"
#include "base/values.h"
#include "chromeos/components/quick_answers/search_result_parsers/result_parser.h"
namespace chromeos {
namespace quick_answers {
TranslationResponseParser::TranslationResponseParser(
TranslationResponseParserCallback complete_callback)
: complete_callback_(std::move(complete_callback)) {}
TranslationResponseParser::~TranslationResponseParser() {
if (complete_callback_)
std::move(complete_callback_).Run(/*quick_answer=*/nullptr);
}
void TranslationResponseParser::ProcessResponse(
std::unique_ptr<std::string> response_body) {
data_decoder::DataDecoder::ParseJsonIsolated(
response_body->c_str(),
base::BindOnce(&TranslationResponseParser::OnJsonParsed,
weak_factory_.GetWeakPtr()));
}
void TranslationResponseParser::OnJsonParsed(
data_decoder::DataDecoder::ValueOrError result) {
DCHECK(complete_callback_);
if (!result.value) {
LOG(ERROR) << "JSON parsing failed: " << *result.error;
std::move(complete_callback_).Run(nullptr);
return;
}
auto* translations = result.value->FindListPath("data.translations");
if (!translations) {
LOG(ERROR) << "Can't find translations result list.";
std::move(complete_callback_).Run(nullptr);
return;
}
DCHECK(translations->GetList().size() == 1);
const std::string* translated_text =
translations->GetList().front().FindStringPath("translatedText");
if (!translated_text) {
LOG(ERROR) << "Can't find a translated text.";
std::move(complete_callback_).Run(nullptr);
return;
}
auto quick_answer = std::make_unique<QuickAnswer>();
quick_answer->result_type = ResultType::kTranslationResult;
quick_answer->primary_answer = *translated_text;
quick_answer->first_answer_row.push_back(
std::make_unique<QuickAnswerResultText>(*translated_text));
std::move(complete_callback_).Run(std::move(quick_answer));
}
} // namespace quick_answers
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESPONSE_PARSER_H_
#define CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESPONSE_PARSER_H_
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
namespace chromeos {
namespace quick_answers {
struct QuickAnswer;
// Parser for extracting quick answer result out of the cloud translation
// response.
class TranslationResponseParser {
public:
// Callback used when parsing of |quick_answer| is complete. Note that
// |quick_answer| may be |nullptr|.
using TranslationResponseParserCallback =
base::OnceCallback<void(std::unique_ptr<QuickAnswer> quick_answer)>;
explicit TranslationResponseParser(
TranslationResponseParserCallback complete_callback);
~TranslationResponseParser();
TranslationResponseParser(const TranslationResponseParser&) = delete;
TranslationResponseParser& operator=(const TranslationResponseParser&) =
delete;
// Starts processing the search response.
void ProcessResponse(std::unique_ptr<std::string> response_body);
private:
void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result);
TranslationResponseParserCallback complete_callback_;
base::WeakPtrFactory<TranslationResponseParser> weak_factory_{this};
};
} // namespace quick_answers
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESPONSE_PARSER_H_
// Copyright 2020 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 "chromeos/components/quick_answers/translation_result_loader.h"
#include <utility>
#include "ash/public/cpp/quick_answers/controller/quick_answers_browser_client.h"
#include "base/json/json_writer.h"
#include "chromeos/components/quick_answers/quick_answers_model.h"
#include "chromeos/services/assistant/public/shared/constants.h"
#include "net/base/escape.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
namespace chromeos {
namespace quick_answers {
namespace {
using base::Value;
using network::mojom::URLLoaderFactory;
// 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 kAuthorizationHeaderFormat[] = "Bearer ";
constexpr base::StringPiece kQueryKey = "q";
constexpr base::StringPiece kSourceLanguageKey = "source";
constexpr base::StringPiece kTargetLanguageKey = "target";
std::string BuildTranslationRequestBody(const IntentInfo& intent_info) {
Value payload(Value::Type::DICTIONARY);
Value query(Value::Type::LIST);
query.Append(intent_info.intent_text);
payload.SetKey(kQueryKey, std::move(query));
payload.SetKey(kSourceLanguageKey, Value(intent_info.source_language));
payload.SetKey(kTargetLanguageKey, Value(intent_info.target_language));
std::string request_payload_str;
base::JSONWriter::Write(payload, &request_payload_str);
return request_payload_str;
}
} // namespace
TranslationResultLoader::TranslationResultLoader(
URLLoaderFactory* url_loader_factory,
ResultLoaderDelegate* delegate)
: ResultLoader(url_loader_factory, delegate) {}
TranslationResultLoader::~TranslationResultLoader() = default;
void TranslationResultLoader::BuildRequest(
const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback) const {
ash::QuickAnswersBrowserClient::Get()->RequestAccessToken(base::BindOnce(
&TranslationResultLoader::OnRequestAccessTokenComplete,
base::Unretained(this), preprocessed_output, std::move(callback)));
}
void TranslationResultLoader::ProcessResponse(
std::unique_ptr<std::string> response_body,
ResponseParserCallback complete_callback) {
translation_response_parser_ =
std::make_unique<TranslationResponseParser>(std::move(complete_callback));
translation_response_parser_->ProcessResponse(std::move(response_body));
}
void TranslationResultLoader::OnRequestAccessTokenComplete(
const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback,
const std::string& access_token) const {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = GURL(kTranslationAPIUrl);
resource_request->method = net::HttpRequestHeaders::kPostMethod;
resource_request->headers.SetHeader(
net::HttpRequestHeaders::kAuthorization,
kAuthorizationHeaderFormat + access_token);
resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept,
"application/json");
resource_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
"application/json");
auto body = BuildTranslationRequestBody(preprocessed_output.intent_info);
resource_request->request_body = new network::ResourceRequestBody();
resource_request->request_body->AppendBytes(body.c_str(), body.length());
std::move(callback).Run(std::move(resource_request));
}
} // namespace quick_answers
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESULT_LOADER_H_
#define CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESULT_LOADER_H_
#include <memory>
#include <string>
#include "chromeos/components/quick_answers/result_loader.h"
#include "chromeos/components/quick_answers/translation_response_parser.h"
namespace network {
namespace mojom {
class URLLoaderFactory;
} // namespace mojom
} // namespace network
namespace chromeos {
namespace quick_answers {
class TranslationResultLoader : public ResultLoader {
public:
TranslationResultLoader(network::mojom::URLLoaderFactory* url_loader_factory,
ResultLoaderDelegate* delegate);
TranslationResultLoader(const TranslationResultLoader&) = delete;
TranslationResultLoader& operator=(const TranslationResultLoader&) = delete;
~TranslationResultLoader() override;
// ResultLoader:
void BuildRequest(const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback) const override;
void ProcessResponse(std::unique_ptr<std::string> response_body,
ResponseParserCallback complete_callback) override;
private:
void OnRequestAccessTokenComplete(
const PreprocessedOutput& preprocessed_output,
BuildRequestCallback callback,
const std::string& access_token) const;
std::unique_ptr<TranslationResponseParser> translation_response_parser_;
};
} // namespace quick_answers
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_QUICK_ANSWERS_TRANSLATION_RESULT_LOADER_H_
...@@ -159,7 +159,7 @@ void IntentGenerator::FindLanguagesCallback( ...@@ -159,7 +159,7 @@ void IntentGenerator::FindLanguagesCallback(
const QuickAnswersRequest& request, const QuickAnswersRequest& request,
std::vector<machine_learning::mojom::TextLanguagePtr> languages) { std::vector<machine_learning::mojom::TextLanguagePtr> languages) {
auto intent_type = IntentType::kUnknown; auto intent_type = IntentType::kUnknown;
// TODO(b/b/150034512): Take confidence level into consideration. // TODO(b/150034512): Take confidence level into consideration.
if (languages.empty() || if (languages.empty() ||
languages.front()->locale == request.context.device_properties.language) { languages.front()->locale == request.context.device_properties.language) {
std::move(complete_callback_) std::move(complete_callback_)
......
...@@ -461,6 +461,10 @@ const base::Feature kQuickAnswersSubToggle{"QuickAnswersSubToggle", ...@@ -461,6 +461,10 @@ const base::Feature kQuickAnswersSubToggle{"QuickAnswersSubToggle",
const base::Feature kQuickAnswersTranslation{"QuickAnswersTranslation", const base::Feature kQuickAnswersTranslation{"QuickAnswersTranslation",
base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether to enable quick answers translation using Cloud API.
const base::Feature kQuickAnswersTranslationCloudAPI{
"QuickAnswersTranslationCloudAPI", base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether the PIN auto submit feature is enabled. // Controls whether the PIN auto submit feature is enabled.
const base::Feature kQuickUnlockPinAutosubmit{"QuickUnlockPinAutosubmit", const base::Feature kQuickUnlockPinAutosubmit{"QuickUnlockPinAutosubmit",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
...@@ -710,6 +714,10 @@ bool IsQuickAnswersTranslationEnabled() { ...@@ -710,6 +714,10 @@ bool IsQuickAnswersTranslationEnabled() {
return base::FeatureList::IsEnabled(kQuickAnswersTranslation); return base::FeatureList::IsEnabled(kQuickAnswersTranslation);
} }
bool IsQuickAnswersTranslationCloudAPIEnabled() {
return base::FeatureList::IsEnabled(kQuickAnswersTranslationCloudAPI);
}
bool IsSplitSettingsSyncEnabled() { bool IsSplitSettingsSyncEnabled() {
return base::FeatureList::IsEnabled(kSplitSettingsSync); return base::FeatureList::IsEnabled(kSplitSettingsSync);
} }
......
...@@ -210,6 +210,8 @@ extern const base::Feature kQuickAnswersSubToggle; ...@@ -210,6 +210,8 @@ extern const base::Feature kQuickAnswersSubToggle;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kQuickAnswersTranslation; extern const base::Feature kQuickAnswersTranslation;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kQuickAnswersTranslationCloudAPI;
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
extern const base::Feature kQuickUnlockPinAutosubmit; extern const base::Feature kQuickUnlockPinAutosubmit;
// TODO(crbug.com/1104164) - Remove this once most // TODO(crbug.com/1104164) - Remove this once most
// users have their preferences backfilled. // users have their preferences backfilled.
...@@ -306,6 +308,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsQuickAnswersSettingToggleEnabled(); ...@@ -306,6 +308,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsQuickAnswersSettingToggleEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
bool IsQuickAnswersTextAnnotatorEnabled(); bool IsQuickAnswersTextAnnotatorEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsQuickAnswersTranslationEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsQuickAnswersTranslationEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
bool IsQuickAnswersTranslationCloudAPIEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsSplitSettingsSyncEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsSplitSettingsSyncEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsViewBasedMultiprofileLoginEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsViewBasedMultiprofileLoginEnabled();
COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsWifiSyncAndroidEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsWifiSyncAndroidEnabled();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment