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

[Autofill Asiistant] Implement wait for dom action

Rename protocols as well

Bug: 806868
Change-Id: Ib24e4d4f8821451a9ee56d27efd1c142a4f2d60b
Reviewed-on: https://chromium-review.googlesource.com/1179966Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Ganggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584176}
parent eab3b960
......@@ -17,6 +17,7 @@ class AssistantAction {
virtual ~AssistantAction() = default;
// Callback returns whether process action is succeed or not.
// Delegate should outlive this object.
using ProcessActionCallback = base::OnceCallback<void(bool)>;
virtual void ProcessAction(AssistantActionDelegate* delegate,
ProcessActionCallback callback) = 0;
......
......@@ -23,6 +23,10 @@ class AssistantActionDelegate {
virtual void ClickElement(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) = 0;
// Check whether the element given by |selectors| exists on the web page.
virtual void ElementExists(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) = 0;
protected:
AssistantActionDelegate() = default;
};
......
......@@ -4,7 +4,20 @@
#include "components/autofill_assistant/browser/actions/assistant_wait_for_dom_action.h"
#include <cmath>
#include "base/bind.h"
#include "base/callback.h"
#include "base/time/time.h"
#include "components/autofill_assistant/browser/actions/assistant_action_delegate.h"
#include "content/public/browser/browser_thread.h"
namespace {
int kCheckPeriodInMilliseconds = 100;
// So it takes about 150*100 milliseconds.
int kDefaultCheckRounds = 150;
} // namespace
namespace autofill_assistant {
......@@ -12,13 +25,62 @@ AssistantWaitForDomAction::AssistantWaitForDomAction(
int timeout_ms,
const std::vector<std::string>& selectors,
bool for_absence)
: target_element_selectors_(selectors) {}
: timeout_ms_(timeout_ms),
target_element_selectors_(selectors),
for_absence_(for_absence),
weak_ptr_factory_(this) {}
AssistantWaitForDomAction::~AssistantWaitForDomAction() {}
void AssistantWaitForDomAction::ProcessAction(AssistantActionDelegate* delegate,
ProcessActionCallback callback) {
NOTIMPLEMENTED();
int check_rounds = kDefaultCheckRounds;
if (timeout_ms_ > 0)
check_rounds = std::ceil(timeout_ms_ / kCheckPeriodInMilliseconds);
CheckElementExists(delegate, check_rounds, std::move(callback));
}
void AssistantWaitForDomAction::CheckElementExists(
AssistantActionDelegate* delegate,
int rounds,
ProcessActionCallback callback) {
DCHECK(rounds > 0);
delegate->ElementExists(
target_element_selectors_,
base::BindOnce(&AssistantWaitForDomAction::OnCheckElementExists,
weak_ptr_factory_.GetWeakPtr(), delegate, rounds,
std::move(callback)));
}
void AssistantWaitForDomAction::OnCheckElementExists(
AssistantActionDelegate* delegate,
int rounds,
ProcessActionCallback callback,
bool result) {
if (for_absence_ && !result) {
std::move(callback).Run(true);
return;
}
if (!for_absence_ && result) {
std::move(callback).Run(true);
return;
}
if (rounds == 0) {
std::move(callback).Run(false);
return;
}
--rounds;
content::BrowserThread::PostDelayedTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&AssistantWaitForDomAction::CheckElementExists,
weak_ptr_factory_.GetWeakPtr(), delegate, rounds,
std::move(callback)),
base::TimeDelta::FromMilliseconds(kCheckPeriodInMilliseconds));
}
} // namespace autofill_assistant.
......@@ -10,7 +10,9 @@
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
namespace autofill_assistant {
// An action to ask Chrome to wait for a DOM element to process next action.
......@@ -29,8 +31,19 @@ class AssistantWaitForDomAction : public AssistantAction {
ProcessActionCallback callback) override;
private:
void CheckElementExists(AssistantActionDelegate* delegate,
int rounds,
ProcessActionCallback callback);
void OnCheckElementExists(AssistantActionDelegate* delegate,
int rounds,
ProcessActionCallback callback,
bool result);
int timeout_ms_;
std::vector<std::string> target_element_selectors_;
bool for_absence_;
base::WeakPtrFactory<AssistantWaitForDomAction> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AssistantWaitForDomAction);
};
......
......@@ -85,11 +85,11 @@ message ActionsResponseProto {
message AssistantActionProto {
// Next action id: 3.
oneof action_info {
ClickSpecificationProto click_specification = 1;
TellSpecificationProto tell_specification = 2;
UseAddressSpecificationProto use_address_specification = 3;
UseCreditCardSpecificationProto use_card_specification = 4;
WaitForDomSpecificationProto wait_for_dom_specification = 5;
ClickProto click = 1;
TellProto tell = 2;
UseAddressProto use_address = 3;
UseCreditCardProto use_card = 4;
WaitForDomProto wait_for_dom = 5;
}
}
......@@ -104,19 +104,19 @@ message ElementReferenceProto {
}
// Contain all arguments to perform a click.
message ClickSpecificationProto {
message ClickProto {
required ElementReferenceProto element_to_click = 1;
}
// Contain a message to tell the user.
message TellSpecificationProto {
message TellProto {
required string message = 1;
}
// TODO(crbug.com/806868): Handle it better when there is no local address.
// Ask user to fill a form with a local address if there is, otherwise fail this
// action.
message UseAddressSpecificationProto {
message UseAddressProto {
// Optional message to show usage of the address, like billing or shipping
// address.
optional string usage = 1;
......@@ -128,19 +128,19 @@ message UseAddressSpecificationProto {
// TODO(crbug.com/806868): Handle it better when there is no local credit card.
// Ask user to fill a form with a local credit card if there is, otherwise fail
// this action.
message UseCreditCardSpecificationProto {
message UseCreditCardProto {
// A reference to the card number field in the form that should be filled.
optional ElementReferenceProto form_field_element = 1;
}
// Ask Chrome to wait for an element in the DOM. This can be used to only
// proceed to the next action once the page is ready.
message WaitForDomSpecificationProto {
// Fail after waiting this amount of time.
required int32 timeout_ms = 1;
message WaitForDomProto {
// The element to wait.
required ElementReferenceProto element = 2;
required ElementReferenceProto element = 1;
// Fail after waiting this amount of time.
optional int32 timeout_ms = 2;
// If true, wait for the given element to be absent, otherwise wait for
// existence.
......
......@@ -129,11 +129,11 @@ bool AssistantProtocolUtils::ParseAssistantActions(
for (const auto& action : response_proto.actions()) {
switch (action.action_info_case()) {
case AssistantActionProto::ActionInfoCase::kClickSpecification: {
DCHECK(action.has_click_specification());
case AssistantActionProto::ActionInfoCase::kClick: {
DCHECK(action.has_click());
std::vector<std::string> selectors;
for (const auto& selector :
action.click_specification().element_to_click().selectors()) {
action.click().element_to_click().selectors()) {
selectors.emplace_back(selector);
}
DCHECK(!selectors.empty());
......@@ -141,34 +141,32 @@ bool AssistantProtocolUtils::ParseAssistantActions(
std::make_unique<AssistantClickAction>(selectors));
break;
}
case AssistantActionProto::ActionInfoCase::kTellSpecification: {
DCHECK(action.has_tell_specification());
assistant_actions->emplace_back(std::make_unique<AssistantTellAction>(
action.tell_specification().message()));
case AssistantActionProto::ActionInfoCase::kTell: {
DCHECK(action.has_tell());
assistant_actions->emplace_back(
std::make_unique<AssistantTellAction>(action.tell().message()));
break;
}
case AssistantActionProto::ActionInfoCase::kUseAddressSpecification: {
DCHECK(action.has_use_address_specification());
case AssistantActionProto::ActionInfoCase::kUseAddress: {
DCHECK(action.has_use_address());
std::vector<std::string> selectors;
for (const auto& selector : action.use_address_specification()
.form_field_element()
.selectors()) {
for (const auto& selector :
action.use_address().form_field_element().selectors()) {
selectors.emplace_back(selector);
}
DCHECK(!selectors.empty());
assistant_actions->emplace_back(
std::make_unique<AssistantUseAddressAction>(
action.use_address_specification().has_usage()
? action.use_address_specification().usage()
action.use_address().has_usage() ? action.use_address().usage()
: "",
selectors));
break;
}
case AssistantActionProto::ActionInfoCase::kUseCardSpecification: {
DCHECK(action.has_use_card_specification());
case AssistantActionProto::ActionInfoCase::kUseCard: {
DCHECK(action.has_use_card());
std::vector<std::string> selectors;
for (const auto& selector :
action.use_card_specification().form_field_element().selectors()) {
action.use_card().form_field_element().selectors()) {
selectors.emplace_back(selector);
}
DCHECK(!selectors.empty());
......@@ -176,19 +174,22 @@ bool AssistantProtocolUtils::ParseAssistantActions(
std::make_unique<AssistantUseCardAction>(selectors));
break;
}
case AssistantActionProto::ActionInfoCase::kWaitForDomSpecification: {
DCHECK(action.has_wait_for_dom_specification());
case AssistantActionProto::ActionInfoCase::kWaitForDom: {
DCHECK(action.has_wait_for_dom());
std::vector<std::string> selectors;
for (const auto& selector :
action.wait_for_dom_specification().element().selectors()) {
action.wait_for_dom().element().selectors()) {
selectors.emplace_back(selector);
}
DCHECK(!selectors.empty());
assistant_actions->emplace_back(
std::make_unique<AssistantWaitForDomAction>(
action.wait_for_dom_specification().timeout_ms(), selectors,
action.wait_for_dom_specification().has_check_for_absence() &&
action.wait_for_dom_specification().check_for_absence()));
action.wait_for_dom().has_timeout_ms()
? action.wait_for_dom().timeout_ms()
: 0,
selectors,
action.wait_for_dom().has_check_for_absence() &&
action.wait_for_dom().check_for_absence()));
break;
}
case AssistantActionProto::ActionInfoCase::ACTION_INFO_NOT_SET: {
......
......@@ -42,6 +42,13 @@ void AssistantScriptExecutor::ClickElement(
std::move(callback));
}
void AssistantScriptExecutor::ElementExists(
const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) {
delegate_->GetAssistantWebController()->ElementExists(selectors,
std::move(callback));
}
void AssistantScriptExecutor::OnGetAssistantActions(
bool result,
const std::string& response) {
......
......@@ -29,6 +29,8 @@ class AssistantScriptExecutor : public AssistantActionDelegate {
void ShowStatusMessage(const std::string& message) override;
void ClickElement(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) override;
void ElementExists(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) override;
private:
void OnGetAssistantActions(bool result, const std::string& response);
......
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