feat(android): WebView crash handling (#1480)

Co-authored-by: Cristiano Coelho <cristianocca@hotmail.com>
This commit is contained in:
cristianoccazinsp
2020-08-06 22:21:01 +02:00
committed by GitHub
co-authored by Cristiano Coelho
parent 8081443c53
commit 8a8b7ceb98
5 changed files with 126 additions and 5 deletions
@@ -17,6 +17,7 @@ import android.os.Environment;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -27,6 +28,7 @@ import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.GeolocationPermissions;
import android.webkit.JavascriptInterface;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.SslErrorHandler;
import android.webkit.PermissionRequest;
import android.webkit.URLUtil;
@@ -69,6 +71,7 @@ import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
import com.reactnativecommunity.webview.events.TopMessageEvent;
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
import com.reactnativecommunity.webview.events.TopRenderProcessGoneEvent;
import org.json.JSONException;
import org.json.JSONObject;
@@ -575,6 +578,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
return export;
}
@@ -771,7 +775,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
mLastLoadFailed = false;
RNCWebView reactWebView = (RNCWebView) webView;
reactWebView.callInjectedJavaScriptBeforeContentLoaded();
reactWebView.callInjectedJavaScriptBeforeContentLoaded();
dispatchEvent(
webView,
@@ -828,11 +832,11 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
case SslError.SSL_UNTRUSTED:
description = "The certificate authority is not trusted";
break;
default:
default:
description = "Unknown SSL Error";
break;
}
description = descriptionPrefix + description;
this.onReceivedError(
@@ -842,7 +846,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
failingUrl
);
}
@Override
public void onReceivedError(
WebView webView,
@@ -899,6 +903,41 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
}
}
@TargetApi(Build.VERSION_CODES.O)
@Override
public boolean onRenderProcessGone(WebView webView, RenderProcessGoneDetail detail) {
// WebViewClient.onRenderProcessGone was added in O.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return false;
}
super.onRenderProcessGone(webView, detail);
if(detail.didCrash()){
Log.e("RNCWebViewManager", "The WebView rendering process crashed.");
}
else{
Log.w("RNCWebViewManager", "The WebView rendering process was killed by the system.");
}
// if webView is null, we cannot return any event
// since the view is already dead/disposed
// still prevent the app crash by returning true.
if(webView == null){
return true;
}
WritableMap event = createWebViewEvent(webView, webView.getUrl());
event.putBoolean("didCrash", detail.didCrash());
dispatchEvent(
webView,
new TopRenderProcessGoneEvent(webView.getId(), event)
);
// returning false would crash the app.
return true;
}
protected void emitFinishEvent(WebView webView, String url) {
dispatchEvent(
webView,