Chromium Code Reviews| 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.text.TextUtils; | 10 import android.text.TextUtils; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |