blob: e7031a371c42466e4c5fdefe853dbbfeb64748df [file] [log] [blame]
// Copyright 2018 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/autofill_assistant/browser/service.h"
#include <string>
#include <utility>
#include <vector>
#include "base/strings/strcat.h"
#include "components/autofill_assistant/browser/protocol_utils.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/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/url_canon_stdstring.h"
namespace {
// TODO(crbug.com/806868): Provide correct server and endpoint.
const char* const kAutofillAssistantServer = "";
const char* const kScriptEndpoint = "";
const char* const kActionEndpoint = "";
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("autofill_service", R"(
semantics {
sender: "Autofill Assistant"
description:
"Chromium posts requests to autofill assistant server to get
scripts for a URL."
trigger:
"Matching URL."
data: "None."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: NO
setting:
"This feature can be disabled in settings."
policy_exception_justification: "Not implemented."
})");
} // namespace
namespace autofill_assistant {
Service::Service(content::BrowserContext* context) : context_(context) {
std::string api_key = google_apis::GetAPIKey();
url::StringPieceReplacements<std::string> script_replacements;
script_replacements.SetPathStr(kScriptEndpoint);
script_replacements.SetQueryStr(api_key);
script_server_url_ =
GURL(kAutofillAssistantServer).ReplaceComponents(script_replacements);
url::StringPieceReplacements<std::string> action_replacements;
action_replacements.SetPathStr(kActionEndpoint);
action_replacements.SetQueryStr(api_key);
script_action_server_url_ =
GURL(kAutofillAssistantServer).ReplaceComponents(action_replacements);
}
Service::~Service() {}
void Service::GetScriptsForUrl(const GURL& url, ResponseCallback callback) {
DCHECK(url.is_valid());
std::unique_ptr<Loader> loader = std::make_unique<Loader>();
loader->callback = std::move(callback);
loader->loader = CreateAndStartLoader(
script_server_url_, ProtocolUtils::CreateGetScriptsRequest(url),
loader.get());
loaders_[loader.get()] = std::move(loader);
}
void Service::GetActions(const std::string& script_path,
ResponseCallback callback) {
DCHECK(!script_path.empty());
std::unique_ptr<Loader> loader = std::make_unique<Loader>();
loader->callback = std::move(callback);
loader->loader = CreateAndStartLoader(
script_action_server_url_,
ProtocolUtils::CreateInitialScriptActionsRequest(script_path),
loader.get());
loaders_[loader.get()] = std::move(loader);
}
void Service::GetNextActions(
const std::string& previous_server_payload,
const std::vector<ProcessedActionProto>& processed_actions,
ResponseCallback callback) {
DCHECK(!previous_server_payload.empty());
std::unique_ptr<Loader> loader = std::make_unique<Loader>();
loader->callback = std::move(callback);
loader->loader =
CreateAndStartLoader(script_action_server_url_,
ProtocolUtils::CreateNextScriptActionsRequest(
previous_server_payload, processed_actions),
loader.get());
loaders_[loader.get()] = std::move(loader);
}
Service::Loader::Loader() {}
Service::Loader::~Loader() {}
std::unique_ptr<::network::SimpleURLLoader> Service::CreateAndStartLoader(
const GURL& server_url,
const std::string& request,
Loader* loader) {
auto resource_request = std::make_unique<::network::ResourceRequest>();
resource_request->url = server_url;
resource_request->method = "POST";
resource_request->fetch_redirect_mode =
::network::mojom::FetchRedirectMode::kError;
resource_request->load_flags =
net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
std::unique_ptr<::network::SimpleURLLoader> simple_loader =
::network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
simple_loader->AttachStringForUpload(request, "application/x-protobuffer");
simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
content::BrowserContext::GetDefaultStoragePartition(context_)
->GetURLLoaderFactoryForBrowserProcess()
.get(),
base::BindOnce(&Service::OnURLLoaderComplete, base::Unretained(this),
loader));
return simple_loader;
}
void Service::OnURLLoaderComplete(Loader* loader,
std::unique_ptr<std::string> response_body) {
auto loader_it = loaders_.find(loader);
DCHECK(loader_it != loaders_.end());
std::unique_ptr<Loader> loader_instance = std::move(loader_it->second);
loaders_.erase(loader_it);
DCHECK(loader_instance);
int response_code = 0;
if (loader_instance->loader->ResponseInfo() &&
loader_instance->loader->ResponseInfo()->headers) {
response_code =
loader_instance->loader->ResponseInfo()->headers->response_code();
}
std::string response_body_str;
if (loader_instance->loader->NetError() != net::OK || response_code != 200) {
LOG(ERROR) << "Communicating with autofill assistant server error NetError="
<< loader_instance->loader->NetError()
<< " response_code=" << response_code;
std::move(loader_instance->callback).Run(false, response_body_str);
return;
}
if (response_body)
response_body_str = std::move(*response_body);
std::move(loader_instance->callback).Run(true, response_body_str);
}
} // namespace autofill_assistant