How does WebChromeClient#onCreateWindow
work?
[TOC]
This is a technical explanation of how onCreateWindow
and the related API are
implemented from content layer APIs.
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");
-
When the parent WebView loads the web page and runs the JavaScript snippet,
AwWebContentsDelegate::AddNewContents
will be called. The corresponding Java sideAwWebContentsDelegate#addNewContents
is called from the native. -
At the same time,
AwContents::SetPendingWebContentsForPopup
creates native popup AwContents with the givenWebContents
and stores it aspending_contents_
in the parentAwContents
object without Java counterpart created. Note that sincepending_contents_
can only store one popup AwContents, WebView doesn't support multiple pending popups. -
WebChromeClient#onCreateWindow
is called from step 1, with the code snippet above,childWebView
is set to theWebViewTransport
andresultMsg.sendToTarget()
will send thechildWebView
to its receiver. -
WebViewContentsClientAdapter
has a handler that receives the message sent fromresultMsg.sendToTarget()
. It will triggerWebViewChromium#completeWindowCreation
, thenAwContents#supplyContentsForPopup
is called on the parent WebView/AwContents. -
AwContents#supplyContentsForPopup
callsAwContents#receivePopupContents
on 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.