Browse Source

Merge branch 'master' into android-download-try-catch

Jason Gaare 4 years ago
parent
commit
fbcfbdc836
No account linked to committer's email address

+ 43
- 4
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java View File

@@ -18,6 +18,7 @@ import android.os.Environment;
18 18
 import androidx.annotation.RequiresApi;
19 19
 import androidx.core.content.ContextCompat;
20 20
 import android.text.TextUtils;
21
+import android.util.Log;
21 22
 import android.view.Gravity;
22 23
 import android.view.View;
23 24
 import android.view.ViewGroup;
@@ -28,6 +29,7 @@ import android.webkit.CookieManager;
28 29
 import android.webkit.DownloadListener;
29 30
 import android.webkit.GeolocationPermissions;
30 31
 import android.webkit.JavascriptInterface;
32
+import android.webkit.RenderProcessGoneDetail;
31 33
 import android.webkit.SslErrorHandler;
32 34
 import android.webkit.PermissionRequest;
33 35
 import android.webkit.URLUtil;
@@ -70,6 +72,7 @@ import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
70 72
 import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
71 73
 import com.reactnativecommunity.webview.events.TopMessageEvent;
72 74
 import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
75
+import com.reactnativecommunity.webview.events.TopRenderProcessGoneEvent;
73 76
 
74 77
 import org.json.JSONException;
75 78
 import org.json.JSONObject;
@@ -580,6 +583,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
580 583
     export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
581 584
     export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
582 585
     export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
586
+    export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
583 587
     return export;
584 588
   }
585 589
 
@@ -776,7 +780,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
776 780
       mLastLoadFailed = false;
777 781
 
778 782
       RNCWebView reactWebView = (RNCWebView) webView;
779
-      reactWebView.callInjectedJavaScriptBeforeContentLoaded();       
783
+      reactWebView.callInjectedJavaScriptBeforeContentLoaded();
780 784
 
781 785
       dispatchEvent(
782 786
         webView,
@@ -833,11 +837,11 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
833 837
           case SslError.SSL_UNTRUSTED:
834 838
             description = "The certificate authority is not trusted";
835 839
             break;
836
-          default: 
840
+          default:
837 841
             description = "Unknown SSL Error";
838 842
             break;
839 843
         }
840
-        
844
+
841 845
         description = descriptionPrefix + description;
842 846
 
843 847
         this.onReceivedError(
@@ -847,7 +851,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
847 851
           failingUrl
848 852
         );
849 853
     }
850
-    
854
+
851 855
     @Override
852 856
     public void onReceivedError(
853 857
       WebView webView,
@@ -904,6 +908,41 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
904 908
       }
905 909
     }
906 910
 
911
+    @TargetApi(Build.VERSION_CODES.O)
912
+    @Override
913
+    public boolean onRenderProcessGone(WebView webView, RenderProcessGoneDetail detail) {
914
+        // WebViewClient.onRenderProcessGone was added in O.
915
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
916
+            return false;
917
+        }
918
+        super.onRenderProcessGone(webView, detail);
919
+
920
+        if(detail.didCrash()){
921
+          Log.e("RNCWebViewManager", "The WebView rendering process crashed.");
922
+        }
923
+        else{
924
+          Log.w("RNCWebViewManager", "The WebView rendering process was killed by the system.");
925
+        }
926
+
927
+        // if webView is null, we cannot return any event
928
+        // since the view is already dead/disposed
929
+        // still prevent the app crash by returning true.
930
+        if(webView == null){
931
+          return true;
932
+        }
933
+
934
+        WritableMap event = createWebViewEvent(webView, webView.getUrl());
935
+        event.putBoolean("didCrash", detail.didCrash());
936
+
937
+        dispatchEvent(
938
+          webView,
939
+          new TopRenderProcessGoneEvent(webView.getId(), event)
940
+        );
941
+
942
+        // returning false would crash the app.
943
+        return true;
944
+    }
945
+
907 946
     protected void emitFinishEvent(WebView webView, String url) {
908 947
       dispatchEvent(
909 948
         webView,

+ 26
- 0
android/src/main/java/com/reactnativecommunity/webview/events/TopRenderProcessGoneEvent.kt View File

@@ -0,0 +1,26 @@
1
+package com.reactnativecommunity.webview.events
2
+
3
+import com.facebook.react.bridge.WritableMap
4
+import com.facebook.react.uimanager.events.Event
5
+import com.facebook.react.uimanager.events.RCTEventEmitter
6
+
7
+/**
8
+ * Event emitted when the WebView's process has crashed or
9
+   was killed by the OS.
10
+ */
11
+class TopRenderProcessGoneEvent(viewId: Int, private val mEventData: WritableMap) :
12
+  Event<TopRenderProcessGoneEvent>(viewId) {
13
+  companion object {
14
+    const val EVENT_NAME = "topRenderProcessGone"
15
+  }
16
+
17
+  override fun getEventName(): String = EVENT_NAME
18
+
19
+  override fun canCoalesce(): Boolean = false
20
+
21
+  override fun getCoalescingKey(): Short = 0
22
+
23
+  override fun dispatch(rctEventEmitter: RCTEventEmitter) =
24
+    rctEventEmitter.receiveEvent(viewTag, eventName, mEventData)
25
+
26
+}

+ 34
- 0
docs/Reference.md View File

@@ -13,6 +13,7 @@ This document lays out the current public properties and methods for the React N
13 13
 - [`mediaPlaybackRequiresUserAction`](Reference.md#mediaplaybackrequiresuseraction)
14 14
 - [`nativeConfig`](Reference.md#nativeconfig)
15 15
 - [`onError`](Reference.md#onerror)
16
+- [`onRenderProcessGone`](Reference.md#onRenderProcessGone)
16 17
 - [`onLoad`](Reference.md#onload)
17 18
 - [`onLoadEnd`](Reference.md#onloadend)
18 19
 - [`onLoadStart`](Reference.md#onloadstart)
@@ -458,6 +459,39 @@ url
458 459
 
459 460
 ---
460 461
 
462
+### `onRenderProcessGone`[⬆](#props-index)<!-- Link generated with jump2header -->
463
+
464
+Function that is invoked when the `WebView` process crashes or is killed by the OS on Android.
465
+
466
+> **_Note_**
467
+> Android API minimum level 26. Android Only
468
+
469
+| Type     | Required |
470
+| -------- | -------- |
471
+| function | No       |
472
+
473
+Example:
474
+
475
+```jsx
476
+<WebView
477
+  source={{ uri: 'https://reactnative.dev' }}
478
+  onRenderProcessGone={syntheticEvent => {
479
+    const { nativeEvent } = syntheticEvent;
480
+    console.warn(
481
+      'WebView Crashed: ',
482
+      nativeEvent.didCrash,
483
+    );
484
+  }}
485
+/>
486
+```
487
+
488
+Function passed to `onRenderProcessGone` is called with a SyntheticEvent wrapping a nativeEvent with these properties:
489
+
490
+```
491
+didCrash
492
+```
493
+---
494
+
461 495
 ### `onMessage`[⬆](#props-index)<!-- Link generated with jump2header -->
462 496
 
463 497
 Function that is invoked when the webview calls `window.ReactNativeWebView.postMessage`. Setting this property will inject this global into your webview.

+ 1
- 1
package.json View File

@@ -8,7 +8,7 @@
8 8
     "Thibault Malbranche <malbranche.thibault@gmail.com>"
9 9
   ],
10 10
   "license": "MIT",
11
-  "version": "10.3.3",
11
+  "version": "10.4.0",
12 12
   "homepage": "https://github.com/react-native-community/react-native-webview#readme",
13 13
   "scripts": {
14 14
     "start": "node node_modules/react-native/local-cli/cli.js start",

+ 9
- 0
src/WebView.android.tsx View File

@@ -21,6 +21,7 @@ import {
21 21
   defaultRenderLoading,
22 22
 } from './WebViewShared';
23 23
 import {
24
+  WebViewRenderProcessGoneEvent,
24 25
   WebViewErrorEvent,
25 26
   WebViewHttpErrorEvent,
26 27
   WebViewMessageEvent,
@@ -228,6 +229,13 @@ class WebView extends React.Component<AndroidWebViewProps, State> {
228 229
     }
229 230
   }
230 231
 
232
+  onRenderProcessGone = (event: WebViewRenderProcessGoneEvent) => {
233
+    const { onRenderProcessGone } = this.props;
234
+    if (onRenderProcessGone) {
235
+      onRenderProcessGone(event);
236
+    }
237
+  }
238
+
231 239
   onLoadingFinish = (event: WebViewNavigationEvent) => {
232 240
     const { onLoad, onLoadEnd } = this.props;
233 241
     const { nativeEvent: { url } } = event;
@@ -347,6 +355,7 @@ class WebView extends React.Component<AndroidWebViewProps, State> {
347 355
         onLoadingProgress={this.onLoadingProgress}
348 356
         onLoadingStart={this.onLoadingStart}
349 357
         onHttpError={this.onHttpError}
358
+        onRenderProcessGone={this.onRenderProcessGone}
350 359
         onMessage={this.onMessage}
351 360
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
352 361
         ref={this.webViewRef}

+ 14
- 1
src/WebViewTypes.ts View File

@@ -137,6 +137,10 @@ export interface WebViewHttpError extends WebViewNativeEvent {
137 137
   statusCode: number;
138 138
 }
139 139
 
140
+export interface WebViewRenderProcessGoneDetail {
141
+  didCrash: boolean;
142
+}
143
+
140 144
 export type WebViewEvent = NativeSyntheticEvent<WebViewNativeEvent>;
141 145
 
142 146
 export type WebViewProgressEvent = NativeSyntheticEvent<
@@ -155,6 +159,8 @@ export type WebViewTerminatedEvent = NativeSyntheticEvent<WebViewNativeEvent>;
155 159
 
156 160
 export type WebViewHttpErrorEvent = NativeSyntheticEvent<WebViewHttpError>;
157 161
 
162
+export type WebViewRenderProcessGoneEvent = NativeSyntheticEvent<WebViewRenderProcessGoneDetail>;
163
+
158 164
 export type DataDetectorTypes =
159 165
   | 'phoneNumber'
160 166
   | 'link'
@@ -277,6 +283,7 @@ export interface AndroidNativeWebViewProps extends CommonNativeWebViewProps {
277 283
   javaScriptEnabled?: boolean;
278 284
   mixedContentMode?: 'never' | 'always' | 'compatibility';
279 285
   onContentSizeChange?: (event: WebViewEvent) => void;
286
+  onRenderProcessGone?: (event: WebViewRenderProcessGoneEvent) => void;
280 287
   overScrollMode?: OverScrollModeType;
281 288
   saveFormDataDisabled?: boolean;
282 289
   textZoom?: number;
@@ -683,6 +690,12 @@ export interface AndroidWebViewProps extends WebViewSharedProps {
683 690
   onNavigationStateChange?: (event: WebViewNavigation) => void;
684 691
   onContentSizeChange?: (event: WebViewEvent) => void;
685 692
 
693
+  /**
694
+   * Function that is invoked when the `WebView` process crashes or is killed by the OS.
695
+   * Works only on Android (minimum API level 26).
696
+   */
697
+  onRenderProcessGone?: (event: WebViewRenderProcessGoneEvent) => void;
698
+
686 699
   /**
687 700
    * https://developer.android.com/reference/android/webkit/WebSettings.html#setCacheMode(int)
688 701
    * Set the cacheMode. Possible values are:
@@ -721,7 +734,7 @@ export interface AndroidWebViewProps extends WebViewSharedProps {
721 734
    */
722 735
   geolocationEnabled?: boolean;
723 736
 
724
-  
737
+
725 738
   /**
726 739
    * Boolean that sets whether JavaScript running in the context of a file
727 740
    * scheme URL should be allowed to access content from other file scheme URLs.