Commit 8a6a8d76 authored by Sahel Sharify's avatar Sahel Sharify Committed by Commit Bot

Reland "[Web Payments][Android] Delegation support for intent based apps [2/3]"

This is a reland of 561f6a86

I reverted the original cl since I wanted to wait for thread safety
review of the following two classes:
-PaymentDetailsUpdateService.java
-PaymentDetailsUpdateServiceHelper.java

Original change's description:
> [Web Payments][Android] Delegation support for intent based apps [2/3]
>
> This cl introduces IPaymentDetailsUpdateService.aidl and
> IPaymentDetailsUpdateServiceCallback.aidl interfaces so that the invoked
> native app can call changePaymentMethod, changeShippingOption, and
> changeShippingAddress methods to notify the browser about the user
> choosing a different payment method, shipping address, or shipping
> option.
>
> This cl implements the plumbing for sending the change events to the
> merchant, but the plumbing for sending the updated payment details from
> the merchant to the invoked app will be landed in a follow up cl.
>
> To test the feature enable "Experimental Web Payments API features" from
> chrome:/flags or use the following commandline flag:
> enable-features=AndroidAppPaymentUpdateEvents
>
> Bug: 1026667
> Change-Id: I799c9dfced15fe2fa916b8ca3634b91366cfc32f
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2168009
> Commit-Queue: Sahel Sharify <sahel@chromium.org>
> Reviewed-by: Robert Sesek <rsesek@chromium.org>
> Reviewed-by: Liquan (Max) Gu <maxlg@chromium.org>
> Reviewed-by: Michael Thiessen <mthiesse@chromium.org>
> Reviewed-by: Rouslan Solomakhin <rouslan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#773401}

TBR=mthiesse@chromium.org,rsesek@chromium.org

Bug: 1026667
Change-Id: I10bfc1778ef950deab59dffef48a027ce7e234bf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2222899Reviewed-by: default avatarSahel Sharify <sahel@chromium.org>
Reviewed-by: default avatarRouslan Solomakhin <rouslan@chromium.org>
Commit-Queue: Sahel Sharify <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773850}
parent 397167be
......@@ -331,6 +331,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/payments/IsReadyToPayServiceHelperTest.java",
"javatests/src/org/chromium/chrome/browser/payments/MockPackageManagerDelegate.java",
"javatests/src/org/chromium/chrome/browser/payments/MockTwaPackageManagerDelegate.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentDetailsUpdateServiceHelperTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentErrorStringsTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerChangePaymentMethodTest.java",
"javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerEnableDelegationsTest.java",
......
......@@ -1086,6 +1086,12 @@ by a child template that "extends" this file.
<service android:name="org.chromium.chrome.browser.incognito.IncognitoNotificationService"
android:exported="false"/>
<!-- service used by payment apps to notify the browser about changes in user selected
payment method, shipping address, or shipping option -->
<service
android:name="org.chromium.components.payments.PaymentDetailsUpdateService"
android:exported="true"/>
<!-- The following service entries exist in order to allow us to
start more than one sandboxed process. -->
......
......@@ -1164,6 +1164,9 @@
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
</intent-filter>
</service>
<service
android:exported="true"
android:name="org.chromium.components.payments.PaymentDetailsUpdateService"/>
<service android:name="androidx.browser.customtabs.PostMessageService"/>
<service
android:exported="true"
......
......@@ -407,4 +407,11 @@ public class AndroidPaymentApp
public @PaymentAppType int getPaymentAppType() {
return PaymentAppType.NATIVE_MOBILE_APP;
}
/**
* @return The package name of the invoked native app.
*/
public String packageName() {
return mPackageName;
}
}
......@@ -57,10 +57,12 @@ import org.chromium.components.payments.ErrorMessageUtil;
import org.chromium.components.payments.ErrorStrings;
import org.chromium.components.payments.MethodStrings;
import org.chromium.components.payments.OriginSecurityChecker;
import org.chromium.components.payments.PackageManagerDelegate;
import org.chromium.components.payments.PayerData;
import org.chromium.components.payments.PaymentApp;
import org.chromium.components.payments.PaymentAppType;
import org.chromium.components.payments.PaymentDetailsConverter;
import org.chromium.components.payments.PaymentDetailsUpdateServiceHelper;
import org.chromium.components.payments.PaymentFeatureList;
import org.chromium.components.payments.PaymentHandlerHost;
import org.chromium.components.payments.PaymentRequestSpec;
......@@ -2120,6 +2122,12 @@ public class PaymentRequestImpl
}
mInvokedPaymentApp.setPaymentHandlerHost(getPaymentHandlerHost());
// Only native apps can use PaymentDetailsUpdateService.
if (mInvokedPaymentApp.getPaymentAppType() == PaymentAppType.NATIVE_MOBILE_APP) {
PaymentDetailsUpdateServiceHelper.getInstance().initialize(new PackageManagerDelegate(),
((AndroidPaymentApp) mInvokedPaymentApp).packageName(),
this /* PaymentApp.PaymentRequestUpdateEventListener */);
}
// Create payment options for the invoked payment app.
PaymentOptions paymentOptions = new PaymentOptions();
......@@ -2276,6 +2284,7 @@ public class PaymentRequestImpl
// Go back to the payment sheet
mUI.onPayButtonProcessingCancelled();
PaymentDetailsUpdateServiceHelper.getInstance().reset();
if (!TextUtils.isEmpty(errors.error)) {
mUI.setRetryErrorMessage(errors.error);
} else {
......@@ -2880,6 +2889,7 @@ public class PaymentRequestImpl
disconnectFromClientWithDebugMessage(errorMessage);
} else {
mUI.onPayButtonProcessingCancelled();
PaymentDetailsUpdateServiceHelper.getInstance().reset();
}
}
......@@ -3016,6 +3026,7 @@ public class PaymentRequestImpl
mSpec.destroy();
mSpec = null;
}
PaymentDetailsUpdateServiceHelper.getInstance().reset();
}
private void closeClient() {
......
......@@ -1321,6 +1321,9 @@
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
</intent-filter>
</service>
<service
android:exported="true"
android:name="org.chromium.components.payments.PaymentDetailsUpdateService"/>
<service android:name="androidx.browser.customtabs.PostMessageService"/>
<service
android:exported="true"
......
......@@ -36,6 +36,8 @@ class MockPackageManagerDelegate extends PackageManagerDelegate {
private final List<ResolveInfo> mServices = new ArrayList<>();
private final Map<ApplicationInfo, List<String[]>> mResources = new HashMap<>();
private String mInvokedAppPackageName;
/**
* Simulates an installed payment app with no supported delegations.
*
......@@ -96,6 +98,7 @@ class MockPackageManagerDelegate extends PackageManagerDelegate {
if (signature != null) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
packageInfo.versionCode = 10;
if (signature.isEmpty()) {
packageInfo.signatures = new Signature[0];
......@@ -177,6 +180,11 @@ class MockPackageManagerDelegate extends PackageManagerDelegate {
return mPackages.get(packageName);
}
@Override
public PackageInfo getPackageInfoWithSignatures(int uid) {
return mPackages.get(mInvokedAppPackageName);
}
@Override
public CharSequence getAppLabel(ResolveInfo resolveInfo) {
return mLabels.get(resolveInfo);
......@@ -194,4 +202,13 @@ class MockPackageManagerDelegate extends PackageManagerDelegate {
assert resourceId > 0 && resourceId <= RESOURCES_SIZE;
return mResources.get(applicationInfo).get(resourceId - 1);
}
/**
* Sets the package name of the invoked payment app.
* @param packageName The package name of the invoked payment app.
*/
public void setInvokedAppPackageName(String packageName) {
assert mPackages.containsKey(packageName);
mInvokedAppPackageName = packageName;
}
}
......@@ -73,6 +73,8 @@ android_library("java") {
"java/src/org/chromium/components/payments/PaymentAddressTypeConverter.java",
"java/src/org/chromium/components/payments/PaymentApp.java",
"java/src/org/chromium/components/payments/PaymentDetailsConverter.java",
"java/src/org/chromium/components/payments/PaymentDetailsUpdateService.java",
"java/src/org/chromium/components/payments/PaymentDetailsUpdateServiceHelper.java",
"java/src/org/chromium/components/payments/PaymentFeatureList.java",
"java/src/org/chromium/components/payments/PaymentHandlerHost.java",
"java/src/org/chromium/components/payments/PaymentManifestDownloader.java",
......@@ -100,6 +102,15 @@ android_library("java") {
srcjar_deps = [
":error_strings_generated_srcjar",
":payment_app_type_generated_enum",
":payment_details_update_service_aidl",
]
}
android_aidl("payment_details_update_service_aidl") {
interface_file = "java/src/org/chromium/components/payments/payment_details_update_service.aidl"
sources = [
"java/src/org/chromium/components/payments/IPaymentDetailsUpdateService.aidl",
"java/src/org/chromium/components/payments/IPaymentDetailsUpdateServiceCallback.aidl",
]
}
......
// Copyright 2020 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.components.payments;
import android.os.Bundle;
import IPaymentDetailsUpdateServiceCallback;
/**
* Helper interface used by the invoked native payment app to notify the
* browser that the user has selected a different payment method, shipping
* option, or shipping address.
*/
interface IPaymentDetailsUpdateService {
/**
* Called to notify the browser that the user has selected a different
* payment method.
*
* @param paymentHandlerMethodData The data containing the selected payment
* method's name and optional stringified details.
*/
oneway void changePaymentMethod(in Bundle paymentHandlerMethodData,
IPaymentDetailsUpdateServiceCallback callback);
/**
* Called to notify the browser that the user has selected a different
* shipping option.
*
* @param shippingOptionId The identifier of the selected shipping option.
*/
oneway void changeShippingOption(in String shippingOptionId,
IPaymentDetailsUpdateServiceCallback callback);
/**
* Called to notify the browser that the user has selected a different
* shipping address.
*
* @param shippingAddress The selected shipping address.
*/
oneway void changeShippingAddress(in Bundle shippingAddress,
IPaymentDetailsUpdateServiceCallback callback);
}
// Copyright 2020 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.components.payments;
import android.os.Bundle;
/**
* Helper interface used by the browser to notify the invoked native app about
* merchant's response to one of the paymentmethodchange, shippingoptionchange,
* or shippingaddresschange events.
*/
interface IPaymentDetailsUpdateServiceCallback {
/**
* Called to notify the invoked payment app about updated payment details
* received from the merchant.
*
* @param updatedPaymentDetails The updated payment details received from
* the merchant.
*/
oneway void updateWith(in Bundle updatedPaymentDetails);
/**
* Called to notify the invoked payment app that the merchant has not
* modified the payment details.
*/
oneway void paymentDetailsNotUpdated();
}
......@@ -5,3 +5,6 @@ file://components/payments/OWNERS
per-file *TypeConverter*.*=set noparent
per-file *TypeConverter*.*=file://ipc/SECURITY_OWNERS
per-file *.aidl=set noparent
per-file *.aidl=file://ipc/SECURITY_OWNERS
......@@ -50,6 +50,20 @@ public class PackageManagerDelegate {
}
}
/**
* Retrieves package information of an installed application.
*
* @param uid The uid of an installed application.
* @return The package information of the installed application.
*/
@SuppressLint("PackageManagerGetSignatures")
public PackageInfo getPackageInfoWithSignatures(int uid) {
String packageName =
ContextUtils.getApplicationContext().getPackageManager().getNameForUid(uid);
if (packageName == null) return null;
return getPackageInfoWithSignatures(packageName);
}
/**
* Retrieves the list of activities that can respond to the given intent.
* @param intent The intent to query.
......
// Copyright 2020 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.components.payments;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import org.chromium.base.task.PostTask;
import org.chromium.content_public.browser.UiThreadTaskTraits;
/**
* A bound service responsible for receiving change payment method, shipping option, and shipping
* address calls from an inoked native payment app.
*/
public class PaymentDetailsUpdateService extends Service {
// AIDL calls can happen on multiple threads in parallel. The binder uses PostTask for
// synchronization since locks are discouraged in Chromium. The UI thread task runner is used
// rather than a SequencedTaskRunner since the state of the helper class is also changed by
// PaymentRequestImpl.java, which runs on the UI thread.
private final IPaymentDetailsUpdateService.Stub mBinder =
new IPaymentDetailsUpdateService.Stub() {
@Override
public void changePaymentMethod(Bundle paymentHandlerMethodData,
IPaymentDetailsUpdateServiceCallback callback) {
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
if (!PaymentDetailsUpdateServiceHelper.getInstance().isCallerAuthorized(
Binder.getCallingUid())) {
return;
}
PaymentDetailsUpdateServiceHelper.getInstance().changePaymentMethod(
paymentHandlerMethodData, callback);
});
}
@Override
public void changeShippingOption(
String shippingOptionId, IPaymentDetailsUpdateServiceCallback callback) {
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
if (!PaymentDetailsUpdateServiceHelper.getInstance().isCallerAuthorized(
Binder.getCallingUid())) {
return;
}
PaymentDetailsUpdateServiceHelper.getInstance().changeShippingOption(
shippingOptionId, callback);
});
}
@Override
public void changeShippingAddress(
Bundle shippingAddress, IPaymentDetailsUpdateServiceCallback callback) {
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
if (!PaymentDetailsUpdateServiceHelper.getInstance().isCallerAuthorized(
Binder.getCallingUid())) {
return;
}
PaymentDetailsUpdateServiceHelper.getInstance().changeShippingAddress(
shippingAddress, callback);
});
}
};
@Override
public IBinder onBind(Intent intent) {
if (!PaymentFeatureList.isEnabledOrExperimentalFeaturesEnabled(
PaymentFeatureList.ANDROID_APP_PAYMENT_UPDATE_EVENTS)) {
return null;
}
return mBinder;
}
}
// Copyright 2020 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.components.payments;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import java.util.Arrays;
/**
* Helper class used by android payment app to notify the browser that the user has selected a
* different payment instrument, shipping option, or shipping address inside native app.
*/
public class PaymentDetailsUpdateServiceHelper {
private static final String TAG = "PaymentDetailsUpdate";
// Bundle keys used to send data to this service.
public static final String KEY_METHOD_NAME = "methodName";
public static final String KEY_STRINGIFIED_DETAILS = "details";
@Nullable
private IPaymentDetailsUpdateServiceCallback mCallback;
@Nullable
private PaymentRequestUpdateEventListener mListener;
@Nullable
private PackageInfo mInvokedAppPackageInfo;
@Nullable
private PackageManagerDelegate mPackageManagerDelegate;
// Singleton instance.
private static PaymentDetailsUpdateServiceHelper sInstance;
private PaymentDetailsUpdateServiceHelper(){};
/**
* Returns the singleton instance, lazily creating one if needed.
* The instance is only useful after its listener is set which happens when a native android app
* gets invoked.
* @return The singleton instance.
*/
public static PaymentDetailsUpdateServiceHelper getInstance() {
ThreadUtils.assertOnUiThread();
if (sInstance == null) sInstance = new PaymentDetailsUpdateServiceHelper();
return sInstance;
}
/**
* Initializes the service helper, called when an AndroidPaymentApp is invoked.
* @param packageManagerDelegate The package manager used used to authorize the connecting app.
* @param invokedAppPackageName The package name of the invoked payment app, used to authorize
* the connecting app.
* @param listener The listener for payment method, shipping address, and shipping option
* changes.
*/
public void initialize(PackageManagerDelegate packageManagerDelegate,
String invokedAppPackageName, PaymentRequestUpdateEventListener listener) {
ThreadUtils.assertOnUiThread();
assert mListener == null;
mListener = listener;
mPackageManagerDelegate = packageManagerDelegate;
mInvokedAppPackageInfo =
mPackageManagerDelegate.getPackageInfoWithSignatures(invokedAppPackageName);
}
/**
* Called to notify the merchant that the user has selected a different payment method.
* @param paymentHandlerMethodData The data containing the selected payment method's name and
* optional stringified details.
* @param callback The callback used to notify the invoked app about updated payment details.
*/
public void changePaymentMethod(
Bundle paymentHandlerMethodData, IPaymentDetailsUpdateServiceCallback callback) {
ThreadUtils.assertOnUiThread();
if (paymentHandlerMethodData == null) {
runCallbackWithError(ErrorStrings.METHOD_DATA_REQUIRED, callback);
return;
}
String methodName = paymentHandlerMethodData.getString(KEY_METHOD_NAME);
if (TextUtils.isEmpty(methodName)) {
runCallbackWithError(ErrorStrings.METHOD_NAME_REQUIRED, callback);
return;
}
@Nullable
String stringifiedDetails = paymentHandlerMethodData.getString(KEY_STRINGIFIED_DETAILS);
if (isWaitingForPaymentDetailsUpdate() || mListener == null
|| !mListener.changePaymentMethodFromInvokedApp(methodName, stringifiedDetails)) {
runCallbackWithError(ErrorStrings.INVALID_STATE, callback);
return;
}
mCallback = callback;
}
/**
* Called to notify the merchant that the user has selected a different shipping option.
* @param shippingOptionId The identifier of the selected shipping option.
* @param callback The callback used to notify the invoked app about updated payment details.
*/
public void changeShippingOption(
String shippingOptionId, IPaymentDetailsUpdateServiceCallback callback) {
ThreadUtils.assertOnUiThread();
if (TextUtils.isEmpty(shippingOptionId)) {
runCallbackWithError(ErrorStrings.SHIPPING_OPTION_ID_REQUIRED, callback);
return;
}
if (isWaitingForPaymentDetailsUpdate() || mListener == null
|| !mListener.changeShippingOptionFromInvokedApp(shippingOptionId)) {
runCallbackWithError(ErrorStrings.INVALID_STATE, callback);
return;
}
mCallback = callback;
}
/**
* Called to notify the merchant that the user has selected a different shipping address.
* @param shippingAddress The selected shipping address
* @param callback The callback used to notify the invoked app about updated payment details.
*/
public void changeShippingAddress(
Bundle shippingAddress, IPaymentDetailsUpdateServiceCallback callback) {
ThreadUtils.assertOnUiThread();
if (shippingAddress == null || shippingAddress.isEmpty()) {
runCallbackWithError(ErrorStrings.SHIPPING_ADDRESS_INVALID, callback);
return;
}
if (isWaitingForPaymentDetailsUpdate() || mListener == null
|| !mListener.changeShippingAddressFromInvokedApp(
PaymentAddressTypeConverter.convertAddressToMojoPaymentAddress(
Address.createFromBundle(shippingAddress)))) {
runCallbackWithError(ErrorStrings.INVALID_STATE, callback);
return;
}
mCallback = callback;
}
/**
* Resets the singleton instance.
*/
public void reset() {
ThreadUtils.assertOnUiThread();
sInstance = null;
}
/**
* Checks whether any payment method, shipping address or shipping option change event is
* ongoing.
* @return True after invoked payment app has bound PaymentDetaialsUpdateService and called
* changePaymentMethod, changeShippingAddress, or changeShippingOption and before the
* merchant replies with either updateWith() or onPaymentDetailsNotUpdated().
*/
public boolean isWaitingForPaymentDetailsUpdate() {
ThreadUtils.assertOnUiThread();
return mCallback != null;
}
/**
* @param callerUid The Uid of the service requester.
* @return True when the service requester's package name and signature are the same as the
* invoked payment app's.
*/
public boolean isCallerAuthorized(int callerUid) {
ThreadUtils.assertOnUiThread();
if (mPackageManagerDelegate == null) {
Log.e(TAG, ErrorStrings.UNATHORIZED_SERVICE_REQUEST);
return false;
}
PackageInfo callerPackageInfo =
mPackageManagerDelegate.getPackageInfoWithSignatures(callerUid);
if (mInvokedAppPackageInfo == null || callerPackageInfo == null
|| !mInvokedAppPackageInfo.packageName.equals(callerPackageInfo.packageName)) {
Log.e(TAG, ErrorStrings.UNATHORIZED_SERVICE_REQUEST);
return false;
}
// TODO(https://crbug.com/1086485): signatures field is deprecated in API level 28.
Signature[] callerSignatures = callerPackageInfo.signatures;
Signature[] invokedAppSignatures = mInvokedAppPackageInfo.signatures;
boolean result = Arrays.equals(callerSignatures, invokedAppSignatures);
if (!result) Log.e(TAG, ErrorStrings.UNATHORIZED_SERVICE_REQUEST);
return result;
}
private void runCallbackWithError(String error, IPaymentDetailsUpdateServiceCallback callback) {
ThreadUtils.assertOnUiThread();
// TODO(https://crbug.com/1026667): Call Callback.updateWith with a
// updatedPaymentDetails bundle including the error message only.
}
}
......@@ -16,6 +16,7 @@ import org.chromium.base.annotations.NativeMethods;
@JNINamespace("payments::android")
public class PaymentFeatureList {
/** Alphabetical: */
public static final String ANDROID_APP_PAYMENT_UPDATE_EVENTS = "AndroidAppPaymentUpdateEvents";
public static final String PAYMENT_REQUEST_SKIP_TO_GPAY = "PaymentRequestSkipToGPay";
public static final String PAYMENT_REQUEST_SKIP_TO_GPAY_IF_NO_CARD =
"PaymentRequestSkipToGPayIfNoCard";
......
// Copyright 2020 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.
interface org.chromium.components.payments.IPaymentDetailsUpdateService;
interface org.chromium.components.payments.IPaymentDetailsUpdateServiceCallback;
......@@ -52,6 +52,9 @@ public abstract class ErrorStrings {{
public static final String MINIMAL_UI_SUPPRESSED = "Payment minimal UI suppressed.";
public static final String UNATHORIZED_SERVICE_REQUEST =
"Caller's signuature or package name does not match invoked app's.";
// Prevent instantiation.
private ErrorStrings() {{}}
}}
......@@ -33,6 +33,7 @@ const base::Feature* kFeaturesExposedToJava[] = {
&features::kWebPaymentsModifiers,
&features::kWebPaymentsRedactShippingAddress,
&features::kWebPaymentsSingleAppUiSkip,
&kAndroidAppPaymentUpdateEvents,
&kScrollToExpandPaymentHandler,
};
......@@ -49,6 +50,8 @@ const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
} // namespace
// Android only features.
const base::Feature kAndroidAppPaymentUpdateEvents{
"AndroidAppPaymentUpdateEvents", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kScrollToExpandPaymentHandler{
"ScrollToExpandPaymentHandler", base::FEATURE_DISABLED_BY_DEFAULT};
......
......@@ -12,6 +12,7 @@ namespace payments {
namespace android {
// Android only payment features in alphabetical order:
extern const base::Feature kAndroidAppPaymentUpdateEvents;
extern const base::Feature kScrollToExpandPaymentHandler;
} // namespace android
......
......@@ -18,6 +18,8 @@ const char kCannotShowWithoutInit[] = "Attempted show without initialization.";
const char kCannotUpdateWithoutInit[] = "Attempted updateWith without initialization.";
const char kCannotUpdateWithoutShow[] = "Attempted updateWith without show.";
const char kInvalidState[] = "Invalid state.";
const char kMethodDataRequired[] = "Method data required.";
const char kMethodNameRequired[] = "Method name required.";
const char kMissingDetailsFromPaymentApp[] = "Payment app returned invalid response. Missing field \"details\".";
const char kMissingMethodNameFromPaymentApp[] = "Payment app returned invalid response. Missing field \"methodName\".";
const char kNotInASecureOrigin[] = "Not in a secure origin.";
......@@ -28,6 +30,7 @@ const char kProhibitedOrigin[] = "Only localhost, file://, and cryptographic sch
const char kProhibitedOriginOrInvalidSslExplanation[] = "No UI will be shown. CanMakePayment and hasEnrolledInstrument will always return false. Show will be rejected with NotSupportedError.";
const char kShippingAddressInvalid[] = "Payment app returned invalid shipping address in response.";
const char kShippingOptionEmpty[] = "Payment app returned invalid response. Missing field \"shipping option\".";
const char kShippingOptionIdRequired[] = "Shipping option identifier required.";
const char kStrictBasicCardShowReject[] = "User does not have valid information on file.";
const char kTotalRequired[] = "Total required.";
const char kUserCancelled[] = "User closed the Payment Request UI.";
......
......@@ -38,6 +38,13 @@ extern const char kCannotUpdateWithoutShow[];
// Used when an invalid state is encountered generically.
extern const char kInvalidState[];
// Used when the {"supportedMethods": "", data: {}} is required, but not
// provided.
extern const char kMethodDataRequired[];
// Used when non-empty "supportedMethods": "" is required, but not provided.
extern const char kMethodNameRequired[];
// The payment handler responded with an empty "details" field.
extern const char kMissingDetailsFromPaymentApp[];
......@@ -69,6 +76,9 @@ extern const char kShippingAddressInvalid[];
// The payment handler responded with an empty "shipping option" field.
extern const char kShippingOptionEmpty[];
// Used when non-empty "shippingOptionId": "" is required, but not provided.
extern const char kShippingOptionIdRequired[];
// Used when rejecting show() with NotSupportedError, because the user did not
// have all valid autofill data.
extern const char kStrictBasicCardShowReject[];
......
......@@ -80,10 +80,6 @@ const char kInvalidWebAppIcon[] =
"Failed to download or decode a non-empty icon for payment app with \"$1\" "
"manifest.";
const char kMethodDataRequired[] = "Method data required.";
const char kMethodNameRequired[] = "Method name required.";
const char kMultiplePaymentMethodsNotSupportedFormat[] =
"The payment methods $ are not supported.";
......@@ -141,8 +137,6 @@ const char kPaymentHandlerInsecureNavigation[] =
const char kSinglePaymentMethodNotSupportedFormat[] =
"The payment method $ is not supported.";
const char kShippingOptionIdRequired[] = "Shipping option identifier required.";
const char kCanMakePaymentEventRejected[] =
"Payment handler rejected the promise passed into "
"CanMakePaymentEvent.respondWith().";
......
......@@ -103,13 +103,6 @@ extern const char kInvalidSslCertificate[];
// work.
extern const char kInvalidWebAppIcon[];
// Used when the {"supportedMethods": "", data: {}} is required, but not
// provided.
extern const char kMethodDataRequired[];
// Used when non-empty "supportedMethods": "" is required, but not provided.
extern const char kMethodNameRequired[];
// The format for the message about multiple payment methods that are not
// supported. This format should be used with base::ReplaceChars() function,
// where "$" is the character to replace.
......@@ -171,9 +164,6 @@ extern const char kReachedMaximumNumberOfRedirects[];
// where "$" is the character to replace.
extern const char kSinglePaymentMethodNotSupportedFormat[];
// Used when non-empty "shippingOptionId": "" is required, but not provided.
extern const char kShippingOptionIdRequired[];
// The payment handler rejected the promise passed into
// CanMakePaymentEvent.respondWith().
extern const char kCanMakePaymentEventRejected[];
......
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