Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java

Issue 2549313002: Show additional display items when instruments change. (Closed)
Patch Set: Reformat #2 Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/payments/ui/ShoppingCart.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.support.v4.util.ArrayMap; 10 import android.support.v4.util.ArrayMap;
(...skipping 24 matching lines...) Expand all
35 import org.chromium.chrome.browser.tabmodel.TabModel; 35 import org.chromium.chrome.browser.tabmodel.TabModel;
36 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; 36 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
37 import org.chromium.chrome.browser.tabmodel.TabModelObserver; 37 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
38 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; 38 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
39 import org.chromium.components.url_formatter.UrlFormatter; 39 import org.chromium.components.url_formatter.UrlFormatter;
40 import org.chromium.content_public.browser.WebContents; 40 import org.chromium.content_public.browser.WebContents;
41 import org.chromium.mojo.system.MojoException; 41 import org.chromium.mojo.system.MojoException;
42 import org.chromium.payments.mojom.CanMakePaymentQueryResult; 42 import org.chromium.payments.mojom.CanMakePaymentQueryResult;
43 import org.chromium.payments.mojom.PaymentComplete; 43 import org.chromium.payments.mojom.PaymentComplete;
44 import org.chromium.payments.mojom.PaymentDetails; 44 import org.chromium.payments.mojom.PaymentDetails;
45 import org.chromium.payments.mojom.PaymentDetailsModifier;
45 import org.chromium.payments.mojom.PaymentErrorReason; 46 import org.chromium.payments.mojom.PaymentErrorReason;
46 import org.chromium.payments.mojom.PaymentItem; 47 import org.chromium.payments.mojom.PaymentItem;
47 import org.chromium.payments.mojom.PaymentMethodData; 48 import org.chromium.payments.mojom.PaymentMethodData;
48 import org.chromium.payments.mojom.PaymentOptions; 49 import org.chromium.payments.mojom.PaymentOptions;
49 import org.chromium.payments.mojom.PaymentRequest; 50 import org.chromium.payments.mojom.PaymentRequest;
50 import org.chromium.payments.mojom.PaymentRequestClient; 51 import org.chromium.payments.mojom.PaymentRequestClient;
51 import org.chromium.payments.mojom.PaymentResponse; 52 import org.chromium.payments.mojom.PaymentResponse;
52 import org.chromium.payments.mojom.PaymentShippingOption; 53 import org.chromium.payments.mojom.PaymentShippingOption;
53 import org.chromium.payments.mojom.PaymentShippingType; 54 import org.chromium.payments.mojom.PaymentShippingType;
54 55
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 */ 216 */
216 private PaymentItem mRawTotal; 217 private PaymentItem mRawTotal;
217 218
218 /** 219 /**
219 * The raw items in the shopping cart, as they were received from the websit e. This data is 220 * The raw items in the shopping cart, as they were received from the websit e. This data is
220 * passed to the payment app. 221 * passed to the payment app.
221 */ 222 */
222 private List<PaymentItem> mRawLineItems; 223 private List<PaymentItem> mRawLineItems;
223 224
224 /** 225 /**
225 * A mapping from method names to modified totals. Used to display modified totals for each 226 * A mapping from method names to modifiers, which include modified totals a nd additional line
226 * payment instrument. 227 * items. Used to display modified totals for each payment instrument, modif ied total in order
228 * summary, and additional line items in order summary.
227 */ 229 */
228 private Map<String, PaymentItem> mModifiedTotals; 230 private Map<String, PaymentDetailsModifier> mModifiers;
229 231
230 /** 232 /**
231 * The UI model of the shopping cart, including the total. Each item include s a label and a 233 * The UI model of the shopping cart, including the total. Each item include s a label and a
232 * price string. This data is passed to the UI. 234 * price string. This data is passed to the UI.
233 */ 235 */
234 private ShoppingCart mUiShoppingCart; 236 private ShoppingCart mUiShoppingCart;
235 237
236 /** 238 /**
237 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping 239 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping
238 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI. 240 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; 385 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION;
384 if (mUiShippingOptions.getSelectedItem() != null && !addresses.isEmp ty() 386 if (mUiShippingOptions.getSelectedItem() != null && !addresses.isEmp ty()
385 && addresses.get(0).isComplete()) { 387 && addresses.get(0).isComplete()) {
386 firstCompleteAddressIndex = 0; 388 firstCompleteAddressIndex = 0;
387 389
388 // The initial label for the selected shipping address should no t include the 390 // The initial label for the selected shipping address should no t include the
389 // country. 391 // country.
390 addresses.get(firstCompleteAddressIndex).setShippingAddressLabel WithoutCountry(); 392 addresses.get(firstCompleteAddressIndex).setShippingAddressLabel WithoutCountry();
391 } 393 }
392 394
393 mShippingAddressesSection = 395 mShippingAddressesSection = new SectionInformation(
394 new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_ADDRES SES, 396 PaymentRequestUI.TYPE_SHIPPING_ADDRESSES,
395 firstCompleteAddressIndex, addresses); 397 firstCompleteAddressIndex, addresses);
396 } 398 }
397 399
398 if (requestPayerName || requestPayerPhone || requestPayerEmail) { 400 if (requestPayerName || requestPayerPhone || requestPayerEmail) {
399 Set<String> uniqueContactInfos = new HashSet<>(); 401 Set<String> uniqueContactInfos = new HashSet<>();
400 mContactEditor = new ContactEditor( 402 mContactEditor = new ContactEditor(
401 requestPayerName, requestPayerPhone, requestPayerEmail); 403 requestPayerName, requestPayerPhone, requestPayerEmail);
402 List<AutofillContact> contacts = new ArrayList<>(); 404 List<AutofillContact> contacts = new ArrayList<>();
403 405
404 for (int i = 0; i < profiles.size(); i++) { 406 for (int i = 0; i < profiles.size(); i++) {
405 AutofillProfile profile = profiles.get(i); 407 AutofillProfile profile = profiles.get(i);
406 String name = requestPayerName && !TextUtils.isEmpty(profile.get FullName()) 408 String name = requestPayerName && !TextUtils.isEmpty(profile.get FullName())
407 ? profile.getFullName() : null; 409 ? profile.getFullName() : null;
408 String phone = requestPayerPhone && !TextUtils.isEmpty(profile.g etPhoneNumber()) 410 String phone = requestPayerPhone && !TextUtils.isEmpty(profile.g etPhoneNumber())
409 ? profile.getPhoneNumber() : null; 411 ? profile.getPhoneNumber() : null;
410 String email = requestPayerEmail && !TextUtils.isEmpty(profile.g etEmailAddress()) 412 String email = requestPayerEmail && !TextUtils.isEmpty(profile.g etEmailAddress())
411 ? profile.getEmailAddress() : null; 413 ? profile.getEmailAddress() : null;
412 mContactEditor.addPayerNameIfValid(name); 414 mContactEditor.addPayerNameIfValid(name);
413 mContactEditor.addPhoneNumberIfValid(phone); 415 mContactEditor.addPhoneNumberIfValid(phone);
414 mContactEditor.addEmailAddressIfValid(email); 416 mContactEditor.addEmailAddressIfValid(email);
415 417
416 if (name != null || phone != null || email != null) { 418 if (name != null || phone != null || email != null) {
417 // Different profiles can have identical contact info. Do no t add the same 419 // Different profiles can have identical contact info. Do no t add the same
418 // contact info to the list twice. 420 // contact info to the list twice.
419 String uniqueContactInfo = name + phone + email; 421 String uniqueContactInfo = name + phone + email;
420 if (!uniqueContactInfos.contains(uniqueContactInfo)) { 422 if (!uniqueContactInfos.contains(uniqueContactInfo)) {
421 uniqueContactInfos.add(uniqueContactInfo); 423 uniqueContactInfos.add(uniqueContactInfo);
422 424
423 boolean isComplete = 425 boolean isComplete = mContactEditor.isContactInformation Complete(name,
424 mContactEditor.isContactInformationComplete(name , phone, email); 426 phone, email);
425 contacts.add(new AutofillContact(profile, name, phone, e mail, isComplete)); 427 contacts.add(new AutofillContact(profile, name, phone, e mail, isComplete));
426 } 428 }
427 } 429 }
428 } 430 }
429 431
430 // Suggest complete contact infos first. 432 // Suggest complete contact infos first.
431 Collections.sort(contacts, COMPLETENESS_COMPARATOR); 433 Collections.sort(contacts, COMPLETENESS_COMPARATOR);
432 434
433 // Limit the number of suggestions. 435 // Limit the number of suggestions.
434 contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS _LIMIT)); 436 contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS _LIMIT));
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 if (getIsShowing()) { 479 if (getIsShowing()) {
478 disconnectFromClientWithDebugMessage("A PaymentRequest UI is already showing"); 480 disconnectFromClientWithDebugMessage("A PaymentRequest UI is already showing");
479 recordAbortReasonHistogram( 481 recordAbortReasonHistogram(
480 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE R); 482 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE R);
481 return; 483 return;
482 } 484 }
483 485
484 setIsShowing(true); 486 setIsShowing(true);
485 if (disconnectIfNoPaymentMethodsSupported()) return; 487 if (disconnectIfNoPaymentMethodsSupported()) return;
486 488
487 // Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be 489 // Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be
488 // allowed to switch tabs, which can happen if the user receives an exte rnal Intent. 490 // allowed to switch tabs, which can happen if the user receives an exte rnal Intent.
489 mContext.getTabModelSelector().addObserver(mSelectorObserver); 491 mContext.getTabModelSelector().addObserver(mSelectorObserver);
490 mContext.getCurrentTabModel().addObserver(mTabModelObserver); 492 mContext.getCurrentTabModel().addObserver(mTabModelObserver);
491 493
492 mUI.show(); 494 mUI.show();
493 recordSuccessFunnelHistograms("Shown"); 495 recordSuccessFunnelHistograms("Shown");
494 } 496 }
495 497
496 private static Map<String, PaymentMethodData> getValidatedMethodData( 498 private static Map<String, PaymentMethodData> getValidatedMethodData(
497 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) { 499 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) {
(...skipping 19 matching lines...) Expand all
517 519
518 /** Queries the installed payment apps for their instruments that merchant s upports. */ 520 /** Queries the installed payment apps for their instruments that merchant s upports. */
519 private void getMatchingPaymentInstruments() { 521 private void getMatchingPaymentInstruments() {
520 mPendingApps = new ArrayList<>(mApps); 522 mPendingApps = new ArrayList<>(mApps);
521 mPendingInstruments = new ArrayList<>(); 523 mPendingInstruments = new ArrayList<>();
522 mPendingAutofillInstruments = new ArrayList<>(); 524 mPendingAutofillInstruments = new ArrayList<>();
523 525
524 Map<PaymentApp, Map<String, PaymentMethodData>> queryApps = new ArrayMap <>(); 526 Map<PaymentApp, Map<String, PaymentMethodData>> queryApps = new ArrayMap <>();
525 for (int i = 0; i < mApps.size(); i++) { 527 for (int i = 0; i < mApps.size(); i++) {
526 PaymentApp app = mApps.get(i); 528 PaymentApp app = mApps.get(i);
527 Map<String, PaymentMethodData> appMethods = 529 Map<String, PaymentMethodData> appMethods = filterMerchantMethodData (mMethodData,
528 filterMerchantMethodData(mMethodData, app.getAppMethodNames( )); 530 app.getAppMethodNames());
529 if (appMethods == null || !app.supportsMethodsAndData(appMethods)) { 531 if (appMethods == null || !app.supportsMethodsAndData(appMethods)) {
530 mPendingApps.remove(app); 532 mPendingApps.remove(app);
531 } else { 533 } else {
532 mArePaymentMethodsSupported = true; 534 mArePaymentMethodsSupported = true;
533 mMerchantSupportsAutofillPaymentInstruments |= app instanceof Au tofillPaymentApp; 535 mMerchantSupportsAutofillPaymentInstruments |= app instanceof Au tofillPaymentApp;
534 queryApps.put(app, appMethods); 536 queryApps.put(app, appMethods);
535 } 537 }
536 } 538 }
537 539
538 // Query instruments after mMerchantSupportsAutofillPaymentInstruments h as been initialized, 540 // Query instruments after mMerchantSupportsAutofillPaymentInstruments h as been initialized,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 * @return True if the data is valid. False if the data is invalid. 600 * @return True if the data is valid. False if the data is invalid.
599 */ 601 */
600 private boolean parseAndValidateDetailsOrDisconnectFromClient(PaymentDetails details) { 602 private boolean parseAndValidateDetailsOrDisconnectFromClient(PaymentDetails details) {
601 if (!PaymentValidator.validatePaymentDetails(details)) { 603 if (!PaymentValidator.validatePaymentDetails(details)) {
602 disconnectFromClientWithDebugMessage("Invalid payment details"); 604 disconnectFromClientWithDebugMessage("Invalid payment details");
603 recordAbortReasonHistogram( 605 recordAbortReasonHistogram(
604 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE R); 606 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE R);
605 return false; 607 return false;
606 } 608 }
607 609
608 String totalCurrency = details.total.amount.currency;
609 if (mFormatter == null) { 610 if (mFormatter == null) {
610 mFormatter = new CurrencyStringFormatter(totalCurrency, Locale.getDe fault()); 611 mFormatter = new CurrencyStringFormatter(details.total.amount.curren cy,
612 Locale.getDefault());
611 } 613 }
612 614
613 // Total is never pending. 615 // Total is never pending.
614 LineItem uiTotal = new LineItem( 616 LineItem uiTotal = new LineItem(
615 details.total.label, mFormatter.getFormattedCurrencyCode(), 617 details.total.label, mFormatter.getFormattedCurrencyCode(),
616 mFormatter.format(details.total.amount.value), /* isPending */ f alse); 618 mFormatter.format(details.total.amount.value), /* isPending */ f alse);
617 619
618 List<LineItem> uiLineItems = getLineItems(details.displayItems, totalCur rency, mFormatter); 620 List<LineItem> uiLineItems = getLineItems(details.displayItems, mFormatt er);
619 621
620 mUiShoppingCart = new ShoppingCart(uiTotal, uiLineItems); 622 mUiShoppingCart = new ShoppingCart(uiTotal, uiLineItems);
621 mRawTotal = details.total; 623 mRawTotal = details.total;
622 mRawLineItems = Collections.unmodifiableList(Arrays.asList(details.displ ayItems)); 624 mRawLineItems = Collections.unmodifiableList(Arrays.asList(details.displ ayItems));
623 625
624 mUiShippingOptions = getShippingOptions(details.shippingOptions, totalCu rrency, mFormatter); 626 mUiShippingOptions = getShippingOptions(details.shippingOptions, mFormat ter);
625 627
626 for (int i = 0; i < details.modifiers.length; i++) { 628 for (int i = 0; i < details.modifiers.length; i++) {
627 PaymentItem total = details.modifiers[i].total; 629 PaymentDetailsModifier modifier = details.modifiers[i];
628 String[] methods = details.modifiers[i].methodData.supportedMethods; 630 String[] methods = modifier.methodData.supportedMethods;
629 if (total != null) { 631 for (int j = 0; j < methods.length; j++) {
630 for (int j = 0; j < methods.length; j++) { 632 if (mModifiers == null) mModifiers = new ArrayMap<>();
631 if (mModifiedTotals == null) mModifiedTotals = new ArrayMap< >(); 633 mModifiers.put(methods[j], modifier);
632 mModifiedTotals.put(methods[j], total);
633 }
634 } 634 }
635 } 635 }
636 636
637 updateInstrumentModifiedTotals(); 637 updateInstrumentModifiedTotals();
638 638
639 return true; 639 return true;
640 } 640 }
641 641
642 /** Updates the modified totals for payment instruments. */ 642 /** Updates the modifiers for payment instruments and order summary. */
643 private void updateInstrumentModifiedTotals() { 643 private void updateInstrumentModifiedTotals() {
644 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER S)) return; 644 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER S)) return;
645 if (mModifiedTotals == null) return; 645 if (mModifiers == null) return;
646 if (mPaymentMethodsSection == null) return; 646 if (mPaymentMethodsSection == null) return;
647 647
648 for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) { 648 for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) {
649 PaymentInstrument instrument = (PaymentInstrument) mPaymentMethodsSe ction.getItem(i); 649 PaymentInstrument instrument = (PaymentInstrument) mPaymentMethodsSe ction.getItem(i);
650 PaymentItem modifiedTotal = getModifiedTotal(instrument); 650 PaymentDetailsModifier modifier = getModifier(instrument);
651 instrument.setModifiedTotal( 651 instrument.setModifiedTotal(modifier == null || modifier.total == nu ll ? null
652 modifiedTotal == null ? null : mFormatter.format(modifiedTot al.amount.value)); 652 : mFormatter.format(modifier.total.amount.value));
653 } 653 }
654 654
655 updateOrderSummaryTotal((PaymentInstrument) mPaymentMethodsSection.getSe lectedItem()); 655 updateOrderSummary((PaymentInstrument) mPaymentMethodsSection.getSelecte dItem());
656 } 656 }
657 657
658 private void updateOrderSummaryTotal(@Nullable PaymentInstrument instrument) { 658 /** Sets the modifier for the order summary based on the given instrument, i f any. */
659 private void updateOrderSummary(@Nullable PaymentInstrument instrument) {
659 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER S)) return; 660 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER S)) return;
660 661
661 PaymentItem total = getModifiedTotal(instrument); 662 PaymentDetailsModifier modifier = getModifier(instrument);
663 PaymentItem total = modifier == null ? null : modifier.total;
662 if (total == null) total = mRawTotal; 664 if (total == null) total = mRawTotal;
663 665
664 mUiShoppingCart.setTotal(new LineItem(total.label, mFormatter.getFormatt edCurrencyCode(), 666 mUiShoppingCart.setTotal(new LineItem(total.label, mFormatter.getFormatt edCurrencyCode(),
665 mFormatter.format(total.amount.value), false /* isPending */)); 667 mFormatter.format(total.amount.value), false /* isPending */));
668 mUiShoppingCart.setAdditionalContents(modifier == null ? null
669 : getLineItems(modifier.additionalDisplayItems, mFormatter));
666 mUI.updateOrderSummarySection(mUiShoppingCart); 670 mUI.updateOrderSummarySection(mUiShoppingCart);
667 } 671 }
668 672
669 @Nullable private PaymentItem getModifiedTotal(@Nullable PaymentInstrument i nstrument) { 673 /** @return The first modifier that matches the given instrument, or null. * /
674 @Nullable private PaymentDetailsModifier getModifier(@Nullable PaymentInstru ment instrument) {
670 if (instrument == null) return null; 675 if (instrument == null) return null;
671 Set<String> methodNames = instrument.getInstrumentMethodNames(); 676 Set<String> methodNames = instrument.getInstrumentMethodNames();
672 methodNames.retainAll(mModifiedTotals.keySet()); 677 methodNames.retainAll(mModifiers.keySet());
673 return methodNames.isEmpty() ? null : mModifiedTotals.get(methodNames.it erator().next()); 678 return methodNames.isEmpty() ? null : mModifiers.get(methodNames.iterato r().next());
674 }
675
676 /**
677 * Returns true if all fields in the payment item are non-null and non-empty .
678 *
679 * @param item The payment item to examine.
680 * @return True if all fields are present and non-empty.
681 */
682 private static boolean hasAllPaymentItemFields(PaymentItem item) {
683 // "label", "currency", and "value" should be non-empty.
684 return item != null && !TextUtils.isEmpty(item.label) && item.amount != null
685 && !TextUtils.isEmpty(item.amount.currency)
686 && !TextUtils.isEmpty(item.amount.value);
687 } 679 }
688 680
689 /** 681 /**
690 * Converts a list of payment items and returns their parsed representation. 682 * Converts a list of payment items and returns their parsed representation.
691 * 683 *
692 * @param items The payment items to parse and validate. 684 * @param items The payment items to parse. Can be null.
693 * @param totalCurrency The currency code for the total amount of payment. 685 * @param formatter A formatter for the currency amount value.
694 * @param formatter A formatter and validator for the currency amount value.
695 * @return A list of valid line items. 686 * @return A list of valid line items.
696 */ 687 */
697 private static List<LineItem> getLineItems( 688 private static List<LineItem> getLineItems(
698 PaymentItem[] items, String totalCurrency, CurrencyStringFormatter f ormatter) { 689 @Nullable PaymentItem[] items, CurrencyStringFormatter formatter) {
699 // Line items are optional. 690 // Line items are optional.
700 if (items == null) return new ArrayList<>(); 691 if (items == null) return new ArrayList<>();
701 692
702 List<LineItem> result = new ArrayList<>(items.length); 693 List<LineItem> result = new ArrayList<>(items.length);
703 for (int i = 0; i < items.length; i++) { 694 for (int i = 0; i < items.length; i++) {
704 PaymentItem item = items[i]; 695 PaymentItem item = items[i];
705 696
706 result.add(new LineItem( 697 result.add(new LineItem(
707 item.label, "", formatter.format(item.amount.value), item.pe nding)); 698 item.label, "", formatter.format(item.amount.value), item.pe nding));
708 } 699 }
709 700
710 return Collections.unmodifiableList(result); 701 return Collections.unmodifiableList(result);
711 } 702 }
712 703
713 /** 704 /**
714 * Converts a list of shipping options and returns their parsed representati on. 705 * Converts a list of shipping options and returns their parsed representati on.
715 * 706 *
716 * @param options The raw shipping options to parse and validate. 707 * @param options The raw shipping options to parse. Can be null.
717 * @param totalCurrency The currency code for the total amount of payment. 708 * @param formatter A formatter for the currency amount value.
718 * @param formatter A formatter and validator for the currency amount value.
719 * @return The UI representation of the shipping options. 709 * @return The UI representation of the shipping options.
720 */ 710 */
721 private static SectionInformation getShippingOptions(PaymentShippingOption[] options, 711 private static SectionInformation getShippingOptions(
722 String totalCurrency, CurrencyStringFormatter formatter) { 712 @Nullable PaymentShippingOption[] options, CurrencyStringFormatter f ormatter) {
723 // Shipping options are optional. 713 // Shipping options are optional.
724 if (options == null || options.length == 0) { 714 if (options == null || options.length == 0) {
725 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS ); 715 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS );
726 } 716 }
727 717
728 List<PaymentOption> result = new ArrayList<>(); 718 List<PaymentOption> result = new ArrayList<>();
729 int selectedItemIndex = SectionInformation.NO_SELECTION; 719 int selectedItemIndex = SectionInformation.NO_SELECTION;
730 for (int i = 0; i < options.length; i++) { 720 for (int i = 0; i < options.length; i++) {
731 PaymentShippingOption option = options[i]; 721 PaymentShippingOption option = options[i];
732 result.add(new PaymentOption(option.id, option.label, 722 result.add(new PaymentOption(option.id, option.label,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 mJourneyLogger.incrementSelectionChanges( 827 mJourneyLogger.incrementSelectionChanges(
838 PaymentRequestJourneyLogger.SECTION_CREDIT_CARDS); 828 PaymentRequestJourneyLogger.SECTION_CREDIT_CARDS);
839 AutofillPaymentInstrument card = (AutofillPaymentInstrument) opt ion; 829 AutofillPaymentInstrument card = (AutofillPaymentInstrument) opt ion;
840 830
841 if (!card.isComplete()) { 831 if (!card.isComplete()) {
842 editCard(card); 832 editCard(card);
843 return PaymentRequestUI.SELECTION_RESULT_EDITOR_LAUNCH; 833 return PaymentRequestUI.SELECTION_RESULT_EDITOR_LAUNCH;
844 } 834 }
845 } 835 }
846 836
847 updateOrderSummaryTotal((PaymentInstrument) option); 837 updateOrderSummary((PaymentInstrument) option);
848 mPaymentMethodsSection.setSelectedItem(option); 838 mPaymentMethodsSection.setSelectedItem(option);
849 } 839 }
850 840
851 return PaymentRequestUI.SELECTION_RESULT_NONE; 841 return PaymentRequestUI.SELECTION_RESULT_NONE;
852 } 842 }
853 843
854 @Override 844 @Override
855 @PaymentRequestUI.SelectionResult 845 @PaymentRequestUI.SelectionResult
856 public int onSectionEditOption(@PaymentRequestUI.DataType int optionType, Pa ymentOption option, 846 public int onSectionEditOption(@PaymentRequestUI.DataType int optionType, Pa ymentOption option,
857 Callback<PaymentInformation> callback) { 847 Callback<PaymentInformation> callback) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 mPaymentResponseHelper.onInstrumentsDetailsLoading(); 973 mPaymentResponseHelper.onInstrumentsDetailsLoading();
984 } 974 }
985 975
986 @Override 976 @Override
987 public boolean onPayClicked(PaymentOption selectedShippingAddress, 977 public boolean onPayClicked(PaymentOption selectedShippingAddress,
988 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) { 978 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) {
989 assert selectedPaymentMethod instanceof PaymentInstrument; 979 assert selectedPaymentMethod instanceof PaymentInstrument;
990 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ; 980 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ;
991 mPaymentAppRunning = true; 981 mPaymentAppRunning = true;
992 982
993 PaymentOption selectedContact = 983 PaymentOption selectedContact = mContactSection != null ? mContactSectio n.getSelectedItem()
994 mContactSection != null ? mContactSection.getSelectedItem() : nu ll; 984 : null;
995 mPaymentResponseHelper = new PaymentResponseHelper( 985 mPaymentResponseHelper = new PaymentResponseHelper(
996 selectedShippingAddress, selectedShippingOption, selectedContact , this); 986 selectedShippingAddress, selectedShippingOption, selectedContact , this);
997 987
998 // Create a map that is the subset of mMethodData that contains the 988 // Create a map that is the subset of mMethodData that contains the
999 // payment methods supported by the selected payment instrument. If this 989 // payment methods supported by the selected payment instrument. If this
1000 // intersection contains more than one payment method, the payment app i s 990 // intersection contains more than one payment method, the payment app i s
1001 // at liberty to choose (or have the user choose) one of the methods. 991 // at liberty to choose (or have the user choose) one of the methods.
1002 Map<String, PaymentMethodData> methodData = new HashMap<>(); 992 Map<String, PaymentMethodData> methodData = new HashMap<>();
1003 for (String instrumentMethodName : instrument.getInstrumentMethodNames() ) { 993 for (String instrumentMethodName : instrument.getInstrumentMethodNames() ) {
1004 if (mMethodData.containsKey(instrumentMethodName)) { 994 if (mMethodData.containsKey(instrumentMethodName)) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 } 1078 }
1089 1079
1090 query.addObserver(this); 1080 query.addObserver(this);
1091 if (mPendingApps.isEmpty() && mPendingInstruments.isEmpty()) { 1081 if (mPendingApps.isEmpty() && mPendingInstruments.isEmpty()) {
1092 query.setResponse(mPaymentMethodsSection != null 1082 query.setResponse(mPaymentMethodsSection != null
1093 && mPaymentMethodsSection.getSelectedItem() != null); 1083 && mPaymentMethodsSection.getSelectedItem() != null);
1094 } 1084 }
1095 } 1085 }
1096 1086
1097 private void respondCanMakePaymentQuery(boolean response) { 1087 private void respondCanMakePaymentQuery(boolean response) {
1098 mClient.onCanMakePayment(response 1088 mClient.onCanMakePayment(response ? CanMakePaymentQueryResult.CAN_MAKE_P AYMENT
1099 ? CanMakePaymentQueryResult.CAN_MAKE_PAYMENT 1089 : CanMakePaymentQueryResult.CANNOT_MAKE_PAYMENT);
1100 : CanMakePaymentQueryResult.CANNOT_MAKE_PAYMENT);
1101 if (sObserverForTest != null) { 1090 if (sObserverForTest != null) {
1102 sObserverForTest.onPaymentRequestServiceCanMakePaymentQueryResponded (); 1091 sObserverForTest.onPaymentRequestServiceCanMakePaymentQueryResponded ();
1103 } 1092 }
1104 } 1093 }
1105 1094
1106 /** 1095 /**
1107 * Called when the renderer closes the Mojo connection. 1096 * Called when the renderer closes the Mojo connection.
1108 */ 1097 */
1109 @Override 1098 @Override
1110 public void close() { 1099 public void close() {
(...skipping 20 matching lines...) Expand all
1131 @Override 1120 @Override
1132 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) { 1121 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) {
1133 if (mClient == null) return; 1122 if (mClient == null) return;
1134 mPendingApps.remove(app); 1123 mPendingApps.remove(app);
1135 1124
1136 // Place the instruments into either "autofill" or "non-autofill" list t o be displayed when 1125 // Place the instruments into either "autofill" or "non-autofill" list t o be displayed when
1137 // all apps have responded. 1126 // all apps have responded.
1138 if (instruments != null) { 1127 if (instruments != null) {
1139 for (int i = 0; i < instruments.size(); i++) { 1128 for (int i = 0; i < instruments.size(); i++) {
1140 PaymentInstrument instrument = instruments.get(i); 1129 PaymentInstrument instrument = instruments.get(i);
1141 Set<String> instrumentMethodNames = 1130 Set<String> instrumentMethodNames = new HashSet<>(
1142 new HashSet<>(instrument.getInstrumentMethodNames()); 1131 instrument.getInstrumentMethodNames());
1143 instrumentMethodNames.retainAll(mMethodData.keySet()); 1132 instrumentMethodNames.retainAll(mMethodData.keySet());
1144 if (!instrumentMethodNames.isEmpty()) { 1133 if (!instrumentMethodNames.isEmpty()) {
1145 addPendingInstrument(instrument); 1134 addPendingInstrument(instrument);
1146 } else { 1135 } else {
1147 instrument.dismissInstrument(); 1136 instrument.dismissInstrument();
1148 } 1137 }
1149 } 1138 }
1150 } 1139 }
1151 1140
1152 // Some payment apps still have not responded. Continue waiting for them . 1141 // Some payment apps still have not responded. Continue waiting for them .
1153 if (!mPendingApps.isEmpty()) return; 1142 if (!mPendingApps.isEmpty()) return;
1154 1143
1155 if (disconnectIfNoPaymentMethodsSupported()) return; 1144 if (disconnectIfNoPaymentMethodsSupported()) return;
1156 1145
1157 // Load the validation rules for each unique region code in the credit c ard billing 1146 // Load the validation rules for each unique region code in the credit c ard billing
1158 // addresses. 1147 // addresses.
1159 Set<String> uniqueCountryCodes = new HashSet<>(); 1148 Set<String> uniqueCountryCodes = new HashSet<>();
1160 for (int i = 0; i < mPendingAutofillInstruments.size(); ++i) { 1149 for (int i = 0; i < mPendingAutofillInstruments.size(); ++i) {
1161 assert mPendingAutofillInstruments.get(i) instanceof AutofillPayment Instrument; 1150 assert mPendingAutofillInstruments.get(i) instanceof AutofillPayment Instrument;
1162 1151
1163 String countryCode = AutofillAddress.getCountryCode(( 1152 String countryCode = AutofillAddress
1164 (AutofillPaymentInstrument) mPendingAutofillInstruments.get( 1153 .getCountryCode(((AutofillPaymentInstrument) mPendingAutofil lInstruments.get(
1165 i)).getBillingAddress()); 1154 i)).getBillingAddress());
1166 if (!uniqueCountryCodes.contains(countryCode)) { 1155 if (!uniqueCountryCodes.contains(countryCode)) {
1167 uniqueCountryCodes.add(countryCode); 1156 uniqueCountryCodes.add(countryCode);
1168 PersonalDataManager.getInstance().loadRulesForRegion(countryCode ); 1157 PersonalDataManager.getInstance().loadRulesForRegion(countryCode );
1169 } 1158 }
1170 } 1159 }
1171 1160
1172 // List order: 1161 // List order:
1173 // > Non-autofill instruments. 1162 // > Non-autofill instruments.
1174 // > Complete autofill instruments. 1163 // > Complete autofill instruments.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 if (mPaymentInformationCallback != null) providePaymentInformation(); 1196 if (mPaymentInformationCallback != null) providePaymentInformation();
1208 } 1197 }
1209 1198
1210 /** 1199 /**
1211 * If no payment methods are supported, disconnect from the client and retur n true. 1200 * If no payment methods are supported, disconnect from the client and retur n true.
1212 * 1201 *
1213 * @return True if no payment methods are supported 1202 * @return True if no payment methods are supported
1214 */ 1203 */
1215 private boolean disconnectIfNoPaymentMethodsSupported() { 1204 private boolean disconnectIfNoPaymentMethodsSupported() {
1216 boolean waitingForPaymentApps = !mPendingApps.isEmpty() || !mPendingInst ruments.isEmpty(); 1205 boolean waitingForPaymentApps = !mPendingApps.isEmpty() || !mPendingInst ruments.isEmpty();
1217 boolean foundPaymentMethods = 1206 boolean foundPaymentMethods = mPaymentMethodsSection != null
1218 mPaymentMethodsSection != null && !mPaymentMethodsSection.isEmpt y(); 1207 && !mPaymentMethodsSection.isEmpty();
1219 boolean userCanAddCreditCard = mMerchantSupportsAutofillPaymentInstrumen ts 1208 boolean userCanAddCreditCard = mMerchantSupportsAutofillPaymentInstrumen ts
1220 && !ChromeFeatureList.isEnabled(ChromeFeatureList.NO_CREDIT_CARD _ABORT); 1209 && !ChromeFeatureList.isEnabled(ChromeFeatureList.NO_CREDIT_CARD _ABORT);
1221 1210
1222 if (!mArePaymentMethodsSupported 1211 if (!mArePaymentMethodsSupported
1223 || (getIsShowing() && !waitingForPaymentApps && !foundPaymentMet hods 1212 || (getIsShowing() && !waitingForPaymentApps && !foundPaymentMet hods
1224 && !userCanAddCreditCard)) { 1213 && !userCanAddCreditCard)) {
1225 // All payment apps have responded, but none of them have instrument s. It's possible to 1214 // All payment apps have responded, but none of them have instrument s. It's possible to
1226 // add credit cards, but the merchant does not support them either. The payment request 1215 // add credit cards, but the merchant does not support them either. The payment request
1227 // must be rejected. 1216 // must be rejected.
1228 disconnectFromClientWithDebugMessage("Requested payment methods have no instruments", 1217 disconnectFromClientWithDebugMessage("Requested payment methods have no instruments",
1229 PaymentErrorReason.NOT_SUPPORTED); 1218 PaymentErrorReason.NOT_SUPPORTED);
1230 recordAbortReasonHistogram(mArePaymentMethodsSupported 1219 recordAbortReasonHistogram(mArePaymentMethodsSupported
1231 ? PaymentRequestMetrics.ABORT_REASON_NO_MATCHING_PAY MENT_METHOD 1220 ? PaymentRequestMetrics.ABORT_REASON_NO_MATCHING_PAYMENT_MET HOD
1232 : PaymentRequestMetrics.ABORT_REASON_NO_SUPPORTED_PA YMENT_METHOD); 1221 : PaymentRequestMetrics.ABORT_REASON_NO_SUPPORTED_PAYMENT_ME THOD);
1233 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi ceShowFailed(); 1222 if (sObserverForTest != null) sObserverForTest.onPaymentRequestServi ceShowFailed();
1234 return true; 1223 return true;
1235 } 1224 }
1236 1225
1237 return false; 1226 return false;
1238 } 1227 }
1239 1228
1240 /** 1229 /**
1241 * Saves the given instrument in either "autofill" or "non-autofill" list. T he separation 1230 * Saves the given instrument in either "autofill" or "non-autofill" list. T he separation
1242 * enables placing autofill instruments on the bottom of the list. 1231 * enables placing autofill instruments on the bottom of the list.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 } 1288 }
1300 1289
1301 @Override 1290 @Override
1302 public void onFocusChanged( 1291 public void onFocusChanged(
1303 @PaymentRequestUI.DataType int dataType, boolean willFocus) { 1292 @PaymentRequestUI.DataType int dataType, boolean willFocus) {
1304 assert dataType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES; 1293 assert dataType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES;
1305 1294
1306 if (mShippingAddressesSection.getSelectedItem() == null) return; 1295 if (mShippingAddressesSection.getSelectedItem() == null) return;
1307 1296
1308 assert mShippingAddressesSection.getSelectedItem() instanceof AutofillAd dress; 1297 assert mShippingAddressesSection.getSelectedItem() instanceof AutofillAd dress;
1309 AutofillAddress selectedAddress = 1298 AutofillAddress selectedAddress = (AutofillAddress) mShippingAddressesSe ction
1310 (AutofillAddress) mShippingAddressesSection.getSelectedItem(); 1299 .getSelectedItem();
1311 1300
1312 // The label should only include the country if the view is focused. 1301 // The label should only include the country if the view is focused.
1313 if (willFocus) { 1302 if (willFocus) {
1314 selectedAddress.setShippingAddressLabelWithCountry(); 1303 selectedAddress.setShippingAddressLabelWithCountry();
1315 } else { 1304 } else {
1316 selectedAddress.setShippingAddressLabelWithoutCountry(); 1305 selectedAddress.setShippingAddressLabelWithoutCountry();
1317 } 1306 }
1318 1307
1319 mUI.updateSection(PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, mShippingAdd ressesSection); 1308 mUI.updateSection(PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, mShippingAdd ressesSection);
1320 } 1309 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1399 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, 1388 "PaymentRequest.CheckoutFunnel.Aborted", abortReason,
1400 PaymentRequestMetrics.ABORT_REASON_MAX); 1389 PaymentRequestMetrics.ABORT_REASON_MAX);
1401 1390
1402 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { 1391 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) {
1403 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); 1392 mJourneyLogger.recordJourneyStatsHistograms("UserAborted");
1404 } else { 1393 } else {
1405 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); 1394 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted");
1406 } 1395 }
1407 } 1396 }
1408 } 1397 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/payments/ui/ShoppingCart.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698