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 side
AwWebContentsDelegate#addNewContents
is called from the native.
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.
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.
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.
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.