User-Agent Client Hints(UA-CH)を取得する

[Googleがユーザーエージェント（UA）文字列を凍結・非推奨する](https://forest.watch.impress.co.jp/docs/serial/yajiuma/1229968.html)ということで、
代替として仕様策定中の[User-Agent Client Hints(UA-CH)](https://wicg.github.io/ua-client-hints/)を今のうちに試してみます。

### User-Agent Client Hints(UA-CH）とは

Google ChromeがUserAgent文字列の非推奨・凍結を計画したことにより、
将来的に、UserAgent文字列から、ブラウザのバージョンなどの情報が正確に取得することが出来なくなってしまう。
代替手段として、``User-Agent Client Hints``の機能が検討中であり、Google Chromeでは実験的な機能として試すことができる。
従来のUserAgent文字列と同じようにHTTPリクエストヘッダーやJavascriptを使って情報を取得することが可能です。

### User-Agent Client Hints(UA-CH)を有効にする

``chrome://flags/`` から、``Experimental Web Platform features``を有効にすることで使用できます。Chrome79以降だと使えるみたいです。

Chrome 90以降は標準で対応済みのようです。


<img width="916" alt="ChromeFlags.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34699/c1dd63e0-1ea8-d632-e5f3-cb115a657140.png">


Chromeを再起動したあと、適当なページを開いて、Chrome デベロッパーツールを開きます。
Network>Doc>Headersタブを開いて``Request Headers``の箇所を見ると、``sec-ch-ua``の項目が取得されています。


<img width="797" alt="devtool.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34699/7d5bf593-fac5-e63b-a1b8-a53a37a2b3c5.png">

さらに詳しい情報を欲しい場合は、``Accept-CH``ヘッダーを返してあげる必要があります。

またはmetaタグにも対応しているようです。
```
<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Downlink">
```

### Webサーバーを用意してAccept-CHヘッダを出力する

``Accept-CH``ヘッダーを返すためのWebサーバーを用意します。

まず、[Node.js](https://nodejs.org/ja/)をインストールしておきます。

適当なディレクトリ上にExpressサーバーをインストールします。

```
npm install express
```

下記の通り``Accept-CH``ヘッダーに「UA, Platform」を出力するように記載します。

```js:main.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.setHeader('Accept-CH', 'UA, Platform');
  // res.setHeader('Accept-CH', 'UA, Platform, Model, Mobile, Arch');
  res.send('Hello World!');
});
app.listen(8000, () => {});
```

サーバーを起動します。

```
node main.js
```

これで、``http://localhost:8000``にアクセスすると、リクエストヘッダーに下記の項目が追加されることが確認できます。

```
sec-ch-ua: Google Chrome 81.0.4042.0
sec-ch-ua-arch: Intel
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: Mac OS X
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4042.0 Safari/537.36
```

ただし、１回目のリクエストでは表示されないので、２回目のリクエストもしくは、iframeなどを使ってサブリエクストを行う必要があります。


### Javascriptで取得

Javascriptだと Chromeに``navigator.getUserAgent()``が用意されているようだ。

* [User-Agent がオワコンになりそう](https://qiita.com/il-m-yamagishi/items/331270e654530a358481)


実際確認してみたところ、上記では無く、``navigator.userAgentData``というのが存在しているようだ。
``chrome://flags/`` から、``Experimental Web Platform features``を有効にすることで使用できる。

以下のua.mobileの部分は今まで常に``false``だったが、Chrome87だと、Developerツールでモバイル表示設定にすると``true``に切り替わるようになっていた。

```js
const ua = navigator.userAgentData;
console.log(ua.mobile); // false
console.log(ua.brands[0].brand); // Google Chrome
console.log(ua.brands[0].version); // 84
```

```js
navigator.userAgentData.getHighEntropyValues([
 "platform",
 "platformVersion",
 "architecture",
 "model",
 "uaFullVersion"
]).then(res => console.log(res)); 
/*
 { "architecture":"Intel",
   "model":"",
   "platform":"Mac OS X",
   "platformVersion":"10_15_4",
   "uaFullVersion":"84.0.4133.0"
 }
*/
```

* [Get Ready for Chrome User-Agent String Phase Out](https://medium.com/@galmeiri/get-ready-for-chrome-user-agent-string-phase-out-c6840da1c31e)

### Chrome以外のChromium系ブラウザの場合

ここでChrome以外のChromium系ブラウザでどうなるか見てみます。

[Operaの元CEOによる高機能ブラウザ・Vivaldiが「ユーザーエージェント文字列をChromeに見せかける」ことを余儀なくされた理由とは？](https://gigazine.net/news/20191213-vivaldi-browser-user-agent-changes/)
にあるようにUserAgentをChromeと同じに変えた``Vivaldi``ですが、``Experimental Web Platform features``を有効にして``sec-ch-ua``の値を見てみると・・・

```
sec-ch-ua: Vivaldi 79
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.131 Safari/537.36
```
こっちはVivaldiと出ていますね。
UA文字列はChromeと同じですが、sec-ch-uaは独自のものが設定されています。


``Chromium``だと、UA文字列はChromeと同じ、sec-ch-uaは独自

```
sec-ch-ua: Chromium 79
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3914.0 Safari/537.36

```

``Opera``だと、UA文字列は独自、sec-ch-uaはChromiumと同じ

```
sec-ch-ua: Chromium 79
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 OPR/66.0.3515.44
```

``Microsoft Edge``だと、UA文字列は独自、sec-ch-uaも独自、EdgではなくEdge表示

```
sec-ch-ua: Microsoft Edge 80
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.66 Safari/537.36 Edg/80.0.361.40
```


``Brave``だと、UA文字列はChromeと同じ、sec-ch-uaは独自

```
sec-ch-ua: Brave Browser 79
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.131 Safari/537.36
```



という風に``UserAgent``は変わらなくても``sec-ch-ua``だと識別できるようになっているものもありますね


その他

```
# CocCoc
sec-ch-ua: CocCoc 79
# Yandex
sec-ch-ua: Yandex 80
# SRWare Iron
sec-ch-ua: Chromium 79
```


### 参考サイト

* [新しいユーザエージェント表現 User Agent Client Hints の提案仕様 ](https://asnokaze.hatenablog.com/entry/2018/11/30/064817)
* [User Agent Client Hintsをサーバ側で取得してみる。](https://http2.try-and-test.net/client_hints.html)
* [User-Agent Client Hints](https://wicg.github.io/ua-client-hints/)
* [Accept-CH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-CH)
* [User-Agent Client Hints - laptrinhx](https://laptrinhx.com/user-agent-client-hints-3170064526/)
* [Client Hints replacing the User-Agent - mpulp](https://mpulp.mobi/2020/01/16/client-hints-replacing-the-user-agent/)
* [ChromeでUserAgentが凍結される日（User Agent Client Hintsの使い方）](https://qiita.com/paddy-oti/items/fae9ecca9facc9797035)
* [User Agent Client Hintsに関する調査](https://qiita.com/tetsurotayama/items/dfa0f22418c226b102aa)