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

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

Issue 2020883002: PaymentRequest: Introduce PaymentMethodData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 6 months 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
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.text.TextUtils; 10 import android.text.TextUtils;
(...skipping 12 matching lines...) Expand all
23 import org.chromium.chrome.browser.preferences.PreferencesLauncher; 23 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
24 import org.chromium.chrome.browser.preferences.autofill.AutofillCreditCardEditor ; 24 import org.chromium.chrome.browser.preferences.autofill.AutofillCreditCardEditor ;
25 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileEditor; 25 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileEditor;
26 import org.chromium.chrome.browser.profiles.Profile; 26 import org.chromium.chrome.browser.profiles.Profile;
27 import org.chromium.chrome.browser.util.UrlUtilities; 27 import org.chromium.chrome.browser.util.UrlUtilities;
28 import org.chromium.content.browser.ContentViewCore; 28 import org.chromium.content.browser.ContentViewCore;
29 import org.chromium.content_public.browser.WebContents; 29 import org.chromium.content_public.browser.WebContents;
30 import org.chromium.mojo.system.MojoException; 30 import org.chromium.mojo.system.MojoException;
31 import org.chromium.mojom.payments.PaymentDetails; 31 import org.chromium.mojom.payments.PaymentDetails;
32 import org.chromium.mojom.payments.PaymentItem; 32 import org.chromium.mojom.payments.PaymentItem;
33 import org.chromium.mojom.payments.PaymentMethodData;
33 import org.chromium.mojom.payments.PaymentOptions; 34 import org.chromium.mojom.payments.PaymentOptions;
34 import org.chromium.mojom.payments.PaymentRequest; 35 import org.chromium.mojom.payments.PaymentRequest;
35 import org.chromium.mojom.payments.PaymentRequestClient; 36 import org.chromium.mojom.payments.PaymentRequestClient;
36 import org.chromium.mojom.payments.PaymentResponse; 37 import org.chromium.mojom.payments.PaymentResponse;
37 import org.chromium.mojom.payments.ShippingOption; 38 import org.chromium.mojom.payments.ShippingOption;
38 import org.chromium.ui.base.WindowAndroid; 39 import org.chromium.ui.base.WindowAndroid;
39 import org.json.JSONException; 40 import org.json.JSONException;
40 import org.json.JSONObject; 41 import org.json.JSONObject;
41 42
42 import java.util.ArrayList; 43 import java.util.ArrayList;
43 import java.util.Arrays; 44 import java.util.Arrays;
44 import java.util.HashSet; 45 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.List; 46 import java.util.List;
47 import java.util.Locale; 47 import java.util.Locale;
48 import java.util.Set; 48 import java.util.Set;
49 import java.util.regex.Pattern; 49 import java.util.regex.Pattern;
50 50
51 /** 51 /**
52 * Android implementation of the PaymentRequest service defined in 52 * Android implementation of the PaymentRequest service defined in
53 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom. 53 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom.
54 */ 54 */
55 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie nt, 55 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie nt,
56 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback { 56 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback {
57 57
58 /** 58 /**
59 * The size for the favicon in density-independent pixels. 59 * The size for the favicon in density-independent pixels.
60 */ 60 */
61 private static final int FAVICON_SIZE_DP = 24; 61 private static final int FAVICON_SIZE_DP = 24;
62 62
63 private static final String TAG = "cr_PaymentRequest"; 63 private static final String TAG = "cr_PaymentRequest";
64 64
65 private final Handler mHandler = new Handler(); 65 private final Handler mHandler = new Handler();
66 66
67 private Activity mContext; 67 private Activity mContext;
68 private String mMerchantName; 68 private String mMerchantName;
69 private String mOrigin; 69 private String mOrigin;
70 private Bitmap mFavicon; 70 private Bitmap mFavicon;
71 private List<PaymentApp> mApps; 71 private List<PaymentApp> mApps;
72 private PaymentRequestClient mClient; 72 private PaymentRequestClient mClient;
73 private Set<String> mSupportedMethods;
74 73
75 /** 74 /**
76 * The raw total amount being charged, as it was received from the website. This data is passed 75 * The raw total amount being charged, as it was received from the website. This data is passed
77 * to the payment app. 76 * to the payment app.
78 */ 77 */
79 private PaymentItem mRawTotal; 78 private PaymentItem mRawTotal;
80 79
81 /** 80 /**
82 * The raw items in the shopping cart, as they were received from the websit e. This data is 81 * The raw items in the shopping cart, as they were received from the websit e. This data is
83 * passed to the payment app. 82 * passed to the payment app.
(...skipping 12 matching lines...) Expand all
96 * due to user selecting a shipping address. 95 * due to user selecting a shipping address.
97 */ 96 */
98 private List<ShippingOption> mRawShippingOptions; 97 private List<ShippingOption> mRawShippingOptions;
99 98
100 /** 99 /**
101 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping 100 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping
102 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI. 101 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI.
103 */ 102 */
104 private SectionInformation mUiShippingOptions; 103 private SectionInformation mUiShippingOptions;
105 104
106 private JSONObject mData; 105 private HashMap<String, JSONObject> mMethodData;
107 private SectionInformation mShippingAddressesSection; 106 private SectionInformation mShippingAddressesSection;
108 private List<PaymentApp> mPendingApps; 107 private List<PaymentApp> mPendingApps;
109 private List<PaymentInstrument> mPendingInstruments; 108 private List<PaymentInstrument> mPendingInstruments;
110 private SectionInformation mPaymentMethodsSection; 109 private SectionInformation mPaymentMethodsSection;
111 private PaymentRequestUI mUI; 110 private PaymentRequestUI mUI;
112 private Callback<PaymentInformation> mPaymentInformationCallback; 111 private Callback<PaymentInformation> mPaymentInformationCallback;
113 private Pattern mRegionCodePattern; 112 private Pattern mRegionCodePattern;
114 private boolean mMerchantNeedsShippingAddress; 113 private boolean mMerchantNeedsShippingAddress;
115 114
116 /** 115 /**
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 167
169 if (mContext == null) { 168 if (mContext == null) {
170 disconnectFromClientWithDebugMessage("Web contents don't have associ ated activity"); 169 disconnectFromClientWithDebugMessage("Web contents don't have associ ated activity");
171 } 170 }
172 } 171 }
173 172
174 /** 173 /**
175 * Called by the merchant website to show the payment request to the user. 174 * Called by the merchant website to show the payment request to the user.
176 */ 175 */
177 @Override 176 @Override
178 public void show(String[] supportedMethods, PaymentDetails details, PaymentO ptions options, 177 public void show(PaymentMethodData[] methodData, PaymentDetails details,
179 String stringifiedData) { 178 PaymentOptions options) {
180 if (mClient == null) return; 179 if (mClient == null) return;
181 180
182 if (mSupportedMethods != null) { 181 if (mMethodData != null) {
183 disconnectFromClientWithDebugMessage("PaymentRequest.show() called m ore than once."); 182 disconnectFromClientWithDebugMessage("PaymentRequest.show() called m ore than once.");
184 return; 183 return;
185 } 184 }
186 185
187 mSupportedMethods = getValidatedSupportedMethods(supportedMethods); 186 mMethodData = getValidatedMethodData(methodData);
188 if (mSupportedMethods == null) { 187 if (mMethodData == null) {
189 disconnectFromClientWithDebugMessage("Invalid payment methods"); 188 disconnectFromClientWithDebugMessage("Invalid payment methods or dat a");
190 return; 189 return;
191 } 190 }
192 191
193 if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; 192 if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return;
194 193
195 // If the merchant requests shipping and does not provide shipping optio ns here, then the 194 // If the merchant requests shipping and does not provide shipping optio ns here, then the
196 // merchant needs the shipping address to calculate shipping price and a vailability. 195 // merchant needs the shipping address to calculate shipping price and a vailability.
197 boolean requestShipping = options != null && options.requestShipping; 196 boolean requestShipping = options != null && options.requestShipping;
198 mMerchantNeedsShippingAddress = requestShipping && mUiShippingOptions.is Empty(); 197 mMerchantNeedsShippingAddress = requestShipping && mUiShippingOptions.is Empty();
199 198
200 mData = getValidatedData(mSupportedMethods, stringifiedData);
201 if (mData == null) {
202 disconnectFromClientWithDebugMessage("Invalid payment method specifi c data");
203 return;
204 }
205
206 List<AutofillAddress> addresses = new ArrayList<>(); 199 List<AutofillAddress> addresses = new ArrayList<>();
207 List<AutofillProfile> profiles = PersonalDataManager.getInstance().getPr ofilesToSuggest(); 200 List<AutofillProfile> profiles = PersonalDataManager.getInstance().getPr ofilesToSuggest();
208 for (int i = 0; i < profiles.size(); i++) { 201 for (int i = 0; i < profiles.size(); i++) {
209 AutofillProfile profile = profiles.get(i); 202 AutofillProfile profile = profiles.get(i);
210 if (profile.getCountryCode() != null 203 if (profile.getCountryCode() != null
211 && mRegionCodePattern.matcher(profile.getCountryCode()).matc hes() 204 && mRegionCodePattern.matcher(profile.getCountryCode()).matc hes()
212 && profile.getStreetAddress() != null && profile.getRegion() != null 205 && profile.getStreetAddress() != null && profile.getRegion() != null
213 && profile.getLocality() != null && profile.getDependentLoca lity() != null 206 && profile.getLocality() != null && profile.getDependentLoca lity() != null
214 && profile.getPostalCode() != null && profile.getSortingCode () != null 207 && profile.getPostalCode() != null && profile.getSortingCode () != null
215 && profile.getCompanyName() != null && profile.getFullName() != null) { 208 && profile.getCompanyName() != null && profile.getFullName() != null) {
216 addresses.add(new AutofillAddress(profile)); 209 addresses.add(new AutofillAddress(profile));
217 } 210 }
218 } 211 }
219 212
220 int selectedIndex = SectionInformation.NO_SELECTION; 213 int selectedIndex = SectionInformation.NO_SELECTION;
221 if (!addresses.isEmpty() && mUiShippingOptions.getSelectedItem() != null ) { 214 if (!addresses.isEmpty() && mUiShippingOptions.getSelectedItem() != null ) {
222 selectedIndex = 0; 215 selectedIndex = 0;
223 } 216 }
224 mShippingAddressesSection = new SectionInformation( 217 mShippingAddressesSection = new SectionInformation(
225 PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, selectedIndex, address es); 218 PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, selectedIndex, address es);
226 219
227 mPendingApps = new ArrayList<>(mApps); 220 mPendingApps = new ArrayList<>(mApps);
228 mPendingInstruments = new ArrayList<>(); 221 mPendingInstruments = new ArrayList<>();
229 boolean isGettingInstruments = false; 222 boolean isGettingInstruments = false;
230 223
231 for (int i = 0; i < mApps.size(); i++) { 224 for (int i = 0; i < mApps.size(); i++) {
232 PaymentApp app = mApps.get(i); 225 PaymentApp app = mApps.get(i);
233 Set<String> appMethods = app.getSupportedMethodNames(); 226 Set<String> appMethods = app.getSupportedMethodNames();
234 appMethods.retainAll(mSupportedMethods); 227 appMethods.retainAll(mMethodData.keySet());
235 if (appMethods.isEmpty()) { 228 if (appMethods.isEmpty()) {
236 mPendingApps.remove(app); 229 mPendingApps.remove(app);
237 } else { 230 } else {
238 isGettingInstruments = true; 231 isGettingInstruments = true;
239 app.getInstruments(mRawTotal, mRawLineItems, this); 232 app.getInstruments(mRawTotal, mRawLineItems, this);
240 } 233 }
241 } 234 }
242 235
243 if (!isGettingInstruments) { 236 if (!isGettingInstruments) {
244 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYP E_PAYMENT_METHODS); 237 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYP E_PAYMENT_METHODS);
245 } 238 }
246 239
247 mUI = PaymentRequestUI.show(mContext, this, requestShipping, mMerchantNa me, mOrigin); 240 mUI = PaymentRequestUI.show(mContext, this, requestShipping, mMerchantNa me, mOrigin);
248 if (mFavicon != null) mUI.setTitleBitmap(mFavicon); 241 if (mFavicon != null) mUI.setTitleBitmap(mFavicon);
249 mFavicon = null; 242 mFavicon = null;
250 } 243 }
251 244
252 private HashSet<String> getValidatedSupportedMethods(String[] methods) { 245 private HashMap<String, JSONObject> getValidatedMethodData(PaymentMethodData [] methodData) {
253 // Payment methods are required. 246 // Payment methodData are required.
254 if (methods == null || methods.length == 0) return null; 247 if (methodData == null || methodData.length == 0) return null;
248 HashMap<String, JSONObject> result = new HashMap<>();
249 for (int i = 0; i < methodData.length; i++) {
250 JSONObject data = null;
251 if (!TextUtils.isEmpty(methodData[i].data)) {
252 try {
253 data = new JSONObject(methodData[i].data);
254 } catch (JSONException e) {
255 // Payment method specific data should be a JSON object.
please use gerrit instead 2016/06/09 02:44:13 Looks like your rebase has removed that very usefu
256 return null;
257 }
258 }
255 259
256 HashSet<String> result = new HashSet<>(); 260 String[] methods = methodData[i].supportedMethods;
257 for (int i = 0; i < methods.length; i++) { 261
258 // Payment methods should be non-empty. 262 // Payment methods are required.
259 if (TextUtils.isEmpty(methods[i])) return null; 263 if (methods == null || methods.length == 0) return null;
260 result.add(methods[i]); 264
265 for (int j = 0; j < methods.length; j++) {
266 // Payment methods should be non-empty.
267 if (TextUtils.isEmpty(methods[j])) return null;
268 result.put(methods[j], data);
269 }
261 } 270 }
262
263 return result; 271 return result;
264 } 272 }
265 273
266 /** 274 /**
267 * Called by merchant to update the shipping options and line items after th e user has selected 275 * Called by merchant to update the shipping options and line items after th e user has selected
268 * their shipping address or shipping option. 276 * their shipping address or shipping option.
269 */ 277 */
270 @Override 278 @Override
271 public void updateWith(PaymentDetails details) { 279 public void updateWith(PaymentDetails details) {
272 if (mClient == null) return; 280 if (mClient == null) return;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 for (int i = 0; i < options.length; i++) { 462 for (int i = 0; i < options.length; i++) {
455 ShippingOption option = options[i]; 463 ShippingOption option = options[i];
456 result.add(new PaymentOption(option.id, option.label, 464 result.add(new PaymentOption(option.id, option.label,
457 formatter.format(option.amount.value), PaymentOption.NO_ICON )); 465 formatter.format(option.amount.value), PaymentOption.NO_ICON ));
458 } 466 }
459 467
460 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS, 468 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS,
461 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result ); 469 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result );
462 } 470 }
463 471
464 private JSONObject getValidatedData(Set<String> supportedMethods, String str ingifiedData) {
465 if (TextUtils.isEmpty(stringifiedData)) return new JSONObject();
466
467 JSONObject result;
468 try {
469 result = new JSONObject(stringifiedData);
470 } catch (JSONException e) {
471 // Payment method specific data should be a JSON object.
472 return null;
473 }
474
475 Iterator<String> it = result.keys();
476 while (it.hasNext()) {
477 String name = it.next();
478 // Each key should be one of the supported payment methods.
479 if (!supportedMethods.contains(name)) return null;
480 // Each value should be a JSON object.
481 if (result.optJSONObject(name) == null) return null;
482 }
483
484 return result;
485 }
486
487 /** 472 /**
488 * Called to retrieve the data to show in the initial PaymentRequest UI. 473 * Called to retrieve the data to show in the initial PaymentRequest UI.
489 */ 474 */
490 @Override 475 @Override
491 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) { 476 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) {
492 mPaymentInformationCallback = callback; 477 mPaymentInformationCallback = callback;
493 478
494 if (mPaymentMethodsSection == null) return; 479 if (mPaymentMethodsSection == null) return;
495 480
496 mHandler.post(new Runnable() { 481 mHandler.post(new Runnable() {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 mContext, AutofillCreditCardEditor.class.getName()); 552 mContext, AutofillCreditCardEditor.class.getName());
568 } 553 }
569 } 554 }
570 555
571 @Override 556 @Override
572 public void onPayClicked(PaymentOption selectedShippingAddress, 557 public void onPayClicked(PaymentOption selectedShippingAddress,
573 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) { 558 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) {
574 assert selectedPaymentMethod instanceof PaymentInstrument; 559 assert selectedPaymentMethod instanceof PaymentInstrument;
575 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ; 560 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ;
576 instrument.getDetails(mMerchantName, mOrigin, mRawTotal, mRawLineItems, 561 instrument.getDetails(mMerchantName, mOrigin, mRawTotal, mRawLineItems,
577 mData.optJSONObject(instrument.getMethodName()), this); 562 mMethodData.get(instrument.getMethodName()), this);
578 } 563 }
579 564
580 @Override 565 @Override
581 public void onDismiss() { 566 public void onDismiss() {
582 disconnectFromClientWithDebugMessage("Dialog dismissed"); 567 disconnectFromClientWithDebugMessage("Dialog dismissed");
583 closeUI(false); 568 closeUI(false);
584 } 569 }
585 570
586 @Override 571 @Override
587 public boolean merchantNeedsShippingAddress() { 572 public boolean merchantNeedsShippingAddress() {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 /** 611 /**
627 * Called after retrieving the list of payment instruments in an app. 612 * Called after retrieving the list of payment instruments in an app.
628 */ 613 */
629 @Override 614 @Override
630 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) { 615 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) {
631 mPendingApps.remove(app); 616 mPendingApps.remove(app);
632 617
633 if (instruments != null) { 618 if (instruments != null) {
634 for (int i = 0; i < instruments.size(); i++) { 619 for (int i = 0; i < instruments.size(); i++) {
635 PaymentInstrument instrument = instruments.get(i); 620 PaymentInstrument instrument = instruments.get(i);
636 if (mSupportedMethods.contains(instrument.getMethodName())) { 621 if (mMethodData.containsKey(instrument.getMethodName())) {
637 mPendingInstruments.add(instrument); 622 mPendingInstruments.add(instrument);
638 } else { 623 } else {
639 instrument.dismiss(); 624 instrument.dismiss();
640 } 625 }
641 } 626 }
642 } 627 }
643 628
644 if (mPendingApps.isEmpty()) { 629 if (mPendingApps.isEmpty()) {
645 mPaymentMethodsSection = new SectionInformation( 630 mPaymentMethodsSection = new SectionInformation(
646 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s); 631 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 } 699 }
715 mPaymentMethodsSection = null; 700 mPaymentMethodsSection = null;
716 } 701 }
717 } 702 }
718 703
719 private void closeClient() { 704 private void closeClient() {
720 if (mClient != null) mClient.close(); 705 if (mClient != null) mClient.close();
721 mClient = null; 706 mClient = null;
722 } 707 }
723 } 708 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698