* 仕様書

[REFS[
- [2] [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>
- [160] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#events>
-- [5] [CITE@en-US[Push API]], [TIME[2020-02-04 16:21:34 +09:00]] <https://w3c.github.io/push-api/#receiving-a-push-message>
]REFS]

* アプリケーションサーバーからプッシュサービスへ

[SEE[ [[プッシュメッセージの送信]] ]]

* プッシュサービスから利用者エージェントへ

[48] 
[[利用者エージェント]]は、
[[プッシュメッセージ購読]]と[[プッシュメッセージ購読集合]]の両方がある場合、
[[プッシュメッセージ購読集合]]を使って[[プッシュメッセージ]]を監視する[SHOULD[べきです]]。
[SRC[>>2 6.1.]]

[30] 
[[利用者エージェント]]は、
[[プッシュメッセージ購読資源]]や[[プッシュメッセージ購読集合]]に対し、
[CODE[GET]]
[[要求]]を送信して新しい[[プッシュメッセージ]]の配送を要求します。
[SRC[>>2 6., 6.1.]]


[38] 
[[利用者エージェント]]は、
[[要求]]に
[CODE[Urgency:]] [[ヘッダー]]を指定できます。
[SEE[ [[Urgency:]] ]]

[43] 
[[利用者エージェント]]は、
[CODE[Prefer:]]
[[ヘッダー]]に
[CODE[wait][Prefer: wait]]
を値 [CODE[0]]
で指定 ([CODE[[[Prefer: wait]]=0]]) して、
即座に[[プッシュメッセージ]]を送信するように求めることができます。
[SRC[>>2 6., 6.1.]]


-*-*-

[39] 
[[プッシュサービス]]は
[CODE[Urgency:]] [[ヘッダー]]を処理しなければなりません。
[SEE[ [[Urgency:]] ]]

[53] 
対象の[[プッシュメッセージ購読]]または[[プッシュメッセージ購読集合]]が[[満期]]となった場合、
[CODE[404]]
[[応答]]を返さなければ[MUST[なりません]]。
[SRC[>>2 7.3., 7.3.1.]]

-*-*-

[31] 
[[プッシュサービス]]は、
[[要求]]に対して[[応答]]しません。
[[HTTP/2 server push]]
によって[[プッシュメッセージ]]の内容を送信します。
[SRC[>>2 6., 6.1.]]

[40] 
[[プッシュサービス]]は、[[プッシュメッセージ]]ごとに、
[CODE[PUSH_PROMISE]]
で
[CODE[GET]] [[要求]]を[[利用者エージェント]]に送信します。
この [CODE[GET]]
[[要求]]は、
[[プッシュメッセージ資源]]を取得するものです。
[SRC[>>2 6., 6.1.]]

[41] 
それに対する[[応答]]は、
[[HTTPヘッダー]]で、
[[プッシュメッセージ購読]]に対応する[[プッシュ資源]]の [[URL]] を、
[[リンク関係型]]
[CODE[urn:ietf:params:push]]
で示す[SHOULD[べきです]]。
[SRC[>>2 6.]]
[[プッシュメッセージ購読集合]]では、
示さなければ[MUST[なりません]]。 [SRC[>>2 6.1.]]
[CODE[Link:]]
[[ヘッダー]]に指定できます。
これを使って[[プッシュメッセージ購読]]を区別できます。

[42] その[[応答本体]]には、
[[アプリケーションサーバー]]が[[プッシュ資源]]に送信した直近の[[要求]]の[[実体本体]]を指定します。
[SRC[>>2 6., 6.1.]]
(と規定されていますが、直近のというのは意味がよくわかりません。
当該[[プッシュメッセージ]]を送るべきでしょう。)

[44] 
[[プッシュサービス]]は、
[[要求]]の
[CODE[Prefer:]]
[[ヘッダー]]で
[CODE[wait][Prefer: wait]]
が
[CODE[0]]
に設定されていた場合、
未配送の[[プッシュメッセージ]]をすべて
[[server  push]]
しなければ[MUST[なりません]]。
[SRC[>>2 6., 6.1.]]

[45] 
[[プッシュサービス]]は、
[CODE[204]]
[[応答]]を送信し、
[[server push]]
を送信しないことで、
[[プッシュメッセージ]]の不存在を示すことができます。
[SRC[>>2 6., 6.1.]]

[46] このような規定の理由は名言されていませんが、
[CODE[wait=0][Prefer: wait]]
が指定されていない限り、
[[プッシュサービス]]は[[プッシュメッセージ]]送信のタイミングを調整してよいということと思われます。

[47] 
特に明言されていないので、
[CODE[204]]
[[応答]]を返しても、そのまま[[ストリーム]]を残し
([CODE[END_STREAM]] を送信せず)
随時 [[server push]]
してもよいとみられます。

[49] 
仕様書では明文規定がありませんが、
例示によると、
[[プッシュサービス]]は適当なタイミングで最後に
[CODE[200]]
[[応答]]を送り[[ストリーム]]を閉じてよいようです。
[SRC[>>2 6., 6.1.]]

[58] 並行送信数を[[利用者エージェント]]は
[CODE[SETTINGS_MAX_CONCURRENT_STREAMS]] 
で指定することが[MAY[でき]]、
[[プッシュサービス]]はこれに従い抑制[MAY[できます]]。
[SRC[>>2 7.5.]]

[121] 
[[利用者エージェント]]は、受信した[[プッシュメッセージ]]について、
適用されるオプション指定との整合性を検査するべきです。
[SEE[ [[PushSubscriptionOptions]] ]]

* 利用者エージェントからサービスワーカーへ

[23] 
[[プッシュメッセージ]]は、
[[プッシュ購読]]に関連付けられた[[活性ワーカー]]に配送されます。
([[サービスワーカー]]が動作中でなければ、起動されます。)
[SRC[>>20]]

[6] 
[[利用者エージェント]]は、
[[プッシュ購読]][VAR[プッシュ購読]]から[[プッシュメッセージ]][VAR[プッシュメッセージ]]を受信したら、
次のようにしなければ[MUST[なりません]]
[SRC[>>5]]。

[FIG(steps)[
= [7] 
[VAR[登録]]を、
[VAR[プッシュ購読]]の[F[サービスワーカー登録]]に設定します。
= [8] [VAR[登録]]が [CODE[null]] の場合、
== [9] ここで停止します。
= [10] [VAR[データ]]を、
[CODE[null]]
に設定します。
= [11] [VAR[プッシュメッセージ]]が [[payload]] を持つ場合、
== [12] [VAR[平文]]を、
[VAR[プッシュメッセージ]]の [[payload]]
を[VAR[プッシュ購読]]について
[CODE[aes128gcm]]
[[復号]]した結果に設定します。
== [13] [VAR[平文]]が[[失敗]]の場合、
=== [14] [VAR[プッシュメッセージ]]について受領肯定します。
[SEE[ [[プッシュメッセージ資源]] ]]
=== [15] ここで停止します。
[NOTE[
[16] [VAR[プッシュメッセージ]]は捨てられます。
[CODE[push][onpush]]
を[[発火]]しては[MUST[なりません]]。
]NOTE]
== [17] 
[VAR[データ]]を、新しい [CODE[PushMessageData]] に設定します。
[FIG(list members)[ [18] [CODE[PushMessageData]]

: [F[バイト群][bytes (PushMessageData)]] : [VAR[平文]]

]FIG]
= [19] 
[[fire a functional event]] します。
[FIG(list members)[

: [F[イベント型]] : [CODE[push][onpush]]
: [F[イベントインターフェイス]] : [CODE[PushEvent]]
: [F[イベント対象]] : [VAR[登録]]
: [F[[CODE[data][PushMessageData]]]] : [VAR[データ]]
: [[extended lifetime promises]] がすべて[[解決]]された後の処理 :
[FIG(steps)[

= [21] すべてが成功裏に[[解決]]されていた場合、
== [22] [VAR[プッシュメッセージ]]を受領肯定します。
[SEE[ [[プッシュメッセージ資源]] ]]
= [24] それ以外の場合、
== [25] [VAR[プッシュメッセージ]]と同じものが既に何度も配送されていて拒絶されていた場合、
=== [26] [VAR[プッシュメッセージ]]を受領肯定します。
[NOTE[
[27] この場合、配送に失敗したにも関わらず、
成功したと通知されることになります。
何度も無限に再送されるのを防ぐためです。
それ以前に何度か拒絶されるのを許容する[SHOULD[べきです]]。
最低3回は認めることが[RUBYB[推奨][recommend]]されます。
]NOTE]

]FIG]

]FIG]

]FIG]



[161] 
[CODE[ServiceWorkerGlobalScope]]
[[インターフェイス]]の
[DFN[[CODE[onpush]]]]
[[属性]]は、
[[イベントハンドラーIDL属性]]です。
[SRC[>>160]]

[162] 
[DFN[[CODE[push][onpush]]]]
[[イベント]]は、
[[プッシュ購読]]が[[プッシュメッセージ]]を受信したことを示します。
[SRC[>>160]]


[1] 
[CODE[PushEvent]]
[[インターフェイス]]は、
[CODE[ExtendableEvent]]
を[[継承]]しており、
[[サービスワーカー環境]]に[[晒され]]ます。
[CODE[SecureContext]] でのみ利用可能です。
[DFN[[CODE[PushEventInit]]]]
[[辞書]]は、
[CODE[PushEvent]]
に対応する[[辞書]]で、
[CODE[ExtendableEventInit]]
を[[継承]]しています。
[SRC[>>160]]

[FIG(list short)[ [4] [CODE[PushEvent]] [[インターフェイスメンバー]]、[CODE[PushEventInit]] [[辞書メンバー]]
- [CODE[ExtendableEvent]], [CODE[ExtendableEventInit]] を[[継承]]
- [CODE[data][PushMessageData]]
]FIG]

[3] 
[CODE[PushEvent]]
[[コンストラクター]]は、
[[イベントコンストラクター]]ですが、
[CODE[data][PushMessageData]]
[[属性]]の処理があります。 [SRC[>>160]]

* メモ