Browse files

Android: Set WebViewManager methods/fields as protected instead of pr…



See discussion in #10946. The motivation is to make `ReactWebViewManager` more extensible.

Re-using logic from the ReactWebViewManager when implementing your own custom WebView is a pain since so much of the logic is set as `private`.

This PR makes for easier extension/overriding of behavior, and less duplication of code, since most of the methods/fields are set as `protected` instead.

I've also made some "create" methods for the `WebView` and `WebViewBridge` so they can more easily be overridden.

**Test plan**
The test plan is the same as the other PR (#10946). I've made an simple test app which extends `RCTWebViewManager`:

See []( for a simple implementation.

CC shergin (#10946 (comment))
Closes #14261

Differential Revision: D5413922

Pulled By: shergin

fbshipit-source-id: d2f6d478f2a147e2e7b5e05c195a8b28a0a3d576
  • Loading branch information...
cbrevik authored and facebook-github-bot committed Jul 13, 2017
1 parent aafccdf commit e2c87b59be3424dfadcb03ca931374d915a47e1f
Showing with 26 additions and 18 deletions.
  1. +26 −18 ReactAndroid/src/main/java/com/facebook/react/views/webview/
@@ -87,11 +87,11 @@
protected static final String REACT_CLASS = "RCTWebView";
private static final String HTML_ENCODING = "UTF-8";
private static final String HTML_MIME_TYPE = "text/html; charset=utf-8";
private static final String BRIDGE_NAME = "__REACT_WEB_VIEW_BRIDGE";
protected static final String HTML_ENCODING = "UTF-8";
protected static final String HTML_MIME_TYPE = "text/html; charset=utf-8";
protected static final String BRIDGE_NAME = "__REACT_WEB_VIEW_BRIDGE";
private static final String HTTP_METHOD_POST = "POST";
protected static final String HTTP_METHOD_POST = "POST";
public static final int COMMAND_GO_BACK = 1;
public static final int COMMAND_GO_FORWARD = 2;
@@ -102,14 +102,14 @@
// Use `webView.loadUrl("about:blank")` to reliably reset the view
// state and release page resources (including any running JavaScript).
private static final String BLANK_URL = "about:blank";
protected static final String BLANK_URL = "about:blank";
private WebViewConfig mWebViewConfig;
private @Nullable WebView.PictureListener mPictureListener;
protected WebViewConfig mWebViewConfig;
protected @Nullable WebView.PictureListener mPictureListener;
protected static class ReactWebViewClient extends WebViewClient {
private boolean mLastLoadFailed = false;
protected boolean mLastLoadFailed = false;
public void onPageFinished(WebView webView, String url) {
@@ -185,15 +185,15 @@ public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload
createWebViewEvent(webView, url)));
private void emitFinishEvent(WebView webView, String url) {
protected void emitFinishEvent(WebView webView, String url) {
new TopLoadingFinishEvent(
createWebViewEvent(webView, url)));
private WritableMap createWebViewEvent(WebView webView, String url) {
protected WritableMap createWebViewEvent(WebView webView, String url) {
WritableMap event = Arguments.createMap();
event.putDouble("target", webView.getId());
// Don't use webView.getUrl() here, the URL isn't updated to the new value yet in callbacks
@@ -212,10 +212,10 @@ private WritableMap createWebViewEvent(WebView webView, String url) {
* to call {@link WebView#destroy} on activty destroy event and also to clear the client
protected static class ReactWebView extends WebView implements LifecycleEventListener {
private @Nullable String injectedJS;
private boolean messagingEnabled = false;
protected @Nullable String injectedJS;
protected boolean messagingEnabled = false;
private class ReactWebViewBridge {
protected class ReactWebViewBridge {
ReactWebView mContext;
ReactWebViewBridge(ReactWebView c) {
@@ -258,14 +258,18 @@ public void setInjectedJavaScript(@Nullable String js) {
injectedJS = js;
protected ReactWebViewBridge createReactWebViewBridge(ReactWebView webView) {
return new ReactWebViewBridge(webView);
public void setMessagingEnabled(boolean enabled) {
if (messagingEnabled == enabled) {
messagingEnabled = enabled;
if (enabled) {
addJavascriptInterface(new ReactWebViewBridge(this), BRIDGE_NAME);
addJavascriptInterface(createReactWebViewBridge(this), BRIDGE_NAME);
} else {
@@ -308,7 +312,7 @@ public void onMessage(String message) {
dispatchEvent(this, new TopMessageEvent(this.getId(), message));
private void cleanupCallbacksAndDestroy() {
protected void cleanupCallbacksAndDestroy() {
@@ -330,9 +334,13 @@ public String getName() {
protected ReactWebView createReactWebViewInstance(ThemedReactContext reactContext) {
return new ReactWebView(reactContext);
protected WebView createViewInstance(ThemedReactContext reactContext) {
ReactWebView webView = new ReactWebView(reactContext);
ReactWebView webView = createReactWebViewInstance(reactContext);
webView.setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage message) {
@@ -568,7 +576,7 @@ public void onDropViewInstance(WebView webView) {
((ReactWebView) webView).cleanupCallbacksAndDestroy();
private WebView.PictureListener getPictureListener() {
protected WebView.PictureListener getPictureListener() {
if (mPictureListener == null) {
mPictureListener = new WebView.PictureListener() {
@@ -585,7 +593,7 @@ public void onNewPicture(WebView webView, Picture picture) {
return mPictureListener;
private static void dispatchEvent(WebView webView, Event event) {
protected static void dispatchEvent(WebView webView, Event event) {
ReactContext reactContext = (ReactContext) webView.getContext();
EventDispatcher eventDispatcher =

0 comments on commit e2c87b5

Please sign in to comment.