| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.payments; | 5 package org.chromium.chrome.browser.payments; |
| 6 | 6 |
| 7 import android.app.Activity; | 7 import android.app.Activity; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.os.Handler; | 9 import android.os.Handler; |
| 10 import android.text.TextUtils; | 10 import android.text.TextUtils; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 | 46 |
| 47 import java.io.IOException; | 47 import java.io.IOException; |
| 48 import java.util.ArrayList; | 48 import java.util.ArrayList; |
| 49 import java.util.Arrays; | 49 import java.util.Arrays; |
| 50 import java.util.Collections; | 50 import java.util.Collections; |
| 51 import java.util.Comparator; | 51 import java.util.Comparator; |
| 52 import java.util.HashMap; | 52 import java.util.HashMap; |
| 53 import java.util.HashSet; | 53 import java.util.HashSet; |
| 54 import java.util.List; | 54 import java.util.List; |
| 55 import java.util.Locale; | 55 import java.util.Locale; |
| 56 import java.util.Map; |
| 56 import java.util.Set; | 57 import java.util.Set; |
| 57 | 58 |
| 58 /** | 59 /** |
| 59 * Android implementation of the PaymentRequest service defined in | 60 * Android implementation of the PaymentRequest service defined in |
| 60 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom. | 61 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom. |
| 61 */ | 62 */ |
| 62 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie
nt, | 63 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie
nt, |
| 63 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback { | 64 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback { |
| 64 | 65 |
| 65 /** | 66 /** |
| (...skipping 16 matching lines...) Expand all Loading... |
| 82 * <ul> | 83 * <ul> |
| 83 * <li>The merchant requests only unsupported payment methods.</li> | 84 * <li>The merchant requests only unsupported payment methods.</li> |
| 84 * <li>The merchant requests only payment methods that don't have inst
ruments and are not | 85 * <li>The merchant requests only payment methods that don't have inst
ruments and are not |
| 85 * able to add instruments from PaymentRequest UI.</li> | 86 * able to add instruments from PaymentRequest UI.</li> |
| 86 * </ul> | 87 * </ul> |
| 87 */ | 88 */ |
| 88 void onPaymentRequestServiceShowFailed(); | 89 void onPaymentRequestServiceShowFailed(); |
| 89 } | 90 } |
| 90 | 91 |
| 91 private static final String TAG = "cr_PaymentRequest"; | 92 private static final String TAG = "cr_PaymentRequest"; |
| 92 | |
| 93 private static final int SUGGESTIONS_LIMIT = 4; | 93 private static final int SUGGESTIONS_LIMIT = 4; |
| 94 private static final Comparator<Completable> COMPLETENESS_COMPARATOR = |
| 95 new Comparator<Completable>() { |
| 96 @Override |
| 97 public int compare(Completable a, Completable b) { |
| 98 return (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0); |
| 99 } |
| 100 }; |
| 94 | 101 |
| 95 private static PaymentRequestServiceObserverForTest sObserverForTest; | 102 private static PaymentRequestServiceObserverForTest sObserverForTest; |
| 96 | 103 |
| 97 private final Handler mHandler = new Handler(); | 104 private final Handler mHandler = new Handler(); |
| 98 | 105 |
| 99 private Activity mContext; | 106 private Activity mContext; |
| 100 private String mMerchantName; | 107 private String mMerchantName; |
| 101 private String mOrigin; | 108 private String mOrigin; |
| 102 private Bitmap mFavicon; | 109 private Bitmap mFavicon; |
| 103 private List<PaymentApp> mApps; | 110 private List<PaymentApp> mApps; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 120 * price string. This data is passed to the UI. | 127 * price string. This data is passed to the UI. |
| 121 */ | 128 */ |
| 122 private ShoppingCart mUiShoppingCart; | 129 private ShoppingCart mUiShoppingCart; |
| 123 | 130 |
| 124 /** | 131 /** |
| 125 * The UI model for the shipping options. Includes the label and sublabel fo
r each shipping | 132 * The UI model for the shipping options. Includes the label and sublabel fo
r each shipping |
| 126 * option. Also keeps track of the selected shipping option. This data is pa
ssed to the UI. | 133 * option. Also keeps track of the selected shipping option. This data is pa
ssed to the UI. |
| 127 */ | 134 */ |
| 128 private SectionInformation mUiShippingOptions; | 135 private SectionInformation mUiShippingOptions; |
| 129 | 136 |
| 130 private HashMap<String, JSONObject> mMethodData; | 137 private Map<String, JSONObject> mMethodData; |
| 131 private SectionInformation mShippingAddressesSection; | 138 private SectionInformation mShippingAddressesSection; |
| 132 private SectionInformation mContactSection; | 139 private SectionInformation mContactSection; |
| 133 private List<PaymentApp> mPendingApps; | 140 private List<PaymentApp> mPendingApps; |
| 134 private int mFirstCompletePendingInstrument; | |
| 135 private List<PaymentInstrument> mPendingInstruments; | 141 private List<PaymentInstrument> mPendingInstruments; |
| 142 private List<PaymentInstrument> mPendingAutofillInstruments; |
| 136 private SectionInformation mPaymentMethodsSection; | 143 private SectionInformation mPaymentMethodsSection; |
| 137 private PaymentRequestUI mUI; | 144 private PaymentRequestUI mUI; |
| 138 private Callback<PaymentInformation> mPaymentInformationCallback; | 145 private Callback<PaymentInformation> mPaymentInformationCallback; |
| 139 private boolean mMerchantNeedsShippingAddress; | 146 private boolean mMerchantNeedsShippingAddress; |
| 140 private boolean mPaymentAppRunning; | 147 private boolean mPaymentAppRunning; |
| 141 private boolean mMerchantSupportsAutofillPaymentInstruments; | 148 private boolean mMerchantSupportsAutofillPaymentInstruments; |
| 142 private AddressEditor mAddressEditor; | 149 private AddressEditor mAddressEditor; |
| 143 private CardEditor mCardEditor; | 150 private CardEditor mCardEditor; |
| 144 private ContactEditor mContactEditor; | 151 private ContactEditor mContactEditor; |
| 145 | 152 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 | 237 |
| 231 if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; | 238 if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; |
| 232 | 239 |
| 233 if (!getMatchingPaymentInstruments()) { | 240 if (!getMatchingPaymentInstruments()) { |
| 234 disconnectFromClientWithDebugMessage("Requested payment methods are
not supported", | 241 disconnectFromClientWithDebugMessage("Requested payment methods are
not supported", |
| 235 PaymentErrorReason.NOT_SUPPORTED); | 242 PaymentErrorReason.NOT_SUPPORTED); |
| 236 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi
ceShowFailed(); | 243 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi
ceShowFailed(); |
| 237 return; | 244 return; |
| 238 } | 245 } |
| 239 | 246 |
| 240 // Create a comparator to sort the suggestions by completeness. | |
| 241 Comparator<Completable> completenessComparator = new Comparator<Completa
ble>() { | |
| 242 @Override | |
| 243 public int compare(Completable a, Completable b) { | |
| 244 if (a.isComplete() == b.isComplete()) { | |
| 245 return 0; | |
| 246 } else if (a.isComplete()) { | |
| 247 return -1; | |
| 248 } else { | |
| 249 return 1; | |
| 250 } | |
| 251 } | |
| 252 }; | |
| 253 | |
| 254 // If the merchant requests shipping and does not provide a selected shi
pping option, then | 247 // If the merchant requests shipping and does not provide a selected shi
pping option, then |
| 255 // the merchant needs the shipping address to calculate the shipping pri
ce and availability. | 248 // the merchant needs the shipping address to calculate the shipping pri
ce and availability. |
| 256 boolean requestShipping = options != null && options.requestShipping; | 249 boolean requestShipping = options != null && options.requestShipping; |
| 257 mMerchantNeedsShippingAddress = | 250 mMerchantNeedsShippingAddress = |
| 258 requestShipping && mUiShippingOptions.getSelectedItem() == null; | 251 requestShipping && mUiShippingOptions.getSelectedItem() == null; |
| 259 | 252 |
| 260 boolean requestPayerPhone = options != null && options.requestPayerPhone
; | 253 boolean requestPayerPhone = options != null && options.requestPayerPhone
; |
| 261 boolean requestPayerEmail = options != null && options.requestPayerEmail
; | 254 boolean requestPayerEmail = options != null && options.requestPayerEmail
; |
| 262 | 255 |
| 263 List<AutofillProfile> profiles = null; | 256 List<AutofillProfile> profiles = null; |
| 264 if (requestShipping || requestPayerPhone || requestPayerEmail) { | 257 if (requestShipping || requestPayerPhone || requestPayerEmail) { |
| 265 profiles = PersonalDataManager.getInstance().getProfilesToSuggest(); | 258 profiles = PersonalDataManager.getInstance().getProfilesToSuggest(); |
| 266 } | 259 } |
| 267 | 260 |
| 268 if (requestShipping) { | 261 if (requestShipping) { |
| 269 List<AutofillAddress> addresses = new ArrayList<>(); | 262 List<AutofillAddress> addresses = new ArrayList<>(); |
| 270 | 263 |
| 271 for (int i = 0; i < profiles.size(); i++) { | 264 for (int i = 0; i < profiles.size(); i++) { |
| 272 AutofillProfile profile = profiles.get(i); | 265 AutofillProfile profile = profiles.get(i); |
| 273 mAddressEditor.addPhoneNumberIfValid(profile.getPhoneNumber()); | 266 mAddressEditor.addPhoneNumberIfValid(profile.getPhoneNumber()); |
| 274 | 267 |
| 275 boolean isComplete = mAddressEditor.isProfileComplete(profile); | 268 boolean isComplete = mAddressEditor.isProfileComplete(profile); |
| 276 addresses.add(new AutofillAddress(profile, isComplete)); | 269 addresses.add(new AutofillAddress(profile, isComplete)); |
| 277 } | 270 } |
| 278 | 271 |
| 279 // Suggest complete addresses first. | 272 // Suggest complete addresses first. |
| 280 Collections.sort(addresses, completenessComparator); | 273 Collections.sort(addresses, COMPLETENESS_COMPARATOR); |
| 281 | 274 |
| 282 // Limit the number of suggestions. | 275 // Limit the number of suggestions. |
| 283 addresses = addresses.subList(0, Math.min(addresses.size(), SUGGESTI
ONS_LIMIT)); | 276 addresses = addresses.subList(0, Math.min(addresses.size(), SUGGESTI
ONS_LIMIT)); |
| 284 | 277 |
| 285 // Automatically select the first address if one is complete and if
the merchant does | 278 // Automatically select the first address if one is complete and if
the merchant does |
| 286 // not require a shipping address to calculate shipping costs. | 279 // not require a shipping address to calculate shipping costs. |
| 287 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; | 280 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; |
| 288 if (!mMerchantNeedsShippingAddress && !addresses.isEmpty() | 281 if (!mMerchantNeedsShippingAddress && !addresses.isEmpty() |
| 289 && addresses.get(0).isComplete()) { | 282 && addresses.get(0).isComplete()) { |
| 290 firstCompleteAddressIndex = 0; | 283 firstCompleteAddressIndex = 0; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 317 uniqueContactInfos.add(uniqueContactInfo); | 310 uniqueContactInfos.add(uniqueContactInfo); |
| 318 | 311 |
| 319 boolean isComplete = | 312 boolean isComplete = |
| 320 mContactEditor.isContactInformationComplete(phon
e, email); | 313 mContactEditor.isContactInformationComplete(phon
e, email); |
| 321 contacts.add(new AutofillContact(profile, phone, email,
isComplete)); | 314 contacts.add(new AutofillContact(profile, phone, email,
isComplete)); |
| 322 } | 315 } |
| 323 } | 316 } |
| 324 } | 317 } |
| 325 | 318 |
| 326 // Suggest complete contact infos first. | 319 // Suggest complete contact infos first. |
| 327 Collections.sort(contacts, completenessComparator); | 320 Collections.sort(contacts, COMPLETENESS_COMPARATOR); |
| 328 | 321 |
| 329 // Limit the number of suggestions. | 322 // Limit the number of suggestions. |
| 330 contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS
_LIMIT)); | 323 contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS
_LIMIT)); |
| 331 | 324 |
| 332 // Automatically select the first address if it is complete. | 325 // Automatically select the first address if it is complete. |
| 333 int firstCompleteContactIndex = SectionInformation.NO_SELECTION; | 326 int firstCompleteContactIndex = SectionInformation.NO_SELECTION; |
| 334 if (!contacts.isEmpty() && contacts.get(0).isComplete()) { | 327 if (!contacts.isEmpty() && contacts.get(0).isComplete()) { |
| 335 firstCompleteContactIndex = 0; | 328 firstCompleteContactIndex = 0; |
| 336 } | 329 } |
| 337 | 330 |
| 338 mContactSection = new SectionInformation( | 331 mContactSection = new SectionInformation( |
| 339 PaymentRequestUI.TYPE_CONTACT_DETAILS, firstCompleteContactI
ndex, contacts); | 332 PaymentRequestUI.TYPE_CONTACT_DETAILS, firstCompleteContactI
ndex, contacts); |
| 340 } | 333 } |
| 341 | 334 |
| 342 mUI = new PaymentRequestUI(mContext, this, requestShipping, | 335 mUI = new PaymentRequestUI(mContext, this, requestShipping, |
| 343 requestPayerPhone || requestPayerEmail, mMerchantSupportsAutofil
lPaymentInstruments, | 336 requestPayerPhone || requestPayerEmail, mMerchantSupportsAutofil
lPaymentInstruments, |
| 344 mMerchantName, mOrigin); | 337 mMerchantName, mOrigin); |
| 345 | 338 |
| 346 if (mFavicon != null) mUI.setTitleBitmap(mFavicon); | 339 if (mFavicon != null) mUI.setTitleBitmap(mFavicon); |
| 347 mFavicon = null; | 340 mFavicon = null; |
| 348 | 341 |
| 349 mAddressEditor.setEditorView(mUI.getEditorView()); | 342 mAddressEditor.setEditorView(mUI.getEditorView()); |
| 350 mCardEditor.setEditorView(mUI.getCardEditorView()); | 343 mCardEditor.setEditorView(mUI.getCardEditorView()); |
| 351 if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorVi
ew()); | 344 if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorVi
ew()); |
| 352 } | 345 } |
| 353 | 346 |
| 354 private static HashMap<String, JSONObject> getValidatedMethodData( | 347 private static Map<String, JSONObject> getValidatedMethodData( |
| 355 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector)
{ | 348 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector)
{ |
| 356 // Payment methodData are required. | 349 // Payment methodData are required. |
| 357 if (methodData == null || methodData.length == 0) return null; | 350 if (methodData == null || methodData.length == 0) return null; |
| 358 HashMap<String, JSONObject> result = new HashMap<>(); | 351 Map<String, JSONObject> result = new HashMap<>(); |
| 359 for (int i = 0; i < methodData.length; i++) { | 352 for (int i = 0; i < methodData.length; i++) { |
| 360 JSONObject data = null; | 353 JSONObject data = null; |
| 361 if (!TextUtils.isEmpty(methodData[i].stringifiedData)) { | 354 if (!TextUtils.isEmpty(methodData[i].stringifiedData)) { |
| 362 try { | 355 try { |
| 363 data = new JSONObject(JsonSanitizer.sanitize(methodData[i].s
tringifiedData)); | 356 data = new JSONObject(JsonSanitizer.sanitize(methodData[i].s
tringifiedData)); |
| 364 } catch (JSONException | IOException | IllegalStateException e)
{ | 357 } catch (JSONException | IOException | IllegalStateException e)
{ |
| 365 // Payment method specific data should be a JSON object. | 358 // Payment method specific data should be a JSON object. |
| 366 // According to the payment request spec[1], for each method
data, | 359 // According to the payment request spec[1], for each method
data, |
| 367 // if the data field is supplied but is not a JSON-serializa
ble object, | 360 // if the data field is supplied but is not a JSON-serializa
ble object, |
| 368 // then should throw a TypeError. So, we should return null
here even if | 361 // then should throw a TypeError. So, we should return null
here even if |
| (...skipping 19 matching lines...) Expand all Loading... |
| 388 return result; | 381 return result; |
| 389 } | 382 } |
| 390 | 383 |
| 391 /** | 384 /** |
| 392 * Queries the installed payment apps for their instruments that merchant su
pports. | 385 * Queries the installed payment apps for their instruments that merchant su
pports. |
| 393 * | 386 * |
| 394 * @return True if any of the requested payment methods are supported. | 387 * @return True if any of the requested payment methods are supported. |
| 395 */ | 388 */ |
| 396 private boolean getMatchingPaymentInstruments() { | 389 private boolean getMatchingPaymentInstruments() { |
| 397 mPendingApps = new ArrayList<>(mApps); | 390 mPendingApps = new ArrayList<>(mApps); |
| 398 mFirstCompletePendingInstrument = SectionInformation.NO_SELECTION; | |
| 399 mPendingInstruments = new ArrayList<>(); | 391 mPendingInstruments = new ArrayList<>(); |
| 392 mPendingAutofillInstruments = new ArrayList<>(); |
| 400 boolean arePaymentMethodsSupported = false; | 393 boolean arePaymentMethodsSupported = false; |
| 401 | 394 |
| 395 Map<PaymentApp, JSONObject> queryApps = new HashMap<>(); |
| 402 for (int i = 0; i < mApps.size(); i++) { | 396 for (int i = 0; i < mApps.size(); i++) { |
| 403 PaymentApp app = mApps.get(i); | 397 PaymentApp app = mApps.get(i); |
| 404 Set<String> appMethods = app.getSupportedMethodNames(); | 398 Set<String> appMethods = app.getSupportedMethodNames(); |
| 405 appMethods.retainAll(mMethodData.keySet()); | 399 appMethods.retainAll(mMethodData.keySet()); |
| 406 if (appMethods.isEmpty()) { | 400 if (appMethods.isEmpty()) { |
| 407 mPendingApps.remove(app); | 401 mPendingApps.remove(app); |
| 408 } else { | 402 } else { |
| 409 arePaymentMethodsSupported = true; | 403 arePaymentMethodsSupported = true; |
| 410 mMerchantSupportsAutofillPaymentInstruments = app instanceof Aut
ofillPaymentApp; | 404 mMerchantSupportsAutofillPaymentInstruments |= app instanceof Au
tofillPaymentApp; |
| 411 app.getInstruments(mMethodData.get(appMethods.iterator().next())
, this); | 405 queryApps.put(app, mMethodData.get(appMethods.iterator().next())
); |
| 412 } | 406 } |
| 413 } | 407 } |
| 414 | 408 |
| 409 // Query instruments after mMerchantSupportsAutofillPaymentInstruments h
as been initialized, |
| 410 // so a fast response from a non-autofill payment app at the front of th
e app list does not |
| 411 // cause NOT_SUPPORTED payment rejection. |
| 412 for (Map.Entry<PaymentApp, JSONObject> q : queryApps.entrySet()) { |
| 413 q.getKey().getInstruments(q.getValue(), this); |
| 414 } |
| 415 |
| 415 return arePaymentMethodsSupported; | 416 return arePaymentMethodsSupported; |
| 416 } | 417 } |
| 417 | 418 |
| 418 /** | 419 /** |
| 419 * Called by merchant to update the shipping options and line items after th
e user has selected | 420 * Called by merchant to update the shipping options and line items after th
e user has selected |
| 420 * their shipping address or shipping option. | 421 * their shipping address or shipping option. |
| 421 */ | 422 */ |
| 422 @Override | 423 @Override |
| 423 public void updateWith(PaymentDetails details) { | 424 public void updateWith(PaymentDetails details) { |
| 424 if (mClient == null) return; | 425 if (mClient == null) return; |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 closeUI(false); | 862 closeUI(false); |
| 862 } | 863 } |
| 863 | 864 |
| 864 /** | 865 /** |
| 865 * Called after retrieving the list of payment instruments in an app. | 866 * Called after retrieving the list of payment instruments in an app. |
| 866 */ | 867 */ |
| 867 @Override | 868 @Override |
| 868 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr
uments) { | 869 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr
uments) { |
| 869 mPendingApps.remove(app); | 870 mPendingApps.remove(app); |
| 870 | 871 |
| 872 // Place the instruments into either "autofill" or "non-autofill" list t
o be displayed when |
| 873 // all apps have responded. |
| 871 if (instruments != null) { | 874 if (instruments != null) { |
| 872 for (int i = 0; i < instruments.size(); i++) { | 875 for (int i = 0; i < instruments.size(); i++) { |
| 873 PaymentInstrument instrument = instruments.get(i); | 876 PaymentInstrument instrument = instruments.get(i); |
| 874 if (mMethodData.containsKey(instrument.getMethodName())) { | 877 if (mMethodData.containsKey(instrument.getMethodName())) { |
| 875 checkForCompletePaymentInstrument(instrument, mPendingInstru
ments.size()); | 878 addPendingInstrument(instrument); |
| 876 mPendingInstruments.add(instrument); | |
| 877 } else { | 879 } else { |
| 878 instrument.dismiss(); | 880 instrument.dismiss(); |
| 879 } | 881 } |
| 880 } | 882 } |
| 881 } | 883 } |
| 882 | 884 |
| 883 // Some payment apps still have not responded. Continue waiting for them
. | 885 // Some payment apps still have not responded. Continue waiting for them
. |
| 884 if (!mPendingApps.isEmpty()) return; | 886 if (!mPendingApps.isEmpty()) return; |
| 885 | 887 |
| 886 if (mPendingInstruments.isEmpty() && !mMerchantSupportsAutofillPaymentIn
struments) { | 888 if (mPendingInstruments.isEmpty() && !mMerchantSupportsAutofillPaymentIn
struments) { |
| 887 // All payment apps have responded, but none of them have instrument
s. It's possible to | 889 // All payment apps have responded, but none of them have instrument
s. It's possible to |
| 888 // add credit cards, but the merchant does not support them either.
The payment request | 890 // add credit cards, but the merchant does not support them either.
The payment request |
| 889 // must be rejected. | 891 // must be rejected. |
| 890 disconnectFromClientWithDebugMessage("Requested payment methods have
no instruments", | 892 disconnectFromClientWithDebugMessage("Requested payment methods have
no instruments", |
| 891 PaymentErrorReason.NOT_SUPPORTED); | 893 PaymentErrorReason.NOT_SUPPORTED); |
| 892 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi
ceShowFailed(); | 894 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi
ceShowFailed(); |
| 893 return; | 895 return; |
| 894 } | 896 } |
| 895 | 897 |
| 898 // List order: |
| 899 // > Non-autofill instruments. |
| 900 // > Complete autofill instruments. |
| 901 // > Incomplete autofill instruments. |
| 902 Collections.sort(mPendingAutofillInstruments, COMPLETENESS_COMPARATOR); |
| 903 mPendingInstruments.addAll(mPendingAutofillInstruments); |
| 904 |
| 905 mPendingAutofillInstruments.clear(); |
| 906 mPendingAutofillInstruments = null; |
| 907 |
| 908 // Pre-select the first instrument on the list, if it is complete. |
| 909 int selection = SectionInformation.NO_SELECTION; |
| 910 if (!mPendingInstruments.isEmpty()) { |
| 911 PaymentInstrument first = mPendingInstruments.get(0); |
| 912 if (!(first instanceof AutofillPaymentInstrument) |
| 913 || ((AutofillPaymentInstrument) first).isComplete()) { |
| 914 selection = 0; |
| 915 } |
| 916 } |
| 917 |
| 896 // The list of payment instruments is ready to display. | 918 // The list of payment instruments is ready to display. |
| 897 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PA
YMENT_METHODS, | 919 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PA
YMENT_METHODS, |
| 898 mFirstCompletePendingInstrument, mPendingInstruments); | 920 selection, mPendingInstruments); |
| 921 |
| 899 mPendingInstruments.clear(); | 922 mPendingInstruments.clear(); |
| 923 mPendingInstruments = null; |
| 900 | 924 |
| 901 // UI has requested the full list of payment instruments. Provide it now
. | 925 // UI has requested the full list of payment instruments. Provide it now
. |
| 902 if (mPaymentInformationCallback != null) providePaymentInformation(); | 926 if (mPaymentInformationCallback != null) providePaymentInformation(); |
| 903 } | 927 } |
| 904 | 928 |
| 905 private void checkForCompletePaymentInstrument(PaymentInstrument instrument,
int index) { | 929 /** |
| 906 boolean isComplete = true; | 930 * Saves the given instrument in either "autofill" or "non-autofill" list. T
he separation |
| 931 * enables placing autofill instruments on the bottom of the list. |
| 932 * |
| 933 * Autofill instruments are also checked for completeness. A complete autofi
ll instrument can be |
| 934 * sent to the merchant as-is, without editing first. Such instruments shoul
d be displayed |
| 935 * higher in the list. |
| 936 * |
| 937 * @param instrument The instrument to add to either "autofill" or "non-auto
fill" list. |
| 938 */ |
| 939 private void addPendingInstrument(PaymentInstrument instrument) { |
| 907 if (instrument instanceof AutofillPaymentInstrument) { | 940 if (instrument instanceof AutofillPaymentInstrument) { |
| 908 AutofillPaymentInstrument autofillInstrument = (AutofillPaymentInstr
ument) instrument; | 941 AutofillPaymentInstrument autofillInstrument = (AutofillPaymentInstr
ument) instrument; |
| 909 isComplete = mCardEditor.isCardComplete(autofillInstrument.getCard()
); | 942 if (mCardEditor.isCardComplete(autofillInstrument.getCard())) { |
| 910 if (isComplete) autofillInstrument.setIsComplete(); | 943 autofillInstrument.setIsComplete(); |
| 911 } | 944 } |
| 912 | 945 mPendingAutofillInstruments.add(instrument); |
| 913 if (isComplete && mFirstCompletePendingInstrument == SectionInformation.
NO_SELECTION) { | 946 } else { |
| 914 mFirstCompletePendingInstrument = index; | 947 mPendingInstruments.add(instrument); |
| 915 } | 948 } |
| 916 } | 949 } |
| 917 | 950 |
| 918 /** | 951 /** |
| 919 * Called after retrieving instrument details. | 952 * Called after retrieving instrument details. |
| 920 */ | 953 */ |
| 921 @Override | 954 @Override |
| 922 public void onInstrumentDetailsReady(String methodName, String stringifiedDe
tails) { | 955 public void onInstrumentDetailsReady(String methodName, String stringifiedDe
tails) { |
| 923 PaymentResponse response = new PaymentResponse(); | 956 PaymentResponse response = new PaymentResponse(); |
| 924 response.methodName = methodName; | 957 response.methodName = methodName; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 private void closeClient() { | 1038 private void closeClient() { |
| 1006 if (mClient != null) mClient.close(); | 1039 if (mClient != null) mClient.close(); |
| 1007 mClient = null; | 1040 mClient = null; |
| 1008 } | 1041 } |
| 1009 | 1042 |
| 1010 @VisibleForTesting | 1043 @VisibleForTesting |
| 1011 public static void setObserverForTest(PaymentRequestServiceObserverForTest o
bserverForTest) { | 1044 public static void setObserverForTest(PaymentRequestServiceObserverForTest o
bserverForTest) { |
| 1012 sObserverForTest = observerForTest; | 1045 sObserverForTest = observerForTest; |
| 1013 } | 1046 } |
| 1014 } | 1047 } |
| OLD | NEW |