@capgo/capacitor-inappbrowser 8.14.0 → 8.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -76,6 +76,14 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
76
76
  }
77
77
  );
78
78
 
79
+ private static final ExecutorService CUSTOM_TABS_LIFECYCLE_EXECUTOR = Executors.newSingleThreadExecutor((runnable) -> {
80
+ Thread thread = new Thread(runnable, "CapgoInAppBrowser-CustomTabsLifecycle");
81
+ thread.setDaemon(true);
82
+ return thread;
83
+ });
84
+
85
+ private final CustomTabsLifecycleSupport customTabsLifecycleSupport = new CustomTabsLifecycleSupport(CUSTOM_TABS_LIFECYCLE_EXECUTOR);
86
+
79
87
  private final String pluginVersion = "8.6.17";
80
88
 
81
89
  private boolean resolveClientCertificatePrompt(PluginCall call) {
@@ -670,10 +678,16 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
670
678
  currentPermissionNeedsMicrophone = false;
671
679
  }
672
680
 
681
+ private final Object customTabsClientLock = new Object();
682
+ private static final long CUSTOM_TABS_CONNECTION_TIMEOUT_MS = 2000;
683
+
673
684
  CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
674
685
  @Override
675
686
  public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
676
687
  customTabsClient = client;
688
+ synchronized (customTabsClientLock) {
689
+ customTabsClientLock.notifyAll();
690
+ }
677
691
  }
678
692
 
679
693
  @Override
@@ -682,6 +696,27 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
682
696
  }
683
697
  };
684
698
 
699
+ private final CustomTabsLifecycleSupport.Binder customTabsBinder = new CustomTabsLifecycleSupport.Binder() {
700
+ @Override
701
+ public boolean bindCustomTabsService() {
702
+ try {
703
+ boolean ok = CustomTabsClient.bindCustomTabsService(getContext(), CUSTOM_TAB_PACKAGE_NAME, connection);
704
+ if (!ok) {
705
+ Log.e(getLogTag(), "Error binding to custom tabs service");
706
+ }
707
+ return ok;
708
+ } catch (RuntimeException e) {
709
+ Log.e(getLogTag(), "Error binding to custom tabs service", e);
710
+ return false;
711
+ }
712
+ }
713
+
714
+ @Override
715
+ public void unbindCustomTabsService() {
716
+ getContext().unbindService(connection);
717
+ }
718
+ };
719
+
685
720
  @PluginMethod
686
721
  public void requestCameraPermission(PluginCall call) {
687
722
  if (isAndroidPermissionGranted(Manifest.permission.CAMERA)) {
@@ -748,8 +783,10 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
748
783
 
749
784
  if (TextUtils.isEmpty(url)) {
750
785
  call.reject("Invalid URL");
786
+ return;
751
787
  }
752
788
  currentUrl = url;
789
+ awaitCustomTabsClientIfNeeded();
753
790
  CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getCustomTabsSession());
754
791
 
755
792
  // --- Chrome Custom Tab UI customization ---
@@ -1839,10 +1876,8 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
1839
1876
  }
1840
1877
 
1841
1878
  protected void handleOnResume() {
1842
- boolean ok = CustomTabsClient.bindCustomTabsService(getContext(), CUSTOM_TAB_PACKAGE_NAME, connection);
1843
- if (!ok) {
1844
- Log.e(getLogTag(), "Error binding to custom tabs service");
1845
- }
1879
+ customTabsLifecycleSupport.onResume(customTabsBinder);
1880
+
1846
1881
  // If we have a saved call and user returned without callback, reject
1847
1882
  if (openSecureWindowSavedCall != null) {
1848
1883
  openSecureWindowSavedCall.reject("OAuth cancelled or no callback received");
@@ -1851,7 +1886,29 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
1851
1886
  }
1852
1887
 
1853
1888
  protected void handleOnPause() {
1854
- getContext().unbindService(connection);
1889
+ customTabsLifecycleSupport.onPause(customTabsBinder);
1890
+ }
1891
+
1892
+ private void awaitCustomTabsClientIfNeeded() {
1893
+ if (customTabsClient != null || !customTabsLifecycleSupport.isBindingOrBound()) {
1894
+ return;
1895
+ }
1896
+
1897
+ synchronized (customTabsClientLock) {
1898
+ long deadline = System.currentTimeMillis() + CUSTOM_TABS_CONNECTION_TIMEOUT_MS;
1899
+ while (customTabsClient == null && customTabsLifecycleSupport.isBindingOrBound() && System.currentTimeMillis() < deadline) {
1900
+ long remaining = deadline - System.currentTimeMillis();
1901
+ if (remaining <= 0) {
1902
+ break;
1903
+ }
1904
+ try {
1905
+ customTabsClientLock.wait(remaining);
1906
+ } catch (InterruptedException e) {
1907
+ Thread.currentThread().interrupt();
1908
+ break;
1909
+ }
1910
+ }
1911
+ }
1855
1912
  }
1856
1913
 
1857
1914
  public CustomTabsSession getCustomTabsSession() {
@@ -0,0 +1,84 @@
1
+ package ee.forgr.capacitor_inappbrowser;
2
+
3
+ import java.util.concurrent.Executor;
4
+
5
+ final class CustomTabsLifecycleSupport {
6
+
7
+ interface Binder {
8
+ boolean bindCustomTabsService();
9
+
10
+ void unbindCustomTabsService();
11
+ }
12
+
13
+ private final Executor executor;
14
+ private final Object lock = new Object();
15
+ private boolean bound = false;
16
+ private boolean bindInProgress = false;
17
+
18
+ CustomTabsLifecycleSupport(Executor executor) {
19
+ this.executor = executor;
20
+ }
21
+
22
+ void onResume(Binder binder) {
23
+ executor.execute(() -> performBind(binder));
24
+ }
25
+
26
+ void onPause(Binder binder) {
27
+ executor.execute(() -> performUnbind(binder));
28
+ }
29
+
30
+ boolean isBindingOrBound() {
31
+ synchronized (lock) {
32
+ return bindInProgress || bound;
33
+ }
34
+ }
35
+
36
+ boolean isBound() {
37
+ synchronized (lock) {
38
+ return bound;
39
+ }
40
+ }
41
+
42
+ private void performBind(Binder binder) {
43
+ synchronized (lock) {
44
+ if (bound || bindInProgress) {
45
+ return;
46
+ }
47
+ bindInProgress = true;
48
+ }
49
+
50
+ boolean ok = false;
51
+ try {
52
+ ok = binder.bindCustomTabsService();
53
+ } catch (RuntimeException ignored) {
54
+ // Caller logs bind failures.
55
+ }
56
+
57
+ synchronized (lock) {
58
+ bindInProgress = false;
59
+ if (!ok) {
60
+ return;
61
+ }
62
+
63
+ bound = true;
64
+ }
65
+ }
66
+
67
+ private void performUnbind(Binder binder) {
68
+ synchronized (lock) {
69
+ if (bindInProgress) {
70
+ return;
71
+ }
72
+ if (!bound) {
73
+ return;
74
+ }
75
+ bound = false;
76
+ }
77
+
78
+ try {
79
+ binder.unbindCustomTabsService();
80
+ } catch (RuntimeException ignored) {
81
+ // Service may already be unbound.
82
+ }
83
+ }
84
+ }
@@ -415,7 +415,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
415
415
  case aware = "AWARE"
416
416
  case fakeVisible = "FAKE_VISIBLE"
417
417
  }
418
- private let pluginVersion: String = "8.14.0"
418
+ private let pluginVersion: String = "8.14.1"
419
419
  public let identifier = "CapgoInAppBrowserPlugin"
420
420
  public let jsName = "CapgoInAppBrowser"
421
421
  public let pluginMethods: [CAPPluginMethod] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-inappbrowser",
3
- "version": "8.14.0",
3
+ "version": "8.14.1",
4
4
  "description": "Capacitor plugin in app browser",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",