Sfoglia il codice sorgente

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

Jason Gaare 4 anni fa
parent
commit
fbcfbdc836
No account linked to committer's email address

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

18
 import androidx.annotation.RequiresApi;
18
 import androidx.annotation.RequiresApi;
19
 import androidx.core.content.ContextCompat;
19
 import androidx.core.content.ContextCompat;
20
 import android.text.TextUtils;
20
 import android.text.TextUtils;
21
+import android.util.Log;
21
 import android.view.Gravity;
22
 import android.view.Gravity;
22
 import android.view.View;
23
 import android.view.View;
23
 import android.view.ViewGroup;
24
 import android.view.ViewGroup;
28
 import android.webkit.DownloadListener;
29
 import android.webkit.DownloadListener;
29
 import android.webkit.GeolocationPermissions;
30
 import android.webkit.GeolocationPermissions;
30
 import android.webkit.JavascriptInterface;
31
 import android.webkit.JavascriptInterface;
32
+import android.webkit.RenderProcessGoneDetail;
31
 import android.webkit.SslErrorHandler;
33
 import android.webkit.SslErrorHandler;
32
 import android.webkit.PermissionRequest;
34
 import android.webkit.PermissionRequest;
33
 import android.webkit.URLUtil;
35
 import android.webkit.URLUtil;
70
 import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
72
 import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
71
 import com.reactnativecommunity.webview.events.TopMessageEvent;
73
 import com.reactnativecommunity.webview.events.TopMessageEvent;
72
 import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
74
 import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
75
+import com.reactnativecommunity.webview.events.TopRenderProcessGoneEvent;
73
 
76
 
74
 import org.json.JSONException;
77
 import org.json.JSONException;
75
 import org.json.JSONObject;
78
 import org.json.JSONObject;
580
     export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
583
     export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
581
     export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
584
     export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
582
     export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
585
     export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
586
+    export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
583
     return export;
587
     return export;
584
   }
588
   }
585
 
589
 
776
       mLastLoadFailed = false;
780
       mLastLoadFailed = false;
777
 
781
 
778
       RNCWebView reactWebView = (RNCWebView) webView;
782
       RNCWebView reactWebView = (RNCWebView) webView;
779
-      reactWebView.callInjectedJavaScriptBeforeContentLoaded();       
783
+      reactWebView.callInjectedJavaScriptBeforeContentLoaded();
780
 
784
 
781
       dispatchEvent(
785
       dispatchEvent(
782
         webView,
786
         webView,
833
           case SslError.SSL_UNTRUSTED:
837
           case SslError.SSL_UNTRUSTED:
834
             description = "The certificate authority is not trusted";
838
             description = "The certificate authority is not trusted";
835
             break;
839
             break;
836
-          default: 
840
+          default:
837
             description = "Unknown SSL Error";
841
             description = "Unknown SSL Error";
838
             break;
842
             break;
839
         }
843
         }
840
-        
844
+
841
         description = descriptionPrefix + description;
845
         description = descriptionPrefix + description;
842
 
846
 
843
         this.onReceivedError(
847
         this.onReceivedError(
847
           failingUrl
851
           failingUrl
848
         );
852
         );
849
     }
853
     }
850
-    
854
+
851
     @Override
855
     @Override
852
     public void onReceivedError(
856
     public void onReceivedError(
853
       WebView webView,
857
       WebView 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
     protected void emitFinishEvent(WebView webView, String url) {
946
     protected void emitFinishEvent(WebView webView, String url) {
908
       dispatchEvent(
947
       dispatchEvent(
909
         webView,
948
         webView,

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

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 Vedi File

13
 - [`mediaPlaybackRequiresUserAction`](Reference.md#mediaplaybackrequiresuseraction)
13
 - [`mediaPlaybackRequiresUserAction`](Reference.md#mediaplaybackrequiresuseraction)
14
 - [`nativeConfig`](Reference.md#nativeconfig)
14
 - [`nativeConfig`](Reference.md#nativeconfig)
15
 - [`onError`](Reference.md#onerror)
15
 - [`onError`](Reference.md#onerror)
16
+- [`onRenderProcessGone`](Reference.md#onRenderProcessGone)
16
 - [`onLoad`](Reference.md#onload)
17
 - [`onLoad`](Reference.md#onload)
17
 - [`onLoadEnd`](Reference.md#onloadend)
18
 - [`onLoadEnd`](Reference.md#onloadend)
18
 - [`onLoadStart`](Reference.md#onloadstart)
19
 - [`onLoadStart`](Reference.md#onloadstart)
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
 ### `onMessage`[⬆](#props-index)<!-- Link generated with jump2header -->
495
 ### `onMessage`[⬆](#props-index)<!-- Link generated with jump2header -->
462
 
496
 
463
 Function that is invoked when the webview calls `window.ReactNativeWebView.postMessage`. Setting this property will inject this global into your webview.
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 Vedi File

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

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

21
   defaultRenderLoading,
21
   defaultRenderLoading,
22
 } from './WebViewShared';
22
 } from './WebViewShared';
23
 import {
23
 import {
24
+  WebViewRenderProcessGoneEvent,
24
   WebViewErrorEvent,
25
   WebViewErrorEvent,
25
   WebViewHttpErrorEvent,
26
   WebViewHttpErrorEvent,
26
   WebViewMessageEvent,
27
   WebViewMessageEvent,
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
   onLoadingFinish = (event: WebViewNavigationEvent) => {
239
   onLoadingFinish = (event: WebViewNavigationEvent) => {
232
     const { onLoad, onLoadEnd } = this.props;
240
     const { onLoad, onLoadEnd } = this.props;
233
     const { nativeEvent: { url } } = event;
241
     const { nativeEvent: { url } } = event;
347
         onLoadingProgress={this.onLoadingProgress}
355
         onLoadingProgress={this.onLoadingProgress}
348
         onLoadingStart={this.onLoadingStart}
356
         onLoadingStart={this.onLoadingStart}
349
         onHttpError={this.onHttpError}
357
         onHttpError={this.onHttpError}
358
+        onRenderProcessGone={this.onRenderProcessGone}
350
         onMessage={this.onMessage}
359
         onMessage={this.onMessage}
351
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
360
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
352
         ref={this.webViewRef}
361
         ref={this.webViewRef}

+ 14
- 1
src/WebViewTypes.ts Vedi File

137
   statusCode: number;
137
   statusCode: number;
138
 }
138
 }
139
 
139
 
140
+export interface WebViewRenderProcessGoneDetail {
141
+  didCrash: boolean;
142
+}
143
+
140
 export type WebViewEvent = NativeSyntheticEvent<WebViewNativeEvent>;
144
 export type WebViewEvent = NativeSyntheticEvent<WebViewNativeEvent>;
141
 
145
 
142
 export type WebViewProgressEvent = NativeSyntheticEvent<
146
 export type WebViewProgressEvent = NativeSyntheticEvent<
155
 
159
 
156
 export type WebViewHttpErrorEvent = NativeSyntheticEvent<WebViewHttpError>;
160
 export type WebViewHttpErrorEvent = NativeSyntheticEvent<WebViewHttpError>;
157
 
161
 
162
+export type WebViewRenderProcessGoneEvent = NativeSyntheticEvent<WebViewRenderProcessGoneDetail>;
163
+
158
 export type DataDetectorTypes =
164
 export type DataDetectorTypes =
159
   | 'phoneNumber'
165
   | 'phoneNumber'
160
   | 'link'
166
   | 'link'
277
   javaScriptEnabled?: boolean;
283
   javaScriptEnabled?: boolean;
278
   mixedContentMode?: 'never' | 'always' | 'compatibility';
284
   mixedContentMode?: 'never' | 'always' | 'compatibility';
279
   onContentSizeChange?: (event: WebViewEvent) => void;
285
   onContentSizeChange?: (event: WebViewEvent) => void;
286
+  onRenderProcessGone?: (event: WebViewRenderProcessGoneEvent) => void;
280
   overScrollMode?: OverScrollModeType;
287
   overScrollMode?: OverScrollModeType;
281
   saveFormDataDisabled?: boolean;
288
   saveFormDataDisabled?: boolean;
282
   textZoom?: number;
289
   textZoom?: number;
683
   onNavigationStateChange?: (event: WebViewNavigation) => void;
690
   onNavigationStateChange?: (event: WebViewNavigation) => void;
684
   onContentSizeChange?: (event: WebViewEvent) => void;
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
    * https://developer.android.com/reference/android/webkit/WebSettings.html#setCacheMode(int)
700
    * https://developer.android.com/reference/android/webkit/WebSettings.html#setCacheMode(int)
688
    * Set the cacheMode. Possible values are:
701
    * Set the cacheMode. Possible values are:
721
    */
734
    */
722
   geolocationEnabled?: boolean;
735
   geolocationEnabled?: boolean;
723
 
736
 
724
-  
737
+
725
   /**
738
   /**
726
    * Boolean that sets whether JavaScript running in the context of a file
739
    * Boolean that sets whether JavaScript running in the context of a file
727
    * scheme URL should be allowed to access content from other file scheme URLs.
740
    * scheme URL should be allowed to access content from other file scheme URLs.