| 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.support.v4.util.ArrayMap; | 10 import android.support.v4.util.ArrayMap; |
| 11 import android.text.TextUtils; | 11 import android.text.TextUtils; |
| 12 | 12 |
| 13 import org.chromium.base.Callback; | 13 import org.chromium.base.Callback; |
| 14 import org.chromium.base.Log; | 14 import org.chromium.base.Log; |
| 15 import org.chromium.base.VisibleForTesting; | 15 import org.chromium.base.VisibleForTesting; |
| 16 import org.chromium.base.metrics.RecordHistogram; | 16 import org.chromium.base.metrics.RecordHistogram; |
| 17 import org.chromium.chrome.R; | 17 import org.chromium.chrome.R; |
| 18 import org.chromium.chrome.browser.ChromeActivity; | 18 import org.chromium.chrome.browser.ChromeActivity; |
| 19 import org.chromium.chrome.browser.ChromeFeatureList; | 19 import org.chromium.chrome.browser.ChromeFeatureList; |
| 20 import org.chromium.chrome.browser.autofill.PersonalDataManager; | 20 import org.chromium.chrome.browser.autofill.PersonalDataManager; |
| 21 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; | 21 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; |
| 22 import org.chromium.chrome.browser.favicon.FaviconHelper; | 22 import org.chromium.chrome.browser.favicon.FaviconHelper; |
| 23 import org.chromium.chrome.browser.payments.ui.Completable; | 23 import org.chromium.chrome.browser.payments.ui.Completable; |
| 24 import org.chromium.chrome.browser.payments.ui.LineItem; | 24 import org.chromium.chrome.browser.payments.ui.LineItem; |
| 25 import org.chromium.chrome.browser.payments.ui.PaymentInformation; | 25 import org.chromium.chrome.browser.payments.ui.PaymentInformation; |
| 26 import org.chromium.chrome.browser.payments.ui.PaymentOption; | 26 import org.chromium.chrome.browser.payments.ui.PaymentOption; |
| 27 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSecti
on.FocusChangedObserver; |
| 27 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; | 28 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; |
| 28 import org.chromium.chrome.browser.payments.ui.SectionInformation; | 29 import org.chromium.chrome.browser.payments.ui.SectionInformation; |
| 29 import org.chromium.chrome.browser.payments.ui.ShoppingCart; | 30 import org.chromium.chrome.browser.payments.ui.ShoppingCart; |
| 30 import org.chromium.chrome.browser.profiles.Profile; | 31 import org.chromium.chrome.browser.profiles.Profile; |
| 31 import org.chromium.chrome.browser.tab.Tab; | 32 import org.chromium.chrome.browser.tab.Tab; |
| 32 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; | 33 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; |
| 33 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; | 34 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; |
| 34 import org.chromium.chrome.browser.tabmodel.TabModel; | 35 import org.chromium.chrome.browser.tabmodel.TabModel; |
| 35 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; | 36 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; |
| 36 import org.chromium.chrome.browser.tabmodel.TabModelObserver; | 37 import org.chromium.chrome.browser.tabmodel.TabModelObserver; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 60 import java.util.Locale; | 61 import java.util.Locale; |
| 61 import java.util.Map; | 62 import java.util.Map; |
| 62 import java.util.Set; | 63 import java.util.Set; |
| 63 | 64 |
| 64 /** | 65 /** |
| 65 * Android implementation of the PaymentRequest service defined in | 66 * Android implementation of the PaymentRequest service defined in |
| 66 * components/payments/payment_request.mojom. | 67 * components/payments/payment_request.mojom. |
| 67 */ | 68 */ |
| 68 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie
nt, | 69 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie
nt, |
| 69 PaymentApp.InstrumentsCallback, PaymentInstrument.InstrumentDetailsCallb
ack, | 70 PaymentApp.InstrumentsCallback, PaymentInstrument.InstrumentDetailsCallb
ack, |
| 70 PaymentResponseHelper.PaymentResponseRequesterDelegate { | 71 PaymentResponseHelper.PaymentResponseRequesterDelegate, FocusChangedObse
rver { |
| 71 /** | 72 /** |
| 72 * A test-only observer for the PaymentRequest service implementation. | 73 * A test-only observer for the PaymentRequest service implementation. |
| 73 */ | 74 */ |
| 74 public interface PaymentRequestServiceObserverForTest { | 75 public interface PaymentRequestServiceObserverForTest { |
| 75 /** | 76 /** |
| 76 * Called when an abort request was denied. | 77 * Called when an abort request was denied. |
| 77 */ | 78 */ |
| 78 void onPaymentRequestServiceUnableToAbort(); | 79 void onPaymentRequestServiceUnableToAbort(); |
| 79 | 80 |
| 80 /** | 81 /** |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 // Log the number of suggested shipping addresses. | 367 // Log the number of suggested shipping addresses. |
| 367 mJourneyLogger.setNumberOfSuggestionsShown( | 368 mJourneyLogger.setNumberOfSuggestionsShown( |
| 368 PaymentRequestJourneyLogger.SECTION_SHIPPING_ADDRESS, addres
ses.size()); | 369 PaymentRequestJourneyLogger.SECTION_SHIPPING_ADDRESS, addres
ses.size()); |
| 369 | 370 |
| 370 // Automatically select the first address if one is complete and if
the merchant does | 371 // Automatically select the first address if one is complete and if
the merchant does |
| 371 // not require a shipping address to calculate shipping costs. | 372 // not require a shipping address to calculate shipping costs. |
| 372 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; | 373 int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; |
| 373 if (mUiShippingOptions.getSelectedItem() != null && !addresses.isEmp
ty() | 374 if (mUiShippingOptions.getSelectedItem() != null && !addresses.isEmp
ty() |
| 374 && addresses.get(0).isComplete()) { | 375 && addresses.get(0).isComplete()) { |
| 375 firstCompleteAddressIndex = 0; | 376 firstCompleteAddressIndex = 0; |
| 377 |
| 378 // The initial label for the selected shipping address should no
t include the |
| 379 // country. |
| 380 addresses.get(firstCompleteAddressIndex).setShippingAddressLabel
WithoutCountry(); |
| 376 } | 381 } |
| 377 | 382 |
| 378 mShippingAddressesSection = | 383 mShippingAddressesSection = |
| 379 new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_ADDRES
SES, | 384 new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_ADDRES
SES, |
| 380 firstCompleteAddressIndex, addresses); | 385 firstCompleteAddressIndex, addresses); |
| 381 } | 386 } |
| 382 | 387 |
| 383 if (requestPayerName || requestPayerPhone || requestPayerEmail) { | 388 if (requestPayerName || requestPayerPhone || requestPayerEmail) { |
| 384 Set<String> uniqueContactInfos = new HashSet<>(); | 389 Set<String> uniqueContactInfos = new HashSet<>(); |
| 385 mContactEditor = new ContactEditor( | 390 mContactEditor = new ContactEditor( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 mContactSection = new SectionInformation( | 436 mContactSection = new SectionInformation( |
| 432 PaymentRequestUI.TYPE_CONTACT_DETAILS, firstCompleteContactI
ndex, contacts); | 437 PaymentRequestUI.TYPE_CONTACT_DETAILS, firstCompleteContactI
ndex, contacts); |
| 433 } | 438 } |
| 434 | 439 |
| 435 mUI = new PaymentRequestUI(mContext, this, requestShipping, | 440 mUI = new PaymentRequestUI(mContext, this, requestShipping, |
| 436 requestPayerName || requestPayerPhone || requestPayerEmail, | 441 requestPayerName || requestPayerPhone || requestPayerEmail, |
| 437 mMerchantSupportsAutofillPaymentInstruments, mMerchantName, mOri
gin, | 442 mMerchantSupportsAutofillPaymentInstruments, mMerchantName, mOri
gin, |
| 438 new ShippingStrings( | 443 new ShippingStrings( |
| 439 options == null ? PaymentShippingType.SHIPPING : options
.shippingType)); | 444 options == null ? PaymentShippingType.SHIPPING : options
.shippingType)); |
| 440 | 445 |
| 446 // Add the callback to change the label of shipping addresses depending
on the focus. |
| 447 if (requestShipping) mUI.setShippingAddressSectionFocusChangedObserver(t
his); |
| 448 |
| 441 if (mFavicon != null) mUI.setTitleBitmap(mFavicon); | 449 if (mFavicon != null) mUI.setTitleBitmap(mFavicon); |
| 442 mFavicon = null; | 450 mFavicon = null; |
| 443 | 451 |
| 444 mAddressEditor.setEditorView(mUI.getEditorView()); | 452 mAddressEditor.setEditorView(mUI.getEditorView()); |
| 445 mCardEditor.setEditorView(mUI.getCardEditorView()); | 453 mCardEditor.setEditorView(mUI.getCardEditorView()); |
| 446 if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorVi
ew()); | 454 if (mContactEditor != null) mContactEditor.setEditorView(mUI.getEditorVi
ew()); |
| 447 | 455 |
| 448 PaymentRequestMetrics.recordRequestedInformationHistogram(requestPayerEm
ail, | 456 PaymentRequestMetrics.recordRequestedInformationHistogram(requestPayerEm
ail, |
| 449 requestPayerPhone, requestShipping, requestPayerName); | 457 requestPayerPhone, requestShipping, requestPayerName); |
| 450 } | 458 } |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 mAddressEditor.edit(toEdit, new Callback<AutofillAddress>() { | 853 mAddressEditor.edit(toEdit, new Callback<AutofillAddress>() { |
| 846 @Override | 854 @Override |
| 847 public void onResult(AutofillAddress completeAddress) { | 855 public void onResult(AutofillAddress completeAddress) { |
| 848 if (mUI == null) return; | 856 if (mUI == null) return; |
| 849 | 857 |
| 850 if (completeAddress == null) { | 858 if (completeAddress == null) { |
| 851 mShippingAddressesSection.setSelectedItemIndex(SectionInform
ation.NO_SELECTION); | 859 mShippingAddressesSection.setSelectedItemIndex(SectionInform
ation.NO_SELECTION); |
| 852 providePaymentInformation(); | 860 providePaymentInformation(); |
| 853 } else { | 861 } else { |
| 854 // Set the shipping address label. | 862 // Set the shipping address label. |
| 855 completeAddress.setShippingAddressLabel(); | 863 completeAddress.setShippingAddressLabelWithCountry(); |
| 856 | 864 |
| 857 if (toEdit == null) mShippingAddressesSection.addAndSelectIt
em(completeAddress); | 865 if (toEdit == null) mShippingAddressesSection.addAndSelectIt
em(completeAddress); |
| 858 mCardEditor.updateBillingAddressIfComplete(completeAddress); | 866 mCardEditor.updateBillingAddressIfComplete(completeAddress); |
| 859 mClient.onShippingAddressChange(completeAddress.toPaymentAdd
ress()); | 867 mClient.onShippingAddressChange(completeAddress.toPaymentAdd
ress()); |
| 860 } | 868 } |
| 861 } | 869 } |
| 862 }); | 870 }); |
| 863 } | 871 } |
| 864 | 872 |
| 865 private void editContact(final AutofillContact toEdit) { | 873 private void editContact(final AutofillContact toEdit) { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 /** | 1215 /** |
| 1208 * Called if unable to retrieve instrument details. | 1216 * Called if unable to retrieve instrument details. |
| 1209 */ | 1217 */ |
| 1210 @Override | 1218 @Override |
| 1211 public void onInstrumentDetailsError() { | 1219 public void onInstrumentDetailsError() { |
| 1212 if (mClient == null) return; | 1220 if (mClient == null) return; |
| 1213 mUI.onPayButtonProcessingCancelled(); | 1221 mUI.onPayButtonProcessingCancelled(); |
| 1214 mPaymentAppRunning = false; | 1222 mPaymentAppRunning = false; |
| 1215 } | 1223 } |
| 1216 | 1224 |
| 1225 @Override |
| 1226 public void onFocusChanged( |
| 1227 @PaymentRequestUI.DataType int dataType, boolean willFocus) { |
| 1228 assert dataType == PaymentRequestUI.TYPE_SHIPPING_ADDRESSES; |
| 1229 |
| 1230 if (mShippingAddressesSection.getSelectedItem() == null) return; |
| 1231 |
| 1232 assert mShippingAddressesSection.getSelectedItem() instanceof AutofillAd
dress; |
| 1233 AutofillAddress selectedAddress = |
| 1234 (AutofillAddress) mShippingAddressesSection.getSelectedItem(); |
| 1235 |
| 1236 // The label should only include the country if the view is focused. |
| 1237 if (willFocus) { |
| 1238 selectedAddress.setShippingAddressLabelWithCountry(); |
| 1239 } else { |
| 1240 selectedAddress.setShippingAddressLabelWithoutCountry(); |
| 1241 } |
| 1242 |
| 1243 mUI.updateSection(PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, mShippingAdd
ressesSection); |
| 1244 } |
| 1245 |
| 1217 /** | 1246 /** |
| 1218 * Closes the UI. If the client is still connected, then it's notified of UI
hiding. | 1247 * Closes the UI. If the client is still connected, then it's notified of UI
hiding. |
| 1219 * | 1248 * |
| 1220 * @param immediateClose If true, then UI immediately closes. If false, the
UI shows the error | 1249 * @param immediateClose If true, then UI immediately closes. If false, the
UI shows the error |
| 1221 * message "There was an error processing your order."
This message | 1250 * message "There was an error processing your order."
This message |
| 1222 * implies that the merchant attempted to process the
order, failed, and | 1251 * implies that the merchant attempted to process the
order, failed, and |
| 1223 * called complete("fail") to notify the user. Therefo
re, this parameter | 1252 * called complete("fail") to notify the user. Therefo
re, this parameter |
| 1224 * may be "false" only when called from | 1253 * may be "false" only when called from |
| 1225 * {@link PaymentRequestImpl#complete(int)}. All other
callers should | 1254 * {@link PaymentRequestImpl#complete(int)}. All other
callers should |
| 1226 * always pass "true." | 1255 * always pass "true." |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, | 1323 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, |
| 1295 PaymentRequestMetrics.ABORT_REASON_MAX); | 1324 PaymentRequestMetrics.ABORT_REASON_MAX); |
| 1296 | 1325 |
| 1297 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { | 1326 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { |
| 1298 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); | 1327 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); |
| 1299 } else { | 1328 } else { |
| 1300 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); | 1329 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); |
| 1301 } | 1330 } |
| 1302 } | 1331 } |
| 1303 } | 1332 } |
| OLD | NEW |