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

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: 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 11 matching lines...) Expand all
22 import org.chromium.chrome.browser.preferences.PreferencesLauncher; 22 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
23 import org.chromium.chrome.browser.preferences.autofill.AutofillCreditCardEditor ; 23 import org.chromium.chrome.browser.preferences.autofill.AutofillCreditCardEditor ;
24 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileEditor; 24 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileEditor;
25 import org.chromium.chrome.browser.profiles.Profile; 25 import org.chromium.chrome.browser.profiles.Profile;
26 import org.chromium.chrome.browser.util.UrlUtilities; 26 import org.chromium.chrome.browser.util.UrlUtilities;
27 import org.chromium.content.browser.ContentViewCore; 27 import org.chromium.content.browser.ContentViewCore;
28 import org.chromium.content_public.browser.WebContents; 28 import org.chromium.content_public.browser.WebContents;
29 import org.chromium.mojo.system.MojoException; 29 import org.chromium.mojo.system.MojoException;
30 import org.chromium.mojom.payments.PaymentDetails; 30 import org.chromium.mojom.payments.PaymentDetails;
31 import org.chromium.mojom.payments.PaymentItem; 31 import org.chromium.mojom.payments.PaymentItem;
32 import org.chromium.mojom.payments.PaymentMethodData;
32 import org.chromium.mojom.payments.PaymentOptions; 33 import org.chromium.mojom.payments.PaymentOptions;
33 import org.chromium.mojom.payments.PaymentRequest; 34 import org.chromium.mojom.payments.PaymentRequest;
34 import org.chromium.mojom.payments.PaymentRequestClient; 35 import org.chromium.mojom.payments.PaymentRequestClient;
35 import org.chromium.mojom.payments.PaymentResponse; 36 import org.chromium.mojom.payments.PaymentResponse;
36 import org.chromium.mojom.payments.ShippingOption; 37 import org.chromium.mojom.payments.ShippingOption;
37 import org.chromium.ui.base.WindowAndroid; 38 import org.chromium.ui.base.WindowAndroid;
38 import org.json.JSONException; 39 import org.json.JSONException;
39 import org.json.JSONObject; 40 import org.json.JSONObject;
40 41
41 import java.util.ArrayList; 42 import java.util.ArrayList;
42 import java.util.Arrays; 43 import java.util.Arrays;
43 import java.util.HashSet; 44 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.List; 45 import java.util.List;
46 import java.util.Locale; 46 import java.util.Locale;
47 import java.util.Set; 47 import java.util.Set;
48 import java.util.regex.Pattern; 48 import java.util.regex.Pattern;
49 49
50 /** 50 /**
51 * Android implementation of the PaymentRequest service defined in 51 * Android implementation of the PaymentRequest service defined in
52 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom. 52 * third_party/WebKit/public/platform/modules/payments/payment_request.mojom.
53 */ 53 */
54 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie nt, 54 public class PaymentRequestImpl implements PaymentRequest, PaymentRequestUI.Clie nt,
55 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback { 55 PaymentApp.InstrumentsCallback, PaymentInstrument.DetailsCallback {
56 /** 56 /**
57 * The size for the favicon in density-independent pixels. 57 * The size for the favicon in density-independent pixels.
58 */ 58 */
59 private static final int FAVICON_SIZE_DP = 24; 59 private static final int FAVICON_SIZE_DP = 24;
60 60
61 private static final String TAG = "cr_PaymentRequest"; 61 private static final String TAG = "cr_PaymentRequest";
62 62
63 private final Handler mHandler = new Handler(); 63 private final Handler mHandler = new Handler();
64 64
65 private Activity mContext; 65 private Activity mContext;
66 private String mMerchantName; 66 private String mMerchantName;
67 private String mOrigin; 67 private String mOrigin;
68 private Bitmap mFavicon; 68 private Bitmap mFavicon;
69 private List<PaymentApp> mApps; 69 private List<PaymentApp> mApps;
70 private PaymentRequestClient mClient; 70 private PaymentRequestClient mClient;
71 private Set<String> mSupportedMethods; 71 private HashMap<String, JSONObject> mMethodData;
72 private List<LineItem> mLineItems; 72 private List<LineItem> mLineItems;
73 private List<PaymentItem> mPaymentItems; 73 private List<PaymentItem> mPaymentItems;
74 private List<ShippingOption> mShippingOptions; 74 private List<ShippingOption> mShippingOptions;
75 private SectionInformation mShippingOptionsSection; 75 private SectionInformation mShippingOptionsSection;
76 private JSONObject mData;
77 private SectionInformation mShippingAddressesSection; 76 private SectionInformation mShippingAddressesSection;
78 private List<PaymentApp> mPendingApps; 77 private List<PaymentApp> mPendingApps;
79 private List<PaymentInstrument> mPendingInstruments; 78 private List<PaymentInstrument> mPendingInstruments;
80 private SectionInformation mPaymentMethodsSection; 79 private SectionInformation mPaymentMethodsSection;
81 private PaymentRequestUI mUI; 80 private PaymentRequestUI mUI;
82 private Callback<PaymentInformation> mPaymentInformationCallback; 81 private Callback<PaymentInformation> mPaymentInformationCallback;
83 private Pattern mRegionCodePattern; 82 private Pattern mRegionCodePattern;
84 private boolean mMerchantNeedsShippingAddress; 83 private boolean mMerchantNeedsShippingAddress;
85 84
86 /** 85 /**
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 137
139 if (mContext == null) { 138 if (mContext == null) {
140 disconnectFromClientWithDebugMessage("Web contents don't have associ ated activity"); 139 disconnectFromClientWithDebugMessage("Web contents don't have associ ated activity");
141 } 140 }
142 } 141 }
143 142
144 /** 143 /**
145 * Called by the merchant website to show the payment request to the user. 144 * Called by the merchant website to show the payment request to the user.
146 */ 145 */
147 @Override 146 @Override
148 public void show(String[] supportedMethods, PaymentDetails details, PaymentO ptions options, 147 public void show(PaymentMethodData[] methodData, PaymentDetails details,
149 String stringifiedData) { 148 PaymentOptions options) {
150 if (mClient == null) return; 149 if (mClient == null) return;
151 150
152 if (mSupportedMethods != null) { 151 if (mMethodData != null) {
153 disconnectFromClientWithDebugMessage("PaymentRequest.show() called m ore than once."); 152 disconnectFromClientWithDebugMessage("PaymentRequest.show() called m ore than once.");
154 return; 153 return;
155 } 154 }
156 155
157 mSupportedMethods = getValidatedSupportedMethods(supportedMethods); 156 mMethodData = getValidatedMethodData(methodData);
158 if (mSupportedMethods == null) { 157 if (mMethodData == null) {
159 disconnectFromClientWithDebugMessage("Invalid payment methods"); 158 disconnectFromClientWithDebugMessage("Invalid payment methods or dat a");
160 return; 159 return;
161 } 160 }
162 161
163 if (!setLineItemsAndShippingOptionsOrDisconnectFromClient(details)) retu rn; 162 if (!setLineItemsAndShippingOptionsOrDisconnectFromClient(details)) retu rn;
164 163
165 // If the merchant requests shipping and does not provide shipping optio ns here, then the 164 // If the merchant requests shipping and does not provide shipping optio ns here, then the
166 // merchant needs the shipping address to calculate shipping price and a vailability. 165 // merchant needs the shipping address to calculate shipping price and a vailability.
167 boolean requestShipping = options != null && options.requestShipping; 166 boolean requestShipping = options != null && options.requestShipping;
168 mMerchantNeedsShippingAddress = requestShipping && mShippingOptionsSecti on.isEmpty(); 167 mMerchantNeedsShippingAddress = requestShipping && mShippingOptionsSecti on.isEmpty();
169 168
170 mData = getValidatedData(mSupportedMethods, stringifiedData);
171 if (mData == null) {
172 disconnectFromClientWithDebugMessage("Invalid payment method specifi c data");
173 return;
174 }
175
176 List<AutofillAddress> addresses = new ArrayList<>(); 169 List<AutofillAddress> addresses = new ArrayList<>();
177 List<AutofillProfile> profiles = PersonalDataManager.getInstance().getAd dressOnlyProfiles(); 170 List<AutofillProfile> profiles = PersonalDataManager.getInstance().getAd dressOnlyProfiles();
178 for (int i = 0; i < profiles.size(); i++) { 171 for (int i = 0; i < profiles.size(); i++) {
179 AutofillProfile profile = profiles.get(i); 172 AutofillProfile profile = profiles.get(i);
180 if (profile.getCountryCode() != null 173 if (profile.getCountryCode() != null
181 && mRegionCodePattern.matcher(profile.getCountryCode()).matc hes() 174 && mRegionCodePattern.matcher(profile.getCountryCode()).matc hes()
182 && profile.getStreetAddress() != null && profile.getRegion() != null 175 && profile.getStreetAddress() != null && profile.getRegion() != null
183 && profile.getLocality() != null && profile.getDependentLoca lity() != null 176 && profile.getLocality() != null && profile.getDependentLoca lity() != null
184 && profile.getPostalCode() != null && profile.getSortingCode () != null 177 && profile.getPostalCode() != null && profile.getSortingCode () != null
185 && profile.getCompanyName() != null && profile.getFullName() != null) { 178 && profile.getCompanyName() != null && profile.getFullName() != null) {
186 addresses.add(new AutofillAddress(profile)); 179 addresses.add(new AutofillAddress(profile));
187 } 180 }
188 } 181 }
189 182
190 int selectedIndex = SectionInformation.NO_SELECTION; 183 int selectedIndex = SectionInformation.NO_SELECTION;
191 if (!addresses.isEmpty() && mShippingOptionsSection.getSelectedItem() != null) { 184 if (!addresses.isEmpty() && mShippingOptionsSection.getSelectedItem() != null) {
192 selectedIndex = 0; 185 selectedIndex = 0;
193 } 186 }
194 mShippingAddressesSection = new SectionInformation( 187 mShippingAddressesSection = new SectionInformation(
195 PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, selectedIndex, address es); 188 PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, selectedIndex, address es);
196 189
197 mPendingApps = new ArrayList<>(mApps); 190 mPendingApps = new ArrayList<>(mApps);
198 mPendingInstruments = new ArrayList<>(); 191 mPendingInstruments = new ArrayList<>();
199 boolean isGettingInstruments = false; 192 boolean isGettingInstruments = false;
200 193
201 for (int i = 0; i < mApps.size(); i++) { 194 for (int i = 0; i < mApps.size(); i++) {
202 PaymentApp app = mApps.get(i); 195 PaymentApp app = mApps.get(i);
203 Set<String> appMethods = app.getSupportedMethodNames(); 196 Set<String> appMethods = app.getSupportedMethodNames();
204 appMethods.retainAll(mSupportedMethods); 197 appMethods.retainAll(mMethodData.keySet());
205 if (appMethods.isEmpty()) { 198 if (appMethods.isEmpty()) {
206 mPendingApps.remove(app); 199 mPendingApps.remove(app);
207 } else { 200 } else {
208 isGettingInstruments = true; 201 isGettingInstruments = true;
209 app.getInstruments(mPaymentItems, this); 202 app.getInstruments(mPaymentItems, this);
210 } 203 }
211 } 204 }
212 205
213 if (!isGettingInstruments) { 206 if (!isGettingInstruments) {
214 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYP E_PAYMENT_METHODS); 207 mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYP E_PAYMENT_METHODS);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 getValidatedShippingOptions(details.items[0].amount.currencyCode , details); 251 getValidatedShippingOptions(details.items[0].amount.currencyCode , details);
259 if (mShippingOptionsSection == null) { 252 if (mShippingOptionsSection == null) {
260 disconnectFromClientWithDebugMessage("Invalid shipping options"); 253 disconnectFromClientWithDebugMessage("Invalid shipping options");
261 return false; 254 return false;
262 } 255 }
263 mShippingOptions = Arrays.asList(details.shippingOptions); 256 mShippingOptions = Arrays.asList(details.shippingOptions);
264 257
265 return true; 258 return true;
266 } 259 }
267 260
268 private HashSet<String> getValidatedSupportedMethods(String[] methods) { 261 private HashMap<String, JSONObject> getValidatedMethodData(PaymentMethodData [] methodData) {
please use gerrit instead 2016/05/29 19:57:11 Check that methodData is not null and not empty.
zino 2016/06/01 17:43:46 Done.
269 // Payment methods are required. 262 HashMap<String, JSONObject> result = new HashMap<>();
270 if (methods == null || methods.length == 0) return null; 263 for (int i = 0; i < methodData.length; i++) {
264 String[] methods = methodData[i].supportedMethods;
please use gerrit instead 2016/05/29 19:57:11 Move |methods| down to line 278-ish, where you're
zino 2016/06/01 17:43:46 Done.
271 265
272 HashSet<String> result = new HashSet<>(); 266 JSONObject data;
273 for (int i = 0; i < methods.length; i++) { 267 if (TextUtils.isEmpty(methodData[i].data)) {
274 // Payment methods should be non-empty. 268 data = new JSONObject();
please use gerrit instead 2016/05/29 19:57:11 Let's use |null| to represent empty data. Object c
zino 2016/06/01 17:43:46 Done.
275 if (TextUtils.isEmpty(methods[i])) return null; 269 } else {
276 result.add(methods[i]); 270 try {
271 data = new JSONObject(methodData[i].data);
272 } catch (JSONException e) {
273 // Payment method specific data should be a JSON object.
274 return null;
275 }
276 }
277
278 // Payment methods are required.
279 if (methods == null || methods.length == 0) return null;
280
281 for (int j = 0; j < methods.length; j++) {
282 // Payment methods should be non-empty.
283 if (TextUtils.isEmpty(methods[j])) return null;
284 result.put(methods[j], data);
285 }
277 } 286 }
278 287
279 return result; 288 return result;
280 } 289 }
281 290
282 private List<LineItem> getValidatedLineItems(PaymentDetails details) { 291 private List<LineItem> getValidatedLineItems(PaymentDetails details) {
283 // Line items are required. 292 // Line items are required.
284 if (details == null || details.items == null || details.items.length == 0) return null; 293 if (details == null || details.items == null || details.items.length == 0) return null;
285 294
286 for (int i = 0; i < details.items.length; i++) { 295 for (int i = 0; i < details.items.length; i++) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 for (int i = 0; i < details.shippingOptions.length; i++) { 373 for (int i = 0; i < details.shippingOptions.length; i++) {
365 ShippingOption option = details.shippingOptions[i]; 374 ShippingOption option = details.shippingOptions[i];
366 result.add(new PaymentOption(option.id, option.label, 375 result.add(new PaymentOption(option.id, option.label,
367 formatter.format(option.amount.value), PaymentOption.NO_ICON )); 376 formatter.format(option.amount.value), PaymentOption.NO_ICON ));
368 } 377 }
369 378
370 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS, 379 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS,
371 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result ); 380 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result );
372 } 381 }
373 382
374 private JSONObject getValidatedData(Set<String> supportedMethods, String str ingifiedData) {
375 if (TextUtils.isEmpty(stringifiedData)) return new JSONObject();
376
377 JSONObject result;
378 try {
379 result = new JSONObject(stringifiedData);
380 } catch (JSONException e) {
381 // Payment method specific data should be a JSON object.
382 return null;
383 }
384
385 Iterator<String> it = result.keys();
386 while (it.hasNext()) {
387 String name = it.next();
388 // Each key should be one of the supported payment methods.
389 if (!supportedMethods.contains(name)) return null;
390 // Each value should be a JSON object.
391 if (result.optJSONObject(name) == null) return null;
392 }
393
394 return result;
395 }
396
397 /** 383 /**
398 * Called to retrieve the data to show in the initial PaymentRequest UI. 384 * Called to retrieve the data to show in the initial PaymentRequest UI.
399 */ 385 */
400 @Override 386 @Override
401 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) { 387 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) {
402 mPaymentInformationCallback = callback; 388 mPaymentInformationCallback = callback;
403 389
404 if (mPaymentMethodsSection == null) return; 390 if (mPaymentMethodsSection == null) return;
405 391
406 mHandler.post(new Runnable() { 392 mHandler.post(new Runnable() {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 mContext, AutofillCreditCardEditor.class.getName()); 464 mContext, AutofillCreditCardEditor.class.getName());
479 } 465 }
480 } 466 }
481 467
482 @Override 468 @Override
483 public void onPayClicked(PaymentOption selectedShippingAddress, 469 public void onPayClicked(PaymentOption selectedShippingAddress,
484 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) { 470 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) {
485 assert selectedPaymentMethod instanceof PaymentInstrument; 471 assert selectedPaymentMethod instanceof PaymentInstrument;
486 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ; 472 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ;
487 instrument.getDetails(mMerchantName, mOrigin, mPaymentItems, 473 instrument.getDetails(mMerchantName, mOrigin, mPaymentItems,
488 mData.optJSONObject(instrument.getMethodName()), this); 474 mMethodData.get(instrument.getMethodName()), this);
489 } 475 }
490 476
491 @Override 477 @Override
492 public void onDismiss() { 478 public void onDismiss() {
493 disconnectFromClientWithDebugMessage("Dialog dismissed"); 479 disconnectFromClientWithDebugMessage("Dialog dismissed");
494 closeUI(false); 480 closeUI(false);
495 } 481 }
496 482
497 /** 483 /**
498 * Called by the merchant website to abort the payment. 484 * Called by the merchant website to abort the payment.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 /** 518 /**
533 * Called after retrieving the list of payment instruments in an app. 519 * Called after retrieving the list of payment instruments in an app.
534 */ 520 */
535 @Override 521 @Override
536 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) { 522 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) {
537 mPendingApps.remove(app); 523 mPendingApps.remove(app);
538 524
539 if (instruments != null) { 525 if (instruments != null) {
540 for (int i = 0; i < instruments.size(); i++) { 526 for (int i = 0; i < instruments.size(); i++) {
541 PaymentInstrument instrument = instruments.get(i); 527 PaymentInstrument instrument = instruments.get(i);
542 if (mSupportedMethods.contains(instrument.getMethodName())) { 528 if (mMethodData.containsKey(instrument.getMethodName())) {
543 mPendingInstruments.add(instrument); 529 mPendingInstruments.add(instrument);
544 } else { 530 } else {
545 instrument.dismiss(); 531 instrument.dismiss();
546 } 532 }
547 } 533 }
548 } 534 }
549 535
550 if (mPendingApps.isEmpty()) { 536 if (mPendingApps.isEmpty()) {
551 mPaymentMethodsSection = new SectionInformation( 537 mPaymentMethodsSection = new SectionInformation(
552 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s); 538 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 } 606 }
621 mPaymentMethodsSection = null; 607 mPaymentMethodsSection = null;
622 } 608 }
623 } 609 }
624 610
625 private void closeClient() { 611 private void closeClient() {
626 if (mClient != null) mClient.close(); 612 if (mClient != null) mClient.close();
627 mClient = null; 613 mClient = null;
628 } 614 }
629 } 615 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/android/payments/free_shipping.js » ('j') | chrome/test/data/android/payments/no_shipping.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698