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
-
When the parent WebView loads the web page and runs the JavaScript snippet,
AwWebContentsDelegate::AddNewContentswill be called. The corresponding Java sideAwWebContentsDelegate#addNewContentsis called from the native. -
At the same time,
AwContents::SetPendingWebContentsForPopupcreates native popup AwContents with the givenWebContentsand stores it aspending_contents_in the parentAwContentsobject without Java counterpart created. Note that sincepending_contents_can only store one popup AwContents, WebView doesn't support multiple pending popups. -
WebChromeClient#onCreateWindowis called from step 1, with the code snippet above,childWebViewis set to theWebViewTransportandresultMsg.sendToTarget()will send thechildWebViewto its receiver. -
WebViewContentsClientAdapterhas a handler that receives the message sent fromresultMsg.sendToTarget(). It will triggerWebViewChromium#completeWindowCreation, thenAwContents#supplyContentsForPopupis called on the parent WebView/AwContents. -
AwContents#supplyContentsForPopupcallsAwContents#receivePopupContentson the child WebView/AwContents. Child AwContents deletes the existing native AwContents from the child WebView/AwContents, and pairs it with thepending_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 thepending_contents_. Loading on the native AwContents is also resumed.