braintree / braintree_android

Braintree SDK for Android
https://developer.paypal.com/braintree/docs/start/hello-client/android/v4
MIT License
409 stars 234 forks source link

Crash in 'BrowserSwitchClient' in version 3.14.0 #313

Closed TatyanaRTB closed 4 years ago

TatyanaRTB commented 4 years ago

General information

Issue description

The issue is related to https://github.com/braintree/braintree_android/issues/308. Firstly we observed crash from the #308 and now after fixes crash happens in next step by code, when BrowserSwitchOptions.start is called:

ThreeDSecure:

public static void continuePerformVerification(BraintreeFragment fragment, ThreeDSecureRequest request, ThreeDSecureLookup threeDSecureLookup) {
    boolean showChallenge = threeDSecureLookup.getAcsUrl() != null;
    String threeDSecureVersion = threeDSecureLookup.getThreeDSecureVersion();
    fragment.sendAnalyticsEvent(String.format("three-d-secure.verification-flow.challenge-presented.%b", showChallenge));
    fragment.sendAnalyticsEvent(String.format("three-d-secure.verification-flow.3ds-version.%s", threeDSecureVersion));
    if (!showChallenge) {
        completeVerificationFlowWithNoncePayload(fragment, threeDSecureLookup.getCardNonce());
    } else if (!threeDSecureVersion.startsWith("2.")) {
        fragment.browserSwitch(13487, ThreeDSecureV1BrowserSwitchHelper.getUrl(fragment.getReturnUrlScheme(), fragment.getConfiguration().getAssetsUrl(), request, threeDSecureLookup));
    } else {
        performCardinalAuthentication(fragment, threeDSecureLookup);
    }
}

BrowserSwitchFragment:

public void browserSwitch(int requestCode, String url) {
    BrowserSwitchOptions browserSwitchOptions = (new BrowserSwitchOptions()).requestCode(requestCode).url(Uri.parse(url));
    this.browserSwitchClient.start(browserSwitchOptions, this);
}

BrowserSwitchClient:

public void start(BrowserSwitchOptions browserSwitchOptions, Fragment fragment) {
    if (fragment instanceof BrowserSwitchListener) {
        this.start(browserSwitchOptions, fragment, (BrowserSwitchListener)fragment);
    } else {
        throw new IllegalArgumentException("Fragment must implement BrowserSwitchListener.");
    }
}

The issue can be reproduced by the following steps:

  1. Select credit card option in DropIn dialog
  2. Enter card parameters
  3. Press Go/Next button on the keyboard two-three times: https://monosnap.com/file/kcCFXR7wLZkKU7MtGu1bgvD6dHJaqF

Please block the button from several payment attempts if request to Braintree API is already in progress. Several payment flows are started in parallel and BraintreeFragment is detached from Activity when receive first successful payment result. Other payment results cause this crash.

java.lang.IllegalStateException: Fragment must be attached to an activity.
    at com.braintreepayments.browserswitch.BrowserSwitchClient.start(BrowserSwitchClient.java:206) ~[na:0.0]
    at com.braintreepayments.browserswitch.BrowserSwitchClient.start(BrowserSwitchClient.java:186) ~[na:0.0]
    at com.braintreepayments.browserswitch.BrowserSwitchFragment.browserSwitch(BrowserSwitchFragment.java:59) ~[na:0.0]
    at com.braintreepayments.api.ThreeDSecure.continuePerformVerification(ThreeDSecure.java:266) ~[na:0.0]
    at com.braintreepayments.api.ThreeDSecure$3.onLookupComplete(ThreeDSecure.java:155) ~[na:0.0]
    at com.braintreepayments.api.ThreeDSecure$7.success(ThreeDSecure.java:503) ~[na:0.0]
    at com.braintreepayments.api.internal.HttpClient$3.run(HttpClient.java:288) ~[na:0.0]
    at android.os.Handler.handleCallback(Handler.java:739) ~[na:0.0]
    at android.os.Handler.dispatchMessage(Handler.java:95) ~[na:0.0]
    at android.os.Looper.loop(Looper.java:157) ~[na:0.0]
    at android.app.ActivityThread.main(ActivityThread.java:5429) ~[na:0.0]
    at java.lang.reflect.Method.invoke(Native Method) ~[na:0.0]
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) ~[na:0.0]
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) ~[na:0.0]
sshropshire commented 4 years ago

@TatyanaRTB thank you for your feedback. For updates on this, please follow https://github.com/braintree/braintree-android-drop-in/issues/196.