Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java |
| index 257ba0c2886ed0720304559fe2ca11b65d2c9514..da04194f889701083c985295221bde55ae137452 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java |
| @@ -7,6 +7,7 @@ package org.chromium.chrome.browser.payments; |
| import android.app.Activity; |
| import android.graphics.Bitmap; |
| import android.os.Handler; |
| +import android.support.v4.util.ArrayMap; |
| import android.text.TextUtils; |
| import org.json.JSONException; |
| @@ -41,6 +42,7 @@ import org.chromium.components.safejson.JsonSanitizer; |
| import org.chromium.components.url_formatter.UrlFormatter; |
| import org.chromium.content_public.browser.WebContents; |
| import org.chromium.mojo.system.MojoException; |
| +import org.chromium.payments.mojom.ActivePaymentQueryResult; |
| import org.chromium.payments.mojom.PaymentComplete; |
| import org.chromium.payments.mojom.PaymentDetails; |
| import org.chromium.payments.mojom.PaymentErrorReason; |
| @@ -58,7 +60,6 @@ import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| -import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Locale; |
| @@ -73,16 +74,6 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| PaymentApp.InstrumentsCallback, PaymentInstrument.InstrumentDetailsCallback, |
| PaymentResponseHelper.PaymentResponseRequesterDelegate { |
| /** |
| - * Observer to be notified when PaymentRequest UI has been dismissed. |
| - */ |
| - public interface PaymentRequestDismissObserver { |
| - /** |
| - * Called when PaymentRequest UI has been dismissed. |
| - */ |
| - void onPaymentRequestDismissed(); |
| - } |
| - |
| - /** |
| * A test-only observer for the PaymentRequest service implementation. |
| */ |
| public interface PaymentRequestServiceObserverForTest { |
| @@ -111,6 +102,11 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| * </ul> |
| */ |
| void onPaymentRequestServiceShowFailed(); |
| + |
| + /** |
| + * Called when the canMakeActivePayment() request has been responded. |
| + */ |
| + void onPaymentRequestServiceActivePaymentQueryResponded(); |
| } |
| private static final String TAG = "cr_PaymentRequest"; |
| @@ -124,8 +120,21 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| } |
| }; |
| + /** Every origin can call canMakeActivePayment() every 30 minutes. */ |
| + private static final int CAN_MAKE_ACTIVE_PAYMENT_QUERY_PERIOD_MS = 30 * 60 * 1000; |
| + |
| private static PaymentRequestServiceObserverForTest sObserverForTest; |
| + /** True if show() was called in any PaymentRequestImpl object. */ |
| + private static boolean sIsShowing; |
| + |
| + /** |
| + * In-memory mapping of the origins of websites that have recently called canMakeActivePayment() |
| + * to the list of the payment methods that were been queried. Used for throttling the usage of |
| + * this call. The user can clear the list by restarting the browser. |
| + */ |
| + private static Map<String, Set<String>> sCanMakeActivePaymentQueries; |
| + |
| /** Monitors changes in the TabModelSelector. */ |
| private final TabModelSelectorObserver mSelectorObserver = new EmptyTabModelSelectorObserver() { |
| @Override |
| @@ -144,7 +153,6 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| private final Handler mHandler = new Handler(); |
| private final ChromeActivity mContext; |
| - private final PaymentRequestDismissObserver mDismissObserver; |
| private final String mMerchantName; |
| private final String mOrigin; |
| private final List<PaymentApp> mApps; |
| @@ -192,13 +200,11 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| private boolean mMerchantSupportsAutofillPaymentInstruments; |
| private ContactEditor mContactEditor; |
| private boolean mHasRecordedAbortReason; |
| + private boolean mQueriedCanMakeActivePayment; |
| /** True if any of the requested payment methods are supported. */ |
| private boolean mArePaymentMethodsSupported; |
| - /** True if show() was called. */ |
| - private boolean mIsShowing; |
| - |
| /** The helper to create and fill the response to send to the merchant. */ |
| private PaymentResponseHelper mPaymentResponseHelper; |
| @@ -207,18 +213,14 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| * |
| * @param context The context where PaymentRequest has been invoked. |
| * @param webContents The web contents that have invoked the PaymentRequest API. |
| - * @param dismissObserver The observer to notify when PaymentRequest UI has been dismissed. |
| */ |
| - public PaymentRequestImpl(Activity context, WebContents webContents, |
| - PaymentRequestDismissObserver dismissObserver) { |
| + public PaymentRequestImpl(Activity context, WebContents webContents) { |
| assert context != null; |
| assert webContents != null; |
| - assert dismissObserver != null; |
| assert context instanceof ChromeActivity; |
| mContext = (ChromeActivity) context; |
| - mDismissObserver = dismissObserver; |
| mMerchantName = webContents.getTitle(); |
| // The feature is available only in secure context, so it's OK to not show HTTPS. |
| mOrigin = UrlFormatter.formatUrlForSecurityDisplay(webContents.getVisibleUrl(), false); |
| @@ -407,9 +409,14 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| */ |
| @Override |
| public void show() { |
| - if (mClient == null || mIsShowing) return; |
| + if (mClient == null) return; |
| - mIsShowing = true; |
| + if (sIsShowing) { |
| + disconnectFromClientWithDebugMessage("A PaymentRequest UI is already showing"); |
| + return; |
| + } |
| + |
| + sIsShowing = true; |
| if (disconnectIfNoPaymentMethodsSupported()) return; |
| // Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be |
| @@ -425,7 +432,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) { |
| // Payment methodData are required. |
| if (methodData == null || methodData.length == 0) return null; |
| - Map<String, JSONObject> result = new HashMap<>(); |
| + Map<String, JSONObject> result = new ArrayMap<>(); |
| for (int i = 0; i < methodData.length; i++) { |
| JSONObject data = null; |
| if (!TextUtils.isEmpty(methodData[i].stringifiedData)) { |
| @@ -464,7 +471,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| mPendingInstruments = new ArrayList<>(); |
| mPendingAutofillInstruments = new ArrayList<>(); |
| - Map<PaymentApp, Map<String, JSONObject>> queryApps = new HashMap<>(); |
| + Map<PaymentApp, Map<String, JSONObject>> queryApps = new ArrayMap<>(); |
| for (int i = 0; i < mApps.size(); i++) { |
| PaymentApp app = mApps.get(i); |
| Map<String, JSONObject> appMethods = |
| @@ -492,7 +499,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| Map<String, JSONObject> result = null; |
| for (String method : appMethods) { |
| if (merchantMethodData.containsKey(method)) { |
| - if (result == null) result = new HashMap<>(); |
| + if (result == null) result = new ArrayMap<>(); |
| result.put(method, merchantMethodData.get(method)); |
| } |
| } |
| @@ -935,6 +942,46 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| } |
| /** |
| + * Called by the merchant website to check if the user has complete payment instruments. |
| + */ |
| + @Override |
| + public void canMakeActivePayment() { |
| + if (mClient == null) return; |
| + |
| + if (sCanMakeActivePaymentQueries == null) sCanMakeActivePaymentQueries = new ArrayMap<>(); |
| + |
| + if (sCanMakeActivePaymentQueries.containsKey(mOrigin)) { |
|
Marijn Kruisselbrink
2016/11/17 18:06:21
Is mOrigin the correct key to use here? I realize
please use gerrit instead
2016/11/17 20:07:21
After reading the comments on these methods, I sho
|
| + if (!mMethodData.keySet().equals(sCanMakeActivePaymentQueries.get(mOrigin))) { |
| + mClient.onCanMakeActivePayment(ActivePaymentQueryResult.QUERY_QUOTA_EXCEEDED); |
| + if (sObserverForTest != null) { |
| + sObserverForTest.onPaymentRequestServiceActivePaymentQueryResponded(); |
| + } |
| + return; |
| + } |
| + } else { |
| + sCanMakeActivePaymentQueries.put(mOrigin, mMethodData.keySet()); |
| + mHandler.postDelayed(new Runnable() { |
| + @Override |
| + public void run() { |
| + sCanMakeActivePaymentQueries.remove(mOrigin); |
| + } |
| + }, CAN_MAKE_ACTIVE_PAYMENT_QUERY_PERIOD_MS); |
| + } |
| + |
| + if (!mPendingApps.isEmpty() || !mPendingInstruments.isEmpty()) { |
| + mQueriedCanMakeActivePayment = true; |
| + } else { |
| + mClient.onCanMakeActivePayment(mPaymentMethodsSection == null |
| + || mPaymentMethodsSection.getSelectedItem() == null |
| + ? ActivePaymentQueryResult.CANNOT_MAKE_ACTIVE_PAYMENT |
| + : ActivePaymentQueryResult.CAN_MAKE_ACTIVE_PAYMENT); |
| + if (sObserverForTest != null) { |
| + sObserverForTest.onPaymentRequestServiceActivePaymentQueryResponded(); |
| + } |
| + } |
| + } |
| + |
| + /** |
| * Called when the renderer closes the Mojo connection. |
| */ |
| @Override |
| @@ -1021,6 +1068,16 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| } |
| } |
| + if (mQueriedCanMakeActivePayment) { |
| + mQueriedCanMakeActivePayment = false; |
| + mClient.onCanMakeActivePayment(selection == 0 |
| + ? ActivePaymentQueryResult.CAN_MAKE_ACTIVE_PAYMENT |
| + : ActivePaymentQueryResult.CANNOT_MAKE_ACTIVE_PAYMENT); |
| + if (sObserverForTest != null) { |
| + sObserverForTest.onPaymentRequestServiceActivePaymentQueryResponded(); |
| + } |
| + } |
| + |
| // The list of payment instruments is ready to display. |
| mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PAYMENT_METHODS, |
| selection, mPendingInstruments); |
| @@ -1044,7 +1101,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| && !ChromeFeatureList.isEnabled(ChromeFeatureList.NO_CREDIT_CARD_ABORT); |
| if (!mArePaymentMethodsSupported |
| - || (mIsShowing && !waitingForPaymentApps && !foundPaymentMethods |
| + || (sIsShowing && !waitingForPaymentApps && !foundPaymentMethods |
| && !userCanAddCreditCard)) { |
| // All payment apps have responded, but none of them have instruments. It's possible to |
| // add credit cards, but the merchant does not support them either. The payment request |
| @@ -1161,7 +1218,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
| private void closeClient() { |
| if (mClient != null) mClient.close(); |
| mClient = null; |
| - mDismissObserver.onPaymentRequestDismissed(); |
| + sIsShowing = false; |
| } |
| @VisibleForTesting |