|
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint;
|
4
|
4
|
import android.annotation.TargetApi;
|
5
|
5
|
import android.app.DownloadManager;
|
6
|
6
|
import android.content.Context;
|
7
|
|
-import android.content.Intent;
|
8
|
7
|
import android.content.pm.ActivityInfo;
|
9
|
8
|
import android.content.pm.PackageManager;
|
10
|
9
|
import android.graphics.Bitmap;
|
|
@@ -14,8 +13,7 @@ import android.net.http.SslError;
|
14
|
13
|
import android.net.Uri;
|
15
|
14
|
import android.os.Build;
|
16
|
15
|
import android.os.Environment;
|
17
|
|
-import androidx.annotation.RequiresApi;
|
18
|
|
-import androidx.core.content.ContextCompat;
|
|
16
|
+import android.os.SystemClock;
|
19
|
17
|
import android.text.TextUtils;
|
20
|
18
|
import android.util.Log;
|
21
|
19
|
import android.view.Gravity;
|
|
@@ -41,6 +39,12 @@ import android.webkit.WebView;
|
41
|
39
|
import android.webkit.WebViewClient;
|
42
|
40
|
import android.widget.FrameLayout;
|
43
|
41
|
|
|
42
|
+import androidx.annotation.Nullable;
|
|
43
|
+import androidx.annotation.RequiresApi;
|
|
44
|
+import androidx.core.content.ContextCompat;
|
|
45
|
+import androidx.core.util.Pair;
|
|
46
|
+
|
|
47
|
+import com.facebook.common.logging.FLog;
|
44
|
48
|
import com.facebook.react.views.scroll.ScrollEvent;
|
45
|
49
|
import com.facebook.react.views.scroll.ScrollEventType;
|
46
|
50
|
import com.facebook.react.views.scroll.OnScrollDispatchHelper;
|
|
@@ -64,6 +68,7 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
64
|
68
|
import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
|
65
|
69
|
import com.facebook.react.uimanager.events.Event;
|
66
|
70
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
|
71
|
+import com.reactnativecommunity.webview.RNCWebViewModule.ShouldOverrideUrlLoadingLock.ShouldOverrideCallbackState;
|
67
|
72
|
import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
|
68
|
73
|
import com.reactnativecommunity.webview.events.TopHttpErrorEvent;
|
69
|
74
|
import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
|
|
@@ -84,8 +89,7 @@ import java.util.ArrayList;
|
84
|
89
|
import java.util.HashMap;
|
85
|
90
|
import java.util.Locale;
|
86
|
91
|
import java.util.Map;
|
87
|
|
-
|
88
|
|
-import javax.annotation.Nullable;
|
|
92
|
+import java.util.concurrent.atomic.AtomicReference;
|
89
|
93
|
|
90
|
94
|
/**
|
91
|
95
|
* Manages instances of {@link WebView}
|
|
@@ -113,6 +117,7 @@ import javax.annotation.Nullable;
|
113
|
117
|
*/
|
114
|
118
|
@ReactModule(name = RNCWebViewManager.REACT_CLASS)
|
115
|
119
|
public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
120
|
+ private static final String TAG = "RNCWebViewManager";
|
116
|
121
|
|
117
|
122
|
public static final int COMMAND_GO_BACK = 1;
|
118
|
123
|
public static final int COMMAND_GO_FORWARD = 2;
|
|
@@ -136,6 +141,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
136
|
141
|
// Use `webView.loadUrl("about:blank")` to reliably reset the view
|
137
|
142
|
// state and release page resources (including any running JavaScript).
|
138
|
143
|
protected static final String BLANK_URL = "about:blank";
|
|
144
|
+ protected static final int SHOULD_OVERRIDE_URL_LOADING_TIMEOUT = 250;
|
139
|
145
|
protected WebViewConfig mWebViewConfig;
|
140
|
146
|
|
141
|
147
|
protected RNCWebChromeClient mWebChromeClient = null;
|
|
@@ -806,15 +812,52 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
806
|
812
|
|
807
|
813
|
@Override
|
808
|
814
|
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
809
|
|
- progressChangedFilter.setWaitingForCommandLoadUrl(true);
|
810
|
|
- dispatchEvent(
|
811
|
|
- view,
|
812
|
|
- new TopShouldStartLoadWithRequestEvent(
|
813
|
|
- view.getId(),
|
814
|
|
- createWebViewEvent(view, url)));
|
815
|
|
- return true;
|
816
|
|
- }
|
|
815
|
+ final RNCWebView rncWebView = (RNCWebView) view;
|
|
816
|
+ final boolean isJsDebugging = ((ReactContext) view.getContext()).getJavaScriptContextHolder().get() == 0;
|
817
|
817
|
|
|
818
|
+ if (!isJsDebugging && rncWebView.mCatalystInstance != null) {
|
|
819
|
+ final Pair<Integer, AtomicReference<ShouldOverrideCallbackState>> lock = RNCWebViewModule.shouldOverrideUrlLoadingLock.getNewLock();
|
|
820
|
+ final int lockIdentifier = lock.first;
|
|
821
|
+ final AtomicReference<ShouldOverrideCallbackState> lockObject = lock.second;
|
|
822
|
+
|
|
823
|
+ final WritableMap event = createWebViewEvent(view, url);
|
|
824
|
+ event.putInt("lockIdentifier", lockIdentifier);
|
|
825
|
+ rncWebView.sendDirectMessage("onShouldStartLoadWithRequest", event);
|
|
826
|
+
|
|
827
|
+ try {
|
|
828
|
+ assert lockObject != null;
|
|
829
|
+ synchronized (lockObject) {
|
|
830
|
+ final long startTime = SystemClock.elapsedRealtime();
|
|
831
|
+ while (lockObject.get() == ShouldOverrideCallbackState.UNDECIDED) {
|
|
832
|
+ if (SystemClock.elapsedRealtime() - startTime > SHOULD_OVERRIDE_URL_LOADING_TIMEOUT) {
|
|
833
|
+ FLog.w(TAG, "Did not receive response to shouldOverrideUrlLoading in time, defaulting to allow loading.");
|
|
834
|
+ RNCWebViewModule.shouldOverrideUrlLoadingLock.removeLock(lockIdentifier);
|
|
835
|
+ return false;
|
|
836
|
+ }
|
|
837
|
+ lockObject.wait(SHOULD_OVERRIDE_URL_LOADING_TIMEOUT);
|
|
838
|
+ }
|
|
839
|
+ }
|
|
840
|
+ } catch (InterruptedException e) {
|
|
841
|
+ FLog.e(TAG, "shouldOverrideUrlLoading was interrupted while waiting for result.", e);
|
|
842
|
+ RNCWebViewModule.shouldOverrideUrlLoadingLock.removeLock(lockIdentifier);
|
|
843
|
+ return false;
|
|
844
|
+ }
|
|
845
|
+
|
|
846
|
+ final boolean shouldOverride = lockObject.get() == ShouldOverrideCallbackState.SHOULD_OVERRIDE;
|
|
847
|
+ RNCWebViewModule.shouldOverrideUrlLoadingLock.removeLock(lockIdentifier);
|
|
848
|
+
|
|
849
|
+ return shouldOverride;
|
|
850
|
+ } else {
|
|
851
|
+ FLog.w(TAG, "Couldn't use blocking synchronous call for onShouldStartLoadWithRequest due to debugging or missing Catalyst instance, falling back to old event-and-load.");
|
|
852
|
+ progressChangedFilter.setWaitingForCommandLoadUrl(true);
|
|
853
|
+ dispatchEvent(
|
|
854
|
+ view,
|
|
855
|
+ new TopShouldStartLoadWithRequestEvent(
|
|
856
|
+ view.getId(),
|
|
857
|
+ createWebViewEvent(view, url)));
|
|
858
|
+ return true;
|
|
859
|
+ }
|
|
860
|
+ }
|
818
|
861
|
|
819
|
862
|
@TargetApi(Build.VERSION_CODES.N)
|
820
|
863
|
@Override
|
|
@@ -1164,6 +1207,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
1164
|
1207
|
*/
|
1165
|
1208
|
public RNCWebView(ThemedReactContext reactContext) {
|
1166
|
1209
|
super(reactContext);
|
|
1210
|
+ this.createCatalystInstance();
|
1167
|
1211
|
progressChangedFilter = new ProgressChangedFilter();
|
1168
|
1212
|
}
|
1169
|
1213
|
|
|
@@ -1272,7 +1316,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
1272
|
1316
|
|
1273
|
1317
|
if (enabled) {
|
1274
|
1318
|
addJavascriptInterface(createRNCWebViewBridge(this), JAVASCRIPT_INTERFACE);
|
1275
|
|
- this.createCatalystInstance();
|
1276
|
1319
|
} else {
|
1277
|
1320
|
removeJavascriptInterface(JAVASCRIPT_INTERFACE);
|
1278
|
1321
|
}
|
|
@@ -1328,7 +1371,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
1328
|
1371
|
data.putString("data", message);
|
1329
|
1372
|
|
1330
|
1373
|
if (mCatalystInstance != null) {
|
1331
|
|
- mContext.sendDirectMessage(data);
|
|
1374
|
+ mContext.sendDirectMessage("onMessage", data);
|
1332
|
1375
|
} else {
|
1333
|
1376
|
dispatchEvent(webView, new TopMessageEvent(webView.getId(), data));
|
1334
|
1377
|
}
|
|
@@ -1339,21 +1382,21 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
1339
|
1382
|
eventData.putString("data", message);
|
1340
|
1383
|
|
1341
|
1384
|
if (mCatalystInstance != null) {
|
1342
|
|
- this.sendDirectMessage(eventData);
|
|
1385
|
+ this.sendDirectMessage("onMessage", eventData);
|
1343
|
1386
|
} else {
|
1344
|
1387
|
dispatchEvent(this, new TopMessageEvent(this.getId(), eventData));
|
1345
|
1388
|
}
|
1346
|
1389
|
}
|
1347
|
1390
|
}
|
1348
|
1391
|
|
1349
|
|
- protected void sendDirectMessage(WritableMap data) {
|
|
1392
|
+ protected void sendDirectMessage(final String method, WritableMap data) {
|
1350
|
1393
|
WritableNativeMap event = new WritableNativeMap();
|
1351
|
1394
|
event.putMap("nativeEvent", data);
|
1352
|
1395
|
|
1353
|
1396
|
WritableNativeArray params = new WritableNativeArray();
|
1354
|
1397
|
params.pushMap(event);
|
1355
|
1398
|
|
1356
|
|
- mCatalystInstance.callFunction(messagingModuleName, "onMessage", params);
|
|
1399
|
+ mCatalystInstance.callFunction(messagingModuleName, method, params);
|
1357
|
1400
|
}
|
1358
|
1401
|
|
1359
|
1402
|
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
|