Accompanist の WebView Wrapper メモ1: `window.confirm` がそのままで表示される

Accompanist の WebView Wrapper を使って
Jetpack Compose で WebView を使うときのメモです。

https://google.github.io/accompanist/web/

👇 次の回

https://qiita.com/mangano-ito/items/e17fc127f698fb944837

:::note warn
このときのバージョンは `com.google.accompanist:accompanist-webview:0.30.1` です。
:::


## JS の `window.confirm` がなにもせず表示されてる

Android View の WebView だと JavaScript の `window.confirm` といったダイアログについて、
自分で `WebChromeClient` を指定しないと表示してくれなかったのですが、
Accompanist の WebView Wrapper だとデフォルトで表示するようになっていることに気づきました:

```kotlin:MyWebView.kt
@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun MyWebView(
    modifier: Modifier = Modifier,
) {
    val state = rememberWebViewState(
        url = "https://codepen.io/mangano_ito/pen/jOeZKxP",
    )
    WebView(
        state = state,
        onCreated = { webView ->
            webView.settings.javaScriptEnabled = true
            webView.settings.domStorageEnabled = true
        },
        modifier = modifier,
    )
}
```

![window.confirm テスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/f999d33a-bc70-d353-58d8-ac46f1a626ca.png)


テストに使ったページはこれのために用意した
ホントに `window.confirm` だけする CodePen のページです:

https://codepen.io/mangano_ito/pen/jOeZKxP


## なぜ表示される？

これは Accompanist だとデフォルト実装の `WebChromeClient` を与えてくれるようになっているからです:

```kotlin:accompanist/web/src/main/java/com/google/accompanist/web/WebView.kt (LL.73-84)
@Composable
fun WebView(
    state: WebViewState,
    modifier: Modifier = Modifier,
    captureBackPresses: Boolean = true,
    navigator: WebViewNavigator = rememberWebViewNavigator(),
    onCreated: (WebView) -> Unit = {},
    onDispose: (WebView) -> Unit = {},
    client: AccompanistWebViewClient = remember { AccompanistWebViewClient() },
    chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() },
    factory: ((Context) -> WebView)? = null
) {
```

https://github.com/google/accompanist/blob/cb7344a8db43ba57007bfe15d3e2c4266cf8a1f6/web/src/main/java/com/google/accompanist/web/WebView.kt#L82


```kotlin:accompanist/web/src/main/java/com/google/accompanist/web/WebView.kt(LL.148-160)
        AndroidView(
            factory = { context ->
                val childView = (factory?.invoke(context) ?: WebView(context)).apply {
                    onCreated(this)

                    layoutParams = LayoutParams(
                        width,
                        height
                    )

                    webChromeClient = chromeClient
                    webViewClient = client
                }.also { webView = it }
```

https://github.com/google/accompanist/blob/cb7344a8db43ba57007bfe15d3e2c4266cf8a1f6/web/src/main/java/com/google/accompanist/web/WebView.kt#L158


## なぜ Android View ではデフォルトで表示されなかった？

`WebChromeClient` の `onJsConfirm` の説明にあるように、
指定しなければ `confirm` は抑止されるようになっているからです:

> Note that if the `WebChromeClient` is set to be `null`, or if `WebChromeClient` is not set at all, the default dialog will be suppressed and the default value of `false` will be returned to the JavaScript code immediately. 

https://developer.android.com/reference/android/webkit/WebChromeClient#onJsConfirm(android.webkit.WebView,%20java.lang.String,%20java.lang.String,%20android.webkit.JsResult)

なので Android View ではデフォルトではなにも指定されずダイアログが表示されないので、
自分で指定してあげないといけなかったという話題がありました:

https://qiita.com/akito0190/items/7d8ade5da14dc12c7d8a

(↑ 先駆者のかたの記事)

したがって、こういう違いにより動作が変わっています:

```kotlin:AndroidViewWebView.kt
binding.webview.apply {
    settings.javaScriptEnabled = true
    settings.domStorageEnabled = true
    // ↓ これが ない または `null` のときは表示されない
    webChromeClient = WebChromeClient()
    loadUrl("https://codepen.io/mangano_ito/pen/jOeZKxP")
}
```

| 未指定 or `null` | 指定 |
|-------|------|
|![android-view-webview-unspecified.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/5c4f0aff-6b9c-f00b-649d-b92062dc6b3b.gif) | ![android-view-webview-specified.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/afa56a4d-f4a6-d676-b492-ebd5e57f78d5.gif)|


## おわりです

`AndroidView` を使わず Accompanist の WebView Wrapper を使う場合はとくに意識せずこれが有効になっているので後でアレっとはなりづらいですね。地味な違い。

以上です。