Properly escape JavaScript code on Android (#20366)

Summary:
These changes will fix executing javascript with any special characters, by making use of the `evaluateJavascript` function on Android 4.4+, and by properly escaping the URI on Android <4.4.

Fixes #19611Fixes #20365Fixes #9749Closes #19655Closes #12321

This PR supersedes #19655 by patching the same problem in all the places, and fixing it for Android <4.4 as well.
Pull Request resolved: https://github.com/facebook/react-native/pull/20366

Differential Revision: D9242968

Pulled By: hramos

fbshipit-source-id: f2e1abc786ba333dbd8aaa8922e716fd99ec26e0
This commit is contained in:
Linus Unnebäck 2018-08-09 11:10:11 -07:00 committed by Facebook Github Bot
parent 8ee9002c76
commit e6b305b722
1 changed files with 21 additions and 4 deletions

View File

@ -16,6 +16,7 @@ import java.util.regex.Pattern;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@ -325,11 +326,25 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
} }
} }
protected void evaluateJavascriptWithFallback(String script) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
evaluateJavascript(script, null);
return;
}
try {
loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// UTF-8 should always be supported
throw new RuntimeException(e);
}
}
public void callInjectedJavaScript() { public void callInjectedJavaScript() {
if (getSettings().getJavaScriptEnabled() && if (getSettings().getJavaScriptEnabled() &&
injectedJS != null && injectedJS != null &&
!TextUtils.isEmpty(injectedJS)) { !TextUtils.isEmpty(injectedJS)) {
loadUrl("javascript:(function() {\n" + injectedJS + ";\n})();"); evaluateJavascriptWithFallback("(function() {\n" + injectedJS + ";\n})();");
} }
} }
@ -348,7 +363,7 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
}); });
} }
loadUrl("javascript:(" + evaluateJavascriptWithFallback("(" +
"window.originalPostMessage = window.postMessage," + "window.originalPostMessage = window.postMessage," +
"window.postMessage = function(data) {" + "window.postMessage = function(data) {" +
BRIDGE_NAME + ".postMessage(String(data));" + BRIDGE_NAME + ".postMessage(String(data));" +
@ -637,9 +652,10 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
break; break;
case COMMAND_POST_MESSAGE: case COMMAND_POST_MESSAGE:
try { try {
ReactWebView reactWebView = (ReactWebView) root;
JSONObject eventInitDict = new JSONObject(); JSONObject eventInitDict = new JSONObject();
eventInitDict.put("data", args.getString(0)); eventInitDict.put("data", args.getString(0));
root.loadUrl("javascript:(function () {" + reactWebView.evaluateJavascriptWithFallback("(function () {" +
"var event;" + "var event;" +
"var data = " + eventInitDict.toString() + ";" + "var data = " + eventInitDict.toString() + ";" +
"try {" + "try {" +
@ -655,7 +671,8 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
} }
break; break;
case COMMAND_INJECT_JAVASCRIPT: case COMMAND_INJECT_JAVASCRIPT:
root.loadUrl("javascript:" + args.getString(0)); ReactWebView reactWebView = (ReactWebView) root;
reactWebView.evaluateJavascriptWithFallback(args.getString(0));
break; break;
} }
} }