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 c198b8c7b85a9e1095961f4f70e6be9111d7008a..b6a653d633b412da13326e5482981ba776773abc 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 |
@@ -53,6 +53,7 @@ import java.util.HashMap; |
import java.util.HashSet; |
import java.util.List; |
import java.util.Locale; |
+import java.util.Map; |
import java.util.Set; |
/** |
@@ -89,8 +90,14 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
} |
private static final String TAG = "cr_PaymentRequest"; |
- |
private static final int SUGGESTIONS_LIMIT = 4; |
+ private static final Comparator<Completable> COMPLETENESS_COMPARATOR = |
+ new Comparator<Completable>() { |
+ @Override |
+ public int compare(Completable a, Completable b) { |
+ return (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); |
+ } |
+ }; |
private static PaymentRequestServiceObserverForTest sObserverForTest; |
@@ -127,12 +134,12 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
*/ |
private SectionInformation mUiShippingOptions; |
- private HashMap<String, JSONObject> mMethodData; |
+ private Map<String, JSONObject> mMethodData; |
private SectionInformation mShippingAddressesSection; |
private SectionInformation mContactSection; |
private List<PaymentApp> mPendingApps; |
- private int mFirstCompletePendingInstrument; |
private List<PaymentInstrument> mPendingInstruments; |
+ private List<PaymentInstrument> mPendingAutofillInstruments; |
private SectionInformation mPaymentMethodsSection; |
private PaymentRequestUI mUI; |
private Callback<PaymentInformation> mPaymentInformationCallback; |
@@ -237,20 +244,6 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
return; |
} |
- // Create a comparator to sort the suggestions by completeness. |
- Comparator<Completable> completenessComparator = new Comparator<Completable>() { |
- @Override |
- public int compare(Completable a, Completable b) { |
- if (a.isComplete() == b.isComplete()) { |
- return 0; |
- } else if (a.isComplete()) { |
- return -1; |
- } else { |
- return 1; |
- } |
- } |
- }; |
- |
// If the merchant requests shipping and does not provide a selected shipping option, then |
// the merchant needs the shipping address to calculate the shipping price and availability. |
boolean requestShipping = options != null && options.requestShipping; |
@@ -277,7 +270,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
} |
// Suggest complete addresses first. |
- Collections.sort(addresses, completenessComparator); |
+ Collections.sort(addresses, COMPLETENESS_COMPARATOR); |
// Limit the number of suggestions. |
addresses = addresses.subList(0, Math.min(addresses.size(), SUGGESTIONS_LIMIT)); |
@@ -324,7 +317,7 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
} |
// Suggest complete contact infos first. |
- Collections.sort(contacts, completenessComparator); |
+ Collections.sort(contacts, COMPLETENESS_COMPARATOR); |
// Limit the number of suggestions. |
contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS_LIMIT)); |
@@ -351,11 +344,11 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorView()); |
} |
- private static HashMap<String, JSONObject> getValidatedMethodData( |
+ private static Map<String, JSONObject> getValidatedMethodData( |
PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) { |
// Payment methodData are required. |
if (methodData == null || methodData.length == 0) return null; |
- HashMap<String, JSONObject> result = new HashMap<>(); |
+ Map<String, JSONObject> result = new HashMap<>(); |
for (int i = 0; i < methodData.length; i++) { |
JSONObject data = null; |
if (!TextUtils.isEmpty(methodData[i].stringifiedData)) { |
@@ -395,10 +388,11 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
*/ |
private boolean getMatchingPaymentInstruments() { |
mPendingApps = new ArrayList<>(mApps); |
- mFirstCompletePendingInstrument = SectionInformation.NO_SELECTION; |
mPendingInstruments = new ArrayList<>(); |
+ mPendingAutofillInstruments = new ArrayList<>(); |
boolean arePaymentMethodsSupported = false; |
+ Map<PaymentApp, JSONObject> queryApps = new HashMap<>(); |
for (int i = 0; i < mApps.size(); i++) { |
PaymentApp app = mApps.get(i); |
Set<String> appMethods = app.getSupportedMethodNames(); |
@@ -407,11 +401,18 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
mPendingApps.remove(app); |
} else { |
arePaymentMethodsSupported = true; |
- mMerchantSupportsAutofillPaymentInstruments = app instanceof AutofillPaymentApp; |
- app.getInstruments(mMethodData.get(appMethods.iterator().next()), this); |
+ mMerchantSupportsAutofillPaymentInstruments |= app instanceof AutofillPaymentApp; |
+ queryApps.put(app, mMethodData.get(appMethods.iterator().next())); |
} |
} |
+ // Query instruments after mMerchantSupportsAutofillPaymentInstruments has been initialized, |
+ // so a fast response from a non-autofill payment app at the front of the app list does not |
+ // cause NOT_SUPPORTED payment rejection. |
+ for (Map.Entry<PaymentApp, JSONObject> q : queryApps.entrySet()) { |
+ q.getKey().getInstruments(q.getValue(), this); |
+ } |
+ |
return arePaymentMethodsSupported; |
} |
@@ -868,12 +869,13 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instruments) { |
mPendingApps.remove(app); |
+ // Place the instruments into either "autofill" or "non-autofill" list to be displayed when |
+ // all apps have responded. |
if (instruments != null) { |
for (int i = 0; i < instruments.size(); i++) { |
PaymentInstrument instrument = instruments.get(i); |
if (mMethodData.containsKey(instrument.getMethodName())) { |
- checkForCompletePaymentInstrument(instrument, mPendingInstruments.size()); |
- mPendingInstruments.add(instrument); |
+ addPendingInstrument(instrument); |
} else { |
instrument.dismiss(); |
} |
@@ -893,25 +895,56 @@ public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie |
return; |
} |
+ // List order: |
+ // > Non-autofill instruments. |
+ // > Complete autofill instruments. |
+ // > Incomplete autofill instruments. |
+ Collections.sort(mPendingAutofillInstruments, COMPLETENESS_COMPARATOR); |
+ mPendingInstruments.addAll(mPendingAutofillInstruments); |
+ |
+ mPendingAutofillInstruments.clear(); |
+ mPendingAutofillInstruments = null; |
+ |
+ // Pre-select the first instrument on the list, if it is complete. |
+ int selection = SectionInformation.NO_SELECTION; |
+ if (!mPendingInstruments.isEmpty()) { |
+ PaymentInstrument first = mPendingInstruments.get(0); |
+ if (!(first instanceof AutofillPaymentInstrument) |
+ || ((AutofillPaymentInstrument) first).isComplete()) { |
+ selection = 0; |
+ } |
+ } |
+ |
// The list of payment instruments is ready to display. |
mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PAYMENT_METHODS, |
- mFirstCompletePendingInstrument, mPendingInstruments); |
+ selection, mPendingInstruments); |
+ |
mPendingInstruments.clear(); |
+ mPendingInstruments = null; |
// UI has requested the full list of payment instruments. Provide it now. |
if (mPaymentInformationCallback != null) providePaymentInformation(); |
} |
- private void checkForCompletePaymentInstrument(PaymentInstrument instrument, int index) { |
- boolean isComplete = true; |
+ /** |
+ * Saves the given instrument in either "autofill" or "non-autofill" list. The separation |
+ * enables placing autofill instruments on the bottom of the list. |
+ * |
+ * Autofill instruments are also checked for completeness. A complete autofill instrument can be |
+ * sent to the merchant as-is, without editing first. Such instruments should be displayed |
+ * higher in the list. |
+ * |
+ * @param instrument The instrument to add to either "autofill" or "non-autofill" list. |
+ */ |
+ private void addPendingInstrument(PaymentInstrument instrument) { |
if (instrument instanceof AutofillPaymentInstrument) { |
AutofillPaymentInstrument autofillInstrument = (AutofillPaymentInstrument) instrument; |
- isComplete = mCardEditor.isCardComplete(autofillInstrument.getCard()); |
- if (isComplete) autofillInstrument.setIsComplete(); |
- } |
- |
- if (isComplete && mFirstCompletePendingInstrument == SectionInformation.NO_SELECTION) { |
- mFirstCompletePendingInstrument = index; |
+ if (mCardEditor.isCardComplete(autofillInstrument.getCard())) { |
+ autofillInstrument.setIsComplete(); |
+ } |
+ mPendingAutofillInstruments.add(instrument); |
+ } else { |
+ mPendingInstruments.add(instrument); |
} |
} |