From a4f80568e38795951da26f6796dac3d3b0462c35 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 10:26:46 -0600 Subject: [PATCH 1/8] Check for listener before returning result --- .../braintreepayments/api/VenmoClient.java | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java index 387bacd081..d2d4d673b2 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java @@ -131,8 +131,8 @@ public void tokenizeVenmoAccount(@NonNull final FragmentActivity activity, @NonN tokenizeVenmoAccount(activity, request, new VenmoTokenizeAccountCallback() { @Override public void onResult(@Nullable Exception error) { - if (error != null) { - listener.onVenmoFailure(error); + if (error != null ) { + deliverVenmoFailure(error); } } }); @@ -254,19 +254,19 @@ public void onResult(@Nullable VenmoAccountNonce nonce, @Nullable Exception erro @Override public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Exception error) { if (venmoAccountNonce != null) { - listener.onVenmoSuccess(venmoAccountNonce); + deliverVenmoSuccess(venmoAccountNonce); } else if (error != null) { - listener.onVenmoFailure(error); + deliverVenmoFailure(error); } } }); } else { braintreeClient.sendAnalyticsEvent("pay-with-venmo.app-switch.failure"); - listener.onVenmoSuccess(nonce); + deliverVenmoSuccess(nonce); } } else { braintreeClient.sendAnalyticsEvent("pay-with-venmo.app-switch.failure"); - listener.onVenmoFailure(error); + deliverVenmoFailure(error); } } }); @@ -278,22 +278,22 @@ public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Ex vaultVenmoAccountNonce(nonce, new VenmoOnActivityResultCallback() { @Override public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Exception error) { - if (venmoAccountNonce != null) { - listener.onVenmoSuccess(venmoAccountNonce); - } else if (error != null) { - listener.onVenmoFailure(error); - } + if (venmoAccountNonce != null) { + deliverVenmoSuccess(venmoAccountNonce); + } else if (error != null) { + deliverVenmoFailure(error); + } } }); } else { String venmoUsername = venmoResult.getVenmoUsername(); VenmoAccountNonce venmoAccountNonce = new VenmoAccountNonce(nonce, venmoUsername, false); - listener.onVenmoSuccess(venmoAccountNonce); + deliverVenmoSuccess(venmoAccountNonce); } } } else if (authError != null) { - listener.onVenmoFailure(authError); + deliverVenmoFailure(authError); } } }); @@ -302,7 +302,19 @@ public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Ex if (venmoResult.getError() instanceof UserCanceledException) { braintreeClient.sendAnalyticsEvent("pay-with-venmo.app-switch.canceled"); } - listener.onVenmoFailure(venmoResult.getError()); + deliverVenmoFailure(venmoResult.getError()); + } + } + + private void deliverVenmoSuccess(VenmoAccountNonce venmoAccountNonce) { + if (listener != null) { + listener.onVenmoSuccess(venmoAccountNonce); + } + } + + private void deliverVenmoFailure(Exception error) { + if (listener != null) { + listener.onVenmoFailure(error); } } From a7d8117c3be5f83a1c50f78fa03a8b0fa02239f1 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 10:31:35 -0600 Subject: [PATCH 2/8] Add unit test --- .../api/VenmoClientUnitTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java index ce883ae498..be54ca7f3b 100644 --- a/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java +++ b/Venmo/src/test/java/com/braintreepayments/api/VenmoClientUnitTest.java @@ -156,6 +156,31 @@ public void showVenmoInGooglePlayStore_sendsAnalyticsEvent() { verify(braintreeClient).sendAnalyticsEvent("android.pay-with-venmo.app-store.invoked"); } + @Test + public void tokenizeVenmoAccount_whenListenerNull_returnsNothing() { + BraintreeClient braintreeClient = new MockBraintreeClientBuilder() + .configuration(venmoEnabledConfiguration) + .sessionId("session-id") + .integration("custom") + .authorizationSuccess(clientToken) + .build(); + + VenmoApi venmoApi = new MockVenmoApiBuilder() + .createPaymentContextSuccess("venmo-payment-context-id") + .build(); + + when(deviceInspector.isVenmoAppSwitchAvailable(activity)).thenReturn(true); + + VenmoRequest request = new VenmoRequest(VenmoPaymentMethodUsage.SINGLE_USE); + request.setProfileId("sample-venmo-merchant"); + request.setCollectCustomerBillingAddress(true); + + VenmoClient sut = new VenmoClient(null, null, braintreeClient, venmoApi, sharedPrefsWriter, deviceInspector); + sut.tokenizeVenmoAccount(activity, request); + verify(listener, never()).onVenmoFailure(any(Exception.class)); + verify(listener, never()).onVenmoSuccess(any(VenmoAccountNonce.class)); + } + @Test public void tokenizeVenmoAccount_whenCreatePaymentContextSucceeds_withObserver_launchesObserverWithVenmoIntentData_andSendsAnalytics() { BraintreeClient braintreeClient = new MockBraintreeClientBuilder() From 2def0c6bcdae256701f7438f5df665bf916f6996 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 10:34:45 -0600 Subject: [PATCH 3/8] Add CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60279ba6cf..26f656aa9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Braintree Android SDK Release Notes +## unreleased + +* Venmo + * Fix NPE when `VenmoListener` is null (fixes #832) + ## 4.40.0 (2023-11-16) * PayPalNativeCheckout From 0721b439249cee4fca57562c7f197092b6e7256e Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 10:35:55 -0600 Subject: [PATCH 4/8] Fix spacing --- .../java/com/braintreepayments/api/VenmoClient.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java index d2d4d673b2..0c2fb85150 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java @@ -131,7 +131,7 @@ public void tokenizeVenmoAccount(@NonNull final FragmentActivity activity, @NonN tokenizeVenmoAccount(activity, request, new VenmoTokenizeAccountCallback() { @Override public void onResult(@Nullable Exception error) { - if (error != null ) { + if (error != null) { deliverVenmoFailure(error); } } @@ -278,11 +278,11 @@ public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Ex vaultVenmoAccountNonce(nonce, new VenmoOnActivityResultCallback() { @Override public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Exception error) { - if (venmoAccountNonce != null) { - deliverVenmoSuccess(venmoAccountNonce); - } else if (error != null) { - deliverVenmoFailure(error); - } + if (venmoAccountNonce != null) { + deliverVenmoSuccess(venmoAccountNonce); + } else if (error != null) { + deliverVenmoFailure(error); + } } }); } else { From c457018fb70d6b8487be85b8379d5555488a4731 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 14:18:25 -0600 Subject: [PATCH 5/8] Log warning if listener is null --- .../main/java/com/braintreepayments/api/VenmoClient.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java index 0c2fb85150..eca5a17cac 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.net.Uri; import android.text.TextUtils; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -33,6 +34,8 @@ public class VenmoClient { static final String EXTRA_USERNAME = "com.braintreepayments.api.EXTRA_USER_NAME"; static final String EXTRA_RESOURCE_ID = "com.braintreepayments.api.EXTRA_RESOURCE_ID"; + static final String LOGGING_TAG = "Braintree"; + private final BraintreeClient braintreeClient; private final VenmoApi venmoApi; private final VenmoSharedPrefsWriter sharedPrefsWriter; @@ -309,12 +312,16 @@ public void onResult(@Nullable VenmoAccountNonce venmoAccountNonce, @Nullable Ex private void deliverVenmoSuccess(VenmoAccountNonce venmoAccountNonce) { if (listener != null) { listener.onVenmoSuccess(venmoAccountNonce); + } else { + Log.w(LOGGING_TAG, "Unable to deliver result to null listener"); } } private void deliverVenmoFailure(Exception error) { if (listener != null) { listener.onVenmoFailure(error); + } else { + Log.w(LOGGING_TAG, "Unable to deliver result to null listener"); } } From dc02b8e77168a11d6d2c2f0c057cd6264fef7cb9 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 14:34:31 -0600 Subject: [PATCH 6/8] Move logging to utils class --- .../com/braintreepayments/api/LoggingUtils.kt | 16 ++++++++++++++++ .../com/braintreepayments/api/VenmoClient.java | 6 ++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt diff --git a/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt new file mode 100644 index 0000000000..a7da7405ba --- /dev/null +++ b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt @@ -0,0 +1,16 @@ +package com.braintreepayments.api + +import androidx.annotation.RestrictTo + +/** + * @suppress + */ +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +object LoggingUtils { + + const val TAG = "Braintree" + + const val LISTENER_WARNING = "Unable to deliver result to null listener" +} + + diff --git a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java index eca5a17cac..2b484dd8bc 100644 --- a/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java +++ b/Venmo/src/main/java/com/braintreepayments/api/VenmoClient.java @@ -34,8 +34,6 @@ public class VenmoClient { static final String EXTRA_USERNAME = "com.braintreepayments.api.EXTRA_USER_NAME"; static final String EXTRA_RESOURCE_ID = "com.braintreepayments.api.EXTRA_RESOURCE_ID"; - static final String LOGGING_TAG = "Braintree"; - private final BraintreeClient braintreeClient; private final VenmoApi venmoApi; private final VenmoSharedPrefsWriter sharedPrefsWriter; @@ -313,7 +311,7 @@ private void deliverVenmoSuccess(VenmoAccountNonce venmoAccountNonce) { if (listener != null) { listener.onVenmoSuccess(venmoAccountNonce); } else { - Log.w(LOGGING_TAG, "Unable to deliver result to null listener"); + Log.w(LoggingUtils.TAG, LoggingUtils.LISTENER_WARNING); } } @@ -321,7 +319,7 @@ private void deliverVenmoFailure(Exception error) { if (listener != null) { listener.onVenmoFailure(error); } else { - Log.w(LOGGING_TAG, "Unable to deliver result to null listener"); + Log.w(LoggingUtils.TAG, LoggingUtils.LISTENER_WARNING); } } From 475ff15eb18e99106a790ed7e26a57a10b822699 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 14:36:16 -0600 Subject: [PATCH 7/8] Update tag name --- .../src/main/java/com/braintreepayments/api/LoggingUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt index a7da7405ba..c32c9e7ec5 100644 --- a/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt +++ b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt @@ -8,7 +8,7 @@ import androidx.annotation.RestrictTo @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) object LoggingUtils { - const val TAG = "Braintree" + const val TAG = "Braintree SDK" const val LISTENER_WARNING = "Unable to deliver result to null listener" } From 033bfb8a0e49a97bcdcfc83e0c02ef08ca51de9d Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Mon, 11 Dec 2023 14:42:38 -0600 Subject: [PATCH 8/8] Fix lint --- .../src/main/java/com/braintreepayments/api/LoggingUtils.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt index c32c9e7ec5..7e07e7a605 100644 --- a/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt +++ b/SharedUtils/src/main/java/com/braintreepayments/api/LoggingUtils.kt @@ -12,5 +12,3 @@ object LoggingUtils { const val LISTENER_WARNING = "Unable to deliver result to null listener" } - -