1. 導入
この節は非規範的です。
この仕様は、スクリプトが、制限付き API を呼び出す能力を、信頼する別の ブラウジングコンテキストへ委譲できる仕組みを定義します。ここでの 焦点は、委譲されたケイパビリティをターゲットの ブラウジングコンテキストへ時間制約付きの方法で公開する、動的な委譲機構です。
1.1. ケイパビリティ委譲とは何か?
Web における多くのケイパビリティは、JS から制限された方法で使用できます。たとえば:
-
ほとんどのブラウザーは、ユーザーが最近ページとやり取りしたか、またはブラウザーがそのページのオリジンからポップアップを開くことを許可している場合にのみ、
Window.open()によるポップアップを許可します。 -
サンドボックス化された iframe は、特定のサンドボックス属性またはフレーム内でのユーザー操作がない限り、 自身を全画面にすることはできません (
requestFullscreen()による場合でも同様です)。
ケイパビリティ委譲とは、フレームが制限付き API を呼び出す能力を動的に放棄し、
その能力を、信頼できる別の(サブ)フレームへ転送できるようにすることを意味します。ここでの
"dynamic" という語は、委譲の効果が、委譲されるケイパビリティにより定義される
限られた時間だけ継続することを意味します。これは、
ブラウジング
コンテキストへの、iframe
allow
属性を通じた、ケイパビリティの静的な(読み込み時の)公開とは異なります。その場合、ケイパビリティはサブフレームに
時間制約なしの方法で公開されます。
1.2. 委譲の開始とケイパビリティの使用
ケイパビリティ委譲が有効に機能するには、2 つの別個の手順が必要です。最初の手順は "initiation" であり、ある ブラウジングコンテキストが、委譲される特定のケイパビリティについて、別の ブラウジング コンテキストに通知します。開始後、2 番目の(つまり受信側の) ブラウジングコンテキストは、委譲された ケイパビリティを "use" します。これは通常、ケイパビリティで定義されたメソッドを呼び出すことを意味します。 ここでのケイパビリティ委譲仕様は、第 2 手順で使用される API インターフェイスを定義しませんが、 API の内部的な振る舞いを再定義します。
このため、この仕様は 2 つの別個の部分で構成されます。すなわち、 開始手順のための API の定義と、特定の 1 つの "user" API のための委譲された振る舞いの定義です。 第 2 部分について、この仕様は Payment Request API に必要な振る舞いの変更に焦点を当てます。これは、 将来ケイパビリティ委譲を利用する他の API における類似の変更の指針となるものです。
1.3. 一時的な利用可能性
上記の 2 つの手順はいずれも、本質的に時間制約付きです:
-
開始手順は activation consuming であるため、その手順は最近のユーザーアクティベーション後にのみ許可されます。 さらに、ここでユーザーアクティベーションを消費することにより、 委譲機構が 1 つのユーザーアクティベーションにつき複数回使用できないことが保証されます。これにより、 複数のフレームへの繰り返しの委譲試行によって、委譲対象 API のユーザーアクティベーション 制限を事実上回避するような、ケイパビリティ委譲の悪意ある使用が防止されます。
-
開始手順が正常に完了した後、委譲された API は、ターゲットの ブラウジングコンテキストで数秒間だけ使用可能になります。 ここでの正確な時間制限は、委譲された API が自身の仕様で委譲された振る舞いをどのように定義するかに依存します。 自身の時間制限を定義しない API については、既定の制限は user activation expiry と同じになります。
2. 例
show()
を呼び出すケイパビリティを委譲したい場合、委譲されたケイパビリティを指定する追加
オプション付きで、サブフレームに
メッセージを投稿
します:
window. onclick= () => { targetWindow. postMessage( 'a_message' , { delegate: "payment" }); };
メッセージを受信すると、サブフレームは、フレームがユーザー
アクティベーションを受け取っていなくても show()
を使用できるようになります:
window. onmessage= () => { const payRequest= new PaymentRequest(...); const payResponse= await payRequest. show(); ... }
3. ケイパビリティ委譲の開始
ブラウジングコンテキストが別の
ブラウジング
コンテキストへケイパビリティを委譲したい場合、そのケイパビリティを指定する
delegate と呼ばれる追加の WindowPostMessageOptions
を付けて、2 番目の
ブラウジングコンテキストにメッセージを投稿します。この
オプションの値は
feature-identifier
でなければなりません。
その値が、ユーザー
エージェントがサポートする機能のいずれにも対応しない場合、このオプションは無視されなければなりません。
3.1. HTML 仕様へのモンキーパッチ
WindowPostMessageOptions
IDL 定義は、次のように追加フィールドを含みます:
DOMString? delegate;
window post message のアルゴリズムにおいて、 次の手順:
transfer を options["transfer"] とします。
の後に、次の 2 つの追加手順が続きます:
-
delegate を options["delegate"] とします。
-
delegate が null でない場合:
-
ユーザーエージェントが delegate により示される機能の委譲をサポートしない場合、 "NotSupportedError" DOMException を投げます。
-
targetWindow の 関連付けられた Document が、delegate により示される機能を allowed-to-use でない場合、 "NotAllowedError" DOMException を投げます。
-
targetOrigin が単一の U+002A ASTERISK 文字 (*) である場合、 "NotAllowedError" DOMException を投げます。
targetOrigin の既定値は "/" であり、メッセージを同一オリジンのターゲットに制限します。追加要件として "*" 以外の文字列を使用することは、 クロスオリジンメッセージが、意図された特定のオリジンを指定しなければならないことを意味します。 -
source を、incumbentSettings の グローバルオブジェクトとします。
-
source が 一時的 アクティベーションを持たない場合、 "NotAllowedError" DOMException を投げます。
-
source における ユーザー アクティベーションを 消費します。
-
4. 委譲されたケイパビリティの追跡
ブラウジングコンテキストへ委譲されたケイパビリティは、
Window.DELEGATED_CAPABILITY_TIMESTAMPS という名前のマップを用いて追跡されます。
ケイパビリティが
Window
へ委譲されるたびに、
DELEGATED_CAPABILITY_TIMESTAMPS にエントリーが追加されます。そのキーは
ケイパビリティを表す
feature-identifier
と等しく、その値は現在の
DOMHighResTimeStamp
と等しくなります。
マップがすでに同じキーのエントリーを持つ場合、既存の値は現在の
DOMHighResTimeStamp
に更新されます。
4.1. HTML 仕様へのモンキーパッチ
window post message のアルゴリズムの直前に、 次のように新しい段落が挿入されます:
ブラウジングコンテキストへ委譲されたケイパビリティを追跡する目的で、 各
Windowは、マップを持ちます。これは、feature-identifier からDOMHighResTimeStampへの DELEGATED_CAPABILITY_TIMESTAMPS と呼ばれます。 このマップは空のマップで初期化されます。
window post message のアルゴリズムにおいて、 現在の手順 8 に 2 つの追加サブ手順が追加されます。最初の追加 サブ手順は、次のサブ手順の後に挿入されます:
グローバルタスクをキューに追加する ...
origin を incumbentSettings の origin の直列化とします。
次のようになります:
-
グローバルタスクをキューに追加する ... (変更なし)
-
delegate を options["delegate"] とします。
-
2 番目の追加サブ手順は、次のサブ手順の後に挿入されます:
グローバルタスクをキューに追加する ...
newPorts を ... からなる新しい凍結配列とします。
次のようになります:
-
グローバルタスクをキューに追加する ... (変更なし)
-
newPorts を ... からなる新しい凍結配列とします。(番号付けを除いて変更なし)
-
delegate が null でなく、かつユーザーエージェントが delegate の委譲をサポートする場合、 DELEGATED_CAPABILITY_TIMESTAMPS[delegate] を 現在の 高解像度 時刻に設定します。
-
5. 委譲されたケイパビリティの振る舞いの定義
委譲された振る舞いを定義するケイパビリティは、対応する
Window.DELEGATED_CAPABILITY_TIMESTAMPS のエントリーを、
そのケイパビリティに適した方法で使用します。
以下は、ある特定のケイパビリティに必要な仕様変更です。
5.1. Payment Request 仕様へのモンキーパッチ
show()
のアルゴリズムにおいて、
委譲された振る舞いを実装するため、次の手順が
置き換えられます:
2 つの手順:
request の関連するグローバルオブジェクトが一時的アクティベーションを持たない場合:
"SecurityError" DOMException で拒否された promise を返します。
関連するグローバルオブジェクトのユーザーアクティベーションを消費します。
は、次の 3 つの手順に置き換えられます:
-
request の関連するグローバルオブジェクトが 一時的 アクティベーションを持たず、 かつ関連するグローバルオブジェクト内の DELEGATED_CAPABILITY_TIMESTAMPS["payment"] のタイムスタンプが 未定義または 期限切れのいずれかである場合:
-
"SecurityError" DOMException で拒否された promise を返します。
-
-
request の関連するグローバルオブジェクトが一時的アクティベーションを持たない場合、 マップエントリー DELEGATED_CAPABILITY_TIMESTAMPS["payment"] をクリアします。
-
そうでない場合、関連するグローバルオブジェクトの ユーザー アクティベーションを 消費します。
5.2. Fullscreen 仕様へのモンキーパッチ
requestFullscreen()
のアルゴリズムにおいて、
委譲された振る舞いを実装するため、次の変更が
行われます:
手順 5 の最後の条件:
次のいずれかの条件が false である場合、error を true に設定します: ...
this の関連するグローバルオブジェクトが一時的アクティベーションを持つ、または アルゴリズムがユーザー生成の向き変更によりトリガーされている。
は、次のように置き換えられます:
-
次のいずれかの条件が false である場合、error を true に設定します: ... (変更なし)
-
this の関連するグローバルオブジェクトが一時的アクティベーションを持つ、または this の関連するグローバルオブジェクト内の DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"] のタイムスタンプが未定義でなく、かつ 期限切れ でもない、または アルゴリズムがユーザー生成の向き変更によりトリガーされている。
-
手順 10 の直前:
fullscreenElements を this からなる順序付き集合とします。
に、次の新しい手順が挿入されます:
-
this の関連するグローバルオブジェクトが一時的アクティベーションを持たない場合、 this の関連するグローバルオブジェクト内のマップエントリー DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"] をクリアします。
-
fullscreenElements を this からなる順序付き集合とします。(番号付けを除いて変更なし)
5.3. [SCREEN-CAPTURE] 仕様へのモンキーパッチ
getDisplayMedia()
のアルゴリズムにおいて、
委譲された振る舞いを実装するため、次の変更が
行われます:
手順 3 の条件:
this の関連するグローバルオブジェクトが一時的アクティベーションを持たない場合、name 属性の値が InvalidStateError である DOMException オブジェクトで 拒否された promise を返します。
は、次のように置き換えられます:
-
this の 関連するグローバルオブジェクトが 一時的アクティベーションを持たず、かつ this の 関連するグローバルオブジェクト内の DELEGATED_CAPABILITY_TIMESTAMPS["display-capture"] のタイムスタンプが未定義または 期限切れのいずれかである場合、
name属性の値がInvalidStateErrorである DOMException オブジェクトで 拒否された promise を返します。