Android WebView enters unrecoverable state if executed JavaScript enters infinite loop

血红的双手。 提交于 2020-01-04 04:30:56

问题


The Android WebView widget appears to enter an unrecoverable state if executed JavaScript code is caught in an infinite loop.

For example, this webpage will cause the problem:

<html>
<head>
<title>FAIL</title>
<script type="text/javascript">
    function test() {
        while (true);
    }
</script>
</head>
<body onload="test();">
Failure Test
</body>

As will simply entering the following URL in any Android browser using WebView:

javascript:while(true);

Once such an infinite loop is encountered, one CPU core will be run at its maximum. The WebView appears to never shut down. This will of course rapidly drain the battery and slow the device. Only terminating the containing application appears to resolve this.

The following appear to be ineffective:

  • Disabling JavaScript: webView.getSettings().setJavaScriptEnabled(false);
  • Stopping the page from loading: webView.stopLoading();
  • Pausing all JS Timers: webView.pauseTimers();
  • Loading an alternate URL: webView.loadUrl("about:blank");
  • Removing the WebView from the widget hierarchy: parent.removeView(browserView);
  • Invoking destroy on the WebView: webView.destroy();
  • Finishing the activity: activity.finish();
  • Returning false from WebChromeClient.onJsTimeout(); (This method was deprecated in API 17, and appears to never be invoked).

The following is effective:

  • Killing the VM: System.exit(0); (This is a method that should never be called on Android.)

It's worth noting that the stock Android browser (not Chrome) suffers this problem as well. Though Chrome does not have the issue, it does still appear to occur when using the Chromium-based WebView shipped in Android 4.4.

Once one WebView enters this state, the application will be unable to load any URL into any other WebViews.

If anyone has any suggestions for terminating a WebView, it'd be greatly appreciated. I can't control the content being loaded into the WebView, as it's being used for a general-purpose browser. Otherwise my default solution will be to attempt to detect the scenario and warn the user if it is encountered, providing the option to forcibly terminate the application to prevent battery drain.

Thank you for any ideas!


回答1:


I don't think you can do too much about that. Because the WebView is single process (this is true for the 4.4 WebView too) and the renderers are running in your app's process a misbehaving web page can lead to your process being OOM killed by allocating tons of memory.

Chrome doesn't suffer from this problem since it runs the renderer in a separate process which can be killed. The WebView could be modified to kill the thread that JavaScript execution is taking place in, however that would lead to memory leaks (since the OS will not clean up for you like it does in the case of a separate process) and like I said above - doing so doesn't really protect you against a malicious web page allocating memory.

I think your solution of displaying a "the page is not responding. kill the app?" popup to the user is the best you can do using the WebView. The alternative is to create your own multi-process browser based on the Chromium code but that will probably take a lot more effort.



来源:https://stackoverflow.com/questions/20681876/android-webview-enters-unrecoverable-state-if-executed-javascript-enters-infinit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!