how-does-on-create-window-work.md 3.9 KB

How does WebChromeClient#onCreateWindow work?

[TOC]

Summary

This is a technical explanation of how onCreateWindow and the related API are implemented from content layer APIs.

Example usage

Let’s look at example code snippets first to see how an app could use these API:

On the app side (in Java):

// Configure parent WebView.
WebView webView = ...;
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setSupportMultipleWindows(true);

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onCreateWindow(
            WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
        // Create child WebView. It is better to not reuse an existing WebView.
        WebView childWebView = ...;

        WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
        transport.setWebView(childWebView);
        resultMsg.sentToTarget();
        return true;
    }
});

webView.loadUrl(...);

On the web page side (in JavaScript):

window.open("www.example.com");

What happened under the hood

  1. When the parent WebView loads the web page and runs the JavaScript snippet, AwWebContentsDelegate::AddNewContents will be called. The corresponding Java side AwWebContentsDelegate#addNewContents is called from the native.

  2. At the same time, AwContents::SetPendingWebContentsForPopup creates native popup AwContents with the given WebContents and stores it as pending_contents_ in the parent AwContents object without Java counterpart created. Note that since pending_contents_ can only store one popup AwContents, WebView doesn’t support multiple pending popups.

  3. WebChromeClient#onCreateWindow is called from step 1, with the code snippet above, childWebView is set to the WebViewTransport and resultMsg.sendToTarget() will send the childWebView to its receiver.

  4. WebViewContentsClientAdapter has a handler that receives the message sent from resultMsg.sendToTarget(). It will trigger WebViewChromium#completeWindowCreation, then AwContents#supplyContentsForPopup is called on the parent WebView/AwContents.

  5. AwContents#supplyContentsForPopup calls AwContents#receivePopupContents on the child WebView/AwContents. Child AwContents deletes the existing native AwContents from the child WebView/AwContents, and pairs it with the pending_contents_ from the parent WebView/AwContents. In order to preserve the status of the child WebView, all the flags and configurations need to be re-applied to the pending_contents_. Loading on the native AwContents is also resumed.