Commit 55ba59a0 authored by Stephane Zermatten's avatar Stephane Zermatten Committed by Commit Bot

Allow prompt action to react to element disappearing.

Before this change, it was possible to make prompt end when element
appeared, but not when they disappeared. Yet, prompt is often used in
interrupt to deal with dialog box and it is useful to detect when such a
dialog box is gone.

With this change, scripts can just ask for prompt to end when a specific
element is gone.

Bug: b/146311363
Change-Id: Ie52fe2b0216533ce92f298fd3b6369ac4af01716
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1969578
Commit-Queue: Stephane Zermatten <szermatt@chromium.org>
Reviewed-by: default avatarMathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726359}
parent 9a0342b7
......@@ -72,14 +72,27 @@ void PromptAction::RegisterChecks(
auto_select_choice_index_ = -1;
for (int i = 0; i < proto_.prompt().choices_size(); i++) {
Selector selector =
Selector(proto_.prompt().choices(i).auto_select_if_element_exists());
if (selector.empty())
continue;
checker->AddElementCheck(
selector, base::BindOnce(&PromptAction::OnAutoSelectElementExists,
weak_ptr_factory_.GetWeakPtr(), i));
const PromptProto::Choice& choice = proto_.prompt().choices(i);
switch (choice.auto_select_case()) {
case PromptProto::Choice::kAutoSelectIfElementExists:
checker->AddElementCheck(
Selector(choice.auto_select_if_element_exists()),
base::BindOnce(&PromptAction::OnAutoSelectElementExists,
weak_ptr_factory_.GetWeakPtr(), i,
/* must_exist= */ true));
break;
case PromptProto::Choice::kAutoSelectIfElementDisappears:
checker->AddElementCheck(
Selector(choice.auto_select_if_element_disappears()),
base::BindOnce(&PromptAction::OnAutoSelectElementExists,
weak_ptr_factory_.GetWeakPtr(), i,
/* must_exist= */ false));
break;
case PromptProto::Choice::AUTO_SELECT_NOT_SET:
break;
}
}
checker->AddAllDoneCallback(base::BindOnce(&PromptAction::OnElementChecksDone,
......@@ -141,19 +154,23 @@ void PromptAction::UpdateUserActions() {
bool PromptAction::HasAutoSelect() {
for (int i = 0; i < proto_.prompt().choices_size(); i++) {
Selector selector =
Selector(proto_.prompt().choices(i).auto_select_if_element_exists());
if (!selector.empty())
if (proto_.prompt().choices(i).auto_select_case() !=
PromptProto::Choice::AUTO_SELECT_NOT_SET) {
return true;
}
}
return false;
}
void PromptAction::OnAutoSelectElementExists(
int choice_index,
bool must_exist,
const ClientStatus& element_status) {
if (element_status.ok())
if ((must_exist && element_status.ok()) ||
(!must_exist &&
element_status.proto_status() == ELEMENT_RESOLUTION_FAILED)) {
auto_select_choice_index_ = choice_index;
}
// Calling OnSuggestionChosen() is delayed until try_done, as it indirectly
// deletes the batch element checker, which isn't supported from an element
......
......@@ -39,6 +39,7 @@ class PromptAction : public Action {
void UpdateUserActions();
bool HasAutoSelect();
void OnAutoSelectElementExists(int choice_index,
bool must_exist,
const ClientStatus& element_status);
void OnElementChecksDone(
base::OnceCallback<void(const ClientStatus&)> wait_for_dom_callback);
......
......@@ -271,6 +271,36 @@ TEST_F(PromptActionTest, AutoSelectWhenElementExists) {
task_env_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
TEST_F(PromptActionTest, AutoSelectWhenElementDisappears) {
auto* choice_proto = prompt_proto_->add_choices();
choice_proto->set_server_payload("auto-select");
choice_proto->mutable_auto_select_if_element_disappears()->add_selectors(
"element");
PromptAction action(&mock_action_delegate_, proto_);
action.ProcessAction(callback_.Get());
EXPECT_THAT(user_actions_, Pointee(SizeIs(0)));
EXPECT_CALL(mock_web_controller_,
OnElementCheck(Eq(Selector({"element"})), _))
.WillOnce(RunOnceCallback<1>(OkClientStatus()))
.WillRepeatedly(
RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED)));
// First round of element checks: element exists.
task_env_.FastForwardBy(base::TimeDelta::FromSeconds(1));
// Second round of element checks: element has gone.
EXPECT_CALL(mock_action_delegate_, CancelPrompt());
EXPECT_CALL(
callback_,
Run(Pointee(AllOf(Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::prompt_choice,
Property(&PromptProto::Choice::server_payload,
"auto-select"))))));
task_env_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
TEST_F(PromptActionTest, AutoSelectWithButton) {
auto* ok_proto = prompt_proto_->add_choices();
ok_proto->mutable_chip()->set_text("Ok");
......
......@@ -1188,8 +1188,13 @@ message PromptProto {
// Map this choice to a direct action.
optional DirectActionProto direct_action = 12;
// Auto-select this choice if the given element exist.
optional ElementReferenceProto auto_select_if_element_exists = 4;
oneof auto_select {
// Auto-select this choice if the given element exist.
ElementReferenceProto auto_select_if_element_exists = 4;
// Auto-select this choice if the given element disappears.
ElementReferenceProto auto_select_if_element_disappears = 14;
}
// The chip is only visible or enabled if all the given element exists.
repeated ElementReferenceProto show_only_if_element_exists = 6;
......
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