Commit 97ac6fc2 authored by Stephane Zermatten's avatar Stephane Zermatten Committed by Commit Bot

[Autofill Assistant] Prompt only shows button if element exists

Before this patch, buttons were always displayed on prompt. That was
incomplete: it did not allow reproducing the behavior we currently have
between scripts where button appear as a result of DOM changes.

With this patch, prompt button reproduce the between-script behavior,
allowing buttons to be shown only conditionally.

Bug: 122825639
Change-Id: I53eee48156cac1f2e5f1b81dd86a48bb25566a0c
Reviewed-on: https://chromium-review.googlesource.com/c/1437084
Commit-Queue: Stephane Zermatten <szermatt@chromium.org>
Reviewed-by: default avatarMathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#626943}
parent 9c079500
...@@ -28,9 +28,52 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate, ...@@ -28,9 +28,52 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate,
delegate->SetStatusMessage(proto_.prompt().message()); delegate->SetStatusMessage(proto_.prompt().message());
callback_ = std::move(callback); callback_ = std::move(callback);
auto chips = std::make_unique<std::vector<Chip>>();
DCHECK_GT(proto_.prompt().choices_size(), 0); DCHECK_GT(proto_.prompt().choices_size(), 0);
delegate->Prompt(CreateChips());
batch_element_checker_ = delegate->CreateBatchElementChecker();
// Register elements whose existence enable new chips.
for (int i = 0; i < proto_.prompt().choices_size(); i++) {
auto& choice_proto = proto_.prompt().choices(i);
Selector selector(choice_proto.show_only_if_element_exists());
if (selector.empty())
continue;
batch_element_checker_->AddElementCheck(
kExistenceCheck, selector,
base::BindOnce(&PromptAction::OnRequiredElementExists,
weak_ptr_factory_.GetWeakPtr(),
base::Unretained(delegate), i));
}
// Wait as long as necessary for one of the elements to show up. This is
// cancelled by CancelProto()
for (const auto& choice_proto : proto_.prompt().choices()) {
Selector selector(choice_proto.element_exists());
if (selector.empty())
continue;
std::string payload;
choice_proto.SerializeToString(&payload);
batch_element_checker_->AddElementCheck(
kExistenceCheck, selector,
base::BindOnce(&PromptAction::OnElementExist,
weak_ptr_factory_.GetWeakPtr(), payload));
}
batch_element_checker_->Run(
base::TimeDelta::Max(),
/* try_done= */
base::BindRepeating(&PromptAction::OnElementChecksDone,
weak_ptr_factory_.GetWeakPtr(),
base::Unretained(delegate)),
/* all_done= */ base::DoNothing());
}
std::unique_ptr<std::vector<Chip>> PromptAction::CreateChips() {
auto chips = std::make_unique<std::vector<Chip>>();
// TODO(crbug.com/806868): Surface type in proto instead of guessing it from // TODO(crbug.com/806868): Surface type in proto instead of guessing it from
// highlight flag. // highlight flag.
Chip::Type non_highlight_type = Chip::Type::CHIP_ASSISTIVE; Chip::Type non_highlight_type = Chip::Type::CHIP_ASSISTIVE;
...@@ -41,8 +84,10 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate, ...@@ -41,8 +84,10 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate,
} }
} }
for (const auto& choice_proto : proto_.prompt().choices()) { for (int i = 0; i < proto_.prompt().choices_size(); i++) {
if (choice_proto.name().empty()) auto& choice_proto = proto_.prompt().choices(i);
if (choice_proto.show_only_if_element_exists().selectors_size() > 0 &&
required_element_found_.count(i) == 0)
continue; continue;
chips->emplace_back(); chips->emplace_back();
...@@ -58,29 +103,7 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate, ...@@ -58,29 +103,7 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate,
base::BindOnce(&PromptAction::OnSuggestionChosen, base::BindOnce(&PromptAction::OnSuggestionChosen,
weak_ptr_factory_.GetWeakPtr(), server_payload); weak_ptr_factory_.GetWeakPtr(), server_payload);
} }
delegate->Prompt(std::move(chips)); return chips;
batch_element_checker_ = delegate->CreateBatchElementChecker();
for (const auto& choice_proto : proto_.prompt().choices()) {
if (choice_proto.element_exists().selectors_size() == 0)
continue;
std::string payload;
choice_proto.SerializeToString(&payload);
batch_element_checker_->AddElementCheck(
kExistenceCheck, Selector(choice_proto.element_exists()),
base::BindOnce(&PromptAction::OnElementExist,
weak_ptr_factory_.GetWeakPtr(), payload));
}
// Wait as long as necessary for one of the elements to show up. This is
// cancelled by OnSuggestionChosen()
batch_element_checker_->Run(
base::TimeDelta::Max(),
/* try_done= */
base::BindRepeating(&PromptAction::OnElementChecksDone,
weak_ptr_factory_.GetWeakPtr(),
base::Unretained(delegate)),
/* all_done= */ base::DoNothing());
} }
void PromptAction::OnElementExist(const std::string& payload, bool exists) { void PromptAction::OnElementExist(const std::string& payload, bool exists) {
...@@ -92,6 +115,16 @@ void PromptAction::OnElementExist(const std::string& payload, bool exists) { ...@@ -92,6 +115,16 @@ void PromptAction::OnElementExist(const std::string& payload, bool exists) {
// callback. // callback.
} }
void PromptAction::OnRequiredElementExists(ActionDelegate* delegate,
int choice_index,
bool exists) {
if (!exists)
return;
required_element_found_.insert(choice_index);
delegate->Prompt(CreateChips());
}
void PromptAction::OnElementChecksDone(ActionDelegate* delegate) { void PromptAction::OnElementChecksDone(ActionDelegate* delegate) {
if (!forced_payload_.empty()) { if (!forced_payload_.empty()) {
delegate->CancelPrompt(); delegate->CancelPrompt();
......
...@@ -6,12 +6,15 @@ ...@@ -6,12 +6,15 @@
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_ACTION_H_ #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_ACTION_H_
#include <memory> #include <memory>
#include <set>
#include <string> #include <string>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h" #include "components/autofill_assistant/browser/actions/action.h"
#include "components/autofill_assistant/browser/batch_element_checker.h" #include "components/autofill_assistant/browser/batch_element_checker.h"
#include "components/autofill_assistant/browser/chip.h"
namespace autofill_assistant { namespace autofill_assistant {
...@@ -26,7 +29,11 @@ class PromptAction : public Action { ...@@ -26,7 +29,11 @@ class PromptAction : public Action {
void InternalProcessAction(ActionDelegate* delegate, void InternalProcessAction(ActionDelegate* delegate,
ProcessActionCallback callback) override; ProcessActionCallback callback) override;
std::unique_ptr<std::vector<Chip>> CreateChips();
void OnElementExist(const std::string& payload, bool exists); void OnElementExist(const std::string& payload, bool exists);
void OnRequiredElementExists(ActionDelegate* delegate,
int choice_index,
bool exists);
void OnElementChecksDone(ActionDelegate* delegate); void OnElementChecksDone(ActionDelegate* delegate);
void OnSuggestionChosen(const std::string& payload); void OnSuggestionChosen(const std::string& payload);
...@@ -34,6 +41,10 @@ class PromptAction : public Action { ...@@ -34,6 +41,10 @@ class PromptAction : public Action {
std::string forced_payload_; std::string forced_payload_;
std::unique_ptr<BatchElementChecker> batch_element_checker_; std::unique_ptr<BatchElementChecker> batch_element_checker_;
// Index of an element in PromptActionProto::choices that has a
// show_only_if_element_exists condition that is met.
std::set<int> required_element_found_;
base::WeakPtrFactory<PromptAction> weak_ptr_factory_; base::WeakPtrFactory<PromptAction> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PromptAction); DISALLOW_COPY_AND_ASSIGN(PromptAction);
......
...@@ -564,6 +564,9 @@ message PromptProto { ...@@ -564,6 +564,9 @@ message PromptProto {
// Server payload originally sent by the server. This should // Server payload originally sent by the server. This should
// be transmitted as-is by the client without interpreting. // be transmitted as-is by the client without interpreting.
optional bytes server_payload = 5; optional bytes server_payload = 5;
// The chip is only visible if the given element exists.
optional ElementReferenceProto show_only_if_element_exists = 6;
} }
repeated Choice choices = 4; repeated Choice choices = 4;
} }
......
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