Search code examples
androidiframeandroid-webviewandroid-chrome

WebView doesn't load iFrame video due to security policy violation


I am trying to load an iFrame in my WebView. The video/iFrame doesn't load reliably

This is what happens :

When I load the screen, in the webview's place there is blank space, but eventually the video might load, but most times, it doesn't load. However, if I lock the screen and unlock it, the video loads just fine.

I extended the ChromiumWebClient and logged the following methods :

onProgressChanged(WebView view, int newProgress) {}
onConsoleMessage(ConsoleMessage consoleMessage) {}

Turns out the video downloads 80% then, incurs the security exception, but it does seem to continue downloading in a short while and downloads 100%.

Despite downloading 100%, the webview doesn't show the video(player).

However, as mentioned above, if I lock and unlock the screen, (the now downloaded) video shows up correctly.

iFrame(could be from any source, not just vimeo) :

"https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F215269493&url=https%3A%2F%2Fvimeo.com%2F215269493&image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F632188996_1280.jpg&key=0a5d85b22c79478aa887a7e8061bef56&type=text%2Fhtml&schema=vimeo' width='525' height='295' scrolling='no' frameborder='0' allowfullscreen>"

Web view code :

fun onResume() {
    videoWebView.onResume()
}

fun onPause() {
    videoWebView.onPause()
}


private fun loadVideo(videoWebView: WebView, iFrame: String) {
    videoWebView.setWebViewClient(WebViewClient())
    videoWebView.setWebChromeClient(WebChromeClient())
    videoWebView.settings.javaScriptEnabled = true
    videoWebView.settings.domStorageEnabled = true
    videoWebView.settings.loadsImagesAutomatically = true
    videoWebView.settings.loadWithOverviewMode = true
    videoWebView.loadData(
            iFrame,
            WebFormatUtil.MIMETYPE_HTML,
            WebFormatUtil.ENCODING_UTF8)      
}

I do have hardwareAcceleration and internet permission enabled in manifest

The Logs throw the following (2 messages):

I/chromium: [INFO:CONSOLE(11)] "The deviceorientation event is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS. See https://shortened url for more details.", source: https://f.vimeocdn.com/p/2.69.8/js/player.js (11)

I/chromium: [INFO:CONSOLE(0)] "Refused to load the image 'android-webview-video-poster:default_video_poster/-1316638038331145773' because it violates the following Content Security Policy directive: "img-src 'self' data: https://i.vimeocdn.com https://secure-b.vimeocdn.com https://f.vimeocdn.com https://vimeo.com https://secure.gravatar.com https://i0.wp.com https://i1.wp.com https://i2.wp.com https://player.vimeo.com https://*.ci.vimeows.com https://f.vimeocdn.com". ", source: https://player.vimeo.com/video/215269493 (0)

This turns out to be a known issue in the Chromium client and has not ben fixed yet.

What I am looking for : I am looking for a way such that when I open the screen the video is shown, without having to turn on and off the screen. Not sure if anything other than a hack around is possible.

Note : I have tried a lot of other answers, most of the deal with other issues such as config and so on. I have isolated out the issue to be in ChromiumClient used for Android WebView, which those other answers are not about.


Solution

  • This is how I fixed my issue :

    private fun loadVideo(videoWebView: WebView, iFrame: String) {
        webView.setWebChromeClient(object: WebChromeClient() {
                    override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
                        if (consoleMessage.messageLevel() == ConsoleMessage.MessageLevel.ERROR) {
                            webView.onResume()
                        }
                        return super.onConsoleMessage(consoleMessage)
                    }
                })
          //......rest of the method like before
        }
    

    Every time after lock/unlocking the screen, the video showed up fine. What that means is that the onPause() and onResume() were fired inside the webView.

    Additionally, Every time the security exception is incurred the onConsoleMessage(consoleMessage: ConsoleMessage) in Chromium client is fired with the tag ERROR.

    This is a hack around, which so far has been safe, from my testing. Until the actual issue is fixed, this works for me.