ブラウザのプッシュ通知のデバッグ

[Google Cloud Messaging (GCM)](http://qiita.com/tomoyukilabs/items/8fffb4280c1914b6aa3d)(Chromeのみ)や[Web Push暗号化](http://qiita.com/tomoyukilabs/items/217915676603fda73b0a)(Chrome, Firefox)でブラウザにプッシュ通知を送れるようになってきていますが、今回はそのデバッグ手段についてメモを書いてみます。

# Service Workerのデバッグ

既に多くの記事で書かれており、詳しい説明が要らないような気がしますので、簡潔に。

## Chrome

`chrome://serviceworker-internals`を開くと、インストール済みService Workerの状態を確認することができます。Service Worker自体はfetchやpushなどのイベント発生時にしか起動しませんが、このページから手動でService Workerを[Start]ボタンで起動して、[Inspect]ボタンをクリックすることで、開発者ツールを開いてService Workerのデバッグを行うことが可能になります。

![Screen Shot 2016-03-11 at 9.27.56 .png](https://qiita-image-store.s3.amazonaws.com/0/48556/4aa0d8f0-356a-d420-5e05-be38ab80fb0b.png)

例えば、Service Workerでプッシュ通知を受信した時の処理が正しく呼ばれているかどうか、等のチェックができるようになります。

## Firefox (46以前)

`about:serviceworkers`を開くと、インストール済みService Workerの状態を確認することができます。プッシュ通知のendpointや受信したプッシュ通知の数などもここで確認できます。

<img width="714" alt="Screen Shot 2016-03-11 at 9.36.55 .png" src="https://qiita-image-store.s3.amazonaws.com/0/48556/eb794e28-5391-8ad7-9538-f1386670c337.png">

Chromeのように、Service Worker自体のコンソールを開くといった機能は用意されていないようですが、`about:config`で詳細設定を開き、`devtools.browserconsole.filter.serviceworkers`という項目の値(Value)を`true`にしていると(現在はデフォルトで`true`になっているようです)、Service Workerのスコープ内にあるWebアプリを開いている時に、Service Workerのコンソールへの出力がWebアプリのコンソールにも出力されるようになります。

<img width="714" alt="Screen Shot 2016-03-11 at 9.52.07 .png" src="https://qiita-image-store.s3.amazonaws.com/0/48556/cc0f4eb5-b310-82b4-7857-69fc8b1853b5.png">

## Firefox 47+

Firefox 47では、「Web開発」(Macでは「ツール」メニューの下)のメニューにService Workersという項目が追加され、[Service Worker単体のデバッグがサポートされるようになりました](https://hacks.mozilla.org/2016/03/debugging-service-workers-and-push-with-firefox-devtools/)。アドレスバーから直接開く場合は、`about:debugging#workers`と入力します。

<img width="875" alt="Screen Shot 2016-03-25 at 9.17.41 .png" src="https://qiita-image-store.s3.amazonaws.com/0/48556/ad6e33f6-8af6-83d9-39dc-d2d5248f7b0f.png">

Chromeの開発者ツールと同様に、Startボタンで待機中のService Workerスレッドを起動状態にすることができ、その状態でDebugボタンをクリックすると、Service Worker単体のデバッガとコンソールが利用できるようになります。また、Pushをクリックするとプッシュ通知(`push`イベント)の動作テストを行えます。

<img width="863" alt="Screen Shot 2016-03-25 at 9.26.06 .png" src="https://qiita-image-store.s3.amazonaws.com/0/48556/b4565c1a-3a9a-4166-b0b7-6526e37f258b.png">

# プッシュ通知の受信確認

Service Workerでは、プッシュ通知が正常に受信できた場合にのみ`push`イベントが発生します。特に、Web Push暗号化を利用している場合は、暗号化されたプッシュ通知が正常に復元できた時にしか`push`イベントが発生しないため、プッシュ通知自体の受信に失敗したのか、それともプッシュ通知の暗号化に問題があるのか、区別しづらくなります。

ChromeとFirefoxそれぞれについて、プッシュ通知自体の状態を確認する方法を以下に挙げておきます。

## Chrome

`chrome://gcm-internals`を開くと、プッシュ通知の購読や受信などの状態を確認することができます。プッシュ通知の受信については[Start Recording]ボタンを押すとモニタリングを開始します。

![Screen Shot 2016-03-11 at 9.21.04 .png](https://qiita-image-store.s3.amazonaws.com/0/48556/ae7bb45f-ab01-6eca-cfba-3c8e5f31501a.png)

ここで、Receive Message Logにプッシュ通知の受信が記録されたにもかかわらず、Service Workerで`push`イベントが発生しない場合は、Web Pushの暗号化に何らかの問題があるものと考えられます。例えば、必要なヘッダ(`Encryption`や`Crypto-Key`等)や暗号化手順を見なおせばよい、ということになります。

## Firefox

`about:config`を開き、`dom.push.loglevel`の値を変更すると、Firefoxの動作のログにPushServiceのログも含まれるようになります。デスクトップ版の場合は、コマンドプロンプト(Windows)やターミナル(OS X, Linux)からFirefoxを起動すると、Firefoxの動作ログがコマンドプロンプトやターミナル(すなわちstdoutやstderr)に出力されるようになります。Android版の場合は、adbのlogcatにGecko等のログとして出力されます。

<img width="714" alt="Screen Shot 2016-03-11 at 10.02.58 .png" src="https://qiita-image-store.s3.amazonaws.com/0/48556/7b3a690a-e3c8-796b-c82a-d7ebcf8c42e3.png">

例えば、OS X版の場合、ターミナルからFirefoxを起動するには次のようにします。

```bash
/Applications/Firefox.app/Contents/MacOS/firefox-bin
```

設定可能な値としては`error`, `warn`, `debug`などがあり、値によって出力されるログの詳細度が変わります。(`debug`にするとFirefox内部の詳細な動作までわかるので、Firefoxやプッシュサーバの動作が正しいかどうかの検証にも使えます。[[参考記事]](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/NSPR_LOG_MODULES))

`debug`を指定している場合は、非常に詳細なログが出力されます。この時、解析が非常に厄介ではありますが、アプリケーションサーバからプッシュサーバに送信したプッシュ通知の内容がどこまでFirefox自体にまで伝わっているか、ヘッダ等も含めてJSON形式でログに記述されたりします。暗号化にエラーがある場合も明示的にログに書かれますので、詳細なデバッグに有用かもしれません。

```text:プッシュ通知受信ログの例(一部抜粋)
console.debug: PushServiceWebSocket: 
  wsOnMessageAvailable()
  {"headers": {"crypto_key": "keyid=p256dh;dh=...", "encoding": 
"aesgcm128", "encryption": "keyid=p256dh;salt=..."}, "version": "...",
"data": "...", "channelID": "...", "messageType": "notification"}
```