1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
android_webview / docs / how-does-on-create-window-work.md [blame]
# How does [`WebChromeClient#onCreateWindow`](https://developer.android.com/reference/android/webkit/WebChromeClient#onCreateWindow(android.webkit.WebView,%20boolean,%20boolean,%20android.os.Message)) 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):
```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):
```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`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/browser/aw_web_contents_delegate.h;l=43;drc=3abb32da2944ffe178dd66f404e7e1bb88a58ed0)
will be called. The corresponding Java side
[`AwWebContentsDelegate#addNewContents`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java;l=30;drc=a19051603849d7810b3569daf158aceb23aad1da)
is called from the native.
1. At the same time,
[`AwContents::SetPendingWebContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/browser/aw_contents.cc;l=1099;drc=7776bbb38c4e394b5be085bc8c5bc02df5fa22dc)
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.
1. `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.
1. `WebViewContentsClientAdapter` has a handler that receives the message sent
from `resultMsg.sendToTarget()`. It will trigger
[`WebViewChromium#completeWindowCreation`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java;l=265;drc=da3bb54157d4603b9c820d6cfdf61859f804dfb2),
then
[`AwContents#supplyContentsForPopup`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwContents.java;l=1455;drc=4afe92995db1279895f8a40b69c374bc298d750f)
is called on the parent WebView/AwContents.
1. `AwContents#supplyContentsForPopup` calls
[`AwContents#receivePopupContents`](https://source.chromium.org/chromium/chromium/src/+/main:android_webview/java/src/org/chromium/android_webview/AwContents.java;l=1475;drc=4afe92995db1279895f8a40b69c374bc298d750f)
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.