Commit a793efbd authored by Stephane Zermatten's avatar Stephane Zermatten Committed by Commit Bot

[Autofill Assistant] Add support for an extended 'prompt' action.

With this patch, scripts can use a 'prompt' action to ask questions
instead of ending the script. The UI of 'prompt' looks just like the UI
that appears between scripts, so the choice between a prompt and
multiple scripts should be a scripter implementation decision.

The prompt action, can:
 - allow a subset of the page to be touchable, as controlled by the
   focus action, like what happens between scripts
 - propose suggestions to be displayed in chips, to simulate script
   execution
 - react to element existence, to simulate preconditions

Limitation: Prompt does not allow navigation outside of the current
page, nor page reloads.

Bug: 1340309
Change-Id: I033399621e5afa0d02021cac6cab6765c913970c
Reviewed-on: https://chromium-review.googlesource.com/c/1343266
Commit-Queue: Stephane Zermatten <szermatt@chromium.org>
Reviewed-by: default avatarGanggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610114}
parent 9877705b
......@@ -23,6 +23,7 @@ import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentOptions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
......@@ -135,6 +136,11 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
nativeOnScriptSelected(mUiControllerAndroid, scriptPath);
}
@Override
public void onSuggestionSelected(String suggestion) {
nativeOnSuggestionSelected(mUiControllerAndroid, suggestion);
}
@Override
public void onAddressSelected(String guid) {
nativeOnAddressSelected(mUiControllerAndroid, guid);
......@@ -224,6 +230,21 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
mUiDelegateHolder.performUiOperation(uiDelegate -> uiDelegate.updateScripts(scriptHandles));
}
@CalledByNative
private void onChoose(String[] suggestions) {
// An empty suggestion list is supported. Selection can still be forced. onForceChoose
// should be a no-op in this case.
if (suggestions.length == 0) return;
mUiDelegateHolder.performUiOperation(
uiDelegate -> uiDelegate.showSuggestions(Arrays.asList(suggestions)));
}
@CalledByNative
private void onForceChoose() {
mUiDelegateHolder.performUiOperation(uiDelegate -> uiDelegate.clearCarousel());
}
@CalledByNative
private void onChooseAddress() {
// TODO(crbug.com/806868): Remove this method once all scripts use payment request.
......@@ -449,6 +470,8 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
long nativeUiControllerAndroid, float distanceXRatio, float distanceYRatio);
private native void nativeUpdateTouchableArea(long nativeUiControllerAndroid);
private native void nativeOnScriptSelected(long nativeUiControllerAndroid, String scriptPath);
private native void nativeOnSuggestionSelected(
long nativeUiControllerAndroid, String selection);
private native void nativeOnAddressSelected(long nativeUiControllerAndroid, String guid);
private native void nativeOnCardSelected(long nativeUiControllerAndroid, String guid);
private native void nativeOnShowDetails(long nativeUiControllerAndroid, boolean canContinue);
......
......@@ -132,6 +132,9 @@ class AutofillAssistantUiDelegate {
*/
void onScriptSelected(String scriptPath);
/** Called when a suggestion has been selected. */
void onSuggestionSelected(String suggestion);
/**
* Called when an address has been selected.
*
......@@ -328,7 +331,7 @@ class AutofillAssistantUiDelegate {
return false;
}
private void clearCarousel() {
public void clearCarousel() {
setCarouselChildViews(Collections.emptyList(), /* alignRight= */ false);
}
......@@ -661,6 +664,20 @@ class AutofillAssistantUiDelegate {
mTouchEventFilter.setPartialOverlay(enabled, boxes);
}
/** Shows chip with the given suggestions. */
public void showSuggestions(List<String> suggestions) {
List<View> childViews = new ArrayList<>();
for (String suggestion : suggestions) {
TextView chipView = createChipView(suggestion, ChipStyle.CHIP_ASSISTIVE);
chipView.setOnClickListener(unusedView -> {
clearCarousel();
mClient.onSuggestionSelected(suggestion);
});
childViews.add(chipView);
}
setCarouselChildViews(childViews, /* alignRight= */ false);
}
/**
* Show profiles in the bar.
*
......
......@@ -180,28 +180,40 @@ void UiControllerAndroid::OnScriptSelected(
ui_delegate_->OnScriptSelected(script_path);
}
void UiControllerAndroid::OnSuggestionSelected(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jstring>& jsuggestion) {
if (!choice_callback_) // possibly duplicate call
return;
std::string suggestion;
base::android::ConvertJavaStringToUTF8(env, jsuggestion, &suggestion);
std::move(choice_callback_).Run(suggestion);
}
void UiControllerAndroid::OnAddressSelected(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jstring>& jaddress_guid) {
if (!address_or_card_callback_) // possibly duplicate call
if (!choice_callback_) // possibly duplicate call
return;
std::string guid;
base::android::ConvertJavaStringToUTF8(env, jaddress_guid, &guid);
std::move(address_or_card_callback_).Run(guid);
std::move(choice_callback_).Run(guid);
}
void UiControllerAndroid::OnCardSelected(
JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
const JavaParamRef<jstring>& jcard_guid) {
if (!address_or_card_callback_) // possibly duplicate call
if (!choice_callback_) // possibly duplicate call
return;
std::string guid;
base::android::ConvertJavaStringToUTF8(env, jcard_guid, &guid);
std::move(address_or_card_callback_).Run(guid);
std::move(choice_callback_).Run(guid);
}
void UiControllerAndroid::OnGetPaymentInformation(
......@@ -294,10 +306,32 @@ UiControllerAndroid::OnRequestDebugContext(
return base::android::ConvertUTF8ToJavaString(env, GetDebugContext());
}
void UiControllerAndroid::Choose(
const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) {
DCHECK(!choice_callback_);
choice_callback_ = std::move(callback);
JNIEnv* env = AttachCurrentThread();
Java_AutofillAssistantUiController_onChoose(
env, java_autofill_assistant_ui_controller_,
base::android::ToJavaArrayOfStrings(env, suggestions));
}
void UiControllerAndroid::ForceChoose(const std::string& result) {
if (!choice_callback_)
return;
JNIEnv* env = AttachCurrentThread();
Java_AutofillAssistantUiController_onForceChoose(
env, java_autofill_assistant_ui_controller_);
std::move(choice_callback_).Run(result);
}
void UiControllerAndroid::ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) {
DCHECK(!address_or_card_callback_);
address_or_card_callback_ = std::move(callback);
DCHECK(!choice_callback_);
choice_callback_ = std::move(callback);
JNIEnv* env = AttachCurrentThread();
Java_AutofillAssistantUiController_onChooseAddress(
env, java_autofill_assistant_ui_controller_);
......@@ -305,8 +339,8 @@ void UiControllerAndroid::ChooseAddress(
void UiControllerAndroid::ChooseCard(
base::OnceCallback<void(const std::string&)> callback) {
DCHECK(!address_or_card_callback_);
address_or_card_callback_ = std::move(callback);
DCHECK(!choice_callback_);
choice_callback_ = std::move(callback);
JNIEnv* env = AttachCurrentThread();
Java_AutofillAssistantUiController_onChooseCard(
env, java_autofill_assistant_ui_controller_);
......
......@@ -44,6 +44,9 @@ class UiControllerAndroid : public UiController,
void ShutdownGracefully() override;
void CloseCustomTab() override;
void UpdateScripts(const std::vector<ScriptHandle>& scripts) override;
void Choose(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) override;
void ForceChoose(const std::string& result) override;
void ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) override;
void ChooseCard(
......@@ -89,6 +92,10 @@ class UiControllerAndroid : public UiController,
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jscript_path);
void OnSuggestionSelected(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jsuggestion);
void OnAddressSelected(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
......@@ -128,7 +135,7 @@ class UiControllerAndroid : public UiController,
UiDelegate* ui_delegate_;
content::BrowserContext* browser_context_;
base::OnceCallback<void(const std::string&)> address_or_card_callback_;
base::OnceCallback<void(const std::string&)> choice_callback_;
base::OnceCallback<void(std::unique_ptr<PaymentInformation>)>
get_payment_information_callback_;
std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
......
......@@ -29,6 +29,8 @@ jumbo_static_library("browser") {
"actions/highlight_element_action.h",
"actions/navigate_action.cc",
"actions/navigate_action.h",
"actions/prompt_action.cc",
"actions/prompt_action.h",
"actions/reset_action.cc",
"actions/reset_action.h",
"actions/select_option_action.cc",
......
......@@ -59,6 +59,20 @@ class ActionDelegate {
virtual void ClickOrTapElement(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) = 0;
// Ask user to select one of the given suggestions.
//
// While Choose is in progress, the UI looks the same as it does between
// scripts, even though we're in the middle of a script. This includes
// allowing access to the touchable elements set previously, in the same
// script.
virtual void Choose(
const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) = 0;
// Cancels a choose action in progress and pass the given result to the
// callback.
virtual void ForceChoose(const std::string& result) = 0;
// Ask user to choose an address in personal data manager. GUID of the chosen
// address will be returned through callback, otherwise empty string if the
// user chose to continue manually.
......@@ -102,8 +116,10 @@ class ActionDelegate {
virtual void FocusElement(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback) = 0;
// Sets selector of elements that can be manipulated after the end of the
// script and before the beginning of the next script.
// Sets selector of elements that can be manipulated:
// - after the end of the script and before the beginning of the next script.
// - during the next call to Choose()
// whichever comes first.
virtual void SetTouchableElements(
const std::vector<std::vector<std::string>>& element_selectors) = 0;
......
......@@ -38,6 +38,17 @@ class MockActionDelegate : public ActionDelegate {
void(const std::vector<std::string>& selectors,
base::OnceCallback<void(bool)> callback));
void Choose(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) override {
OnChoose(suggestions, callback);
}
MOCK_METHOD2(OnChoose,
void(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)>& callback));
MOCK_METHOD1(ForceChoose, void(const std::string&));
void ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) override {
OnChooseAddress(callback);
......
// 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/actions/prompt_action.h"
#include <memory>
#include <utility>
#include "base/callback.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "url/gurl.h"
namespace autofill_assistant {
PromptAction::PromptAction(const ActionProto& proto)
: Action(proto), weak_ptr_factory_(this) {
DCHECK(proto_.has_prompt());
}
PromptAction::~PromptAction() {}
void PromptAction::InternalProcessAction(ActionDelegate* delegate,
ProcessActionCallback callback) {
delegate->ShowStatusMessage(proto_.prompt().message());
DCHECK_GT(proto_.prompt().suggestion_size(), 0);
callback_ = std::move(callback);
delegate->Choose(ExtractVector(proto_.prompt().suggestion()),
base::BindOnce(&PromptAction::OnSuggestionChosen,
weak_ptr_factory_.GetWeakPtr()));
if (proto_.prompt().auto_select_size() > 0) {
batch_element_checker_ = delegate->CreateBatchElementChecker();
for (const auto& auto_select : proto_.prompt().auto_select()) {
batch_element_checker_->AddElementCheck(
kExistenceCheck, ExtractVector(auto_select.element().selectors()),
base::BindOnce(&PromptAction::OnElementExist, base::Unretained(this),
auto_select.result()));
}
// 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,
base::Unretained(this), base::Unretained(delegate)),
/* all_done= */ base::DoNothing());
}
}
void PromptAction::OnElementExist(const std::string& result, bool exists) {
if (exists)
forced_result_ = result;
// Calling ForceChoose is delayed until try_done, as it indirectly deletes
// batch_element_checker_, which isn't supported from an element check
// callback.
}
void PromptAction::OnElementChecksDone(ActionDelegate* delegate) {
if (!forced_result_.empty())
delegate->ForceChoose(forced_result_);
}
void PromptAction::OnSuggestionChosen(const std::string& chosen) {
batch_element_checker_.reset();
UpdateProcessedAction(ACTION_APPLIED);
processed_action_proto_->mutable_prompt_result()->set_result(chosen);
std::move(callback_).Run(std::move(processed_action_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_ACTIONS_PROMPT_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_ACTION_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
#include "components/autofill_assistant/browser/batch_element_checker.h"
namespace autofill_assistant {
// Allow the selection of one or more suggestions.
class PromptAction : public Action {
public:
explicit PromptAction(const ActionProto& proto);
~PromptAction() override;
private:
// Overrides Action:
void InternalProcessAction(ActionDelegate* delegate,
ProcessActionCallback callback) override;
void OnElementExist(const std::string& result, bool exists);
void OnElementChecksDone(ActionDelegate* delegate);
void OnSuggestionChosen(const std::string& chosen);
ProcessActionCallback callback_;
std::string forced_result_;
std::unique_ptr<BatchElementChecker> batch_element_checker_;
base::WeakPtrFactory<PromptAction> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PromptAction);
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PROMPT_ACTION_H_
......@@ -50,11 +50,15 @@ class BatchElementChecker {
virtual ~BatchElementChecker();
// Callback for AddElementCheck. Argument is true if the check passed.
//
// An ElementCheckCallback must not delete its calling BatchElementChecker.
using ElementCheckCallback = base::OnceCallback<void(bool)>;
// Callback for AddFieldValueCheck. Argument is true is the element exists.
// The string contains the field value, or an empty string if accessing the
// value failed.
//
// An ElementCheckCallback must not delete its calling BatchElementChecker.
using GetFieldValueCallback =
base::OnceCallback<void(bool, const std::string&)>;
......@@ -84,6 +88,10 @@ class BatchElementChecker {
//
// |duration| can be 0. In this case the checks are run once, without waiting.
// |try_done| is run at the end of each try.
//
// |try_done| or |all_done| can delete their calling BatchElementChecker to
// interrupt any future checks. If |try_done| deletes BatchElementChecker,
// |all_done| will never be called.
void Run(const base::TimeDelta& duration,
base::RepeatingCallback<void()> try_done,
base::OnceCallback<void()> all_done);
......
......@@ -88,6 +88,11 @@ content::WebContents* Controller::GetWebContents() {
return web_contents();
}
void Controller::SetTouchableElementArea(
const std::vector<std::vector<std::string>>& elements) {
touchable_element_area_.SetElements(elements);
}
Controller::Controller(
content::WebContents* web_contents,
std::unique_ptr<Client> client,
......@@ -438,7 +443,8 @@ void Controller::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
// The following types of navigations are allowed for the main frame:
// - first-time URL load
// - script-directed navigation, while a script is running
// - script-directed navigation, while a script is running unless
// there's a touchable area.
// - server redirections, which might happen outside of a script, but
// because of a load triggered by a previously-running script.
// - same-document modifications, which might happen automatically
......@@ -457,6 +463,15 @@ void Controller::DidStartNavigation(
GiveUp();
return;
}
// Special case: during a prompt, forbid render-initiated navigation. This is
// necessary as there won't be any script lookup to tell us whether the
// destination page is acceptable.
if (script_tracker_->running() && touchable_element_area_.HasElements() &&
navigation_handle->IsRendererInitiated()) {
GiveUp();
return;
}
}
void Controller::RenderProcessGone(base::TerminationStatus status) {
......
......@@ -55,6 +55,8 @@ class Controller : public ScriptExecutorDelegate,
const std::map<std::string, std::string>& GetParameters() override;
autofill::PersonalDataManager* GetPersonalDataManager() override;
content::WebContents* GetWebContents() override;
void SetTouchableElementArea(
const std::vector<std::vector<std::string>>& elements) override;
private:
friend ControllerTest;
......
......@@ -30,6 +30,14 @@ class MockUiController : public UiController {
MOCK_METHOD0(CloseCustomTab, void());
MOCK_METHOD1(UpdateScripts, void(const std::vector<ScriptHandle>& scripts));
void Choose(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) override {
OnChoose(suggestions, callback);
}
MOCK_METHOD2(OnChoose,
void(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)>& callback));
void ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) override {
OnChooseAddress(callback);
......@@ -37,6 +45,8 @@ class MockUiController : public UiController {
MOCK_METHOD1(OnChooseAddress,
void(base::OnceCallback<void(const std::string&)>& callback));
MOCK_METHOD1(ForceChoose, void(const std::string&));
void ChooseCard(
base::OnceCallback<void(const std::string&)> callback) override {
OnChooseCard(callback);
......
......@@ -14,6 +14,7 @@
#include "components/autofill_assistant/browser/actions/get_payment_information_action.h"
#include "components/autofill_assistant/browser/actions/highlight_element_action.h"
#include "components/autofill_assistant/browser/actions/navigate_action.h"
#include "components/autofill_assistant/browser/actions/prompt_action.h"
#include "components/autofill_assistant/browser/actions/reset_action.h"
#include "components/autofill_assistant/browser/actions/select_option_action.h"
#include "components/autofill_assistant/browser/actions/set_attribute_action.h"
......@@ -199,6 +200,10 @@ bool ProtocolUtils::ParseActions(
actions->emplace_back(std::make_unique<NavigateAction>(action));
break;
}
case ActionProto::ActionInfoCase::kPrompt: {
actions->emplace_back(std::make_unique<PromptAction>(action));
break;
}
case ActionProto::ActionInfoCase::kStop: {
actions->emplace_back(std::make_unique<StopAction>(action));
break;
......
......@@ -104,6 +104,33 @@ void ScriptExecutor::GetPaymentInformation(
supported_basic_card_networks);
}
void ScriptExecutor::Choose(
const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) {
if (!touchable_elements_.empty()) {
// Choose reproduces the end-of-script appearance and behavior during script
// execution. This includes allowing access to touchable elements, set
// through a previous call to the focus action with touchable_elements set.
delegate_->SetTouchableElementArea(touchable_elements_);
delegate_->GetUiController()->HideOverlay();
// The touchable_elements_ currently set in the script is reset, so that it
// won't affect the real end of the script.
touchable_elements_.clear();
// The touchable element and overlays are cleared again in
// ScriptExecutor::OnChosen
}
delegate_->GetUiController()->Choose(
suggestions,
base::BindOnce(&ScriptExecutor::OnChosen, weak_ptr_factory_.GetWeakPtr(),
std::move(callback)));
}
void ScriptExecutor::ForceChoose(const std::string& result) {
delegate_->GetUiController()->ForceChoose(result);
}
void ScriptExecutor::ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) {
delegate_->GetUiController()->ChooseAddress(std::move(callback));
......@@ -344,4 +371,14 @@ void ScriptExecutor::OnProcessedAction(
ProcessNextAction();
}
void ScriptExecutor::OnChosen(
base::OnceCallback<void(const std::string&)> callback,
const std::string& choice) {
// This simulates the beginning of a script and removes any touchable element
// area set by Choose().
delegate_->GetUiController()->ShowOverlay();
delegate_->ClearTouchableElementArea();
std::move(callback).Run(choice);
}
} // namespace autofill_assistant
......@@ -85,6 +85,9 @@ class ScriptExecutor : public ActionDelegate {
base::OnceCallback<void(std::unique_ptr<PaymentInformation>)> callback,
const std::string& title,
const std::vector<std::string>& supported_basic_card_networks) override;
void Choose(const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) override;
void ForceChoose(const std::string&) override;
void ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) override;
void FillAddressForm(const autofill::AutofillProfile* profile,
......@@ -139,6 +142,8 @@ class ScriptExecutor : public ActionDelegate {
void ProcessAction(Action* action);
void GetNextActions();
void OnProcessedAction(std::unique_ptr<ProcessedActionProto> action);
void OnChosen(base::OnceCallback<void(const std::string&)> callback,
const std::string& chosen);
std::string script_path_;
std::string last_server_payload_;
......
......@@ -39,6 +39,14 @@ class ScriptExecutorDelegate {
virtual content::WebContents* GetWebContents() = 0;
// Make the area of the screen that correspond to the given elements
// touchable.
virtual void SetTouchableElementArea(
const std::vector<std::vector<std::string>>& elements) = 0;
// Makes no area of the screen touchable.
void ClearTouchableElementArea() { SetTouchableElementArea({}); }
protected:
virtual ~ScriptExecutorDelegate() {}
};
......
......@@ -72,6 +72,9 @@ class ScriptExecutorTest : public testing::Test,
ClientMemory* GetClientMemory() override { return &memory_; }
void SetTouchableElementArea(
const std::vector<std::vector<std::string>>& elements) {}
const std::map<std::string, std::string>& GetParameters() override {
return parameters_;
}
......
......@@ -70,6 +70,9 @@ class ScriptTrackerTest : public testing::Test,
content::WebContents* GetWebContents() override { return nullptr; }
virtual void SetTouchableElementArea(
const std::vector<std::vector<std::string>>& elements) override {}
// Overrides ScriptTracker::Listener
void OnRunnableScriptsChanged(
const std::vector<ScriptHandle>& runnable_scripts) override {
......
......@@ -219,6 +219,7 @@ message ActionProto {
SetFormFieldValueProto set_form_value = 6;
SelectOptionProto select_option = 7;
NavigateProto navigate = 9;
PromptProto prompt = 10;
TellProto tell = 11;
FocusElementProto focus_element = 12;
WaitForDomProto wait_for_dom = 19;
......@@ -254,6 +255,7 @@ message ProcessedActionProto {
optional ProcessedActionStatusProto status = 2;
oneof result_data {
PromptProto.Result prompt_result = 5;
string html_source = 12;
// Should be set as a result of GetPaymentInformationAction.
PaymentDetails payment_details = 15;
......@@ -424,6 +426,31 @@ message NavigateProto {
optional string url = 1;
}
// Allow the selection of one or more suggestions. If FocusElement was called
// just before, allow interaction with the touchable element area, otherwise
// don't allow any interactions.
message PromptProto {
message Result {
// One of the suggestions from PromptProto.suggestion or
// PromptProto.AutoSelect.result.
optional string result = 1;
}
// Localized text message to display.
optional string message = 1;
// Localized suggestions to propose.
repeated string suggestion = 2;
// Auto-select the prompt with the given result once the given element exists.
message AutoSelect {
// Result to send to the server.
optional string result = 1;
optional ElementReferenceProto element = 2;
}
repeated AutoSelect auto_select = 3;
}
message ContactDetailsProto {
// Data saved under this name can be reused by UseAddressAction.
optional string contact_details_name = 1;
......
......@@ -52,6 +52,16 @@ class UiController {
// Update the list of scripts in the UI.
virtual void UpdateScripts(const std::vector<ScriptHandle>& scripts) = 0;
// Show UI to ask user to select one of the suggestions. Sends the selected
// suggestion to the callback.
virtual void Choose(
const std::vector<std::string>& suggestions,
base::OnceCallback<void(const std::string&)> callback) = 0;
// Cancels a choose action in progress. Calls the registered callback, if any,
// with the given result.
virtual void ForceChoose(const std::string& choice) = 0;
// Show UI to ask user to choose an address in personal data manager. GUID of
// the chosen address will be returned through callback, otherwise empty
// string if the user chose to continue manually.
......
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