Commit b85b6cdd authored by gogerald's avatar gogerald Committed by Commit Bot

[AutofillAssistant] Introduce autofill assistant in components/autofill_assistant/browser

Bug: 806868
Change-Id: Id1204fad26029f7358d9628590d713b9c2af01f3
Reviewed-on: https://chromium-review.googlesource.com/1143895Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Ganggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577945}
parent 6eadc4cb
...@@ -2428,6 +2428,7 @@ jumbo_split_static_library("browser") { ...@@ -2428,6 +2428,7 @@ jumbo_split_static_library("browser") {
"//chrome/browser/android/webapk:proto", "//chrome/browser/android/webapk:proto",
"//chrome/services/media_gallery_util:manifest", # TODO(xingliu): Tries to remove this. "//chrome/services/media_gallery_util:manifest", # TODO(xingliu): Tries to remove this.
"//chrome/services/media_gallery_util/public/cpp", "//chrome/services/media_gallery_util/public/cpp",
"//components/autofill_assistant/browser",
"//components/cdm/browser", "//components/cdm/browser",
"//components/embedder_support/android:web_contents_delegate", "//components/embedder_support/android:web_contents_delegate",
"//components/feed:buildflags", "//components/feed:buildflags",
......
gogerald@chromium.org
\ No newline at end of file
# 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.
import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
sources = [
"assistant.proto",
]
}
static_library("browser") {
sources = [
"assistant_controller.cc",
"assistant_controller.h",
"assistant_protocol_utils.cc",
"assistant_protocol_utils.h",
"assistant_script.h",
"assistant_script_executor.cc",
"assistant_script_executor.h",
"assistant_script_executor_delegate.h",
"assistant_service.cc",
"assistant_service.h",
]
public_deps = [
":proto",
"//base",
"//components/version_info",
"//content/public/browser",
"//google_apis",
"//net",
]
}
include_rules = [
"+components/version_info/version_info.h",
"+content/public/browser",
"+google_apis",
"+net",
"+services/network/public/cpp",
]
\ No newline at end of file
// 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.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package autofill_assistant;
// Context contains client environment details. It's used to filter the
// scripts that can be surfaced to the user.
message ClientContextProto {
required string chrome_version = 1;
}
// Get the list of scripts that can potentially be run on a url.
message SupportsScriptRequestProto {
required string url = 1;
required ClientContextProto client_context = 2;
}
// Response of the list of supported scripts.
message SupportsScriptResponseProto {
repeated SupportedScriptProto scripts = 1;
}
// Supported script.
message SupportedScriptProto {
// This is the internal name of the script.
required string path = 1;
message PresentationProto {
// Name to use when suggesting this script to users.
optional string name = 1;
}
optional PresentationProto presentation = 2;
}
enum PolicyType {
UNKNOWN_POLICY = 0;
SCRIPT = 1;
PAGE = 2;
VALIDATION = 3;
TRACE = 4;
}
// Initial request to get a script's actions.
message InitialScriptActionRequestProto {
message QueryProto {
required string script_path = 1;
optional PolicyType policy = 2;
}
required QueryProto query = 1;
}
// 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/assistant_controller.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
namespace autofill_assistant {
// static
void AssistantController::CreateAndStartForWebContents(
content::WebContents* web_contents) {
new AssistantController(web_contents);
}
AssistantService* AssistantController::GetAssistantService() {
return assistant_service_.get();
}
AssistantController::AssistantController(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
assistant_service_(std::make_unique<AssistantService>(
web_contents->GetBrowserContext())) {
if (!web_contents->IsLoading()) {
GetAssistantScripts();
}
}
AssistantController::~AssistantController() {}
void AssistantController::OnGetAssistantScripts(
AssistantService::AssistantScripts scripts) {
assistant_scripts_ = std::move(scripts);
}
void AssistantController::DidFinishLoad(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
// TODO(crbug.com/806868): Find a better time to get and update assistant
// scripts.
GetAssistantScripts();
}
void AssistantController::WebContentsDestroyed() {
delete this;
}
void AssistantController::GetAssistantScripts() {
assistant_service_->GetAssistantScriptsForUrl(
web_contents()->GetLastCommittedURL(),
base::BindOnce(&AssistantController::OnGetAssistantScripts,
base::Unretained(this)));
}
} // namespace autofill_assistant
\ No newline at end of file
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_CONTROLLER_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_CONTROLLER_H_
#include "components/autofill_assistant/browser/assistant_script_executor_delegate.h"
#include "components/autofill_assistant/browser/assistant_service.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
class RenderFrameHost;
class WebContents;
} // namespace content
namespace autofill_assistant {
// Autofill assistant controller controls autofill assistant action detection,
// display, execution and so on. The instance of this object self deletes when
// the web contents is being destroyed.
class AssistantController : public AssistantScriptExecutorDelegate,
private content::WebContentsObserver {
public:
static void CreateAndStartForWebContents(content::WebContents* web_contents);
// Overrides AssistantScriptExecutorDelegate:
AssistantService* GetAssistantService() override;
private:
explicit AssistantController(content::WebContents* web_contents);
~AssistantController() override;
void GetAssistantScripts();
void OnGetAssistantScripts(AssistantService::AssistantScripts scripts);
// Overrides content::WebContentsObserver:
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
void WebContentsDestroyed() override;
std::unique_ptr<AssistantService> assistant_service_;
AssistantService::AssistantScripts assistant_scripts_;
DISALLOW_COPY_AND_ASSIGN(AssistantController);
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_CONTROLLER_H_
\ No newline at end of file
// 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/assistant_protocol_utils.h"
#include "base/logging.h"
#include "components/autofill_assistant/browser/assistant.pb.h"
#include "components/version_info/version_info.h"
#include "url/gurl.h"
namespace autofill_assistant {
// static
std::string AssistantProtocolUtils::CreateGetScriptsRequest(const GURL& url) {
DCHECK(!url.is_empty());
ClientContextProto context_proto;
context_proto.set_chrome_version(
version_info::GetProductNameAndVersionForUserAgent());
SupportsScriptRequestProto script_proto;
script_proto.set_url(url.spec());
script_proto.set_allocated_client_context(&context_proto);
std::string serialized_script_proto;
bool success = script_proto.SerializeToString(&serialized_script_proto);
DCHECK(success);
return serialized_script_proto;
}
// static
AssistantProtocolUtils::AssistantScripts
AssistantProtocolUtils::ParseAssistantScripts(const std::string& response) {
DCHECK(!response.empty());
AssistantScripts scripts;
SupportsScriptResponseProto response_proto;
if (!response_proto.ParseFromString(response)) {
LOG(ERROR) << "Failed to parse getting assistant scripts response.";
return scripts;
}
for (const auto& script : response_proto.scripts()) {
std::string name = "";
if (script.has_presentation() && script.presentation().has_name()) {
name = script.presentation().name();
}
auto assistant_script = std::make_unique<AssistantScript>();
assistant_script->name = name;
assistant_script->path = script.path();
scripts[assistant_script.get()] = std::move(assistant_script);
}
return scripts;
}
// static
std::string AssistantProtocolUtils::CreateInitialScriptActionRequest(
const std::string& script_path) {
InitialScriptActionRequestProto::QueryProto query;
query.set_script_path(script_path);
query.set_policy(PolicyType::SCRIPT);
InitialScriptActionRequestProto initial_request_proto;
initial_request_proto.set_allocated_query(&query);
std::string serialized_initial_request_proto;
bool success = initial_request_proto.SerializeToString(
&serialized_initial_request_proto);
DCHECK(success);
return serialized_initial_request_proto;
}
} // namespace autofill_assistant
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_PROTOCOL_UTILS_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_PROTOCOL_UTILS_H_
#include "components/autofill_assistant/browser/assistant_script.h"
#include <map>
#include <string>
class GURL;
namespace autofill_assistant {
// Autofill assistant protocol related convenient utils.
class AssistantProtocolUtils {
public:
// Create getting autofill assistant scripts request for the given
// |url|.
static std::string CreateGetScriptsRequest(const GURL& url);
using AssistantScripts =
std::map<AssistantScript*, std::unique_ptr<AssistantScript>>;
// Parse assistant scripts from the given |response|, which should not be an
// empty string.
static AssistantScripts ParseAssistantScripts(const std::string& response);
// Create initial request to get script actions for the given |script_path|.
static std::string CreateInitialScriptActionRequest(
const std::string& script_path);
private:
// To avoid instantiate this class by accident.
AssistantProtocolUtils() = delete;
~AssistantProtocolUtils() = delete;
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_PROTOCOL_UTILS_H_
\ No newline at end of file
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_H_
#include <string>
namespace autofill_assistant {
// Assistant script represents a sequence of client actions.
struct AssistantScript {
std::string name;
std::string path;
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_H_
\ No newline at end of file
// 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/assistant_script_executor.h"
#include "base/bind.h"
#include "components/autofill_assistant/browser/assistant_service.h"
namespace autofill_assistant {
AssistantScriptExecutor::AssistantScriptExecutor(
AssistantScript* script,
AssistantScriptExecutorDelegate* delegate)
: script_(script), delegate_(delegate), weak_ptr_factory_(this) {
DCHECK(script_);
DCHECK(delegate_);
}
AssistantScriptExecutor::~AssistantScriptExecutor() {}
void AssistantScriptExecutor::Run(RunScriptCallback callback) {
callback_ = std::move(callback);
DCHECK(delegate_->GetAssistantService());
delegate_->GetAssistantService()->GetAssistantActions(
script_->path,
base::BindOnce(&AssistantScriptExecutor::onGetAssistantActions,
weak_ptr_factory_.GetWeakPtr()));
}
void AssistantScriptExecutor::onGetAssistantActions(bool result) {
NOTIMPLEMENTED();
}
} // namespace autofill_assistant
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_H_
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/assistant_script.h"
#include "components/autofill_assistant/browser/assistant_script_executor_delegate.h"
namespace autofill_assistant {
// Class to execute an assistant script.
class AssistantScriptExecutor {
public:
// |script| and |delegate| should outlive this object and should not be
// nullptr.
AssistantScriptExecutor(AssistantScript* script,
AssistantScriptExecutorDelegate* delegate);
~AssistantScriptExecutor();
using RunScriptCallback = base::OnceCallback<void(bool)>;
void Run(RunScriptCallback callback);
private:
void onGetAssistantActions(bool result);
AssistantScript* script_;
AssistantScriptExecutorDelegate* delegate_;
RunScriptCallback callback_;
base::WeakPtrFactory<AssistantScriptExecutor> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AssistantScriptExecutor);
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_H_
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_DELEGATE_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_DELEGATE_H_
namespace autofill_assistant {
class AssistantService;
class AssistantScriptExecutorDelegate {
public:
virtual AssistantService* GetAssistantService() = 0;
protected:
virtual ~AssistantScriptExecutorDelegate() {}
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SCRIPT_EXECUTOR_DELEGATE_H_
// 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/assistant_service.h"
#include "base/strings/strcat.h"
#include "components/autofill_assistant/browser/assistant_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_assistant_service", R"(
semantics {
sender: "Autofill Assistant"
description:
"Chromium posts requests to autofill assistant server to get
assistant scripts for a URL."
trigger:
"A user opens a URL that could be assisted by autofill
assistant server."
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 {
AssistantService::AssistantService(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);
assistant_script_server_url_ =
GURL(kAutofillAssistantServer).ReplaceComponents(script_replacements);
url::StringPieceReplacements<std::string> action_replacements;
action_replacements.SetPathStr(kActionEndpoint);
action_replacements.SetQueryStr(api_key);
assistant_script_action_server_url_ =
GURL(kAutofillAssistantServer).ReplaceComponents(action_replacements);
}
AssistantService::~AssistantService() {}
void AssistantService::GetAssistantScriptsForUrl(
const GURL& url,
GetAssistantScriptsForUrlCallback callback) {
DCHECK(url.is_valid());
std::unique_ptr<AssistantLoader> assistant_loader =
std::make_unique<AssistantLoader>();
assistant_loader->scripts_callback = std::move(callback);
assistant_loader->loader =
CreateAndStartLoader(assistant_script_server_url_,
AssistantProtocolUtils::CreateGetScriptsRequest(url),
assistant_loader.get());
assistant_loaders_[assistant_loader.get()] = std::move(assistant_loader);
}
void AssistantService::GetAssistantActions(
const std::string& script_path,
GetAssistantActionsCallback callback) {
DCHECK(!script_path.empty());
std::unique_ptr<AssistantLoader> assistant_loader =
std::make_unique<AssistantLoader>();
assistant_loader->actions_callback = std::move(callback);
assistant_loader->loader = CreateAndStartLoader(
assistant_script_action_server_url_,
AssistantProtocolUtils::CreateInitialScriptActionRequest(script_path),
assistant_loader.get());
assistant_loaders_[assistant_loader.get()] = std::move(assistant_loader);
}
AssistantService::AssistantLoader::AssistantLoader() {}
AssistantService::AssistantLoader::~AssistantLoader() {}
std::unique_ptr<network::SimpleURLLoader>
AssistantService::CreateAndStartLoader(const GURL& server_url,
const std::string& request,
AssistantLoader* 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(&AssistantService::OnURLLoaderComplete,
base::Unretained(this), loader));
return simple_loader;
}
void AssistantService::OnURLLoaderComplete(
AssistantLoader* loader,
std::unique_ptr<std::string> response_body) {
auto loader_it = assistant_loaders_.find(loader);
DCHECK(loader_it != assistant_loaders_.end());
std::unique_ptr<AssistantLoader> assistant_loader =
std::move(loader_it->second);
assistant_loaders_.erase(loader_it);
DCHECK(assistant_loader);
int response_code = 0;
if (assistant_loader->loader->ResponseInfo() &&
assistant_loader->loader->ResponseInfo()->headers) {
response_code =
assistant_loader->loader->ResponseInfo()->headers->response_code();
}
if (assistant_loader->loader->NetError() != net::OK || response_code != 200) {
LOG(ERROR) << "Communicating with autofill assistant server error NetError="
<< assistant_loader->loader->NetError()
<< " response_code=" << response_code;
DCHECK(assistant_loader->scripts_callback ||
assistant_loader->actions_callback);
if (assistant_loader->scripts_callback)
std::move(assistant_loader->scripts_callback).Run(AssistantScripts());
else if (assistant_loader->actions_callback)
std::move(assistant_loader->actions_callback).Run(false);
return;
}
std::string response_body_str;
if (response_body)
response_body_str = std::move(*response_body);
DCHECK(assistant_loader->scripts_callback ||
assistant_loader->actions_callback);
if (assistant_loader->scripts_callback) {
std::move(assistant_loader->scripts_callback)
.Run(AssistantProtocolUtils::ParseAssistantScripts(response_body_str));
} else if (assistant_loader->actions_callback) {
// TODO(crbug.com/806868): Parse assistant actions.
std::move(assistant_loader->actions_callback).Run(false);
}
}
} // namespace autofill_assistant
// 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SERVICE_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SERVICE_H_
#include <map>
#include <memory>
#include "base/callback.h"
#include "components/autofill_assistant/browser/assistant_script.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
}
namespace autofill_assistant {
// Autofill assistant service to communicate with the server to get scripts and
// client actions.
class AssistantService {
public:
AssistantService(content::BrowserContext* context);
~AssistantService();
// Get assistant scripts for a given |url|, which should be a valid URL.
using AssistantScripts =
std::map<AssistantScript*, std::unique_ptr<AssistantScript>>;
using GetAssistantScriptsForUrlCallback =
base::OnceCallback<void(AssistantScripts)>;
void GetAssistantScriptsForUrl(const GURL& url,
GetAssistantScriptsForUrlCallback callback);
// Get assistant actions.
using GetAssistantActionsCallback = base::OnceCallback<void(bool)>;
void GetAssistantActions(const std::string& script_path,
GetAssistantActionsCallback callback);
private:
// Struct to store assistant scripts and actions request.
struct AssistantLoader {
AssistantLoader();
~AssistantLoader();
// One of the |scripts_callback| and |actions_callback| must be nullptr;
GetAssistantScriptsForUrlCallback scripts_callback;
GetAssistantActionsCallback actions_callback;
std::unique_ptr<network::SimpleURLLoader> loader;
};
std::unique_ptr<network::SimpleURLLoader> CreateAndStartLoader(
const GURL& server_url,
const std::string& request,
AssistantLoader* loader);
void OnURLLoaderComplete(AssistantLoader* loader,
std::unique_ptr<std::string> response_body);
content::BrowserContext* context_;
GURL assistant_script_server_url_;
GURL assistant_script_action_server_url_;
// Destroying this object will cancel ongoing requests.
std::map<AssistantLoader*, std::unique_ptr<AssistantLoader>>
assistant_loaders_;
DISALLOW_COPY_AND_ASSIGN(AssistantService);
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ASSISTANT_SERVICE_H_
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