WebChromeClient#onCreateWindow
work?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.