[21] 
[DFN[[RUBYB[プッシュメッセージ][push message]]]]は、
[[プッシュ配信]]されるメッセージです。

* 仕様書

[REFS[
- [1] [CITE@en[RFC 8030 - Generic Event Delivery Using HTTP Push]], [TIME[2020-03-09 00:13:33 +09:00]] <https://tools.ietf.org/html/rfc8030>
- [20] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#dfn-push-message>
- [24] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#dom-pushmanager-supportedcontentencodings>
- [28] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#pushmessagedata-interface>
- [23] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#events>
]REFS]

* 意味

[2] 
[[Web Push]] の定義では、
[DFN[[RUBYB[プッシュメッセージ][push message]]]]は、
[[アプリケーションサーバー]]から[[利用者エージェント]]へと[[プッシュサービス]]を介して送られる[[メッセージ]]です。
[SRC[>>1 1.1.]]

[22] 
[[Push API]] の定義では、
[DFN[[RUBYB[プッシュメッセージ][push message]]]]は[[アプリケーションサーバー]]から
[[Webアプリケーション]]に送信されるデータです。
[SRC[>>20]]




[3] 
[[RFC 8030]] がただ「message」とのみ書いているときでも、多くは[[プッシュメッセージ]]とみられます。


* 状態

[6] [[プッシュメッセージ]]は、それが送信された (受信した) こと自体が情報になります。
それに加えて、付随する情報がいくつかあります。

[FIG(list members)[ [38] [[プッシュメッセージ]]

: [F[[CODE[Last-Modified]]]] : 
[[TTL][TTL:]]
の[[元期]]となる、
[[プッシュサービス]]が[[プッシュメッセージ]]を受信した[[日時]]です。
([[プッシュサービス]]が保持します。)
: [F[有効期限][TTL (プッシュメッセージ)]] :
[[プッシュメッセージ]]には、 
必ず有効期限があります。
[[アプリケーションサーバー]]は、
[CODE[TTL:]] 
[[HTTPヘッダー]]で有効期限を指定できます。
期限到来後、未配送の[[プッシュメッセージ]]は捨てられます。
同時に[[プッシュメッセージ資源]]も削除されるかもしれません。
([[アプリケーションサーバー]]が指定し、
[[プッシュサービス]]が適宜修正します。)
: [F[緊急度][Urgency (プッシュメッセージ)]] :
[[アプリケーションサーバー]]は、
[CODE[Urgency:]]
[[HTTPヘッダー]]で緊急度を指定できます。
([[アプリケーションサーバー]]が指定し、
[[プッシュサービス]]が保持します。)
: [F[データ][PushMessageData]] :
([[アプリケーションサーバー]]と[[利用者エージェント]]は暗号化されたデータを送受信しますが、
元のデータを知り得ます。
[[プッシュサービス]]は暗号化されたデータのみ知り得ます。
[[Webブラウザー]]上の[[アプリケーション]]は元のデータのみ見ます。)
: [F[[[プッシュメッセージ資源]]の [[URL]]]]:
([[プッシュサービス]]が決定し、
[[アプリケーションサーバー]]と[[利用者エージェント]]が知り得ます。)

]FIG]

* データ

[7] 
[[プッシュメッセージ]]には[F[データ][PushMessageData]]を含めることができます。
データは含めても含めなくても構いません。
[[プッシュメッセージ]]を受信したという事実により、
その事由や[[利用者]]に提示するべき事項などは他の手段で取得すればいいので、
データは省略したり、最低限に抑えたりできるのです。
([[Chrome]] の古い実装では、
データを含めることができませんでした。)

[39] 
データは、
[[プッシュメッセージ]]の本質的な内容たる形態と、
それを転送用に[[暗号化]]した形態の2種類があります。
そのどちらも、関係する各[[仕様書]]は
data、content、payload、 ([[HTTPメッセージ]]の) [[body][本体]]
のような呼び方を混在させていて、
明瞭さを欠きます。

[40] 
データは[[アプリケーションサーバー]] → ([[プッシュエンドポイント]]) →
[[プッシュサービス]] → ([[プッシュメッセージ購読資源]]) →
[[Webブラウザー本体][プッシュメッセージの受信]] → ([CODE[PushEvent]])
→ [[サービスワーカー]]と転送されますが、
このうち[[アプリケーションサーバー]]から
[[Webブラウザー本体]]までは、暗号化された状態で移動します。
[CODE[PushEvent]] で[[アプリケーション]]に提示される状態で[[解読]]済みの形に戻ります。

-*-*-

[5] 
データは [[HTTPメッセージ]]の[[本体]]として転送されます。
[[Web Push Protocol]] 単体ではこの[[本体]]に具体的な制約を規定していません。
[[応用][アプリケーション (プッシュ)]]は、
[[末端対末端]]で[[機密性]]、
[[一貫性]]、
データ起源[[認証]]を提供する機構を用いなければ[MUST[ならない]]
[SRC[>>1 8.1.]]
とだけ定められています。

[43] 
[[Push API]]
は、
[[利用者エージェント]]が
[CODE[aes128gcm]]
に対応しなければ[MUST[ならない]]、
互換性のため以前の [[I-D]] で定義されていた版にも対応して[MAY[構わない]]、
と規定しています
[SRC[>>24]]。
(古い版への対応は、いずれ[[廃止]]される想定とみられます。)
[[利用者エージェント]]への要件という形を採っていますが、
[[アプリケーションサーバー]]もこれに従う他選択肢はありません。


[25] 
[CODE[PushManager]]
[[インターフェイス]]の
[DFN[[CODE[supportedContentEncodings]]]]
[[属性]] [SRC[>>24]] は、
次のようにしなければ[MUST[なりません]]。

[FIG(steps)[
= [26] 
[CODE[SameObject]]:
[[プッシュメッセージ]]の [[payload]]
の[[暗号化]]に使える[[内容符号化]]の
[CODE[[[FrozenArray]]<[[DOMString]]>]]
を返します [SRC[>>24]]。
]FIG]

[44]
データに付随して転送される
[[HTTPヘッダー]]が[[プッシュメッセージ]]の一部を構成するのか、
[[RFC]] は明言していません。
例示には
[CODE[[[Content-Type:]] [[text/plain]][SNIP[; ...]]]]
が常に示されていて、これがデータの形式を表すようにもみえます。
一方で [[Push API]]
ではこの情報は使われませんし、
[[Push API]] が扱うデータは[[バイト列]]であって[[文字列]]ではないので、
この例示はあまり現実の利用に近いものでもありません。
実際上 [[HTTPヘッダー]]は[[プッシュメッセージ]]を構成しないとみるべきでしょう。

-*-*-

[45] 
[[プッシュメッセージ]]の[F[データ][PushMessageData]]の
(転送用ではない) 本質的な内容は、
[[アプリケーション]]依存の任意の[[バイト列]]です。

[46] 
理論上任意の長さの[[バイト列]]を扱えないこともないとされていますが、
[[プロトコル]]によって[[相互運用性]]が保証される長さ制限があって、
現実的にはその範囲に収める必要があります。
つまりデータは、
'''[N[0]] [[バイト]][[以上]]、[N[3993]] [[バイト]][[以下]]の[[バイト列]]'''でなければなりません。

[47] 
データが表すものは、[[テキスト]]でも [[JSON]] でも[[画像]]でも、
何でも構いません。


[48] 
[[アプリケーションサーバー]]は、
データを[[暗号化]]して[[プッシュサービス]]に送信することになります。
その手順は[[プッシュメッセージ]]の送信に使う[[ライブラリー]]などにより異なります。

[49] 
[[Webブラウザー]]上の[[アプリケーション]]は、
[[Webブラウザー]]の[[プッシュメッセージの受信]]処理によって[[解読]]されたデータを
[CODE[PushEvent]]
から受け取ることになります。
データは
[CODE[PushMessageData]]
[[オブジェクト]]として表されます。

-*-*-

[27] [DFN[[CODE[PushMessageData]]]]
[[インターフェイス]] [SRC[>>28]]
は、
[[プッシュメッセージ]]の[F[データ][PushMessageData]]を表します。
[[サービスワーカー環境]]に[[晒され]]ます
[SRC[>>28]]。
[CODE[SecureContext]] のみ利用可能です [SRC[>>28]]。

[30] 状態として[F[バイト群][bytes (PushMessageData)]]を持ちます。

[FIG(list short)[ [29] [CODE[PushMessageData]] の[[メンバー]]
- [CODE[arrayBuffer][bytes (PushMessageData)]]
- [CODE[json][bytes (PushMessageData)]]
- [CODE[text][bytes (PushMessageData)]]
- [CODE[blob][bytes (PushMessageData)]]
]FIG]


[31] 
[CODE[PushEvent]] [[インターフェイス]]の
[DFN[[CODE[data][PushMessageData]]]]
[[属性]]の[[取得器]] [SRC[>>23]] は、
次のようにしなければ[MUST[なりません]]。

[FIG(steps)[
= [32] [[文脈オブジェクト]]の
[F[[CODE[data][PushMessageData]]]]
を返します [SRC[>>23]]。
]FIG]

[33] 
[CODE[PushEventInit]] [[辞書]]の
[DFN[[CODE[data][PushMessageData]]]]
メンバー [SRC[>>23]] は、
[CODE[PushEvent]]
[[インターフェイス]]の
[CODE[data][PushMessageData]]
に対応します。値は
[CODE[PushMessageDataInit]] とされています [SRC[>>23]]
が、他に
[CODE[null]]
もあり得るようです。 
既定値は
[CODE[null]] です。


[36] 
[CODE[PushEvent]]
[[インターフェイス]]の[[イベント構築手順群]]の
[CODE[data][PushMessageData]]
の処理は、
[VAR[辞書]]と[VAR[イベント]]について、
次のようにします。
[SRC[>>23]]

[FIG(steps)[
= [37] [VAR[辞書]]の [F[[CODE[data][PushMessageData]]]] が [CODE[null]] でない場合、
== [41] [VAR[イベント]]の
[F[[CODE[data][PushMessageData]]]]
を、
新しい [CODE[PushMessageData]]
に設定します。
[FIG(list members)[ [42] [CODE[PushMessageData]]

: [F[バイト列][bytes (PushMessageData)]] :
[[extract a byte sequence]]
を[VAR[辞書]]の
[F[[CODE[data][PushMessageData]]]]
について実行した結果
]FIG]

]FIG]


[34] 
[DFN[[CODE[PushMessageDataInit]]]]
は、
[CODE[BufferSource]]
または
[CODE[USVString]]
に
[[typedef]]
されています。
[SRC[>>23]]

[35] 
[VAR[オブジェクト]]について
[DFN[extract a byte sequence]]
するには、
次のようにします。
[SRC[>>28]]

[FIG(steps)[
= [18] [VAR[オブジェクト]]が [CODE[BufferSource]] の場合、
== [19] [VAR[オブジェクト]]の内容の複製を返します。
= [20] [VAR[オブジェクト]]が [CODE[USVString]] の場合、
== [21] [VAR[オブジェクト]]を [[UTF-8符号化]]した結果を返します。
]FIG]

* プッシュメッセージ資源

[4] 
[DFN[[RUBYB[プッシュメッセージ資源][push message resource]]]]は、
[[プッシュサービス]]において[[プッシュメッセージ]]を識別する[[資源]]です。
[SRC[>>1 2.1.]]
[[URL]] によって識別されます。

[50] [[プッシュサービス]]は、
[[アプリケーションサーバー]]の求める[[プッシュメッセージ]]の配送を受理したとき[[プッシュメッセージ資源]]を作成し、
[[利用者エージェント]]が[[プッシュメッセージの受領肯定]]したとき[[プッシュメッセージ資源]]を削除します。
[SRC[>>1 2.1.]]

[51] 
[[Web Push Protocol]] 上[[プッシュメッセージ資源]]を能動的に操作することはできません。
次のように使われます。

- [52] 
[[プッシュメッセージの受信]]で、
[[server push]] される [CODE[GET]] [[要求]]という形で[[プッシュメッセージ]]配送に使われます。
- [53] 
[[プッシュメッセージの配送確認]]で、
[[server push]] される [CODE[GET]] [[要求]]という形で[[プッシュメッセージ]]受領の伝達に使われます。
-- [54] それとの照合のため、[[プッシュ資源]]の[[応答]]に [[URL]] が示されます。


[9] 
両者は同じ [[URL]] の [CODE[GET]]
でありながら、内容も意味も違います。

[17] 
理論上、
[[server push]] の[[意味論]]的には、
[[プッシュメッセージ資源]]を直接 [CODE[GET]]
することでも同じようにアクセスできるはずですが、
このような特殊な構造になっている以上、
[[server push]] 以外の方法で使うことは考えられていないのでしょう。



* 送信

[10] [[プッシュメッセージ]]は、
[[アプリケーションサーバー]]が[[プッシュサービス]]の[[プッシュ資源]]へと送信することで作成されます。
[SEE[ [[プッシュメッセージの送信]] ]]

* 受信

[8] [[プッシュメッセージ]]は、
[[プッシュサービス]]から[[利用者エージェント]]へと、
[[プッシュメッセージ購読]]や[[プッシュメッセージ購読集合]]の[[要求]]に対する
[[server push]] で配送されます。
[[Webブラウザー]]は、
適切な[[サービスワーカー]]を起動し、
[CODE[push][onpush]]
[[イベント]]によって配送します。
[SEE[ [[プッシュメッセージの受信]] ]]



* 受領


[55] 
[[プッシュサービス]]は、
受理した[[プッシュメッセージ]]を配送のため保持します。
次の場合に[[プッシュメッセージ]]は削除されます。

- [56] [[利用者エージェント]]への[[配送確認]]ができた場合
- [57] [F[[CODE[Last-Modified]]]] + [F[TTL][TTL:]] が[[現在時刻]]を超えた場合
- [59] 新しい[[プッシュメッセージ]]の [CODE[Topic:]] と重複した場合
- [58] その他[[プッシュサービス]]が配送を断念せざるを得ない場合


[11] 
[[利用者エージェント]]は、
[[プッシュメッセージ]]を最低1回は配送されたことを示す、
受領肯定を表明しなければ[MUST[なりません]]。
[SRC[>>1 6.2.]]

[12] 
[[利用者エージェント]]は、
[[プッシュメッセージ資源]]に
[CODE[DELETE]]
[[要求]]を送らなければ[MUST[なりません]]
[SRC[>>1 6.2.]]。


[16] 
[CODE[DELETE]]
に対して[[プッシュサービス]]が送るべき[[応答]]は、特に規定されていません。
[CODE[200]] や [CODE[204]]
が適当でしょうか。
[CODE[DELETE]] が既に行われている場合などのエラー処理も特に規定がありません。

[14] 
[[プッシュサービス]]は、
十分な時間内に肯定を受信しない場合、
未配送とみなします。
[CODE[TTL:]] 到来まで配送を試み続ける[SHOULD[べきです]]。
[SRC[>>1 6.2.]]

[15] 
[[プッシュサービス]]は、
それ以前でも事情に鑑み適宜再配送を中断して[MAY[構いません]]。
[SRC[>>1 6.2.]]

[13] 
受領されたかどうか、
[[プッシュサービス]]は[[受領証購読]]に適宜通知する必要があります。



* メモ
