Commit 04f43afb authored by Lukasz Suder's avatar Lukasz Suder Committed by Commit Bot

[Autofill Assistant] Displays the difference in Details if there is any.

If there is a difference between current and new details it's
highlighted and two chips are displayed; to allow move forward or
go back (which closes CCT).

Screenshot: https://screenshot.googleplex.com/kOoC3B1frUp

Bug: 806868
Change-Id: I95ff09c379398d5a5858aa3947d4c578f39b14c9
Reviewed-on: https://chromium-review.googlesource.com/c/1335941
Commit-Queue: Lukasz Suder <lsuder@chromium.org>
Reviewed-by: default avatarStephane Zermatten <szermatt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608759}
parent 0c3be6d9
...@@ -15,26 +15,15 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; ...@@ -15,26 +15,15 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
/** Facade for starting Autofill Assistant on a custom tab. */ /** Facade for starting Autofill Assistant on a custom tab. */
public class AutofillAssistantFacade { public class AutofillAssistantFacade {
private static final String RFC_3339_FORMAT_WITHOUT_TIMEZONE = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
/** Prefix for Intent extras relevant to this feature. */ /** Prefix for Intent extras relevant to this feature. */
private static final String INTENT_EXTRA_PREFIX = private static final String INTENT_EXTRA_PREFIX =
"org.chromium.chrome.browser.autofill_assistant."; "org.chromium.chrome.browser.autofill_assistant.";
/** Autofill Assistant Study name. */
private static final String STUDY_NAME = "AutofillAssistant";
/** Variation url parameter name. */
private static final String URL_PARAMETER_NAME = "url";
/** Special parameter that enables the feature. */ /** Special parameter that enables the feature. */
private static final String PARAMETER_ENABLED = "ENABLED"; private static final String PARAMETER_ENABLED = "ENABLED";
...@@ -60,8 +49,7 @@ public class AutofillAssistantFacade { ...@@ -60,8 +49,7 @@ public class AutofillAssistantFacade {
controller.setUiDelegateHolder(delegateHolder); controller.setUiDelegateHolder(delegateHolder);
initTabObservers(activity, delegateHolder); initTabObservers(activity, delegateHolder);
AutofillAssistantUiDelegate.Details initialDetails = makeDetailsFromParameters(parameters); controller.maybeUpdateDetails(Details.makeFromParameters(parameters));
controller.maybeUpdateDetails(initialDetails);
uiDelegate.startOrSkipInitScreen(); uiDelegate.startOrSkipInitScreen();
} }
...@@ -106,38 +94,4 @@ public class AutofillAssistantFacade { ...@@ -106,38 +94,4 @@ public class AutofillAssistantFacade {
} }
return result; return result;
} }
// TODO(crbug.com/806868): Create a fallback when there are no parameters for details.
// TODO(crbug.com/806868): Create a fallback when there are no parameters for details.
private static AutofillAssistantUiDelegate.Details makeDetailsFromParameters(
Map<String, String> parameters) {
String title = "";
String description = "";
Date date = null;
for (String key : parameters.keySet()) {
if (key.contains("E_NAME")) {
title = parameters.get(key);
continue;
}
if (key.contains("R_NAME")) {
description = parameters.get(key);
continue;
}
if (key.contains("DATETIME")) {
try {
// The parameter contains the timezone shift from the current location, that we
// don't care about.
date = new SimpleDateFormat(RFC_3339_FORMAT_WITHOUT_TIMEZONE, Locale.ROOT)
.parse(parameters.get(key));
} catch (ParseException e) {
// Ignore.
}
}
}
return new AutofillAssistantUiDelegate.Details(
title, /* url= */ "", date, description, /* isFinal= */ false);
}
} }
...@@ -24,6 +24,7 @@ import org.chromium.payments.mojom.PaymentOptions; ...@@ -24,6 +24,7 @@ import org.chromium.payments.mojom.PaymentOptions;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -34,13 +35,6 @@ import java.util.Map; ...@@ -34,13 +35,6 @@ import java.util.Map;
*/ */
@JNINamespace("autofill_assistant") @JNINamespace("autofill_assistant")
public class AutofillAssistantUiController implements AutofillAssistantUiDelegate.Client { public class AutofillAssistantUiController implements AutofillAssistantUiDelegate.Client {
/** Prefix for Intent extras relevant to this feature. */
private static final String INTENT_EXTRA_PREFIX =
"org.chromium.chrome.browser.autofill_assistant.";
/** Special parameter that enables the feature. */
private static final String PARAMETER_ENABLED = "ENABLED";
/** OAuth2 scope that RPCs require. */ /** OAuth2 scope that RPCs require. */
private static final String AUTH_TOKEN_TYPE = private static final String AUTH_TOKEN_TYPE =
"oauth2:https://www.googleapis.com/auth/userinfo.profile"; "oauth2:https://www.googleapis.com/auth/userinfo.profile";
...@@ -49,8 +43,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -49,8 +43,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
private final String mInitialUrl; private final String mInitialUrl;
// TODO(crbug.com/806868): Move mCurrentDetails and mStatusMessage to a Model (refactor to MVC). // TODO(crbug.com/806868): Move mCurrentDetails and mStatusMessage to a Model (refactor to MVC).
private AutofillAssistantUiDelegate.Details mCurrentDetails = private Details mCurrentDetails = Details.EMPTY_DETAILS;
AutofillAssistantUiDelegate.Details.getEmptyDetails();
private String mStatusMessage; private String mStatusMessage;
/** Native pointer to the UIController. */ /** Native pointer to the UIController. */
...@@ -83,6 +76,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -83,6 +76,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
CustomTabActivity activity, Map<String, String> parameters) { CustomTabActivity activity, Map<String, String> parameters) {
mWebContents = activity.getActivityTab().getWebContents(); mWebContents = activity.getActivityTab().getWebContents();
mInitialUrl = activity.getInitialIntent().getDataString(); mInitialUrl = activity.getInitialIntent().getDataString();
mUiControllerAndroid = mUiControllerAndroid =
nativeInit(mWebContents, parameters.keySet().toArray(new String[parameters.size()]), nativeInit(mWebContents, parameters.keySet().toArray(new String[parameters.size()]),
parameters.values().toArray(new String[parameters.size()]), parameters.values().toArray(new String[parameters.size()]),
...@@ -112,7 +106,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -112,7 +106,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
} }
@Override @Override
public AutofillAssistantUiDelegate.Details getDetails() { public Details getDetails() {
return mCurrentDetails; return mCurrentDetails;
} }
...@@ -151,6 +145,12 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -151,6 +145,12 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
nativeOnCardSelected(mUiControllerAndroid, guid); nativeOnCardSelected(mUiControllerAndroid, guid);
} }
@Override
public void onDetailsAcknowledged(Details displayedDetails, boolean canContinue) {
mCurrentDetails = displayedDetails;
nativeOnShowDetails(mUiControllerAndroid, canContinue);
}
@Override @Override
public String getDebugContext() { public String getDebugContext() {
return nativeOnRequestDebugContext(mUiControllerAndroid); return nativeOnRequestDebugContext(mUiControllerAndroid);
...@@ -197,6 +197,11 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -197,6 +197,11 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
mUiDelegateHolder.shutdown(); mUiDelegateHolder.shutdown();
} }
@CalledByNative
private void onCloseCustomTab() {
mUiDelegateHolder.closeCustomTab();
}
@CalledByNative @CalledByNative
private void onShutdownGracefully() { private void onShutdownGracefully() {
mUiDelegateHolder.enterGracefulShutdownMode(); mUiDelegateHolder.enterGracefulShutdownMode();
...@@ -272,21 +277,16 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -272,21 +277,16 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
/** /**
* Updates the currently shown details. * Updates the currently shown details.
* *
* @return false if details were rejected. * @param newDetails details to display.
*/ */
boolean maybeUpdateDetails(AutofillAssistantUiDelegate.Details newDetails) { void maybeUpdateDetails(Details newDetails) {
if (!mCurrentDetails.isSimilarTo(newDetails)) {
return false;
}
if (mCurrentDetails.isEmpty() && newDetails.isEmpty()) { if (mCurrentDetails.isEmpty() && newDetails.isEmpty()) {
// No update on UI needed. // No update on UI needed.
return true; nativeOnShowDetails(mUiControllerAndroid, /* canContinue= */ true);
} }
mCurrentDetails = AutofillAssistantUiDelegate.Details.merge(mCurrentDetails, newDetails); Details mergedDetails = Details.merge(mCurrentDetails, newDetails);
mUiDelegateHolder.performUiOperation(uiDelegate -> uiDelegate.showDetails(mCurrentDetails)); mUiDelegateHolder.performUiOperation(uiDelegate -> uiDelegate.showDetails(mergedDetails));
return true;
} }
@CalledByNative @CalledByNative
...@@ -295,7 +295,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -295,7 +295,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
} }
@CalledByNative @CalledByNative
private boolean onShowDetails(String title, String url, String description, int year, int month, private void onShowDetails(String title, String url, String description, int year, int month,
int day, int hour, int minute, int second) { int day, int hour, int minute, int second) {
Date date; Date date;
if (year > 0 && month > 0 && day > 0 && hour >= 0 && minute >= 0 && second >= 0) { if (year > 0 && month > 0 && day > 0 && hour >= 0 && minute >= 0 && second >= 0) {
...@@ -308,8 +308,8 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -308,8 +308,8 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
date = null; date = null;
} }
return maybeUpdateDetails(new AutofillAssistantUiDelegate.Details( maybeUpdateDetails(new Details(
title, url, date, description, /* isFinal= */ true)); title, url, date, description, /* isFinal= */ true, Collections.emptySet()));
} }
@CalledByNative @CalledByNative
...@@ -449,6 +449,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat ...@@ -449,6 +449,7 @@ public class AutofillAssistantUiController implements AutofillAssistantUiDelegat
private native void nativeOnScriptSelected(long nativeUiControllerAndroid, String scriptPath); private native void nativeOnScriptSelected(long nativeUiControllerAndroid, String scriptPath);
private native void nativeOnAddressSelected(long nativeUiControllerAndroid, String guid); private native void nativeOnAddressSelected(long nativeUiControllerAndroid, String guid);
private native void nativeOnCardSelected(long nativeUiControllerAndroid, String guid); private native void nativeOnCardSelected(long nativeUiControllerAndroid, String guid);
private native void nativeOnShowDetails(long nativeUiControllerAndroid, boolean canContinue);
private native void nativeOnGetPaymentInformation(long nativeUiControllerAndroid, private native void nativeOnGetPaymentInformation(long nativeUiControllerAndroid,
boolean succeed, @Nullable PersonalDataManager.CreditCard card, boolean succeed, @Nullable PersonalDataManager.CreditCard card,
@Nullable PersonalDataManager.AutofillProfile address, @Nullable String payerName, @Nullable PersonalDataManager.AutofillProfile address, @Nullable String payerName,
......
// 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.
package org.chromium.chrome.browser.autofill_assistant;
import android.support.annotation.Nullable;
import org.json.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
/**
* Java side equivalent of autofill_assistant::DetailsProto.
*/
class Details {
enum DetailsField { TITLE, URL, DATE, DESCRIPTION, IS_FINAL }
private final String mTitle;
private final String mUrl;
@Nullable
private final Date mDate;
private final String mDescription;
private final boolean mIsFinal;
/** Contains the fields that have changed when merging with other Details object. */
private final Set<DetailsField> mFieldsChanged;
// NOTE: When adding a new field, update the isEmpty method.
static final Details EMPTY_DETAILS =
new Details("", "", null, "", false, Collections.emptySet());
private static final String RFC_3339_FORMAT_WITHOUT_TIMEZONE = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
Details(String title, String url, @Nullable Date date, String description, boolean isFinal,
Set<DetailsField> fieldsChanged) {
this.mTitle = title;
this.mUrl = url;
this.mDate = date;
this.mDescription = description;
this.mIsFinal = isFinal;
this.mFieldsChanged = fieldsChanged;
}
String getTitle() {
return mTitle;
}
String getUrl() {
return mUrl;
}
@Nullable
Date getDate() {
return mDate;
}
String getDescription() {
return mDescription;
}
JSONObject toJSONObject() {
// Details are part of the feedback form, hence they need a JSON representation.
Map<String, String> movieDetails = new HashMap<>();
movieDetails.put("title", mTitle);
movieDetails.put("url", mUrl);
if (mDate != null) movieDetails.put("date", mDate.toString());
movieDetails.put("description", mDescription);
return new JSONObject(movieDetails);
}
/**
* Whether the details are not subject to change anymore. If set to false the animated
* placeholders will be displayed in place of missing data.
*/
boolean isFinal() {
return mIsFinal;
}
Set<DetailsField> getFieldsChanged() {
return mFieldsChanged;
}
boolean isEmpty() {
return mTitle.isEmpty() && mUrl.isEmpty() && mDescription.isEmpty() && mDate == null;
}
// TODO(crbug.com/806868): Create a fallback when there are no parameters for details.
static Details makeFromParameters(Map<String, String> parameters) {
String title = "";
String description = "";
Date date = null;
for (String key : parameters.keySet()) {
if (key.contains("E_NAME")) {
title = parameters.get(key);
continue;
}
if (key.contains("R_NAME")) {
description = parameters.get(key);
continue;
}
if (key.contains("DATETIME")) {
try {
// The parameter contains the timezone shift from the current location, that we
// don't care about.
date = new SimpleDateFormat(RFC_3339_FORMAT_WITHOUT_TIMEZONE, Locale.ROOT)
.parse(parameters.get(key));
} catch (ParseException e) {
// Ignore.
}
}
}
return new Details(title, /* url= */ "", date, description, /* isFinal= */ false,
/* fieldsChanged= */ Collections.emptySet());
}
/**
* Merges {@param oldDetails} with the {@param newDetails} filling the missing fields.
*
* <p>The distinction is important, as the fields from old version take precedence, with the
* exception of date and isFinal fields.
*
* <p>If {@param oldDetails} are empty copy of {@param newDetails} with empty
* {@code changedFields} is returned
*/
static Details merge(Details oldDetails, Details newDetails) {
if (oldDetails.isEmpty()) {
return new Details(newDetails.getTitle(), newDetails.getUrl(), newDetails.getDate(),
newDetails.getDescription(), newDetails.isFinal(), Collections.emptySet());
}
Set<DetailsField> changedFields = new HashSet<>();
// TODO(crbug.com/806868): Change title if mid doesn't match.
String title =
oldDetails.getTitle().isEmpty() ? newDetails.getTitle() : oldDetails.getTitle();
String url = oldDetails.getUrl().isEmpty() ? newDetails.getUrl() : oldDetails.getUrl();
Date date = oldDetails.getDate();
if (newDetails.getDate() != null && oldDetails.getDate() != null
&& !newDetails.getDate().equals(oldDetails.getDate())) {
changedFields.add(DetailsField.DATE);
date = newDetails.getDate();
}
String description = oldDetails.getDescription().isEmpty() ? newDetails.getDescription()
: oldDetails.getDescription();
boolean isFinal = newDetails.isFinal();
return new Details(title, url, date, description, isFinal, changedFields);
}
}
\ No newline at end of file
...@@ -14,8 +14,8 @@ import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiDelegat ...@@ -14,8 +14,8 @@ import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiDelegat
* Automatically extracts context information and serializes it in JSON form. * Automatically extracts context information and serializes it in JSON form.
*/ */
class FeedbackContext extends JSONObject { class FeedbackContext extends JSONObject {
static String buildContextString(ChromeActivity activity, Client client, static String buildContextString(ChromeActivity activity, Client client, Details details,
AutofillAssistantUiDelegate.Details details, String statusMessage, int indentSpaces) { String statusMessage, int indentSpaces) {
try { try {
return new FeedbackContext(activity, client, details, statusMessage) return new FeedbackContext(activity, client, details, statusMessage)
.toString(indentSpaces); .toString(indentSpaces);
...@@ -24,9 +24,8 @@ class FeedbackContext extends JSONObject { ...@@ -24,9 +24,8 @@ class FeedbackContext extends JSONObject {
} }
} }
private FeedbackContext(ChromeActivity activity, Client client, private FeedbackContext(ChromeActivity activity, Client client, Details details,
AutofillAssistantUiDelegate.Details details, String statusMessage) String statusMessage) throws JSONException {
throws JSONException {
addActivityInformation(activity); addActivityInformation(activity);
addClientContext(client); addClientContext(client);
put("movie", details.toJSONObject()); put("movie", details.toJSONObject());
......
...@@ -129,6 +129,14 @@ class UiDelegateHolder { ...@@ -129,6 +129,14 @@ class UiDelegateHolder {
mUiController.unsafeDestroy(); mUiController.unsafeDestroy();
} }
/**
* Closes the Chrome Custom Tab.
*/
void closeCustomTab() {
shutdown();
mUiDelegate.closeCustomTab();
}
/** /**
* Pause all UI operations such that they can potentially be ran later using {@link * Pause all UI operations such that they can potentially be ran later using {@link
* #unpauseUiOperations()}. * #unpauseUiOperations()}.
......
...@@ -129,6 +129,7 @@ chrome_java_sources = [ ...@@ -129,6 +129,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantStudy.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantStudy.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/Details.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/FeedbackContext.java", "java/src/org/chromium/chrome/browser/autofill_assistant/FeedbackContext.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/InitScreenController.java", "java/src/org/chromium/chrome/browser/autofill_assistant/InitScreenController.java",
"java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java", "java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java",
......
...@@ -131,6 +131,11 @@ void UiControllerAndroid::ShutdownGracefully() { ...@@ -131,6 +131,11 @@ void UiControllerAndroid::ShutdownGracefully() {
AttachCurrentThread(), java_autofill_assistant_ui_controller_); AttachCurrentThread(), java_autofill_assistant_ui_controller_);
} }
void UiControllerAndroid::CloseCustomTab() {
Java_AutofillAssistantUiController_onCloseCustomTab(
AttachCurrentThread(), java_autofill_assistant_ui_controller_);
}
void UiControllerAndroid::UpdateScripts( void UiControllerAndroid::UpdateScripts(
const std::vector<ScriptHandle>& scripts) { const std::vector<ScriptHandle>& scripts) {
std::vector<std::string> script_paths; std::vector<std::string> script_paths;
...@@ -254,6 +259,14 @@ void UiControllerAndroid::OnAccessToken( ...@@ -254,6 +259,14 @@ void UiControllerAndroid::OnAccessToken(
} }
} }
void UiControllerAndroid::OnShowDetails(JNIEnv* env,
const JavaParamRef<jobject>& jcaller,
jboolean jcan_continue) {
if (show_details_callback_) {
std::move(show_details_callback_).Run(jcan_continue);
}
}
base::android::ScopedJavaLocalRef<jstring> base::android::ScopedJavaLocalRef<jstring>
UiControllerAndroid::GetPrimaryAccountName( UiControllerAndroid::GetPrimaryAccountName(
JNIEnv* env, JNIEnv* env,
...@@ -312,7 +325,9 @@ void UiControllerAndroid::HideDetails() { ...@@ -312,7 +325,9 @@ void UiControllerAndroid::HideDetails() {
AttachCurrentThread(), java_autofill_assistant_ui_controller_); AttachCurrentThread(), java_autofill_assistant_ui_controller_);
} }
bool UiControllerAndroid::ShowDetails(const DetailsProto& details) { void UiControllerAndroid::ShowDetails(const DetailsProto& details,
base::OnceCallback<void(bool)> callback) {
show_details_callback_ = std::move(callback);
int year = details.datetime().date().year(); int year = details.datetime().date().year();
int month = details.datetime().date().month(); int month = details.datetime().date().month();
int day = details.datetime().date().day(); int day = details.datetime().date().day();
......
...@@ -42,6 +42,7 @@ class UiControllerAndroid : public UiController, ...@@ -42,6 +42,7 @@ class UiControllerAndroid : public UiController,
void HideOverlay() override; void HideOverlay() override;
void Shutdown() override; void Shutdown() override;
void ShutdownGracefully() override; void ShutdownGracefully() override;
void CloseCustomTab() override;
void UpdateScripts(const std::vector<ScriptHandle>& scripts) override; void UpdateScripts(const std::vector<ScriptHandle>& scripts) override;
void ChooseAddress( void ChooseAddress(
base::OnceCallback<void(const std::string&)> callback) override; base::OnceCallback<void(const std::string&)> callback) override;
...@@ -53,7 +54,8 @@ class UiControllerAndroid : public UiController, ...@@ -53,7 +54,8 @@ class UiControllerAndroid : public UiController,
const std::string& title, const std::string& title,
const std::vector<std::string>& supported_basic_card_networks) override; const std::vector<std::string>& supported_basic_card_networks) override;
void HideDetails() override; void HideDetails() override;
bool ShowDetails(const DetailsProto& details) override; void ShowDetails(const DetailsProto& details,
base::OnceCallback<void(bool)> callback) override;
void ShowProgressBar(int progress, const std::string& message) override; void ShowProgressBar(int progress, const std::string& message) override;
void HideProgressBar() override; void HideProgressBar() override;
void UpdateTouchableArea(bool enabled, void UpdateTouchableArea(bool enabled,
...@@ -108,6 +110,9 @@ class UiControllerAndroid : public UiController, ...@@ -108,6 +110,9 @@ class UiControllerAndroid : public UiController,
const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jobject>& jcaller,
jboolean success, jboolean success,
const base::android::JavaParamRef<jstring>& access_token); const base::android::JavaParamRef<jstring>& access_token);
void OnShowDetails(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
jboolean success);
base::android::ScopedJavaLocalRef<jstring> GetPrimaryAccountName( base::android::ScopedJavaLocalRef<jstring> GetPrimaryAccountName(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller); const base::android::JavaParamRef<jobject>& jcaller);
...@@ -129,6 +134,7 @@ class UiControllerAndroid : public UiController, ...@@ -129,6 +134,7 @@ class UiControllerAndroid : public UiController,
std::unique_ptr<AccessTokenFetcher> access_token_fetcher_; std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
base::OnceCallback<void(bool, const std::string&)> base::OnceCallback<void(bool, const std::string&)>
fetch_access_token_callback_; fetch_access_token_callback_;
base::OnceCallback<void(bool)> show_details_callback_;
DISALLOW_COPY_AND_ASSIGN(UiControllerAndroid); DISALLOW_COPY_AND_ASSIGN(UiControllerAndroid);
}; };
......
...@@ -138,6 +138,9 @@ class ActionDelegate { ...@@ -138,6 +138,9 @@ class ActionDelegate {
// Shut down Autofill Assistant at the end of the current script. // Shut down Autofill Assistant at the end of the current script.
virtual void Shutdown() = 0; virtual void Shutdown() = 0;
// Shut down Autofill Assistant and close the CCT.
virtual void CloseCustomTab() = 0;
// Restart Autofill Assistant at the end of the current script with a cleared // Restart Autofill Assistant at the end of the current script with a cleared
// state. // state.
virtual void Restart() = 0; virtual void Restart() = 0;
...@@ -159,7 +162,8 @@ class ActionDelegate { ...@@ -159,7 +162,8 @@ class ActionDelegate {
virtual void HideDetails() = 0; virtual void HideDetails() = 0;
// Show contextual information. // Show contextual information.
virtual bool ShowDetails(const DetailsProto& details) = 0; virtual void ShowDetails(const DetailsProto& details,
base::OnceCallback<void(bool)> callback) = 0;
// Show the progress bar with |message| and set it at |progress|%. // Show the progress bar with |message| and set it at |progress|%.
virtual void ShowProgressBar(int progress, const std::string& message) = 0; virtual void ShowProgressBar(int progress, const std::string& message) = 0;
......
...@@ -122,13 +122,16 @@ class MockActionDelegate : public ActionDelegate { ...@@ -122,13 +122,16 @@ class MockActionDelegate : public ActionDelegate {
base::OnceCallback<void(bool, const std::string&)> callback)); base::OnceCallback<void(bool, const std::string&)> callback));
MOCK_METHOD1(LoadURL, void(const GURL& url)); MOCK_METHOD1(LoadURL, void(const GURL& url));
MOCK_METHOD0(Shutdown, void()); MOCK_METHOD0(Shutdown, void());
MOCK_METHOD0(CloseCustomTab, void());
MOCK_METHOD0(Restart, void()); MOCK_METHOD0(Restart, void());
MOCK_METHOD0(GetClientMemory, ClientMemory*()); MOCK_METHOD0(GetClientMemory, ClientMemory*());
MOCK_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*()); MOCK_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*());
MOCK_METHOD0(GetWebContents, content::WebContents*()); MOCK_METHOD0(GetWebContents, content::WebContents*());
MOCK_METHOD1(StopCurrentScriptAndShutdown, void(const std::string& message)); MOCK_METHOD1(StopCurrentScriptAndShutdown, void(const std::string& message));
MOCK_METHOD0(HideDetails, void()); MOCK_METHOD0(HideDetails, void());
MOCK_METHOD1(ShowDetails, bool(const DetailsProto& details)); MOCK_METHOD2(ShowDetails,
void(const DetailsProto& details,
base::OnceCallback<void(bool)> callback));
MOCK_METHOD2(ShowProgressBar, void(int progress, const std::string& message)); MOCK_METHOD2(ShowProgressBar, void(int progress, const std::string& message));
MOCK_METHOD0(HideProgressBar, void()); MOCK_METHOD0(HideProgressBar, void());
MOCK_METHOD0(ShowOverlay, void()); MOCK_METHOD0(ShowOverlay, void());
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
namespace autofill_assistant { namespace autofill_assistant {
ShowDetailsAction::ShowDetailsAction(const ActionProto& proto) : Action(proto) { ShowDetailsAction::ShowDetailsAction(const ActionProto& proto)
: Action(proto), weak_ptr_factory_(this) {
DCHECK(proto_.has_show_details()); DCHECK(proto_.has_show_details());
} }
...@@ -24,9 +25,20 @@ void ShowDetailsAction::InternalProcessAction(ActionDelegate* delegate, ...@@ -24,9 +25,20 @@ void ShowDetailsAction::InternalProcessAction(ActionDelegate* delegate,
UpdateProcessedAction(ACTION_APPLIED); UpdateProcessedAction(ACTION_APPLIED);
std::move(callback).Run(std::move(processed_action_proto_)); std::move(callback).Run(std::move(processed_action_proto_));
} else { } else {
bool result = delegate->ShowDetails(proto_.show_details().details()); delegate->ShowDetails(proto_.show_details().details(),
UpdateProcessedAction(result ? ACTION_APPLIED : OTHER_ACTION_STATUS); base::BindOnce(&ShowDetailsAction::OnShowDetails,
std::move(callback).Run(std::move(processed_action_proto_)); weak_ptr_factory_.GetWeakPtr(),
std::move(callback), delegate));
}
}
void ShowDetailsAction::OnShowDetails(ProcessActionCallback callback,
ActionDelegate* delegate,
bool can_continue) {
if (!can_continue) {
delegate->CloseCustomTab();
} }
UpdateProcessedAction(ACTION_APPLIED);
std::move(callback).Run(std::move(processed_action_proto_));
} }
} // namespace autofill_assistant } // namespace autofill_assistant
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_DETAILS_ACTION_H_ #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_DETAILS_ACTION_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h" #include "components/autofill_assistant/browser/actions/action.h"
namespace autofill_assistant { namespace autofill_assistant {
...@@ -19,6 +20,11 @@ class ShowDetailsAction : public Action { ...@@ -19,6 +20,11 @@ class ShowDetailsAction : public Action {
// Overrides Action: // Overrides Action:
void InternalProcessAction(ActionDelegate* delegate, void InternalProcessAction(ActionDelegate* delegate,
ProcessActionCallback callback) override; ProcessActionCallback callback) override;
void OnShowDetails(ProcessActionCallback callback,
ActionDelegate* delegate,
bool can_continue);
base::WeakPtrFactory<ShowDetailsAction> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ShowDetailsAction); DISALLOW_COPY_AND_ASSIGN(ShowDetailsAction);
}; };
......
...@@ -257,6 +257,10 @@ void Controller::OnScriptExecuted(const std::string& script_path, ...@@ -257,6 +257,10 @@ void Controller::OnScriptExecuted(const std::string& script_path,
GetUiController()->ShutdownGracefully(); GetUiController()->ShutdownGracefully();
return; return;
case ScriptExecutor::CLOSE_CUSTOM_TAB:
GetUiController()->CloseCustomTab();
return;
case ScriptExecutor::RESTART: case ScriptExecutor::RESTART:
script_tracker_ = std::make_unique<ScriptTracker>(/* delegate= */ this, script_tracker_ = std::make_unique<ScriptTracker>(/* delegate= */ this,
/* listener= */ this); /* listener= */ this);
......
...@@ -27,6 +27,7 @@ class MockUiController : public UiController { ...@@ -27,6 +27,7 @@ class MockUiController : public UiController {
MOCK_METHOD0(HideOverlay, void()); MOCK_METHOD0(HideOverlay, void());
MOCK_METHOD0(Shutdown, void()); MOCK_METHOD0(Shutdown, void());
MOCK_METHOD0(ShutdownGracefully, void()); MOCK_METHOD0(ShutdownGracefully, void());
MOCK_METHOD0(CloseCustomTab, void());
MOCK_METHOD1(UpdateScripts, void(const std::vector<ScriptHandle>& scripts)); MOCK_METHOD1(UpdateScripts, void(const std::vector<ScriptHandle>& scripts));
void ChooseAddress( void ChooseAddress(
...@@ -50,7 +51,9 @@ class MockUiController : public UiController { ...@@ -50,7 +51,9 @@ class MockUiController : public UiController {
const std::string& title, const std::string& title,
const std::vector<std::string>& supported_basic_card_networks)); const std::vector<std::string>& supported_basic_card_networks));
MOCK_METHOD0(HideDetails, void()); MOCK_METHOD0(HideDetails, void());
MOCK_METHOD1(ShowDetails, bool(const DetailsProto& details)); MOCK_METHOD2(ShowDetails,
void(const DetailsProto& details,
base::OnceCallback<void(bool)> callback));
MOCK_METHOD2(ShowProgressBar, void(int progress, const std::string& message)); MOCK_METHOD2(ShowProgressBar, void(int progress, const std::string& message));
MOCK_METHOD0(HideProgressBar, void()); MOCK_METHOD0(HideProgressBar, void());
MOCK_METHOD2(UpdateTouchableArea, MOCK_METHOD2(UpdateTouchableArea,
......
...@@ -205,6 +205,11 @@ void ScriptExecutor::Shutdown() { ...@@ -205,6 +205,11 @@ void ScriptExecutor::Shutdown() {
} }
} }
void ScriptExecutor::CloseCustomTab() {
at_end_ = CLOSE_CUSTOM_TAB;
should_stop_script_ = true;
}
void ScriptExecutor::Restart() { void ScriptExecutor::Restart() {
at_end_ = RESTART; at_end_ = RESTART;
} }
...@@ -234,8 +239,10 @@ void ScriptExecutor::HideDetails() { ...@@ -234,8 +239,10 @@ void ScriptExecutor::HideDetails() {
delegate_->GetUiController()->HideDetails(); delegate_->GetUiController()->HideDetails();
} }
bool ScriptExecutor::ShowDetails(const DetailsProto& details) { void ScriptExecutor::ShowDetails(const DetailsProto& details,
return delegate_->GetUiController()->ShowDetails(details); base::OnceCallback<void(bool)> callback) {
return delegate_->GetUiController()->ShowDetails(details,
std::move(callback));
} }
void ScriptExecutor::OnGetActions(bool result, const std::string& response) { void ScriptExecutor::OnGetActions(bool result, const std::string& response) {
......
...@@ -52,6 +52,9 @@ class ScriptExecutor : public ActionDelegate { ...@@ -52,6 +52,9 @@ class ScriptExecutor : public ActionDelegate {
// Shut down Autofill Assistant after a delay. // Shut down Autofill Assistant after a delay.
SHUTDOWN_GRACEFULLY, SHUTDOWN_GRACEFULLY,
// Shut down Autofill Assistant and CCT.
CLOSE_CUSTOM_TAB,
// Reset all state and restart. // Reset all state and restart.
RESTART RESTART
}; };
...@@ -115,13 +118,15 @@ class ScriptExecutor : public ActionDelegate { ...@@ -115,13 +118,15 @@ class ScriptExecutor : public ActionDelegate {
base::OnceCallback<void(bool, const std::string&)> callback) override; base::OnceCallback<void(bool, const std::string&)> callback) override;
void LoadURL(const GURL& url) override; void LoadURL(const GURL& url) override;
void Shutdown() override; void Shutdown() override;
void CloseCustomTab() override;
void Restart() override; void Restart() override;
ClientMemory* GetClientMemory() override; ClientMemory* GetClientMemory() override;
autofill::PersonalDataManager* GetPersonalDataManager() override; autofill::PersonalDataManager* GetPersonalDataManager() override;
content::WebContents* GetWebContents() override; content::WebContents* GetWebContents() override;
void StopCurrentScriptAndShutdown(const std::string& message) override; void StopCurrentScriptAndShutdown(const std::string& message) override;
void HideDetails() override; void HideDetails() override;
bool ShowDetails(const DetailsProto& details) override; void ShowDetails(const DetailsProto& details,
base::OnceCallback<void(bool)> callback) override;
void ShowProgressBar(int progress, const std::string& message) override; void ShowProgressBar(int progress, const std::string& message) override;
void HideProgressBar() override; void HideProgressBar() override;
void ShowOverlay() override; void ShowOverlay() override;
......
...@@ -46,6 +46,9 @@ class UiController { ...@@ -46,6 +46,9 @@ class UiController {
// Warning: this indirectly deletes the caller. // Warning: this indirectly deletes the caller.
virtual void ShutdownGracefully() = 0; virtual void ShutdownGracefully() = 0;
// Shuts down Autofill Assistant and closes CCT.
virtual void CloseCustomTab();
// Update the list of scripts in the UI. // Update the list of scripts in the UI.
virtual void UpdateScripts(const std::vector<ScriptHandle>& scripts) = 0; virtual void UpdateScripts(const std::vector<ScriptHandle>& scripts) = 0;
...@@ -80,7 +83,8 @@ class UiController { ...@@ -80,7 +83,8 @@ class UiController {
// not similar to the current one. // not similar to the current one.
// TODO(806868): Pass details to the native side instead of comparing on the // TODO(806868): Pass details to the native side instead of comparing on the
// Java side. // Java side.
virtual bool ShowDetails(const DetailsProto& details) = 0; virtual void ShowDetails(const DetailsProto& details,
base::OnceCallback<void(bool)> callback) = 0;
// Show the progress bar with |message| and set it at |progress|%. // Show the progress bar with |message| and set it at |progress|%.
virtual void ShowProgressBar(int progress, const std::string& message) = 0; virtual void ShowProgressBar(int progress, const std::string& message) = 0;
......
...@@ -19,5 +19,11 @@ ...@@ -19,5 +19,11 @@
<message name="IDS_AUTOFILL_ASSISTANT_TERMS" desc="The text for the terms and service acceptance checkbox. Sentence-cased." formatter_data="android_java"> <message name="IDS_AUTOFILL_ASSISTANT_TERMS" desc="The text for the terms and service acceptance checkbox. Sentence-cased." formatter_data="android_java">
I know the terms and conditions, privacy policy and right of withdrawal of <ph name="BEGIN_BOLD">&lt;b&gt;</ph><ph name="ORIGIN">%1$s<ex>google.com</ex></ph><ph name="END_BOLD">&lt;/b&gt;</ph> (leave unchecked to read). I know the terms and conditions, privacy policy and right of withdrawal of <ph name="BEGIN_BOLD">&lt;b&gt;</ph><ph name="ORIGIN">%1$s<ex>google.com</ex></ph><ph name="END_BOLD">&lt;/b&gt;</ph> (leave unchecked to read).
</message> </message>
<message name="IDS_AUTOFILL_ASSISTANT_DETAILS_DIFFER" desc="Shown as Status Message when details differ." formatter_data="android_java">
The movie screening is different, do you want to continue?
</message>
<message name="IDS_AUTOFILL_ASSISTANT_DETAILS_DIFFER_GO_BACK" desc="Shown on a button allowing going back when details differ." formatter_data="android_java">
Go back
</message>
</if> </if>
</grit-part> </grit-part>
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