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

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> mDisplayItems; 73 private List<PaymentItem> mDisplayItems;
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(mDisplayItems, this); 202 app.getInstruments(mDisplayItems, 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.displayItems[0].amount.curre ncyCode, details); 251 getValidatedShippingOptions(details.displayItems[0].amount.curre ncyCode, 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) {
269 // Payment methods are required. 262 // Payment methodData are required.
270 if (methods == null || methods.length == 0) return null; 263 if (methodData == null || methodData.length == 0) return null;
gone 2016/06/06 18:07:33 nit: newline here.
264 HashMap<String, JSONObject> result = new HashMap<>();
265 for (int i = 0; i < methodData.length; i++) {
266 JSONObject data = null;
267 if (!TextUtils.isEmpty(methodData[i].data)) {
268 try {
269 data = new JSONObject(methodData[i].data);
270 } catch (JSONException e) {
271 // Payment method specific data should be a JSON object.
272 return null;
gone 2016/06/06 18:07:33 I confirmed with rouslan that you're intentionally
273 }
274 }
271 275
272 HashSet<String> result = new HashSet<>(); 276 String[] methods = methodData[i].supportedMethods;
273 for (int i = 0; i < methods.length; i++) { 277
274 // Payment methods should be non-empty. 278 // Payment methods are required.
275 if (TextUtils.isEmpty(methods[i])) return null; 279 if (methods == null || methods.length == 0) return null;
276 result.add(methods[i]); 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.displayItems == null || details.displayIt ems.length == 0) { 293 if (details == null || details.displayItems == null || details.displayIt ems.length == 0) {
285 return null; 294 return null;
286 } 295 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 for (int i = 0; i < details.shippingOptions.length; i++) { 379 for (int i = 0; i < details.shippingOptions.length; i++) {
371 ShippingOption option = details.shippingOptions[i]; 380 ShippingOption option = details.shippingOptions[i];
372 result.add(new PaymentOption(option.id, option.label, 381 result.add(new PaymentOption(option.id, option.label,
373 formatter.format(option.amount.value), PaymentOption.NO_ICON )); 382 formatter.format(option.amount.value), PaymentOption.NO_ICON ));
374 } 383 }
375 384
376 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS, 385 return new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_OPTIONS,
377 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result ); 386 result.size() == 1 ? 0 : SectionInformation.NO_SELECTION, result );
378 } 387 }
379 388
380 private JSONObject getValidatedData(Set<String> supportedMethods, String str ingifiedData) {
381 if (TextUtils.isEmpty(stringifiedData)) return new JSONObject();
382
383 JSONObject result;
384 try {
385 result = new JSONObject(stringifiedData);
386 } catch (JSONException e) {
387 // Payment method specific data should be a JSON object.
388 return null;
389 }
390
391 Iterator<String> it = result.keys();
392 while (it.hasNext()) {
393 String name = it.next();
394 // Each key should be one of the supported payment methods.
395 if (!supportedMethods.contains(name)) return null;
396 // Each value should be a JSON object.
397 if (result.optJSONObject(name) == null) return null;
398 }
399
400 return result;
401 }
402
403 /** 389 /**
404 * Called to retrieve the data to show in the initial PaymentRequest UI. 390 * Called to retrieve the data to show in the initial PaymentRequest UI.
405 */ 391 */
406 @Override 392 @Override
407 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) { 393 public void getDefaultPaymentInformation(Callback<PaymentInformation> callba ck) {
408 mPaymentInformationCallback = callback; 394 mPaymentInformationCallback = callback;
409 395
410 if (mPaymentMethodsSection == null) return; 396 if (mPaymentMethodsSection == null) return;
411 397
412 mHandler.post(new Runnable() { 398 mHandler.post(new Runnable() {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 mContext, AutofillCreditCardEditor.class.getName()); 470 mContext, AutofillCreditCardEditor.class.getName());
485 } 471 }
486 } 472 }
487 473
488 @Override 474 @Override
489 public void onPayClicked(PaymentOption selectedShippingAddress, 475 public void onPayClicked(PaymentOption selectedShippingAddress,
490 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) { 476 PaymentOption selectedShippingOption, PaymentOption selectedPaymentM ethod) {
491 assert selectedPaymentMethod instanceof PaymentInstrument; 477 assert selectedPaymentMethod instanceof PaymentInstrument;
492 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ; 478 PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod ;
493 instrument.getDetails(mMerchantName, mOrigin, mDisplayItems, 479 instrument.getDetails(mMerchantName, mOrigin, mDisplayItems,
494 mData.optJSONObject(instrument.getMethodName()), this); 480 mMethodData.get(instrument.getMethodName()), this);
495 } 481 }
496 482
497 @Override 483 @Override
498 public void onDismiss() { 484 public void onDismiss() {
499 disconnectFromClientWithDebugMessage("Dialog dismissed"); 485 disconnectFromClientWithDebugMessage("Dialog dismissed");
500 closeUI(false); 486 closeUI(false);
501 } 487 }
502 488
503 /** 489 /**
504 * Called by the merchant website to abort the payment. 490 * Called by the merchant website to abort the payment.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 /** 524 /**
539 * Called after retrieving the list of payment instruments in an app. 525 * Called after retrieving the list of payment instruments in an app.
540 */ 526 */
541 @Override 527 @Override
542 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) { 528 public void onInstrumentsReady(PaymentApp app, List<PaymentInstrument> instr uments) {
543 mPendingApps.remove(app); 529 mPendingApps.remove(app);
544 530
545 if (instruments != null) { 531 if (instruments != null) {
546 for (int i = 0; i < instruments.size(); i++) { 532 for (int i = 0; i < instruments.size(); i++) {
547 PaymentInstrument instrument = instruments.get(i); 533 PaymentInstrument instrument = instruments.get(i);
548 if (mSupportedMethods.contains(instrument.getMethodName())) { 534 if (mMethodData.containsKey(instrument.getMethodName())) {
549 mPendingInstruments.add(instrument); 535 mPendingInstruments.add(instrument);
550 } else { 536 } else {
551 instrument.dismiss(); 537 instrument.dismiss();
552 } 538 }
553 } 539 }
554 } 540 }
555 541
556 if (mPendingApps.isEmpty()) { 542 if (mPendingApps.isEmpty()) {
557 mPaymentMethodsSection = new SectionInformation( 543 mPaymentMethodsSection = new SectionInformation(
558 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s); 544 PaymentRequestUI.TYPE_PAYMENT_METHODS, 0, mPendingInstrument s);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 } 612 }
627 mPaymentMethodsSection = null; 613 mPaymentMethodsSection = null;
628 } 614 }
629 } 615 }
630 616
631 private void closeClient() { 617 private void closeClient() {
632 if (mClient != null) mClient.close(); 618 if (mClient != null) mClient.close();
633 mClient = null; 619 mClient = null;
634 } 620 }
635 } 621 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698