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

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

Issue 2500183002: Do not parse JSON in the browser. (Closed)
Patch Set: Created 4 years, 1 month 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;
11 11
12 import org.json.JSONException;
13 import org.json.JSONObject;
14
15 import org.chromium.base.Callback; 12 import org.chromium.base.Callback;
16 import org.chromium.base.Log; 13 import org.chromium.base.Log;
17 import org.chromium.base.VisibleForTesting; 14 import org.chromium.base.VisibleForTesting;
18 import org.chromium.base.metrics.RecordHistogram; 15 import org.chromium.base.metrics.RecordHistogram;
19 import org.chromium.chrome.R; 16 import org.chromium.chrome.R;
20 import org.chromium.chrome.browser.ChromeActivity; 17 import org.chromium.chrome.browser.ChromeActivity;
21 import org.chromium.chrome.browser.ChromeFeatureList; 18 import org.chromium.chrome.browser.ChromeFeatureList;
22 import org.chromium.chrome.browser.autofill.PersonalDataManager; 19 import org.chromium.chrome.browser.autofill.PersonalDataManager;
23 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; 20 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
24 import org.chromium.chrome.browser.favicon.FaviconHelper; 21 import org.chromium.chrome.browser.favicon.FaviconHelper;
25 import org.chromium.chrome.browser.payments.ui.Completable; 22 import org.chromium.chrome.browser.payments.ui.Completable;
26 import org.chromium.chrome.browser.payments.ui.LineItem; 23 import org.chromium.chrome.browser.payments.ui.LineItem;
27 import org.chromium.chrome.browser.payments.ui.PaymentInformation; 24 import org.chromium.chrome.browser.payments.ui.PaymentInformation;
28 import org.chromium.chrome.browser.payments.ui.PaymentOption; 25 import org.chromium.chrome.browser.payments.ui.PaymentOption;
29 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; 26 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
30 import org.chromium.chrome.browser.payments.ui.SectionInformation; 27 import org.chromium.chrome.browser.payments.ui.SectionInformation;
31 import org.chromium.chrome.browser.payments.ui.ShoppingCart; 28 import org.chromium.chrome.browser.payments.ui.ShoppingCart;
32 import org.chromium.chrome.browser.profiles.Profile; 29 import org.chromium.chrome.browser.profiles.Profile;
33 import org.chromium.chrome.browser.tab.Tab; 30 import org.chromium.chrome.browser.tab.Tab;
34 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; 31 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
35 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; 32 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
36 import org.chromium.chrome.browser.tabmodel.TabModel; 33 import org.chromium.chrome.browser.tabmodel.TabModel;
37 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType; 34 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
38 import org.chromium.chrome.browser.tabmodel.TabModelObserver; 35 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
39 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; 36 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
40 import org.chromium.components.safejson.JsonSanitizer;
41 import org.chromium.components.url_formatter.UrlFormatter; 37 import org.chromium.components.url_formatter.UrlFormatter;
42 import org.chromium.content_public.browser.WebContents; 38 import org.chromium.content_public.browser.WebContents;
43 import org.chromium.mojo.system.MojoException; 39 import org.chromium.mojo.system.MojoException;
44 import org.chromium.payments.mojom.PaymentComplete; 40 import org.chromium.payments.mojom.PaymentComplete;
45 import org.chromium.payments.mojom.PaymentDetails; 41 import org.chromium.payments.mojom.PaymentDetails;
46 import org.chromium.payments.mojom.PaymentErrorReason; 42 import org.chromium.payments.mojom.PaymentErrorReason;
47 import org.chromium.payments.mojom.PaymentItem; 43 import org.chromium.payments.mojom.PaymentItem;
48 import org.chromium.payments.mojom.PaymentMethodData; 44 import org.chromium.payments.mojom.PaymentMethodData;
49 import org.chromium.payments.mojom.PaymentOptions; 45 import org.chromium.payments.mojom.PaymentOptions;
50 import org.chromium.payments.mojom.PaymentRequest; 46 import org.chromium.payments.mojom.PaymentRequest;
51 import org.chromium.payments.mojom.PaymentRequestClient; 47 import org.chromium.payments.mojom.PaymentRequestClient;
52 import org.chromium.payments.mojom.PaymentResponse; 48 import org.chromium.payments.mojom.PaymentResponse;
53 import org.chromium.payments.mojom.PaymentShippingOption; 49 import org.chromium.payments.mojom.PaymentShippingOption;
54 import org.chromium.payments.mojom.PaymentShippingType; 50 import org.chromium.payments.mojom.PaymentShippingType;
55 51
56 import java.io.IOException;
57 import java.util.ArrayList; 52 import java.util.ArrayList;
58 import java.util.Arrays; 53 import java.util.Arrays;
59 import java.util.Collections; 54 import java.util.Collections;
60 import java.util.Comparator; 55 import java.util.Comparator;
61 import java.util.HashMap; 56 import java.util.HashMap;
62 import java.util.HashSet; 57 import java.util.HashSet;
63 import java.util.List; 58 import java.util.List;
64 import java.util.Locale; 59 import java.util.Locale;
65 import java.util.Map; 60 import java.util.Map;
66 import java.util.Set; 61 import java.util.Set;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 * price string. This data is passed to the UI. 167 * price string. This data is passed to the UI.
173 */ 168 */
174 private ShoppingCart mUiShoppingCart; 169 private ShoppingCart mUiShoppingCart;
175 170
176 /** 171 /**
177 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping 172 * The UI model for the shipping options. Includes the label and sublabel fo r each shipping
178 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI. 173 * option. Also keeps track of the selected shipping option. This data is pa ssed to the UI.
179 */ 174 */
180 private SectionInformation mUiShippingOptions; 175 private SectionInformation mUiShippingOptions;
181 176
182 private Map<String, JSONObject> mMethodData; 177 private Map<String, PaymentMethodData> mMethodData;
183 private SectionInformation mShippingAddressesSection; 178 private SectionInformation mShippingAddressesSection;
184 private SectionInformation mContactSection; 179 private SectionInformation mContactSection;
185 private List<PaymentApp> mPendingApps; 180 private List<PaymentApp> mPendingApps;
186 private List<PaymentInstrument> mPendingInstruments; 181 private List<PaymentInstrument> mPendingInstruments;
187 private List<PaymentInstrument> mPendingAutofillInstruments; 182 private List<PaymentInstrument> mPendingAutofillInstruments;
188 private SectionInformation mPaymentMethodsSection; 183 private SectionInformation mPaymentMethodsSection;
189 private PaymentRequestUI mUI; 184 private PaymentRequestUI mUI;
190 private Callback<PaymentInformation> mPaymentInformationCallback; 185 private Callback<PaymentInformation> mPaymentInformationCallback;
191 private boolean mPaymentAppRunning; 186 private boolean mPaymentAppRunning;
192 private boolean mMerchantSupportsAutofillPaymentInstruments; 187 private boolean mMerchantSupportsAutofillPaymentInstruments;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 409
415 // Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be 410 // Catch any time the user switches tabs. Because the dialog is modal, a user shouldn't be
416 // allowed to switch tabs, which can happen if the user receives an exte rnal Intent. 411 // allowed to switch tabs, which can happen if the user receives an exte rnal Intent.
417 mContext.getTabModelSelector().addObserver(mSelectorObserver); 412 mContext.getTabModelSelector().addObserver(mSelectorObserver);
418 mContext.getCurrentTabModel().addObserver(mTabModelObserver); 413 mContext.getCurrentTabModel().addObserver(mTabModelObserver);
419 414
420 mUI.show(); 415 mUI.show();
421 recordSuccessFunnelHistograms("Shown"); 416 recordSuccessFunnelHistograms("Shown");
422 } 417 }
423 418
424 private static Map<String, JSONObject> getValidatedMethodData( 419 private static Map<String, PaymentMethodData> getValidatedMethodData(
425 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) { 420 PaymentMethodData[] methodData, CardEditor paymentMethodsCollector) {
426 // Payment methodData are required. 421 // Payment methodData are required.
427 if (methodData == null || methodData.length == 0) return null; 422 if (methodData == null || methodData.length == 0) return null;
428 Map<String, JSONObject> result = new HashMap<>(); 423 Map<String, PaymentMethodData> result = new HashMap<>();
429 for (int i = 0; i < methodData.length; i++) { 424 for (int i = 0; i < methodData.length; i++) {
430 JSONObject data = null;
431 if (!TextUtils.isEmpty(methodData[i].stringifiedData)) {
432 try {
433 data = new JSONObject(JsonSanitizer.sanitize(methodData[i].s tringifiedData));
434 } catch (JSONException | IOException | IllegalStateException e) {
435 // Payment method specific data should be a JSON object.
436 // According to the payment request spec[1], for each method data,
437 // if the data field is supplied but is not a JSON-serializa ble object,
438 // then should throw a TypeError. So, we should return null here even if
439 // only one is bad.
440 // [1] https://w3c.github.io/browser-payment-api/
441 return null;
442 }
443 }
444
445 String[] methods = methodData[i].supportedMethods; 425 String[] methods = methodData[i].supportedMethods;
446 426
447 // Payment methods are required. 427 // Payment methods are required.
448 if (methods == null || methods.length == 0) return null; 428 if (methods == null || methods.length == 0) return null;
449 429
450 for (int j = 0; j < methods.length; j++) { 430 for (int j = 0; j < methods.length; j++) {
451 // Payment methods should be non-empty. 431 // Payment methods should be non-empty.
452 if (TextUtils.isEmpty(methods[j])) return null; 432 if (TextUtils.isEmpty(methods[j])) return null;
453 result.put(methods[j], data); 433 result.put(methods[j], methodData[i]);
454 } 434 }
455 435
456 paymentMethodsCollector.addAcceptedPaymentMethodsIfRecognized(method s); 436 paymentMethodsCollector.addAcceptedPaymentMethodsIfRecognized(method s);
457 } 437 }
458 return result; 438 return result;
459 } 439 }
460 440
461 /** Queries the installed payment apps for their instruments that merchant s upports. */ 441 /** Queries the installed payment apps for their instruments that merchant s upports. */
462 private void getMatchingPaymentInstruments() { 442 private void getMatchingPaymentInstruments() {
463 mPendingApps = new ArrayList<>(mApps); 443 mPendingApps = new ArrayList<>(mApps);
464 mPendingInstruments = new ArrayList<>(); 444 mPendingInstruments = new ArrayList<>();
465 mPendingAutofillInstruments = new ArrayList<>(); 445 mPendingAutofillInstruments = new ArrayList<>();
466 446
467 Map<PaymentApp, Map<String, JSONObject>> queryApps = new HashMap<>(); 447 Map<PaymentApp, Map<String, PaymentMethodData>> queryApps = new HashMap< >();
468 for (int i = 0; i < mApps.size(); i++) { 448 for (int i = 0; i < mApps.size(); i++) {
469 PaymentApp app = mApps.get(i); 449 PaymentApp app = mApps.get(i);
470 Map<String, JSONObject> appMethods = 450 Map<String, PaymentMethodData> appMethods =
471 filterMerchantMethodData(mMethodData, app.getAppMethodNames( )); 451 filterMerchantMethodData(mMethodData, app.getAppMethodNames( ));
472 if (appMethods == null) { 452 if (appMethods == null) {
473 mPendingApps.remove(app); 453 mPendingApps.remove(app);
474 } else { 454 } else {
475 mArePaymentMethodsSupported = true; 455 mArePaymentMethodsSupported = true;
476 mMerchantSupportsAutofillPaymentInstruments |= app instanceof Au tofillPaymentApp; 456 mMerchantSupportsAutofillPaymentInstruments |= app instanceof Au tofillPaymentApp;
477 queryApps.put(app, appMethods); 457 queryApps.put(app, appMethods);
478 } 458 }
479 } 459 }
480 460
481 // Query instruments after mMerchantSupportsAutofillPaymentInstruments h as been initialized, 461 // Query instruments after mMerchantSupportsAutofillPaymentInstruments h as been initialized,
482 // so a fast response from a non-autofill payment app at the front of th e app list does not 462 // so a fast response from a non-autofill payment app at the front of th e app list does not
483 // cause NOT_SUPPORTED payment rejection. 463 // cause NOT_SUPPORTED payment rejection.
484 for (Map.Entry<PaymentApp, Map<String, JSONObject>> q : queryApps.entryS et()) { 464 for (Map.Entry<PaymentApp, Map<String, PaymentMethodData>> q : queryApps .entrySet()) {
485 q.getKey().getInstruments(q.getValue(), this); 465 q.getKey().getInstruments(q.getValue(), this);
486 } 466 }
487 } 467 }
488 468
489 /** Filter out merchant method data that's not relevant to a payment app. Ca n return null. */ 469 /** Filter out merchant method data that's not relevant to a payment app. Ca n return null. */
490 private static Map<String, JSONObject> filterMerchantMethodData( 470 private static Map<String, PaymentMethodData> filterMerchantMethodData(
491 Map<String, JSONObject> merchantMethodData, Set<String> appMethods) { 471 Map<String, PaymentMethodData> merchantMethodData, Set<String> appMe thods) {
492 Map<String, JSONObject> result = null; 472 Map<String, PaymentMethodData> result = null;
493 for (String method : appMethods) { 473 for (String method : appMethods) {
494 if (merchantMethodData.containsKey(method)) { 474 if (merchantMethodData.containsKey(method)) {
495 if (result == null) result = new HashMap<>(); 475 if (result == null) result = new HashMap<>();
496 result.put(method, merchantMethodData.get(method)); 476 result.put(method, merchantMethodData.get(method));
497 } 477 }
498 } 478 }
499 return result; 479 return result;
500 } 480 }
501 481
502 /** 482 /**
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 "PaymentRequest.CheckoutFunnel.Aborted", abortReason, 1146 "PaymentRequest.CheckoutFunnel.Aborted", abortReason,
1167 PaymentRequestMetrics.ABORT_REASON_MAX); 1147 PaymentRequestMetrics.ABORT_REASON_MAX);
1168 1148
1169 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) { 1149 if (abortReason == PaymentRequestMetrics.ABORT_REASON_ABORTED_BY_USER) {
1170 mJourneyLogger.recordJourneyStatsHistograms("UserAborted"); 1150 mJourneyLogger.recordJourneyStatsHistograms("UserAborted");
1171 } else { 1151 } else {
1172 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted"); 1152 mJourneyLogger.recordJourneyStatsHistograms("OtherAborted");
1173 } 1153 }
1174 } 1154 }
1175 } 1155 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698