diff --git a/Examples/UIExplorer/js/WebViewExample.js b/Examples/UIExplorer/js/WebViewExample.js
index be1fb44aec1148..a0f3c635737ca6 100644
--- a/Examples/UIExplorer/js/WebViewExample.js
+++ b/Examples/UIExplorer/js/WebViewExample.js
@@ -264,6 +264,35 @@ class MessagingTest extends React.Component {
}
}
+class InjectJS extends React.Component {
+ webview = null;
+ injectJS = () => {
+ const script = 'document.write("Injected JS ")'; // eslint-disable-line quotes
+ if (this.webview) {
+ this.webview.injectJavaScript(script);
+ }
+ }
+ render() {
+ return (
+
+ { this.webview = webview; }}
+ style={{
+ backgroundColor: BGWASH,
+ height: 300,
+ }}
+ source={{uri: 'https://www.facebook.com'}}
+ scalesPageToFit={true}
+ />
+
+
+
+
+ );
+ }
+}
+
+
var styles = StyleSheet.create({
container: {
flex: 1,
@@ -442,5 +471,9 @@ exports.examples = [
{
title: 'Mesaging Test',
render(): ReactElement { return ; }
- }
+ },
+ {
+ title: 'Inject JavaScript',
+ render(): React.Element { return ; }
+ },
];
diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js
index 4617b2cb6a73b5..294095035d36a0 100644
--- a/Libraries/Components/WebView/WebView.android.js
+++ b/Libraries/Components/WebView/WebView.android.js
@@ -286,6 +286,20 @@ class WebView extends React.Component {
);
};
+ /**
+ * Injects a javascript string into the referenced WebView. Deliberately does not
+ * return a response because using eval() to return a response breaks this method
+ * on pages with a Content Security Policy that disallows eval(). If you need that
+ * functionality, look into postMessage/onMessage.
+ */
+ injectJavaScript = (data) => {
+ UIManager.dispatchViewManagerCommand(
+ this.getWebViewHandle(),
+ UIManager.RCTWebView.Commands.injectJavaScript,
+ [data]
+ );
+ };
+
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js
index 7961d777f7fc1b..15409e2cc2b22d 100644
--- a/Libraries/Components/WebView/WebView.ios.js
+++ b/Libraries/Components/WebView/WebView.ios.js
@@ -489,6 +489,20 @@ class WebView extends React.Component {
);
};
+ /**
+ * Injects a javascript string into the referenced WebView. Deliberately does not
+ * return a response because using eval() to return a response breaks this method
+ * on pages with a Content Security Policy that disallows eval(). If you need that
+ * functionality, look into postMessage/onMessage.
+ */
+ injectJavaScript = (data) => {
+ UIManager.dispatchViewManagerCommand(
+ this.getWebViewHandle(),
+ UIManager.RCTWebView.Commands.injectJavaScript,
+ [data]
+ );
+ };
+
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
diff --git a/React/Views/RCTWebView.h b/React/Views/RCTWebView.h
index c2c41431f632d2..633e780ac716ab 100644
--- a/React/Views/RCTWebView.h
+++ b/React/Views/RCTWebView.h
@@ -43,5 +43,6 @@ shouldStartLoadForRequest:(NSMutableDictionary *)request
- (void)reload;
- (void)stopLoading;
- (void)postMessage:(NSString *)message;
+- (void)injectJavaScript:(NSString *)script;
@end
diff --git a/React/Views/RCTWebView.m b/React/Views/RCTWebView.m
index 23fe37b84dca0f..7220fddeb8b300 100644
--- a/React/Views/RCTWebView.m
+++ b/React/Views/RCTWebView.m
@@ -96,6 +96,11 @@ - (void)postMessage:(NSString *)message
[_webView stringByEvaluatingJavaScriptFromString:source];
}
+- (void)injectJavaScript:(NSString *)script
+{
+ [_webView stringByEvaluatingJavaScriptFromString:script];
+}
+
- (void)setSource:(NSDictionary *)source
{
if (![_source isEqualToDictionary:source]) {
diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m
index 2730124fffa281..ddc66e2b8f13cf 100644
--- a/React/Views/RCTWebViewManager.m
+++ b/React/Views/RCTWebViewManager.m
@@ -111,6 +111,18 @@ - (UIView *)view
}];
}
+RCT_EXPORT_METHOD(injectJavaScript:(nonnull NSNumber *)reactTag script:(NSString *)script)
+{
+ [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) {
+ RCTWebView *view = viewRegistry[reactTag];
+ if (![view isKindOfClass:[RCTWebView class]]) {
+ RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view);
+ } else {
+ [view injectJavaScript:script];
+ }
+ }];
+}
+
#pragma mark - Exported synchronous methods
- (BOOL)webView:(__unused RCTWebView *)webView
diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java
index 1a80722fe00b8a..ebbb4b9c53b15a 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java
+++ b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java
@@ -94,6 +94,7 @@ public class ReactWebViewManager extends SimpleViewManager {
public static final int COMMAND_RELOAD = 3;
public static final int COMMAND_STOP_LOADING = 4;
public static final int COMMAND_POST_MESSAGE = 5;
+ public static final int COMMAND_INJECT_JAVASCRIPT = 6;
// Use `webView.loadUrl("about:blank")` to reliably reset the view
// state and release page resources (including any running JavaScript).
@@ -472,7 +473,9 @@ protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
"goForward", COMMAND_GO_FORWARD,
"reload", COMMAND_RELOAD,
"stopLoading", COMMAND_STOP_LOADING,
- "postMessage", COMMAND_POST_MESSAGE);
+ "postMessage", COMMAND_POST_MESSAGE,
+ "injectJavaScript", COMMAND_INJECT_JAVASCRIPT
+ );
}
@Override
@@ -499,6 +502,9 @@ public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray
throw new RuntimeException(e);
}
break;
+ case COMMAND_INJECT_JAVASCRIPT:
+ root.loadUrl("javascript:" + args.getString(0));
+ break;
}
}