Skip to content

Commit

Permalink
fix(sdk): missing webview (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
CAMOBAP authored Apr 18, 2023
1 parent 122be4e commit d90ef66
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

# 3.8.1

- Bugfix: report error when missing WebView provider

# 3.8.0

- Feat: new `HCaptcha.reset` to force stop verification and release all resources.
Expand Down
4 changes: 2 additions & 2 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ android {
// See https://developer.android.com/studio/publish/versioning
// versionCode must be integer and be incremented by one for every new update
// android system uses this to prevent downgrades
versionCode 32
versionCode 33

// version number visible to the user
// should follow semantic versioning (See https://semver.org)
versionName "3.8.0"
versionName "3.8.1"

buildConfigField 'String', 'VERSION_NAME', "\"${defaultConfig.versionName}_${defaultConfig.versionCode}\""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import static org.mockito.Mockito.when;

import android.os.Bundle;
import android.util.AndroidRuntimeException;
import android.view.InflateException;
import android.view.LayoutInflater;
import androidx.fragment.app.testing.FragmentScenario;
import androidx.lifecycle.Lifecycle;
Expand Down Expand Up @@ -187,7 +187,7 @@ void onFailure(HCaptchaException exception) {
public void webViewNotInstalled() throws InterruptedException {
final LayoutInflater inflater = mock(LayoutInflater.class);
when(inflater.inflate(eq(R.layout.hcaptcha_fragment), any(), eq(false)))
.thenThrow(AndroidRuntimeException.class);
.thenThrow(InflateException.class);

final CountDownLatch latch = new CountDownLatch(1);

Expand Down
32 changes: 20 additions & 12 deletions sdk/src/main/java/com/hcaptcha/sdk/HCaptcha.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.AndroidRuntimeException;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;

Expand Down Expand Up @@ -91,16 +92,20 @@ void onFailure(final HCaptchaException exception) {
setException(exception);
}
};
if (inputConfig.getHideDialog()) {
// Overwrite certain config values in case the dialog is hidden to avoid behavior collision
this.config = inputConfig.toBuilder()
.size(HCaptchaSize.INVISIBLE)
.loading(false)
.build();
captchaVerifier = new HCaptchaHeadlessWebView(activity, this.config, internalConfig, listener);
} else {
captchaVerifier = HCaptchaDialogFragment.newInstance(inputConfig, internalConfig, listener);
this.config = inputConfig;
try {
if (inputConfig.getHideDialog()) {
// Overwrite certain config values in case the dialog is hidden to avoid behavior collision
this.config = inputConfig.toBuilder()
.size(HCaptchaSize.INVISIBLE)
.loading(false)
.build();
captchaVerifier = new HCaptchaHeadlessWebView(activity, this.config, internalConfig, listener);
} else {
captchaVerifier = HCaptchaDialogFragment.newInstance(inputConfig, internalConfig, listener);
this.config = inputConfig;
}
} catch (AndroidRuntimeException e) {
listener.onFailure(new HCaptchaException(HCaptchaError.ERROR));
}
return this;
}
Expand Down Expand Up @@ -148,8 +153,11 @@ public void reset() {
private HCaptcha startVerification() {
HCaptchaLog.d("HCaptcha.startVerification");
handler.removeCallbacksAndMessages(null);
assert captchaVerifier != null;
captchaVerifier.startVerification(activity);
if (captchaVerifier == null) {
setException(new HCaptchaException(HCaptchaError.ERROR));
} else {
captchaVerifier.startVerification(activity);
}
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.AndroidRuntimeException;
import android.view.InflateException;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
Expand Down Expand Up @@ -120,7 +120,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
loadingContainer.setVisibility(config.getLoading() ? View.VISIBLE : View.GONE);
webViewHelper = new HCaptchaWebViewHelper(new Handler(Looper.getMainLooper()),
requireContext(), config, internalConfig, this, listener, webView);
} catch (AndroidRuntimeException | ClassCastException e) {
} catch (InflateException | ClassCastException e) {
HCaptchaLog.w("Cannot create view. Dismissing dialog...");
// Happens when fragment tries to reconstruct because the activity was killed
// And thus there is no way of communicating back
Expand Down
30 changes: 30 additions & 0 deletions sdk/src/test/java/com/hcaptcha/sdk/HCaptchaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.AndroidRuntimeException;
import androidx.fragment.app.FragmentActivity;

import com.hcaptcha.sdk.tasks.OnFailureListener;
Expand All @@ -28,6 +31,7 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
Expand Down Expand Up @@ -248,4 +252,30 @@ public void test_clear_all_listener() {
.addOnOpenListener(onOpenListener)
.removeAllListeners();
}

@Test
public void test_webview_not_installed() throws Exception {
final ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
final Bundle bundle = mock(Bundle.class);
when(bundle.getString(META_SITE_KEY)).thenReturn(HCaptchaConfigTest.MOCK_SITE_KEY);
bundle.putString(META_SITE_KEY, HCaptchaConfigTest.MOCK_SITE_KEY);
applicationInfo.metaData = bundle;

when(fragmentActivity.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
when(fragmentActivity.getPackageManager()).thenReturn(packageManager);
when(packageManager.getApplicationInfo(TEST_PACKAGE_NAME, PackageManager.GET_META_DATA))
.thenReturn(applicationInfo);

try (MockedConstruction<HCaptchaWebView> mock = mockConstruction(HCaptchaWebView.class,
withSettings().defaultAnswer(invocation -> {
throw new AndroidRuntimeException(
"android.webkit.WebViewFactory$MissingWebViewPackageException");
})
)) {
HCaptcha.getClient(fragmentActivity)
.setup(config.toBuilder().hideDialog(true).build())
.verifyWithHCaptcha()
.addOnFailureListener(e -> assertEquals(HCaptchaError.ERROR, e.getHCaptchaError()));
}
}
}

0 comments on commit d90ef66

Please sign in to comment.