Dong Nguyen
Dong Nguyen

Reputation: 41

Android webview refused to execute inline script

I'm writing an Android application which host a webview to load a webpage. I got a lot of errors like below in logcat:

Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

Please note that Javascript is executed well if it's not an inline script. For example, with an HTML file like below:

<htnl>
<head>
<script type="text/javascript" src="abc.js"></script>
</head>
<body>
<script type="text/javascript">
    alert("This is inline script");
</script>
</body>
</html>

Script in abc.js is executed properly, but the inline script is refused to execute.

I understand that the webview refuses to execute inline Javascript due to "Contect Security Policy". But the webpage need to execute those inline scripts to function properly and I cannot make any change on the webpage.

This problem only KitKat (Android 4.4)

Is there any way to overcome this problem, modify "Content Security Policy" to allow inline script to be executed.

Upvotes: 4

Views: 3988

Answers (2)

ivan8m8
ivan8m8

Reputation: 447

I had

Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash, or a nonce ('nonce-...') is required to enable inline execution. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.

& fixed that by

webView.settings.domStorageEnabled = true

Upvotes: 0

Stan
Stan

Reputation: 8768

According to information from WebView developers, injected javascripts run in the host page itself, not in an isolated world as it is with Chromium extensions. This is why they should pass common security checkups imposed by Content Security Policy header (if it exists). As a result, it can be impossible to inject a script as a file via src attribute or inline, or in both ways, depending from the header directive (for example, if unsafe-inline is mentioned, you'll be unable to inject a script tag with inline code).

The workaround is to use loadUrl or evaluateJavascript methods to execute javascript code "as is", without adding a script tag. For example:

webview.loadUrl("javascript:alert('hello')");

will be executed successfully.

For Android 4.4 and up it's recommended to use the new evaluateJavascript method, because loadUrl has a side effect when your app is targeted to one of these newer Android versions (and I think this is the case for most projects nowadays): if the script returns a value - it will replace DOM content of the current page. On targets prior 4.4, both methods are the same except for the possibility to return a value via optional callback in evaluateJavascript.

One could think of other tricks but this should be enough to solve your problems.

Upvotes: 1

Related Questions