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.content.Intent; | 8 import android.content.Intent; |
9 import android.graphics.Bitmap; | 9 import android.graphics.Bitmap; |
10 import android.os.Handler; | 10 import android.os.Handler; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 private List<PaymentInstrument> mPendingInstruments; | 259 private List<PaymentInstrument> mPendingInstruments; |
260 private List<PaymentInstrument> mPendingAutofillInstruments; | 260 private List<PaymentInstrument> mPendingAutofillInstruments; |
261 private SectionInformation mPaymentMethodsSection; | 261 private SectionInformation mPaymentMethodsSection; |
262 private PaymentRequestUI mUI; | 262 private PaymentRequestUI mUI; |
263 private Callback<PaymentInformation> mPaymentInformationCallback; | 263 private Callback<PaymentInformation> mPaymentInformationCallback; |
264 private boolean mPaymentAppRunning; | 264 private boolean mPaymentAppRunning; |
265 private boolean mMerchantSupportsAutofillPaymentInstruments; | 265 private boolean mMerchantSupportsAutofillPaymentInstruments; |
266 private ContactEditor mContactEditor; | 266 private ContactEditor mContactEditor; |
267 private boolean mHasRecordedAbortReason; | 267 private boolean mHasRecordedAbortReason; |
268 private boolean mQueriedCanMakePayment; | 268 private boolean mQueriedCanMakePayment; |
269 private CurrencyStringFormatter mFormatter; | 269 private CurrencyFormatter mCurrencyFormatter; |
270 | 270 |
271 /** True if any of the requested payment methods are supported. */ | 271 /** True if any of the requested payment methods are supported. */ |
272 private boolean mArePaymentMethodsSupported; | 272 private boolean mArePaymentMethodsSupported; |
273 | 273 |
274 /** | 274 /** |
275 * True after at least one usable payment instrument has been found. Should
be read only after | 275 * True after at least one usable payment instrument has been found. Should
be read only after |
276 * all payment apps have been queried. | 276 * all payment apps have been queried. |
277 */ | 277 */ |
278 private boolean mCanMakePayment; | 278 private boolean mCanMakePayment; |
279 | 279 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 mApps = new ArrayList<>(); | 319 mApps = new ArrayList<>(); |
320 | 320 |
321 mAddressEditor = new AddressEditor(); | 321 mAddressEditor = new AddressEditor(); |
322 mCardEditor = new CardEditor(webContents, mAddressEditor, sObserverForTe
st); | 322 mCardEditor = new CardEditor(webContents, mAddressEditor, sObserverForTe
st); |
323 | 323 |
324 if (sCanMakePaymentQueries == null) sCanMakePaymentQueries = new ArrayMa
p<>(); | 324 if (sCanMakePaymentQueries == null) sCanMakePaymentQueries = new ArrayMa
p<>(); |
325 | 325 |
326 recordSuccessFunnelHistograms("Initiated"); | 326 recordSuccessFunnelHistograms("Initiated"); |
327 } | 327 } |
328 | 328 |
| 329 protected void finalize() throws Throwable { |
| 330 super.finalize(); |
| 331 if (mCurrencyFormatter != null) { |
| 332 // Ensures the native implementation of currency formatter does not
leak. |
| 333 mCurrencyFormatter.destroy(); |
| 334 } |
| 335 } |
| 336 |
329 /** | 337 /** |
330 * Called by the merchant website to initialize the payment request data. | 338 * Called by the merchant website to initialize the payment request data. |
331 */ | 339 */ |
332 @Override | 340 @Override |
333 public void init(PaymentRequestClient client, PaymentMethodData[] methodData
, | 341 public void init(PaymentRequestClient client, PaymentMethodData[] methodData
, |
334 PaymentDetails details, PaymentOptions options) { | 342 PaymentDetails details, PaymentOptions options) { |
335 if (mClient != null || client == null) return; | 343 if (mClient != null || client == null) return; |
336 mClient = client; | 344 mClient = client; |
337 | 345 |
338 if (mMethodData != null) { | 346 if (mMethodData != null) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 * @return True if the data is valid. False if the data is invalid. | 596 * @return True if the data is valid. False if the data is invalid. |
589 */ | 597 */ |
590 private boolean parseAndValidateDetailsOrDisconnectFromClient(PaymentDetails
details) { | 598 private boolean parseAndValidateDetailsOrDisconnectFromClient(PaymentDetails
details) { |
591 if (!PaymentValidator.validatePaymentDetails(details)) { | 599 if (!PaymentValidator.validatePaymentDetails(details)) { |
592 disconnectFromClientWithDebugMessage("Invalid payment details"); | 600 disconnectFromClientWithDebugMessage("Invalid payment details"); |
593 recordAbortReasonHistogram( | 601 recordAbortReasonHistogram( |
594 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE
R); | 602 PaymentRequestMetrics.ABORT_REASON_INVALID_DATA_FROM_RENDERE
R); |
595 return false; | 603 return false; |
596 } | 604 } |
597 | 605 |
598 if (mFormatter == null) { | 606 if (mCurrencyFormatter == null) { |
599 mFormatter = new CurrencyStringFormatter(details.total.amount.curren
cy, | 607 mCurrencyFormatter = new CurrencyFormatter(details.total.amount.curr
ency, |
600 Locale.getDefault()); | 608 details.total.amount.currencySystem, Locale.getDefault()); |
601 } | 609 } |
602 | 610 |
603 // Total is never pending. | 611 // Total is never pending. |
604 LineItem uiTotal = new LineItem( | 612 LineItem uiTotal = new LineItem(details.total.label, |
605 details.total.label, mFormatter.getFormattedCurrencyCode(), | 613 mCurrencyFormatter.getFormattedCurrencyCode(), |
606 mFormatter.format(details.total.amount.value), /* isPending */ f
alse); | 614 mCurrencyFormatter.format(details.total.amount.value), /* isPend
ing */ false); |
607 | 615 |
608 List<LineItem> uiLineItems = getLineItems(details.displayItems, mFormatt
er); | 616 List<LineItem> uiLineItems = getLineItems(details.displayItems, mCurrenc
yFormatter); |
609 | 617 |
610 mUiShoppingCart = new ShoppingCart(uiTotal, uiLineItems); | 618 mUiShoppingCart = new ShoppingCart(uiTotal, uiLineItems); |
611 mRawTotal = details.total; | 619 mRawTotal = details.total; |
612 mRawLineItems = Collections.unmodifiableList(Arrays.asList(details.displ
ayItems)); | 620 mRawLineItems = Collections.unmodifiableList(Arrays.asList(details.displ
ayItems)); |
613 | 621 |
614 mUiShippingOptions = getShippingOptions(details.shippingOptions, mFormat
ter); | 622 mUiShippingOptions = getShippingOptions(details.shippingOptions, mCurren
cyFormatter); |
615 | 623 |
616 for (int i = 0; i < details.modifiers.length; i++) { | 624 for (int i = 0; i < details.modifiers.length; i++) { |
617 PaymentDetailsModifier modifier = details.modifiers[i]; | 625 PaymentDetailsModifier modifier = details.modifiers[i]; |
618 String[] methods = modifier.methodData.supportedMethods; | 626 String[] methods = modifier.methodData.supportedMethods; |
619 for (int j = 0; j < methods.length; j++) { | 627 for (int j = 0; j < methods.length; j++) { |
620 if (mModifiers == null) mModifiers = new ArrayMap<>(); | 628 if (mModifiers == null) mModifiers = new ArrayMap<>(); |
621 mModifiers.put(methods[j], modifier); | 629 mModifiers.put(methods[j], modifier); |
622 } | 630 } |
623 } | 631 } |
624 | 632 |
625 updateInstrumentModifiedTotals(); | 633 updateInstrumentModifiedTotals(); |
626 | 634 |
627 return true; | 635 return true; |
628 } | 636 } |
629 | 637 |
630 /** Updates the modifiers for payment instruments and order summary. */ | 638 /** Updates the modifiers for payment instruments and order summary. */ |
631 private void updateInstrumentModifiedTotals() { | 639 private void updateInstrumentModifiedTotals() { |
632 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER
S)) return; | 640 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER
S)) return; |
633 if (mModifiers == null) return; | 641 if (mModifiers == null) return; |
634 if (mPaymentMethodsSection == null) return; | 642 if (mPaymentMethodsSection == null) return; |
635 | 643 |
636 for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) { | 644 for (int i = 0; i < mPaymentMethodsSection.getSize(); i++) { |
637 PaymentInstrument instrument = (PaymentInstrument) mPaymentMethodsSe
ction.getItem(i); | 645 PaymentInstrument instrument = (PaymentInstrument) mPaymentMethodsSe
ction.getItem(i); |
638 PaymentDetailsModifier modifier = getModifier(instrument); | 646 PaymentDetailsModifier modifier = getModifier(instrument); |
639 instrument.setModifiedTotal(modifier == null || modifier.total == nu
ll ? null | 647 instrument.setModifiedTotal(modifier == null || modifier.total == nu
ll |
640 : mFormatter.format(modifier.total.amount.value)); | 648 ? null |
| 649 : mCurrencyFormatter.format(modifier.total.amount.va
lue)); |
641 } | 650 } |
642 | 651 |
643 updateOrderSummary((PaymentInstrument) mPaymentMethodsSection.getSelecte
dItem()); | 652 updateOrderSummary((PaymentInstrument) mPaymentMethodsSection.getSelecte
dItem()); |
644 } | 653 } |
645 | 654 |
646 /** Sets the modifier for the order summary based on the given instrument, i
f any. */ | 655 /** Sets the modifier for the order summary based on the given instrument, i
f any. */ |
647 private void updateOrderSummary(@Nullable PaymentInstrument instrument) { | 656 private void updateOrderSummary(@Nullable PaymentInstrument instrument) { |
648 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER
S)) return; | 657 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MODIFIER
S)) return; |
649 | 658 |
650 PaymentDetailsModifier modifier = getModifier(instrument); | 659 PaymentDetailsModifier modifier = getModifier(instrument); |
651 PaymentItem total = modifier == null ? null : modifier.total; | 660 PaymentItem total = modifier == null ? null : modifier.total; |
652 if (total == null) total = mRawTotal; | 661 if (total == null) total = mRawTotal; |
653 | 662 |
654 mUiShoppingCart.setTotal(new LineItem(total.label, mFormatter.getFormatt
edCurrencyCode(), | 663 mUiShoppingCart.setTotal( |
655 mFormatter.format(total.amount.value), false /* isPending */)); | 664 new LineItem(total.label, mCurrencyFormatter.getFormattedCurrenc
yCode(), |
656 mUiShoppingCart.setAdditionalContents(modifier == null ? null | 665 mCurrencyFormatter.format(total.amount.value), false /*
isPending */)); |
657 : getLineItems(modifier.additionalDisplayItems, mFormatter)); | 666 mUiShoppingCart.setAdditionalContents(modifier == null |
| 667 ? null |
| 668 : getLineItems(modifier.additionalDisplayItems, mCurrenc
yFormatter)); |
658 mUI.updateOrderSummarySection(mUiShoppingCart); | 669 mUI.updateOrderSummarySection(mUiShoppingCart); |
659 } | 670 } |
660 | 671 |
661 /** @return The first modifier that matches the given instrument, or null. *
/ | 672 /** @return The first modifier that matches the given instrument, or null. *
/ |
662 @Nullable private PaymentDetailsModifier getModifier(@Nullable PaymentInstru
ment instrument) { | 673 @Nullable private PaymentDetailsModifier getModifier(@Nullable PaymentInstru
ment instrument) { |
663 if (instrument == null) return null; | 674 if (instrument == null) return null; |
664 Set<String> methodNames = instrument.getInstrumentMethodNames(); | 675 Set<String> methodNames = instrument.getInstrumentMethodNames(); |
665 methodNames.retainAll(mModifiers.keySet()); | 676 methodNames.retainAll(mModifiers.keySet()); |
666 return methodNames.isEmpty() ? null : mModifiers.get(methodNames.iterato
r().next()); | 677 return methodNames.isEmpty() ? null : mModifiers.get(methodNames.iterato
r().next()); |
667 } | 678 } |
668 | 679 |
669 /** | 680 /** |
670 * Converts a list of payment items and returns their parsed representation. | 681 * Converts a list of payment items and returns their parsed representation. |
671 * | 682 * |
672 * @param items The payment items to parse. Can be null. | 683 * @param items The payment items to parse. Can be null. |
673 * @param formatter A formatter for the currency amount value. | 684 * @param formatter A formatter for the currency amount value. |
674 * @return A list of valid line items. | 685 * @return A list of valid line items. |
675 */ | 686 */ |
676 private static List<LineItem> getLineItems( | 687 private static List<LineItem> getLineItems( |
677 @Nullable PaymentItem[] items, CurrencyStringFormatter formatter) { | 688 @Nullable PaymentItem[] items, CurrencyFormatter formatter) { |
678 // Line items are optional. | 689 // Line items are optional. |
679 if (items == null) return new ArrayList<>(); | 690 if (items == null) return new ArrayList<>(); |
680 | 691 |
681 List<LineItem> result = new ArrayList<>(items.length); | 692 List<LineItem> result = new ArrayList<>(items.length); |
682 for (int i = 0; i < items.length; i++) { | 693 for (int i = 0; i < items.length; i++) { |
683 PaymentItem item = items[i]; | 694 PaymentItem item = items[i]; |
684 | 695 |
685 result.add(new LineItem( | 696 result.add(new LineItem( |
686 item.label, "", formatter.format(item.amount.value), item.pe
nding)); | 697 item.label, "", formatter.format(item.amount.value), item.pe
nding)); |
687 } | 698 } |
688 | 699 |
689 return Collections.unmodifiableList(result); | 700 return Collections.unmodifiableList(result); |
690 } | 701 } |
691 | 702 |
692 /** | 703 /** |
693 * Converts a list of shipping options and returns their parsed representati
on. | 704 * Converts a list of shipping options and returns their parsed representati
on. |
694 * | 705 * |
695 * @param options The raw shipping options to parse. Can be null. | 706 * @param options The raw shipping options to parse. Can be null. |
696 * @param formatter A formatter for the currency amount value. | 707 * @param formatter A formatter for the currency amount value. |
697 * @return The UI representation of the shipping options. | 708 * @return The UI representation of the shipping options. |
698 */ | 709 */ |
699 private static SectionInformation getShippingOptions( | 710 private static SectionInformation getShippingOptions( |
700 @Nullable PaymentShippingOption[] options, CurrencyStringFormatter f
ormatter) { | 711 @Nullable PaymentShippingOption[] options, CurrencyFormatter formatt
er) { |
701 // Shipping options are optional. | 712 // Shipping options are optional. |
702 if (options == null || options.length == 0) { | 713 if (options == null || options.length == 0) { |
703 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS
); | 714 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS
); |
704 } | 715 } |
705 | 716 |
706 List<PaymentOption> result = new ArrayList<>(); | 717 List<PaymentOption> result = new ArrayList<>(); |
707 int selectedItemIndex = SectionInformation.NO_SELECTION; | 718 int selectedItemIndex = SectionInformation.NO_SELECTION; |
708 for (int i = 0; i < options.length; i++) { | 719 for (int i = 0; i < options.length; i++) { |
709 PaymentShippingOption option = options[i]; | 720 PaymentShippingOption option = options[i]; |
710 result.add(new PaymentOption(option.id, option.label, | 721 result.add(new PaymentOption(option.id, option.label, |
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, | 1467 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, |
1457 PaymentRequestMetrics.ABORT_REASON_MAX); | 1468 PaymentRequestMetrics.ABORT_REASON_MAX); |
1458 | 1469 |
1459 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { | 1470 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { |
1460 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); | 1471 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); |
1461 } else { | 1472 } else { |
1462 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); | 1473 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); |
1463 } | 1474 } |
1464 } | 1475 } |
1465 } | 1476 } |
OLD | NEW |