Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
この仕様は、HTMLMediaElement [HTML]
を拡張し、暗号化されたコンテンツの再生を制御するための API を提供します。
この API は、単純な Clear Key による復号から、高価値のビデオ(適切なユーザーエージェントの実装がある場合)までのユースケースをサポートします。ライセンス/鍵交換はアプリケーション側で制御され、さまざまなコンテンツ復号および保護技術をサポートする堅牢な再生アプリケーションの開発を容易にします。
この仕様はコンテンツ保護や Digital Rights Management(DRM)システムを定義するものではありません。代わりに、これらのシステムやより単純なコンテンツ暗号化システムを検出、選択、相互作用するために使用できる共通の API を定義します。本仕様への準拠のために DRM の実装は必須ではありません。共通のベースラインとして実装が要求されるのは Clear Key システムのみです。
共通 API は単純なコンテンツ暗号化機能のセットをサポートし、認証や認可などのアプリケーション機能はページ作成者に委ねます。これは、コンテンツ保護システム固有のメッセージングが暗号化システムとライセンスや他のサーバー間の帯外通信を前提とするのではなく、ページによって媒介されることを要求することで実現されます。
このセクションは、発行時点におけるこの文書の状態を説明します。現在の W3C 公開物と本技術報告書の最新改訂版は、W3C standards and drafts index で確認できます。
2017年9月の W3C Recommendation の公開以降、二つの新機能が追加されました:
encryptionScheme
属性を通じて可能にすること。
getStatusForPolicy()
メソッドを通じて提供すること。
その他の機能の追加は Media Working Group の対象外です。編集上の更新に加え、本仕様へのその他の実質的な変更は、本仕様に対する保守上の問題に対処しています:
encrypted-media 識別子を通じて統合すること。
usable-in-future
を、まだ復号に使用できない鍵のために MediaKeyStatus に追加すること。
QuotaExceededError を返すこと。
MediaKeySessionClosedReason
を追加してセッション閉鎖の可能な理由を記述し、それに応じてアルゴリズムを調整すること。
以前のバージョン以降の変更の完全な一覧については、コミット履歴 を参照してください。
この文書は Media Working Group により、Recommendation track を用いて Working Draft として公開されました。
Working Draft としての公開は、W3C およびそのメンバーによる支持を意味するものではありません。
これは草案文書であり、いつでも更新、置換、廃止される可能性があります。本文書を進行中の作業以外の目的で引用することは適切ではありません。
この文書は、W3C Patent Policy の下で運営されるグループによって作成されました。
W3C は、グループの成果物に関連して行われた特許開示の公開リストを維持しています。該当ページには特許の開示方法についての指示も含まれています。個人が、当該個人が本質的請求(Essential Claim(s))を含むと信じる特許を実際に知っている場合、その情報は W3C 特許方針セクション6 に従って開示しなければなりません。
この文書は 2025年8月18日付の W3C プロセス文書 に従って管理されています。
このセクションは非規範的です。
この仕様はスクリプトがコンテンツ保護メカニズムを選択し、ライセンス/鍵交換を制御し、カスタムのライセンス管理アルゴリズムを実行できるようにします。各ユースケースごとに各ユーザーエージェント側でクライアント改変を要求することなく、幅広いユースケースをサポートします。これにより、コンテンツ提供者はすべてのデバイス向けに単一のアプリケーションソリューションを開発できます。
サポートされるコンテンツはコンテナ固有の「共通暗号化」仕様に従って暗号化され、キーシステム間での利用を可能にします。サポートされるコンテンツはコンテナ自体は暗号化されていないため、メタデータをアプリケーションに提供でき、他の
HTMLMediaElement の機能との互換性を維持します。
実装者は、本仕様で記述されているセキュリティおよびプライバシーの脅威と懸念に対する緩和策に注意を払うべきです。特に、セキュリティおよびプライバシー要件は Key System とその実装のセキュリティおよびプライバシー特性を把握していないと満たせません。8. Implementation Requirements には基盤となる Key System 実装の統合および使用に関するセキュリティとプライバシーの条項が含まれています。10. Security は入力データやネットワーク攻撃など外部からの脅威に焦点を当てています。11. Privacy はユーザー固有の情報の取り扱いと、ユーザーが自身のプライバシーを適切に制御できるようにすることに焦点を当てています。
この仕様はメディアデータの供給元に依存しませんが、多くの実装が Media Source Extensions [MEDIA-SOURCE] 経由で提供されるメディアデータの復号のみをサポートしていることに著者は注意すべきです。
API を用いて実装された一般的なスタックの例を以下に示します。この図は一例のフローを示しており、他の API 呼び出しやイベントの組み合わせも可能です。
コンテンツ復号モジュール(CDM)は、1 つ以上の Key Systems に対して復号を含む機能を提供するクライアント側のコンポーネントです。
実装は CDM の実装とユーザーエージェントの実装を分離する場合と分離しない場合があります。本仕様ではこれは API とアプリケーションに対して透過的です。
Key System は復号メカニズムおよび/またはコンテンツ保護プロバイダを指す一般的な用語です。Key System 文字列は Key System を一意に識別します。これらはユーザーエージェントによって CDM を選択したり、鍵に関連するイベントの発生源を特定するために使用されます。ユーザーエージェントは MUST で Common Key Systems をサポートしなければなりません。ユーザーエージェントは追加の CDMs と対応する Key System 文字列を提供してもよい(MAY)です。
Key System 文字列は常に逆ドメイン名です。Key System 文字列の比較は大文字小文字を区別して行われます。RECOMMENDED として、CDMs は単純な小文字の ASCII キーシステム文字列を使用することが推奨されます。
例えば "com.example.somesystem" のようになります。
与えられたシステム内(例では "somesystem")では、キーシステムプロバイダによって決定されるサブシステムが定義される場合があります。例えば "com.example.somesystem.1" や "com.example.somesystem.1_5" のようなものです。キーシステムプロバイダはこれらが比較や発見に使用されることを念頭に置き、比較しやすく構造を合理的に単純に保つべきです。
Key Session(単に Session とも呼ぶ)は CDM とのメッセージ交換の文脈を提供し、その結果として鍵が CDM に利用可能になります。セッションは MediaKeySession オブジェクトとして具現化されます。各 Key
Session は Initialization Data の単一インスタンスに関連付けられ、これは generateRequest()
呼び出しで提供されます。
各 Key Session は単一の MediaKeys オブジェクトに関連付けられ、その MediaKeys
オブジェクトに関連付けられたメディア要素のみがセッションに関連付けられた鍵にアクセスできます。その他の MediaKeys オブジェクト、CDM インスタンス、およびメディア要素はセッションにアクセスしたりその鍵を使用してはなりません(MUST NOT)。セッションとその含む鍵は、usable for decryption ではなくなります。これは MediaKeySession オブジェクトが破棄された場合も含みます。
明示的に保存されていないすべてのライセンスおよび鍵は、Key Session が閉じられたときに破棄されなければなりません(MUST)。
Key IDs はセッション内で一意でなければなりません(MUST)。
Session ID は CDM によって生成される一意の文字列識別子で、アプリケーションが MediaKeySession オブジェクトを識別するために使用できます。
ユーザーエージェントと CDM が新しいセッションを正常に作成するたびに、新しい Session ID が生成されます。
各 Session ID は、作成されたブラウジングコンテキスト内で一意でなければなりません(SHALL)。Is persistent session type? アルゴリズムが
true を返すセッションタイプについては、Session ID はオリジン内で時間を越えて、一貫して一意でなければなりません(MUST)、閲覧セッションを跨いでも含みます。
基盤となるコンテンツ保護プロトコルは必ずしも Session ID をサポートする必要はありません。
特に明記されない限り、key は media data
内のブロックを復号するために使用される復号キーを指します。各キーは key ID によって一意に識別されます。キーはそれを session に提供するために使用された CDM に関連付けられます。(同じキーが複数のセッションに存在する場合があります。)そのような鍵は update() 呼び出しを通じてのみ CDM に提供されなければなりません(MUST)。(後で保存されたセッションデータの一部として load() によって読み込まれる場合があります。)
著者は、意味のある異なるポリシーを強制する必要がある各ストリーム集合を別個のキー(および key ID)で暗号化することを推奨します(SHOULD)。例えば、二つのビデオ解像度間でポリシーが異なる可能性がある場合、ある解像度を含むストリームは他の解像度を含むストリームを暗号化するのに使用されたキーと同じキーで暗号化してはいけません。音声ストリームが暗号化される場合、音声はビデオストリームと同じキーを使用すべきではありません(SHOULD NOT)。これはクライアント間での強制と互換性を保証する唯一の方法です。
キーが復号に使用可能と見なされるのは、CDM が当該キーが現在 1 個以上の media data のブロックを復号するために使用可能であると確信できる場合です。
例えば、ライセンスが期限切れの場合、そのキーは復号に使用できません。ライセンスが期限切れでない場合でも、出力保護などの使用条件が現在満たされていない場合は、そのキーは復号に使用できません。
key はバイト列である key ID に関連付けられ、キーを一意に識別します。コンテナは media data 内のブロックまたはブロック集合を復号できるキーの ID を指定します。Initialization Data はメディアデータを復号するために必要なキーを識別するための key ID を含んでいてもよい(MAY)。しかし、Initialization Data にメディアデータやメディアリソースで使用されるすべての key ID が含まれることを要求するものではありません。Licenses が CDM に提供されると、各キーは key ID に関連付けられ、CDM が暗号化されたメディアデータのブロックを復号する際に適切なキーを選択できるようになります。
キーがセッションに「既知」であるとは、CDM のセッション実装がそのキーについて何らかの情報を含んでいる(特に key
ID)ことを指し、実際のキーの値が既知であるかどうか、またはそのキーが使用可能かどうかは問いません。既知のキーは keyStatuses 属性を通じて公開されます。
キーは、例えば expiration によって使用不能になった場合や、削除されたが record of license destruction が利用可能な場合でも、既知と見なされます。キーは明示的にセッションから削除され、かつライセンス解除メッセージが確認されるときにのみ未知になります。
例えば、update()
呼び出しが以前キーを含んでいたライセンスを置換するような新しいライセンスを提供し、その新しいライセンスにそのキーが含まれていない場合、キーは未知になる可能性があります。
ライセンスはキーシステム固有の状態情報で、一つ以上の key(s)(各々が key ID に関連付けられる)および鍵利用に関する他の情報を含む場合があります。
Key Systems は通常、ライセンス要求メッセージを構築する前に、復号対象ストリームに関する情報を含む初期化データのブロックを必要とします。このブロックは単純なキーやコンテンツ ID であったり、より複雑な構造を含む場合があります。初期化データは 必要なキー を一意に識別できるように常にするべきです(SHOULD)。この初期化情報はアプリケーション固有の方法で取得されるか、media data と共に提供される場合があります(MAY)。
Initialization Data は CDM がライセンス要求を生成するために使用するコンテナ固有データの総称です。
初期化データの形式はコンテナの種類に依存し、コンテナは複数の初期化データ形式をサポートしている場合があります。Initialization Data Type は、付随する Initialization Data の形式を示す文字列です。Initialization Data Type 文字列は常に大文字小文字を区別して照合されます。Initialization Data Type 文字列は小文字 ASCII 文字列にすることが RECOMMENDED です。
Encrypted Media Extensions Initialization Data Format Registry [EME-INITDATA-REGISTRY] は、Initialization Data Type 文字列と各形式の仕様との対応を提供します。
ユーザーエージェントが media data 内で
Initialization Data を検出したとき、それを initData
属性としてアプリケーションに イベントで提供します。ユーザーエージェントはその時点で
Initialization Data を保存したり、その 内容 を使用してはなりません(MUST NOT)。アプリケーションは
Initialization Data を CDM に encryptedgenerateRequest()
を通じて提供します。ユーザーエージェントは他の手段で Initialization Data を CDM に提供してはなりません(MUST NOT)。
Initialization Data は与えられたストリーム集合または media data に対して固定値でなければなりません(MUST)。それは与えられたストリーム集合またはメディアデータの復号に必要な鍵に関連する情報のみを含まなければなりません(MUST)。Initialization Data はアプリケーションデータ、クライアント固有データ、ユーザー固有データ、または実行可能なコードを含んではなりません(MUST NOT)。
Initialization Data は Key System 固有のデータや値を含むべきではありません(SHOULD NOT)。実装は各サポートする Initialization Data Type に対して [EME-INITDATA-REGISTRY] で定義された共通形式をサポートしなければなりません(MUST)。
独自形式/独自コンテンツの使用は推奨されず、独自形式のみをサポートまたは使用することは強く非推奨です。独自形式は既存のコンテンツや共通形式をサポートしない既存クライアントデバイスと共にのみ使用すべきです。
二つ以上の識別子または他の値は、同一であるか、あるいは合理的な時間と労力で相関または関連付けることが可能である場合、互いに「associable(関連付け可能)」であると言われます。そうでない場合、それらの値は non-associable(非関連付け可能) です。
例えば、次の方法で作成された値は associable(関連付け可能) とされます:
簡単に逆変換可能なハッシュ関数を使用している場合。
プレフィックスや他の部分集合を共有している場合
ランダム値 N を N+10 に置き換える場合
オリジンに固定値を XOR する(簡単に逆変換可能であるため)
対照的に、完全に無関係または暗号学的に区別される、例えば強力な非可逆ハッシュ関数を用いた値は non-associable(非関連付け可能) とされます。
二つ以上の識別子または他の値は associable by an entity(ある主体によって関連付け可能) と言われます。これは参照された主体または主体の集合が追加の主体の参加なしにそれらを相関または関連付けることが合理的な時間と労力で可能である場合を意味します。そうでない場合、それらの値は non-associable by an entity(主体によって関連付け不可能) です。
二つ以上の識別子または他の値は non-associable by the application(アプリケーションによって関連付け不能) と言われます。これはそれらが non-associable by an entity であり、その主体がアプリケーション、他のすべてのアプリケーション、およびそれらが使用または通信するサーバを含む集合である場合を意味します。そうでない場合、これらの値は associable by the application(アプリケーションによって関連付け可能) と見なされ、これは禁止されます。
Distinctive Value は、多数のユーザーまたはクライアントデバイス間で共有されない値、データの断片、その所持を示す示唆、または観測可能な振る舞いやタイミングであり、メモリ内または永続化されうるものです。
Distinctive Value の例には次が含まれますがこれに限定されません:
その他の識別子
その他のセッションデータ
Distinctive Value は通常ユーザーやクライアントデバイスに固有ですが、絶対的に一意である必要はありません。例えば少数のユーザー間で共有される値でも識別的でありうる場合があります。
Permanent Identifier は何らかの方法で消去困難、またはユーザーが削除・リセット・変更するのが非自明な値、データ、所持の示唆、または観測可能な振る舞いやタイミングを指します。これには次のものが含まれますがこれに限定されません:
ハードウェアまたはハードウェアに基づく識別子
工場でデバイスにプロビジョニングされた値
オペレーティングシステムのインストールインスタンスに関連する値
ユーザーエージェントのインストールインスタンスに関連する値
CDM や他のソフトウェアコンポーネントに関連する値
クライアントで生成されても設定ファイルなどに保存された半永続的なデータ内の値
クライアントまたは他のユーザーアカウントに関連する値
Distinctive Permanent Identifier は、Permanent Identifier であって distinctive なものです。
クライアント外に露出される場合、Distinctive Permanent Identifiers およびそれらから派生または関連する値は MUST 暗号化されなければなりません(encrypt)。Distinctive Permanent Identifiers はアプリケーションに対して決して露出されてはなりません(MUST NOT)、たとえ暗号化形式であってもです。
Distinctive Permanent Identifier は通常ユーザーやクライアントデバイスに固有ですが、厳密に一意である必要はありません。例えば少数のユーザー間で共有される値でも識別的でありうる場合があります。
Distinctive Permanent Identifier は生成や派生の範囲内ではないため、Distinctive Identifier ではありません。
distinctiveIdentifier
は Distinctive Permanent Identifiers の使用可否を制御します。具体的には、Distinctive Permanent Identifiers
が使用できるのは、distinctiveIdentifier
メンバーが MediaKeySystemAccess の生成に使用された値が
"required" の場合に限られます。
Distinctive Identifier は、クライアント外の任意の主体がウェブプラットフォーム上でユーザーが期待する以上に値を相関・関連付けできる値(不透明または暗号化形式を含む)です(例:クッキーや他のサイトデータを越えた相関)。例えば、ある値がオリジンやブラウジングプロファイル、閲覧セッションを跨いで外部の主体によって相関可能である場合、これは Distinctive Identifier と見なされます。これは個別化(individualization)要求に共通の値が含まれていたり、個別化要求で提供された値が中央サーバ(例:個別化サーバ)によって相関可能である場合に起こり得ます。
アプリケーションに露出される Distinctive Identifiers は、暗号化形式であっても、識別子要件(暗号化、オリジン・プロファイルごとの一意性、消去可能性など)に従わなければなりません(MUST)。
Distinctive Identifier の生成や使用は本仕様の API の使用によってトリガーされますが、その識別子をアプリケーションに提供する必要はありません(ただし Distinctive Permanent Identifiers は決してアプリケーションに提供されるべきではありません)。
distinctiveIdentifier
は Distinctive Identifiers の使用可否を制御します。具体的には、Distinctive Identifiers が使用できるのは、distinctiveIdentifier
メンバーが MediaKeySystemAccess の生成に使用された値が
"required" の場合に限られることを示します。
Distinctive Identifier は次のすべての基準を満たす値、データ断片、所持の示唆、または観測可能な振る舞いやタイミングです:
Distinctive Identifier は通常ユーザーやクライアントデバイスに固有ですが、厳密に一意である必要はありません。例えば少数のユーザー間で共有される識別子でも識別的でありえます。
それ自体、あるいはそれに関する情報や派生値がクライアント外に(暗号化形式であっても)露出されること。これにはアプリケーションやライセンス、individualization サーバ、その他のサーバへの提供が含まれます。
次の一つ以上の性質を持つこと:
それが一つ以上の Distinctive Permanent Identifier から派生していること。
その値を生成したプロセス(生成、individualization、プロビジョニングなど)が一つ以上の Distinctive Permanent Identifier または他の Distinctive Identifier を使ったか、関連していること。
それは 消去可能(clearable) だが、クッキーなどのサイトデータと一緒には消去されないこと。
例えば OS レベルの外部メカニズムを介する場合などです。
アプリケーションに露出される値について規範的に禁止される他の性質には次が含まれますがこれに限定されません:
それが Distinctive Permanent Identifier であること。
消去不能(not clearable) であること。
値が オリジンおよびプロファイルごとに一意でない こと。
異なるオリジンの値がアプリケーションによって 関連付け可能 であること。
規範的に禁止されるそのような値の例には次が含まれますがこれに限定されません:
すべてのオリジンで使用される単一のハードウェアベースの値。
すべてのオリジンで使用される単一のランダムベースの値。
すべてのオリジンで使用される単一の個別化プロセス(individualization)により得られた値。
上記の値の全部または一部を含む値。
複数のオリジンで使用されるがすべてのオリジンではない単一値。
ドメイン内のすべてのオリジンで使用される単一値。(識別子はオリジンごとでなければなりません。)
事前プロビジョニングされたオリジン固有値。
生成が簡単に逆変換可能な手段で行われた値(したがってアプリケーションによって関連付け可能である)。例えば、オリジンの一部を固定値と XOR するなど。
Distinctive Identifier は通常それらを生成した主体によって 相関可能である が、アプリケーションによって相関されてはなりません(non-associable by applications)。言い換えると、そのような相関は元々 Distinctive Identifier を生成した主体(例えば個別化サーバ)のみが行えるべきです。Distinctive Permanent Identifier にアクセスできる主体は、その相関機能をアプリケーションに露出してはならず(MUST NOT)、他の主体や第三者に対してもそのような相関を露出しないよう注意を払うべきです(SHOULD)。
Distinctive Identifier の例には次が含まれますがこれに限定されません:
キー要求に含まれるバイト列で、他のクライアントデバイスが含めるバイト列と異なり、Distinctive Permanent Identifier に基づく、あるいはそれを直接または間接に使用して取得されたもの。
キー要求に含まれる公開鍵で、他のクライアントデバイスの要求に含まれる公開鍵と異なり、Distinctive Permanent Identifier に基づく、あるいはそれを直接または間接に使用して取得されたもの。
例えば一部データに署名するなど、他のクライアントデバイスが持たない秘密鍵の保有を示す証明で、Distinctive Permanent Identifier に基づく、あるいはそれを直接または間接に使用して取得されたもの。
そのような鍵の識別子。
第1の値が直接露出されていなくても、それを使って導出された別の露出される値。
他の Distinctive Identifier から導出された値。
個別化サーバなどに報告されたランダム値で、Distinctive Permanent Identifier と共に提供されたか、またはそのようなサーバから Distinctive Permanent Identifier 提供後に返されたもの。
工場でデバイスにプロビジョニングされた一意の値から導出された値。
工場で埋め込まれた一意のハードウェア値(例:MAC アドレスやシリアル番号)やソフトウェア値(例:OS インストールインスタンスや OS ユーザーアカウント名)から導出された値。
Distinctive Identifier でない例には次が含まれます:
インストールベースが大きい場合、ある CDM バージョンのすべてのコピーで共有される公開鍵。
一意だが一つのセッションでのみ使用されるノンスやエフェメラルキー。
外部に露出しない値(個別化や類似の方法を含めて)で、クライアント外に派生形や類似の形で露出されないもの。
例えばビデオパイプラインと CDM 間の認証で使用されるデバイス固有キーのように、CDM がそれらの認証をアプリケーションに流さず、代わりに Distinctive Identifier を構成しないキーを用いて新たな認証を行う場合。
クッキー等と共に完全に消去可能であり、その後中央サーバ(例えば個別化サーバ)によっても相関され得ない(non-associable)新しい値に置き換えられる値、かつ以下のいずれかを満たすもの。
生成に Distinctive Permanent Identifier や Distinctive Identifier が関与していないこと。
システムからの入力なしに生成されたランダム値であること。
サーバから提供された値であり、他の Distinctive Identifier の使用や知識を伴わないこと。
実装、設定、インスタンス、またはオブジェクトが Distinctive Identifier(s) を使用する とは、そのライフタイム中または関連するエンティティのライフタイム中のいかなる時点でも、アプリケーションやライセンス、individualization サーバ、その他のサーバに対して、たとえ暗号化形式であっても一つ以上の Distinctive Identifier(s)、それらに関する情報、またはそれらから派生・関連する値を露出することを意味します。
実装、設定、インスタンス、またはオブジェクトが Distinctive Permanent Identifier(s) を使用する とは、そのライフタイム中または関連するエンティティのライフタイム中のいかなる時点でも、たとえ暗号化形式であっても一つ以上の Distinctive Permanent Identifier(s)、それらに関する情報、またはそれらから派生・関連する値をクライアント外に露出することを意味します。これには個別化サーバへの提供などが含まれます。こうした値はアプリケーションに提供されてはなりません(MUST NOT)。
実装、設定、インスタンス、またはオブジェクトが uses Distinctive Identifier(s) or Distinctive Permanent Identifier(s) とは、それが uses Distinctive Identifier(s) および/または uses Distinctive Permanent Identifier(s) のいずれかであることを意味します。
distinctiveIdentifier
は Distinctive Identifiers および Distinctive Permanent Identifiers の使用可否を制御します。具体的には、これらの識別子は distinctiveIdentifier
メンバーが MediaKeySystemAccess の生成に使用された値が
"required"
の場合にのみ使用できることを示します。
再生中、埋め込まれたメディアデータは埋め込み元の origin
のスクリプトに晒されます。API が Initialization Data を イベントで提供するためには、media
data は埋め込みページと CORS-same-origin でなければなりません(MUST)。メディアデータが埋め込み文書とクロスオリジンである場合、著者は encryptedcrossOrigin
属性を HTMLMediaElement
に設定し、メディアデータのレスポンスに CORS ヘッダを付与して CORS-same-origin にするべきです(SHOULD)。
再生中、埋め込まれたメディアデータは埋め込み元の origin
のスクリプトに晒されます。API が Initialization Data を イベントで提供するためには、media
data は Mixed Content であってはなりません(MUST NOT)[MIXED-CONTENT]。
encrypted
時刻(Time)は ECMAScript の Time Values and Time Range に表現されるものと同等でなければなりません(MUST)。
該当する時刻が存在しない、または時刻が不確定である場合、Time は NaN をとります。Infinity の値を持つべきではありません。
Time は通常ミリ秒精度の時刻を表しますが、それだけでは十分な定義ではありません。定義された Time Values and Time Range 参照が他の重要な要件を追加します。
キーがもはや usable for decryption ではなくなる時刻を指します。
与えられたマシン上のユーザーエージェントは、アプリケーションに可視な状態やデータに関して独立して振る舞うことが期待される様々なコンテキストやモード、一時的状態で実行できる場合があります。特に、保存されたすべてのデータは独立していることが期待されます。本仕様ではそのような独立したコンテキストやモードを「Browsing Profiles」と呼びます。
そのような独立コンテキストの例としては、ユーザーエージェントが異なる OS ユーザーアカウントで実行されている場合や、単一アカウントで複数の独立プロファイルを定義する機能をユーザーエージェントが提供している場合などがあります。
このセクションでは、Key System へのアクセスを取得する仕組みを定義します。リクエストに機能を含めることで、機能検出も可能になります。
アルゴリズムの手順は、プロミスが拒否されると常に中止されます。
requestMediaKeySystemAccess()
は、文字列
encrypted-media
によって識別される ポリシー制御機能 です。
その デフォルト許可リスト
は 'self' です [PERMISSIONS-POLICY].
WebIDLenum MediaKeysRequirement {
"required",
"optional",
"not-allowed"
};
MediaKeysRequirement 列挙型は以下のように定義されます:
| 列挙型の説明 | |
|---|---|
required
|
|
optional
|
|
not-allowed
|
|
WebIDLdictionary MediaKeySystemConfiguration {
DOMString label = "";
sequence<DOMString> initDataTypes = [];
sequence<MediaKeySystemMediaCapability> audioCapabilities = [];
sequence<MediaKeySystemMediaCapability> videoCapabilities = [];
MediaKeysRequirement distinctiveIdentifier = "optional";
MediaKeysRequirement persistentState = "optional";
sequence<DOMString> sessionTypes;
};
辞書 MediaKeySystemConfiguration
は以下のメンバーを持ちます:
label
型 DOMString、デフォルト値
""
MediaKeySystemConfiguration
が getConfiguration()
メソッドで返される際に保持されます。
MediaKeySystemAccess のメソッドです。
initDataTypes
型 sequence<DOMString>、デフォルト値
[]
audioCapabilities
型 sequence<MediaKeySystemMediaCapability>、デフォルト値
[]
videoCapabilities
メンバーは空であってはなりません。
videoCapabilities
型 sequence<MediaKeySystemMediaCapability>、デフォルト値
[]
audioCapabilities
メンバーは空であってはなりません。
distinctiveIdentifier
型 MediaKeysRequirement、デフォルト値
"optional"
このメンバーが "not-allowed"
の場合、実装はこの構成から生成されたいかなるオブジェクトの処理において Distinctive
Identifier(s) または Distinctive Permanent Identifier(s) の使用 を MUST
NOT 行ってはなりません。
persistentState
型 MediaKeysRequirement、デフォルト値
"optional"
このメンバーが "not-allowed" の場合、CDM はこのオブジェクトの origin や Document、アプリケーションに関連するいかなる状態も永続化してはなりません(MUST NOT)。
このメンバーに関して、永続状態にはキーシステム実装が管理する永続的な一意識別子(Distinctive Identifiers)は含みません。distinctiveIdentifier
がこの要件を個別に反映します。
永続状態がサポートされない場合は、"temporary" セッションのみ作成可能です。
"temporary"
セッションでは、状態の保存の必要性や可能性はキーシステム実装依存であり、使用される機能によって異なる場合があります。
"temporary"
以外のセッションを作成したいアプリケーションは、
requestMediaKeySystemAccess()
呼び出し時にこのメンバーを "required" に設定すべきです。
sessionTypes
型 sequence<DOMString>
MediaKeySessionType
のリストです。すべての値がサポートされている必要があります。
このメンバーが辞書に 存在しない [Infra] 状態で
requestMediaKeySystemAccess()
に渡された場合、[ " が設定されているものとして扱われます。
temporary"
]
実装はこの辞書にメンバーを追加すべきではありません(SHOULD NOT)。もし追加する場合、型は MediaKeysRequirement にしなければならず(MUST)、デフォルト値は "optional" とすることが推奨されます(RECOMMENDED)。これにより最も幅広いアプリケーションとクライアントの組み合わせをサポートできます。
ユーザーエージェント実装が認識しない辞書メンバーは [WEBIDL] に従い無視され、requestMediaKeySystemAccess()
アルゴリズムで考慮されません。アプリケーションが非標準的な辞書メンバーを使用する場合、ユーザーエージェント実装がそのような辞書メンバーを含む構成を拒否することを前提にしてはなりません(MUST NOT)。
この辞書は CDM に状態やデータを渡すために使用してはなりません(MUST NOT)。
WebIDLdictionary MediaKeySystemMediaCapability {
DOMString contentType = "";
DOMString? encryptionScheme = null;
DOMString robustness = "";
};
MediaKeySystemMediaCapability
のメンバー
contentType
型 DOMString、デフォルト値
""
アプリケーションは、MIMEタイプが明示的にコーデックやコーデック制約(たとえば [RFC6381])を指定することを 推奨 します(SHOULD)。これらがコンテナによって規範的に暗示されない限りです。
encryptionScheme
型 DOMString、デフォルト値
null
content type に関連付けられる暗号化方式。値が null または存在しない場合、アプリケーションが特定の暗号化方式を要求しないことをユーザーエージェントに示し、そのためいかなる暗号化方式でも許容されます。
このフィールドを認識しているアプリケーションは、必要な暗号化方式を指定すべきです(SHOULD)。異なる暗号化方式は一般的に互換性がありません。アプリケーションが「いかなる方式でも可」とするのは非現実的ですが、デフォルトの null と null の「任意」としての解釈は、未認識アプリや古いユーザーエージェントへのポリフィルの道を提供します。
空文字列は null や未指定とは異なり、認識できない暗号化方式として扱われます。
robustness
型 DOMString、デフォルト値
""
content type に関連付けられる堅牢性レベル。空文字列の場合、コンテンツタイプの復号およびデコードができる能力であれば何でも許容されます。
実装は CDM を、MediaKeySystemAccess
オブジェクトの構成で指定された堅牢性レベルを少なくともサポートするように設定しなければなりません(MUST)。MediaKeys
オブジェクトの生成に使用されます。CDM の正確な設定は実装依存であり、実装は構成内の最高堅牢性レベルを使うように設定してもよい(MAY)、より高い堅牢性レベルが利用可能であってもです。空文字列のみ指定された場合、実装はサポートする最低堅牢性レベルを使うように設定してもよいです(MAY)。
アプリケーションは想定外のクライアント非互換性を避けるために必要な堅牢性レベルを指定するべきです(SHOULD)。
このオブジェクトが表す機能がサポートされているとみなされるためには、contentType
は空文字列であってはならず(MUST NOT)、値全体(すべてのコーデックを含む)が robustness
とともにサポートされていなければなりません(MUST)。
受け入れ可能なコーデックが複数ある場合は、各コーデックごとにこの辞書の別インスタンスを使用してください。
MediaKeySystemAccess
オブジェクトは Key System へのアクセスを提供します。
WebIDL[Exposed=Window, SecureContext] interface MediaKeySystemAccess {
readonly attribute DOMString keySystem;
MediaKeySystemConfiguration getConfiguration ();
Promise<MediaKeys> createMediaKeys ();
};
keySystem 型 DOMString、readonly
getConfiguration()
requestMediaKeySystemAccess()
アルゴリズムによって選択されたサポートされる構成オプションの組み合わせを返します。
返されるオブジェクトは、最初に満たされた MediaKeySystemConfiguration
構成(+暗黙のデフォルト)からなる非厳密な部分集合です。これは requestMediaKeySystemAccess()
の呼び出しに渡され、その呼び出しで解決されたプロミスに対応します。その単一構成で指定されていない機能(暗黙のデフォルト以外)は含まれず、Key System
実装のすべての機能を必ずしも反映しません。構成内のすべての値は任意の組み合わせで使用できます。型 MediaKeysRequirement
のメンバーは、どの組み合わせでその機能が要求されるかを反映します。これらは "optional" の値にはなりません。
このメソッドが呼び出された際、ユーザーエージェントは次の手順を 必ず実行しなければなりません:
このオブジェクトの configuration の値を返します。
このメソッドが呼び出されるたびに configuration から新しいオブジェクトが作成・初期化されます。
encryptionScheme
がアプリケーションによって指定されなかった場合でも、累積された configuration には値 null の encryptionScheme
フィールドが含まれていなければならず(MUST)、ポリフィルがユーザーエージェントのフィールドサポートを特定値指定せずに検出できるようにします。
createMediaKeys()
keySystem 用の新しい MediaKeys オブジェクトを作成します。
このメソッドが呼び出された際、ユーザーエージェントは次の手順を 必ず実行しなければなりません:
promise を新しいプロミスとして作成します。
次の手順を並行して実行します:
configuration をこのオブジェクトの configuration の値とします。
use distinctive identifier を、configuration の distinctiveIdentifier
メンバーの値が "required"
なら true、そうでなければ false とします。
persistent state allowed を、configuration の persistentState
メンバーの値が "required"
なら true、そうでなければ false とします。
必要ならこのオブジェクトの cdm implementation の値で表される Key System 実装をロード・初期化します。
instance をこのオブジェクトの cdm implementation の値で表される Key System 実装の新しいインスタンスとします。
configuration を使って instance を Key System 機能の有効化・無効化・選択に初期化します。
use distinctive identifier が false
の場合、instance が Distinctive
Identifier(s) および Distinctive Permanent Identifier(s) を使用 できないようにします。
persistent state allowed が false の場合、instance
がこのオブジェクトの origin
や Document、アプリケーションに関連するいかなる状態も永続化できないようにします。
直前のいずれかの手順が失敗した場合、新しい DOMException(名前は適切な
エラー名)で promise を拒否します。
media keys を新しい MediaKeys
オブジェクトとし、以下のように初期化します:
use distinctive identifier の値を media keys の値として設定します。
persistent state allowed の値を media keys の値として設定します。
supported session types の値を configuration の sessionTypes
メンバーの値とします。
cdm implementation の値をこのオブジェクトの cdm implementation の値とします。
cdm instance の値を instance とします。
promise を media keys で解決します。
promise を返します。
MediaKeys オブジェクトは、関連付けられた HTMLMediaElement が再生中に media data
の復号に使用できる一連の鍵を表します。また、CDM インスタンスも表します。
MediaKeys
オブジェクトは、もはやアクセス可能でないとユーザーエージェントが判断した場合に破棄されることがあります。
例えば、スクリプトからの参照が存在せず、添付されたメディア要素がない場合などです。
プロミスを返すメソッドにおいて、すべてのエラーは返された Promise を拒否することで非同期に報告されます。これには [WEBIDL] の型マッピングエラーも含まれます。
アルゴリズムの手順は、プロミスが拒否されると常に中止されます。
WebIDLenum MediaKeySessionType {
"temporary",
"persistent-license"
};
MediaKeySessionType 列挙型は次のように定義されます:
| 列挙型の説明 | |
|---|---|
temporary
|
ライセンス、鍵およびセッションに関連する記録やデータが永続化されないセッション。 アプリケーションはそのような保存の管理を心配する必要はありません。このセッションタイプのサポートは 必須 です。 |
persistent-license
|
ライセンス(および必要に応じてセッションに関連する他のデータ)が永続化されるセッション。ライセンスとそれが含む鍵が破棄されるとき、record of license destruction が必ず永続化されなければなりません。record of license destruction は、そのライセンスと含まれる鍵がクライアントによって使用不能であることを示す Key System 固有の証明です。このセッションタイプのサポートは 任意 です。
このタイプのセッションは、このオブジェクトを生成した そのようなセッションのために永続化されたデータが不要になったときに削除する責任はアプリケーションにあります。詳細は Session Storage and Persistence を参照してください。 |
WebIDL[Exposed=Window, SecureContext] interface MediaKeys {
MediaKeySession createSession (optional MediaKeySessionType sessionType = "temporary");
Promise<MediaKeyStatus> getStatusForPolicy (optional MediaKeysPolicy policy = {});
Promise<boolean> setServerCertificate (BufferSource serverCertificate);
};
createSession()
新しい MediaKeySession
オブジェクトを返します。
sessionType パラメータは返されるオブジェクトの挙動に影響します。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:
もしこのオブジェクトの supported session types 値が sessionType を含まない場合、throw
[WEBIDL] として
を投げます。
NotSupportedError
sessionType に対して Is persistent session type?
アルゴリズムが true を返す値は、このオブジェクトの persistent state allowed 値が
false の場合に失敗します。
実装が現在の状態で MediaKeySession
操作をサポートしていない場合、throw [WEBIDL] として
を投げます。
InvalidStateError
一部の実装では、この MediaKeySession
アルゴリズムを実行するために、まずこの MediaKeys オブジェクトを setMediaKeys()
を使ってメディア要素に関連付ける必要がある場合があります。この手順は、そのような珍しい挙動を検出することで、その後の操作実行前に検出できるようにするものです。
session を新しい MediaKeySession
オブジェクトとし、次のように初期化します:
sessionId
属性を空文字列とします。
expiration
属性を NaN とします。
closed
属性を新しいプロミスとします。
key status を新しい空の MediaKeyStatusMap
オブジェクトとし、次のように初期化します:
size
属性を 0 とします。
session type の値を sessionType とします。
uninitialized の値を true とします。
callable の値を false とします。
closing or closed の値を false とします。
use distinctive identifier の値をこのオブジェクトの use distinctive identifier 値とします。
cdm implementation の値をこのオブジェクトの cdm implementation とします。
cdm instance の値をこのオブジェクトの cdm instance とします。
session を返します。
getStatusForPolicy()
指定された MediaKeysPolicy に対する
MediaKeyStatus を返します。
WebIDLdictionary MediaKeysPolicy {
DOMString minHdcpVersion;
};
MediaKeysPolicy
辞書はオプションのプロパティのみからなるオブジェクトです。各プロパティはポリシー要件を表します。ポリシーは、すべての要件に基づいて CDM が復号済みメディアデータの表示を許可する場合に満たされたと見なされます。
HDCP ポリシーは minHdcpVersion
で表されます。システムが指定された HDCP バージョン以上を有効にできる場合、ポリシーは "usable" の MediaKeyStatus
をもたらします。[EME-HDCP-VERSION-REGISTRY]
は minHdcpVersion の値と
HDCP 仕様との対応を提供します。
HDCP 状況の判定は、再生中に CDM がそのような制限を強制するのと同じ方法で行うべきです。こうすることで、アプリケーション開発者は再生を開始するために取得すべきコンテンツを最適化するための合理的なヒントを得られます。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:
TypeError
で拒否された promise を返します。
promise を新しい promise とします。
タスクをキューに追加し、次の手順を実行します:
policy の各 dictionary member について、次の手順を実行します:
キーが有効な MediaKeysPolicy
メンバーでない
または値の型が不正な場合、promise を
で拒否し、
これらの手順を中止します。
TypeError
policy の各 dictionary member について、次の手順を実行します:
CDM が当該
dictionary
member の MediaKeyStatus
を判定できない場合、
promise を
で拒否し、
これらの手順を中止します。
NotSupportedError
policy の各 dictionary member について、次の手順を実行します:
CDM が当該
dictionary
member に対して復号済みメディアデータの表示をブロックする場合、
promise を "output-restricted"
で解決します。
promise を "usable" で解決します。
promise を返します。
setServerCertificate()
ライセンスサーバーへのメッセージを暗号化するために使用されるサーバー証明書を提供します。
このような証明書を使用するキーシステムに対して、アプリケーションはSHOULD
setServerCertificate()
を呼び出して、サーバー証明書を明示的に設定する必要があります。
そうしない場合は、ライセンスの交換に失敗する可能性があります。
一部のキーシステムでは、「message」イベントをキューするアルゴリズムを介して、証明書をサーバーから取得することもサポートされています。しかし、この機能はそのような証明書を使用するすべてのキーシステムでサポートされているわけではありません。
サーバー証明書の内容は Key System 固有です。実行可能なコードを含んではいけません(MUST NOT)。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:
このオブジェクトの cdm implementation 値で表される Key
System 実装がサーバー証明書をサポートしていない場合、false で解決されたプロミスを返します。
もし serverCertificate が空の配列であれば、新しく作成した
で拒否されたプロミスを返します。
TypeError
certificate を serverCertificate パラメータの内容のコピーとします。
promise を新しいプロミスとします。
次の手順を並行して実行します:
sanitized certificate を certificate の検証および/またはサニタイズされたバージョンとします。
ユーザーエージェントは証明書を CDM に渡す前に十分に検証すべきです。これには、値が妥当な範囲内であることの確認、無関係なデータやフィールドの削除、事前解析、サニタイズ、あるいは完全にサニタイズされたバージョンの生成が含まれる場合があります。ユーザーエージェントはフィールドの長さや値が妥当であることを確認すべきです。未知のフィールドは拒否または削除すべきです。
このオブジェクトの cdm instance を使って sanitized certificate を処理します。
前述の手順が失敗した場合、適切な エラー名 を持つ新しい DOMException
で promise を拒否します。
promise を true で解決します。
promise を返します。
Is persistent session type?
アルゴリズムは、指定されたセッションタイプが何らかの永続化をサポートするかどうかを判定するために実行されます。このアルゴリズムを実行するリクエストには MediaKeySessionType の値が含まれます。
次の手順が実行されます:
session type を指定された MediaKeySessionType の値とします。
次のリストの session type の値に対応する手順に従います:
temporary"
false.
persistent-license"
true.
本節では、ストレージおよび永続化に関連する一般的な要件について説明します。
もし MediaKeys オブジェクトの persistent state
allowed 値が
false である場合、そのオブジェクトの cdm instance
は、このオブジェクトまたはそれが生成するいかなるセッションに対する操作の結果として状態を永続化したり、以前に永続化された状態にアクセスしてはならない(SHALL
NOT)。
もし MediaKeys オブジェクトの persistent state
allowed 値が
true である場合、そのオブジェクトの cdm instance
は、このオブジェクトまたはそれが生成するいかなるセッションに対する操作の結果として状態を永続化したり、以前に永続化された状態にアクセスしてもよい(MAY)。
永続化されたデータは常に、このオブジェクトの origin を持つ Document のみがアクセスできるように保存されなければならない(MUST)。さらに、そのデータは現在の browsing profile のみがアクセス可能でなければならず、他のブラウジングプロファイル、ユーザーエージェント、およびアプリケーションは保存されたデータにアクセスしてはならない(MUST NOT)。詳細は Information Stored on User Devices を参照してください。
永続ストレージをサポートする際の追加の考慮事項については、10. Security および 11. Privacy を参照してください。
MediaKeySession オブジェクトはキーセッションを表します。
MediaKeySession オブジェクトは、そのオブジェクトの closed 属性が解決済みである場合に限り closed と見なされます。
ユーザーエージェントは、CDM 状態変化の監視 アルゴリズムを、MediaKeySession オブジェクトごとに、そのオブジェクトが closed でない限り継続的に実行しなければなりません。CDM 状態変化の監視 アルゴリズムは、メインイベントループと並列して実行されなければならない(MUST)が、本仕様で並列実行と定義されている他の手続きと並行して実行してはなりません。
MediaKeySession オブジェクトは、もしそのオブジェクトが closed でなく、かつそれを生成した MediaKeys
オブジェクトが引き続きアクセス可能である場合、破棄されてはならず(SHALL)、イベントを受け取り続けなければなりません。そうでない場合、もはやアクセス可能でない
MediaKeySession オブジェクトは更なるイベントを受け取ってはならず(SHALL NOT)、破棄されてもよい(MAY)。
上記の規則は、CDM インスタンスは、すべての MediaKeys
オブジェクトおよび MediaKeySession オブジェクト(CDM
インスタンスに関連付けられたもの)が破棄されるまで破棄してはならないことを意味します。
MediaKeySession オブジェクトがページからアクセス不能になったときにそれが closed でない場合、CDM は当該オブジェクトに関連する キーセッション を閉じなければなりません(SHALL)。
キーセッションを閉じると、明示的に保存されていないライセンスや鍵が破棄されます。
キーセッションが正確にいつ閉じられるかは実装依存であり、アプリケーションは特定のタイミングに依存してはなりません(SHOULD NOT)。
あるアクションを行う前にセッションが閉じられていることを確実にしたいアプリケーションは、close()
を呼び出し、返されたプロミスが解決されるのを待つべきです(SHOULD)。
プロミスを返すメソッドにおいて、すべてのエラーは返された Promise を拒否することで非同期に報告されます。これには [WEBIDL] の型マッピングエラーも含まれます。
アルゴリズムの以下の手順は、プロミスが拒否されると常に中止されます。
WebIDLenum MediaKeySessionClosedReason {
"internal-error",
"closed-by-application",
"release-acknowledged",
"hardware-context-reset",
"resource-evicted"
};
MediaKeySessionClosedReason 列挙型は次のように定義されます:
| 列挙型の説明 | |
|---|---|
internal-error
|
セッションは、CDM で回復不能なエラーが発生したために閉じられました。この場合、アプリケーションはこの MediaKeys インスタンス上で新しいセッションを作成してはなりません。
|
closed-by-application
|
セッションはアプリケーションがセッションの close()
メソッドを明示的に呼び出したことで閉じられました。
|
release-acknowledged
|
セッションは、CDM が ライセンス破棄の記録 の受領確認を受け取ったために閉じられました。 |
hardware-context-reset
|
セッションは、CDM の元のハードウェアコンテキストがリセットされたために閉じられました。この場合、ユーザーエージェントはこの MediaKeys
インスタンス上でアプリケーションが新しいセッションを作成できるようにしなければなりません。
注
これは、デバイスの休止やモニターの設定変更など、さまざまな理由で発生する場合があります。ハードウェアコンテキストリセットの正確な理由は実装依存です。 |
resource-evicted
|
セッションは、システムが他のセッションを作成できるようにリソースを回収する必要があったため、閉じられました。
注
これは、アプリケーションがデバイス固有のセッションリソースの制限に達していることを示唆しています。もし閉じられたセッションが依然として必要な場合、アプリケーション開発者は必要なセッション数を減らす、または不要なセッションを積極的に閉じる戦略を検討してください。 |
WebIDL[Exposed=Window, SecureContext] interface MediaKeySession : EventTarget {
readonly attribute DOMString sessionId;
readonly attribute unrestricted double expiration;
readonly attribute Promise<MediaKeySessionClosedReason> closed;
readonly attribute MediaKeyStatusMap keyStatuses;
attribute EventHandler onkeystatuseschange;
attribute EventHandler onmessage;
Promise<undefined> generateRequest (DOMString initDataType, BufferSource initData);
Promise<boolean> load (DOMString sessionId);
Promise<undefined> update (BufferSource response);
Promise<undefined> close ();
Promise<undefined> remove ();
};
sessionId 型 DOMString, 読み取り専用
このオブジェクトおよび関連するキーやライセンスのセッション ID。
expiration 型 unrestricted double、
読み取り専用
セッション内のすべてのキーの有効期限。CDM
により有効期限が存在しない場合、またはライセンスが明示的に期限切れとならない場合は NaN となる。
この値は、ウィンドウの開始などのアクションによって、セッションの存続期間中に変化することがある。
closed 型 Promise<MediaKeySessionClosedReason>、
読み取り専用
このオブジェクトがセッション終了アルゴリズムの実行によって閉じられたことを通知する。 この Promise は解決されるのみで、拒否されることはない。
keyStatuses 型 MediaKeyStatusMap、
読み取り専用
このセッションが認識しているキー IDと、関連するキーの現在の状況との読み取り専用マップへの参照。各エントリはユニークなキー IDを持たなければならない。
マップのエントリと値はイベントループが回るたびに更新される場合がある。マップは不整合や部分的な更新になってはならないが、イベントループの間にアクセスした場合は変更されている可能性がある。キー ID
は、このオブジェクトを表すセッションで load() や update()
の呼び出しによって追加されることがある。
update()
の呼び出しによって既存のキーの知識が削除されたり、新しいセットに置き換えられたりすると、キー ID は削除されることがある。キーが利用不能になった(例:
有効期限切れ)ことを理由にして削除してはならず、代わりにキーには "expired" など適切なステータスを付与しなければならない。
一部の古いプラットフォームにはキーシステム実装があり、キー ID
を公開しないため、準拠したユーザーエージェント実装を提供できないことがある。相互運用性を最大限確保するために、そのようなCDM を公開するユーザーエージェント実装は次のようにこのメンバーを実装すべきである:非空のリストが適切な場合(例: このオブジェクトで表されるキ―セッションにキーが含まれる可能性がある場合)、マップを
1 バイトのキー ID 0 とこのオブジェクトの集約状況に最もふさわしいMediaKeyStatus の組で埋めること。
onkeystatuseschange 型 EventHandler
イベントのためのイベントハンドラ。
keystatuseschange
onmessage 型 EventHandler
イベントのためのイベントハンドラ。
message
generateRequest()
initData に基づいてライセンス要求を生成します。アルゴリズムが成功して promise が解決された場合、タイプが
"license-request"
または
"individualization-request"
の は常にキューされます。
message
このメソッドが呼び出されたとき、ユーザーエージェントはMUST次の手順を実行します:
このオブジェクトの closing or closed 値が true の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの uninitialized 値が false の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの uninitialized 値を false にします。
initDataType が空文字列である場合、新しく作成した で拒否された promise
を返します。
TypeError
initData が空の配列である場合、新しく作成した で拒否された promise
を返します。
TypeError
このオブジェクトの Key System を表す cdm implementation 値が
initDataType を Initialization Data Type
としてサポートしていない場合、
で拒否された promise を返します。文字列比較は大文字小文字を区別します。
NotSupportedError
init data に initData パラメータの内容のコピーを代入します。
session type にこのオブジェクトの session type を代入します。
promise に新しい promise を代入します。
次の手順を並列して実行します:
init data が initDataType に対して有効でない場合、promise
を新しく作成した で拒否します。
TypeError
sanitized init data に init data の検証およびサニタイズされたバージョンを代入します。
ユーザーエージェントは、Initialization Data を CDM に渡す前に徹底的に検証しなければなりません。これにはフィールドの長さや値が妥当であることの確認、値が合理的な限度内にあることの検証、不要・非サポート・不明なデータやフィールドの削除などが含まれます。ユーザーエージェントは Initialization Data を事前解析、サニタイズ、または完全にサニタイズされたバージョンを生成することがRECOMMENDEDです。initDataType で指定された Initialization Data フォーマットが複数のエントリをサポートする場合、ユーザーエージェントは CDM に不要なエントリを削除することをSHOULD 行うべきです。ユーザーエージェントは Initialization Data 内のエントリの順序を変更してはなりません。
前のステップが失敗した場合、promise を新しく作成した で拒否します。
TypeError
sanitized init data が空である場合、promise を
で拒否します。
NotSupportedError
session id を空文字列にします。
message を null にします。
message type を null にします。
cdm にこのオブジェクトの cdm instance 値で表される CDM インスタンスを代入します。
cdm を使って次の手順を実行します:
sanitized init data が cdm
によりサポートされていない場合、promise を
で拒否します。
NotSupportedError
以下のリストから session type の値に応じた手順に従います:
temporary"
requested license type を一時的な非永続ライセンスとします。
返されるライセンスは永続化可能であってはならず、それに関連する永続化情報を必要としてはなりません。
persistent-license"
requested license type を永続化可能なライセンスとします。
session id を一意の Session ID 文字列にします。
Is persistent session
type? アルゴリズムを session type に対して実行した結果が
true の場合、ID はこのオブジェクトの Document の origin
内で時間を超えて、Documents や閲覧セッションをまたいで一意でなければならないことがMUSTです。
message を sanitized init data を initDataType に従って解釈して基づき生成された、requested license type のライセンス要求にします。
cdm は sanitized init data で提供されていないストリーム固有データ(メディアデータ を含む)を使用してはなりません。
cdm はこの時点でセッションデータ(セッション ID を含む)を保存してはSHOULD NOTです。詳細は Session Storage and Persistence を参照してください。
message type を "license-request"
にします。
message を、sanitized init data に基づいて requested license type のライセンス要求を生成する前に処理する必要がある要求にします。
後続の update()
の呼び出しにおいて、CDM は
initDataType に従って解釈された sanitized init
data に基づいて requested license type
のライセンス要求を生成しなければなりません。
message type を、message
の種類を反映する値にします。すなわち "license-request"
または
"individualization-request"
のいずれかにします。
Queue a task を登録して次の手順を実行します:
前のいずれかのステップがリソース不足のため失敗した場合、promise を
で拒否します。
QuotaExceededError
前のいずれかのステップがその他の理由で失敗した場合、適切な error name を
name とする新しい DOMException
で promise を拒否します。
sessionId
属性を session id に設定します。
このオブジェクトの callable 値を true に設定します。
promise を undefined で解決します。
Queue a "message" Event アルゴリズムを session 上で実行し、message type と message を提供します。
promise を返します。
load()
指定されたセッションのために保存されているデータをこのオブジェクトに読み込みます。
このメソッドが呼び出されたとき、ユーザーエージェントはMUST次の手順を実行します:
このオブジェクトの closing or closed 値が true の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの uninitialized 値が false の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの uninitialized 値を false にします。
sessionId が空文字列である場合、新しく作成した で拒否された promise
を返します。
TypeError
このオブジェクトの session type に対して Is persistent session type?
アルゴリズムを実行した結果が false の場合、新しく作成した で拒否された promise
を返します。
TypeError
origin をこのオブジェクトの Document の origin に設定します。
promise に新しい promise を代入します。
次の手順を並列して実行します:
sanitized session ID に sessionId の検証およびサニタイズされたバージョンを代入します。
ユーザーエージェントは sessionId の値を CDM に渡す前に十分に検証するべきです。最低でも長さや値が妥当であること(例えば数十文字を超えない、英数字など)を確認するべきです。
前のステップが失敗した場合、または sanitized session ID が空である場合、promise
を新しく作成した
で拒否します。
TypeError
このオブジェクトの Document 内に存在し、かつ closed
でない MediaKeySession
オブジェクトがあり、その sessionId 属性が
sanitized session ID である場合、promise を
で拒否します。
QuotaExceededError
言い換えると、この閲覧コンテキスト内で非閉鎖のセッションが既に存在する場合、その sanitized session ID に対してセッションを作成してはなりません。
expiration time を NaN にします。
message を null にします。
message type を null にします。
cdm にこのオブジェクトの cdm instance 値で表される CDM インスタンスを代入します。
cdm を使って次の手順を実行します:
origin に sanitized session ID
のために保存されているデータがない場合、promise を false
で解決し、これらの手順を中止します。
保存されているセッションの session type が現在のこのオブジェクトの MediaKeySession
の session type と同じでない場合、promise を新しく作成した
で拒否します。
TypeError
session data を、origin に保存されている sanitized session ID のためのデータとします。このデータは他の origin のデータや origin に関連付かないデータを含んではなりません。
もし任意の Document 内にあって closed でない MediaKeySession
オブジェクトが存在し、かつそれが session data を表す場合、promise を
で拒否します。
QuotaExceededError
言い換えると、任意の閲覧コンテキスト内ですでに非閉鎖の永続セッションが存在する場合、その sanitized session ID に対してセッションを作成してはなりません。
session data を読み込みます。
session data がセッションの expiration time を示している場合、expiration time をその有効期限に設定します。
メッセージを送信する必要がある場合、以下の手順を実行します:
message を session data に基づいて生成されたメッセージにします。
message type をそのメッセージに適切な MediaKeyMessageType
にします。
Queue a task を登録して次の手順を実行します:
前のいずれかのステップが失敗した場合、promise を適切な error name で拒否します。
sessionId
属性を sanitized session ID に設定します。
このオブジェクトの callable 値を true に設定します。
読み込まれたセッションが任意のキーに関する情報を含む場合(known
keys がある場合)、Update Key Statuses
アルゴリズムを session 上で実行し、各キーの key ID
と適切な MediaKeyStatus
を提供します。
キーの状態を確定するために追加処理が必要な場合は "status-pending"
を使用します。1つ以上のキーについて追加処理が完了したら、実際のステータスで Update
Key Statuses アルゴリズムを再度実行します。
Update Expiration アルゴリズムを session 上で実行し、expiration time を与えます。
promise を true で解決します。
message が null でない場合、Queue a "message" Event アルゴリズムを session 上で実行し、message type と message を提供します。
promise を返します。
update()
ライセンスを含むメッセージを CDM に提供します。
response パラメータは CDM に提供されるメッセージを含みます。内容は Key System 固有です。実行可能なコードを含んではMUST NOTなりません。
このメソッドが呼び出されたとき、ユーザーエージェントはMUST次の手順を実行します:
このオブジェクトの closing or closed 値が true の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの callable 値が false の場合、
で拒否された promise を返します。
InvalidStateError
response が空の配列である場合、新しく作成した で拒否された promise
を返します。
TypeError
response copy に response パラメータの内容のコピーを代入します。
promise に新しい promise を代入します。
次の手順を並列して実行します:
sanitized response に response copy の検証およびサニタイズされたバージョンを代入します。
ユーザーエージェントは、response を CDM に渡す前に徹底的に検証するべきです。これには値が合理的な限度内にあることの確認、不要なデータやフィールドの削除、事前解析、サニタイズ、または完全にサニタイズされたバージョンの生成が含まれる場合があります。ユーザーエージェントはフィールドの長さや値が妥当か確認し、不明なフィールドは拒否または削除するべきです。
前のステップが失敗した場合、または sanitized response が空である場合、promise
を新しく作成した
で拒否します。
TypeError
message を null にします。
message type を null にします。
session closed を false にします。
cdm にこのオブジェクトの cdm instance 値で表される CDM インスタンスを代入します。
cdm を使って次の手順を実行します:
sanitized response のフォーマットが何らかの点で無効である場合、promise
を新しく作成した
で拒否します。
TypeError
sanitized response を処理し、次のリストの先頭の一致条件に従います:
これには初期ライセンス、更新されたライセンス、およびライセンス更新メッセージが含まれます。
次のリストの最初に一致する条件に従って sanitized response を処理します:
temporary"
であり、sanitized response
がその中に含まれるセッションデータ(ライセンス、キー、または類似のセッションデータ)を保存するべきことを指定していない場合
sanitized response を処理し、いかなるセッションデータも保存しません。
persistent-license"
であり、sanitized response が永続化可能なライセンスを含む場合
sanitized response に含まれるライセンス/キーおよび関連するセッションデータを保存します。そのようなデータはこのオブジェクトの Document の origin のみがアクセスできるように保存されなければなりません。
promise を新しく作成した
で拒否します。
TypeError
詳細は Session Storage and Persistence を参照してください。
各セッションの状態情報(キーを含む)は、あるセッションを閉じても他のセッションの観測可能な状態に影響を与えないように保存されなければなりません。たとえキー ID が重複していてもです。
sanitized response がキーや関連データを含む場合、cdm はおそらくキーと関連データをキー ID で索引付けして(メモリ内に)保存します。
セッション内の置換アルゴリズムは Key System に依存します。
CDM
実装は、各 MediaKeySession
オブジェクトあたり標準的かつ十分に多い最低キー数、標準の置換アルゴリズム、および標準かつ十分に多い最低の MediaKeySession
オブジェクト数をサポートすることがRECOMMENDEDです。これにより、ユーザーエージェント間で合理的なキー回転アルゴリズムの実装が可能になり、同じ要素内で異なるキーを使用する複数ストリーム(例:アダプティブストリーム、様々な音声・映像トラック)を含むユースケースでの再生中断の可能性を減らせます。
persistent-license"
である場合
次の手順を実行します:
key session
を閉じ、このオブジェクトに関連する すべての保存されたセッションデータ(sessionId
および record
of license destruction を含む)を消去します。
session closed を true に設定します。
sanitized response を処理し、セッションデータは保存しません。
例えば sanitized response が別の
イベントを生成するための情報を含む場合、この場合は sessionType
に対して内容を検証する必要はありません。
message
メッセージを送信する必要がある場合、以下の手順を実行します:
message をそのメッセージにします。
message type をそのメッセージに適切な MediaKeyMessageType
にします。
Queue a task を登録して次の手順を実行します:
このオブジェクト上で Session Closed
アルゴリズムを理由 "release-acknowledged"
で実行します。
次の手順を実行します:
このオブジェクトに対する CDM
に知られているキーの集合が変更されたか、いずれかのキーのステータスが変更された場合、各既知キーの key ID と適切な
MediaKeyStatus
を提供して、Update Key
Statuses アルゴリズムを session 上で実行します。
キーの状態を確定するために追加処理が必要な場合は "status-pending"
を使用します。追加処理が完了したら、実際のステータスで Update Key
Statuses を再度実行します。
セッションの expiration time が変更された場合、Update Expiration アルゴリズムを session 上で実行し、新しい有効期限を提供します。
前のいずれかのステップが失敗した場合、promise を適切な error name を name とする新しい DOMException
で拒否します。
message が null でない場合、Queue a "message" Event アルゴリズムを session 上で実行し、message type と message を提供します。
promise を undefined で解決します。
promise を返します。
close()
アプリケーションがもはやセッションを必要としないことを示し、CDM にセッションに関連するリソースを解放し閉じるよう指示します。永続化されたデータは解放または消去されてはなりません。
返される promise は要求が処理されたときに解決され、closed
属性の promise はセッションが閉じられたときに理由 "closed-by-application"
で解決されます。
このメソッドが呼び出されたとき、ユーザーエージェントはMUST次の手順を実行します:
このオブジェクトの closing or closed 値が true の場合、undefined で解決された promise
を返します。
このオブジェクトの callable 値が false の場合、
で拒否された promise を返します。
InvalidStateError
promise に新しい promise を代入します。
このオブジェクトの closing or closed 値を true に設定します。
次の手順を並列して実行します:
cdm にこのオブジェクトの cdm instance 値で表される CDM インスタンスを代入します。
cdm を用いてこのオブジェクトに関連付けられた key session を閉じます。
key session を閉じると、明示的に保存されていないライセンスやキーは破棄されます。
Queue a task を登録して次の手順を実行します:
promise を undefined で解決します。
Session
Closed アルゴリズムをこのオブジェクト上で理由 "closed-by-application"
で実行します。
promise を返します。
remove()
セッションに関連するすべてのライセンスおよびキーを削除します。persistent session
types の場合、他のセッションデータは各セッションタイプについて定義されたとおり、リリースメッセージの確認が update()
によって処理されたときに消去されます。
このメソッドが呼び出されたとき、ユーザーエージェントはMUST次の手順を実行します:
このオブジェクトの closing or closed 値が true の場合、
で拒否された promise を返します。
InvalidStateError
このオブジェクトの callable 値が false の場合、
で拒否された promise を返します。
InvalidStateError
promise に新しい promise を代入します。
次の手順を並列して実行します:
cdm にこのオブジェクトの cdm instance 値で表される CDM インスタンスを代入します。
message を null にします。
message type を null にします。
cdm を使って次の手順を実行します:
セッションにライセンスおよび/またはキーが関連付けられている場合:
セッションに関連付けられたライセンスおよび/またはキーを破棄します。
これは、ライセンスおよび/またはキーがメモリ内であれ永続ストアであれ、あるいはその両方であれ破棄することを意味します。
このオブジェクトの session type の値に応じた手順に従います:
temporary"
以下の手順を続行します。
persistent-license"
record of license destruction をこのオブジェクトが表すライセンスのための record of license destruction にします。
record of license destruction を保存します。
message を record of license destruction を含むかそれを反映するメッセージにします。
Queue a task を登録して次の手順を実行します:
Update
Key Statuses アルゴリズムを session 上で実行し、セッション内のすべての key ID
に対して各キーの MediaKeyStatus
値として "released"
を提供します。
Update
Expiration アルゴリズムを session 上で実行し、NaN
を提供します。
前のいずれかのステップが失敗した場合、promise を適切な error
name を name とする新しい DOMException
で拒否します。
message type を "license-release"
にします。
promise を undefined で解決します。
message が null でない場合、Queue a
"message" Event アルゴリズムを session 上で実行し、message
type と message を提供します。
promise を返します。
MediaKeyStatusMap オブジェクトは、
key IDs と、対応する鍵の現在の状態への読み取り専用マップです。
鍵の状態は、その鍵が現在使用されているかどうかやメディアデータに依存しません。
例えば、鍵に対して現在満たせない出力要件がある場合、その鍵がメディアデータの復号に必要であったかどうかに関わらず、鍵の状態は状況に応じて "output-downscaled" または
"output-restricted" とするべきです。
WebIDL[Exposed=Window, SecureContext] interface MediaKeyStatusMap {
iterable<BufferSource,MediaKeyStatus>;
readonly attribute unsigned long size;
boolean has (BufferSource keyId);
(MediaKeyStatus or undefined) get (BufferSource keyId);
};
size 型 unsigned long,
readonly
known keys の数。
has()
keyId で識別される鍵の状態が既知であれば true を返します。
get()
keyId で識別される鍵の MediaKeyStatus を返すか、
その鍵の状態が既知でなければ undefined を返します。
このインターフェースは、entries、keys、values、
forEach および @@iterator メソッドを iterable により提供します
[WebIDL]。
反復対象となる値のペアは、すべての known keys に対して形成された (key
ID, 対応する MediaKeyStatus)
のスナップショットであり、
key ID によってソートされています。key ID の比較は次のように行われます: 長さが
m の key ID A と長さが n の B(m <= n
に割り当てられている)について、A の方が小さい (A < B) のは、A の m
オクテットが B の最初の m オクテットより辞書順で小さい場合、またはそれらが等しくかつ m < n
の場合です。
WebIDLenum MediaKeyStatus {
"usable",
"expired",
"released",
"output-restricted",
"output-downscaled",
"usable-in-future",
"status-pending",
"internal-error"
};
MediaKeyStatus 列挙型は次のように定義されます:
| 列挙型の説明 | |
|---|---|
usable
|
CDM が、その鍵が現在 復号に使用可能である と確信している状態です。 復号に現在使用できない可能性のある鍵は、この状態を持ってはなりません(MUST NOT)。 |
expired
|
鍵はその 復号使用可能性 を失っており、その理由は鍵の
expiration time が経過したためです。expiration
属性が表す時刻は現在時刻よりも前であることが MUST です。セッション内のすべての他の鍵はこの状態でなければなりません(MUST)。
|
released
|
鍵自体はもはや CDM に利用可能ではありませんが、 record of license destruction のような鍵に関する情報は利用可能です。 |
output-restricted
|
鍵に関連する出力制限があり、それらが現在満たせない状態です。必要に応じて、この鍵で復号されたメディアデータの表示はブロックされる可能性があります。アプリケーションは、その鍵に関連する出力制限を引き起こすストリームの使用を避けるべきです。 |
output-downscaled
|
鍵に関連する出力制限があり、それらが現在満たせない状態です。必要に応じて、この鍵で復号されたメディアデータは低品質(例えば解像度)で表示される可能性があります。アプリケーションは、その鍵に関連する出力制限を引き起こすストリームの使用を避けるべきです。 ダウンスケーリングのサポートは OPTIONAL です。出力要件が満たせないときに中断なく再生を保証するためにダウンスケーリングに依存してはならない(SHOULD NOT)ことに注意してください。 |
usable-in-future
|
鍵はまだ 復号に使用可能ではありません。開始時刻が将来に設定されているためで、開始時刻に達すると鍵は使用可能になります。 |
status-pending
|
鍵の状態はまだ不明で、判定中です。状態が判定されたときに実際の状態で更新されます。 |
internal-error
|
鍵は、他の値とは無関係な CDM 内のエラーのため現在 復号に使用できない 状態です。この値はアプリケーションによって対処可能なものではありません。 |
MediaKeyMessageEvent オブジェクトは イベントに使用されます。
message
WebIDLenum MediaKeyMessageType {
"license-request",
"license-renewal",
"license-release",
"individualization-request"
};
MediaKeyMessageType は次のように定義されます:
| 列挙型の説明 | |
|---|---|
license-request
|
メッセージが新しいライセンスの要求を含む場合。 |
license-renewal
|
メッセージが既存ライセンスの更新要求を含む場合。 |
license-release
|
メッセージが record of license destruction を含む場合。 |
individualization-request
|
メッセージが App-Assisted
Individualization(または再個体化)の要求を含む場合です。 他のすべてのメッセージと同様に、メッセージ内の識別子は MUST origin と profile ごとに区別できるものであり、かつ MUST NOT Distinctive Permanent Identifiers であってはなりません。 |
WebIDL[Exposed=Window, SecureContext]
interface MediaKeyMessageEvent : Event {
constructor(DOMString type, MediaKeyMessageEventInit eventInitDict);
readonly attribute MediaKeyMessageType messageType;
readonly attribute ArrayBuffer message;
};
messageType 型 MediaKeyMessageType, readonly
実装はアプリケーションにメッセージタイプの処理を要求してはなりません(MUST NOT)。実装はメッセージを区別しないアプリケーションをサポートしなければならず(MUST)、メッセージタイプの処理を強制してはなりません(MUST NOT)。 具体的には、Key Systems はすべての種類のメッセージを単一の URL に渡すことをサポートしなければなりません(MUST)。
この属性は、メッセージを解析せずにアプリケーションがメッセージを区別できるようにするためのものです。これはオプションのアプリケーションやサーバーの最適化を可能にすることを意図していますが、アプリケーションはこれを使用する必要はありません。
message 型 ArrayBuffer,
readonly
CDM からのメッセージ。メッセージは Key System 固有です。
WebIDLdictionary MediaKeyMessageEventInit : EventInit {
required MediaKeyMessageType messageType;
required ArrayBuffer message;
};
MediaKeyMessageEventInit
のメンバー
messageType
型 MediaKeyMessageType
message
型 ArrayBuffer
この節は非規範的です。
| イベント名 | インターフェース | 発生条件 |
|---|---|---|
keystatuseschange
|
Event
|
セッション内の鍵やその状態に変化があったとき。 |
message
|
MediaKeyMessageEvent
|
CDM がセッションのためにメッセージを生成したとき。 |
「message」イベントをキューするアルゴリズムは、MediaKeySession オブジェクトに対してメッセージイベントをキューします。
このアルゴリズムを実行する要求には、ターゲットとなる MediaKeySession オブジェクト、message
type、および message が含まれます。
message は暗号化された形であっても Distinctive Permanent Identifier(s)
を含んではいけません(MUST NOT)。また、もし該当の MediaKeySession オブジェクトの use
distinctive identifier 値が false の場合、message は暗号化された形であっても Distinctive Identifier(s) を含んではいけません(MUST NOT)。
次の手順を実行します:
session を指定された MediaKeySession オブジェクトとします。
タスクをキューして、バブリングせずキャンセル不可能な名前が
というイベントを作成し、messageMediaKeyMessageEvent
インターフェースを用いてそのイベントを生成し、type 属性を message に、isTrusted 属性を
true に初期化し、それを session に対してディスパッチします。
イベントインターフェース MediaKeyMessageEvent は次を持ちます:
messageType =
指定された message typemessage = 指定された
message
鍵の状態を更新するアルゴリズムは、known 鍵の集合や、1つ以上の鍵の状態を MediaKeySession
に対して更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession オブジェクトと、key ID とそれに対応する MediaKeyStatus の対の列が含まれます。
このアルゴリズムは常にタスク内で実行されます。
次の手順を実行します:
session を該当する MediaKeySession オブジェクトとします。
input statuses を、key ID とそれに対応する MediaKeyStatus の対の列とします。
statuses を session の keyStatuses 属性とします。
statuses の内容を置き換えるために次の手順を実行します:
statuses を空にします。
input statuses の各対について以下を行います。
pair をその対とします。
pair の key ID に対するエントリを statuses に挿入し、pair
の MediaKeyStatus
値を設定します。
この手順の効果は、session の keyStatuses
属性の内容が既存の参照を無効にすることなく置き換えられる、ということです。この置換はスクリプトの観点から原子操作です。つまり、スクリプトは決して部分的にしか埋められていない状態を観測してはなりません(MUST NOT)。
タスクをキューして、イベントを発火
する処理を実行し、名前が
のイベントを session に対して発火します。
keystatuseschange
タスクをキューして、各メディア要素について
mediaKeys 属性がこの
session を作成した MediaKeys
オブジェクトである場合に、Attempt to Resume Playback If
Necessary アルゴリズムを実行します。
有効期限を更新するアルゴリズムは、expiration time を MediaKeySession
に対して更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession
オブジェクトと、新しい有効期限(NaN である場合があります)が含まれます。
このアルゴリズムは常にタスク内で実行されます。
次の手順を実行します:
session を該当する MediaKeySession オブジェクトとします。
expiration time を NaN とします。
新しい有効期限が NaN でないなら、expiration time をその値とします。
session の expiration 属性を、time として表現された expiration time に設定します。
セッションが閉じられたアルゴリズムは、MediaKeySession の状態を、key session が CDM
によって閉じられた後に更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession オブジェクトと、MediaKeySessionClosedReason
が含まれます。
このアルゴリズムは常にタスク内で実行されます。
セッションが閉じられると、当該セッションに関連するライセンスや鍵はメディアデータの復号に利用できなくなります。すべての MediaKeySession
のメソッドは失敗し、このアルゴリズム実行後はこのオブジェクトに対してさらにイベントがキューされることはありません。
The CDM は、セッションがもはや必要でなくなった場合やシステムリソースが失われた場合など、任意の時点でセッションを閉じることがあります。その場合、Monitor for CDM State Changes アルゴリズムがその変化を検出し、このアルゴリズムを実行します。
他のセッション内のキーは、キー ID が重複していても、MUST 影響を受けてはならない。
このアルゴリズムが実行された後、このアルゴリズムによってキューされたイベントのイベントハンドラは実行されますが、それ以降イベントをキューすることはできません。その結果、セッションを閉じたことにより CDM がメッセージを送信することはできません。
次の手順を実行します:
session を該当する MediaKeySession オブジェクトとします。
promise を session の closed 属性とします。
もし promise が既に解決されているなら、この手順を中止します。
session の closing or closed 値を true に設定します。
Update Key Statuses アルゴリズムを session 上で空の列を提供して実行します。
Update Expiration アルゴリズムを session 上で
NaN を提供して実行します。
promise を与えられた理由で解決します。
Monitor for CDM State Changes アルゴリズムは、さまざまな側面の CDM の状態変化があったときに必要な手順を実行します。
このアルゴリズムは、他のアルゴリズムで扱われない CDM の状態変化にのみ適用されます。例えば、update()
によりメッセージ、キーの状態変化、および/または有効期限の変化が生じることがありますが、それらはすべて当該アルゴリズム内で処理されます。
このアルゴリズムは常にメインのイベントループと並列して実行されます。
次の手順を実行します:
session を MediaKeySession オブジェクトとします。
cdm を session の cdm instance 値で表される CDM インスタンスとします。
もし cdm にまだ送信されていない送信メッセージがあるなら、タスクをキューして次の手順を実行します:
message type と message をメッセージの種類とメッセージにそれぞれ設定します。
「message」イベントをキューする アルゴリズムを実行し、session、message type、message を渡します。
もし cdm が session に対して known な鍵の集合を変更したか、あるいは 1つ以上の鍵の状態を変更したなら、タスクをキューして次の手順を実行します:
statuses を、session に known な各鍵につき
1 対の key ID と MediaKeyStatus 値を含むリストとします。
鍵の状態を更新する アルゴリズムを実行し、session と statuses を渡します。
もし cdm が session の expiration time を変更したなら、タスクをキューして次の手順を実行します:
expiration time を session の新しい有効期限とします。
有効期限を更新する アルゴリズムを実行し、session と expiration time を渡します。
もし cdm が session を閉じたなら、タスクをキューして、セッションが閉じられた アルゴリズムを適切な MediaKeySessionClosedReason
値で session に対して実行します。
もし cdm がハードウェアコンテキストリセットにより利用不能になったなら、タスクをキューして、CDM Unavailable アルゴリズムを理由 "hardware-context-reset"
で実行します。
もし cdm が他の理由で利用不能になったなら、タスクをキューして、CDM Unavailable アルゴリズムを理由 "internal-error"
で実行します。
メソッドは、返されたプロミスを 単純例外
[WEBIDL] または DOMException
で拒否することでエラーを報告します。以下の
[WEBIDL] のアルゴリズムで使用される 単純例外 および DOMException 名
を示します。アルゴリズムで指定された原因は各名前の横に記載されていますが、これらの名前は他の理由でも使われることがあります(MAY)。
| 名前 | 主な原因(例示、網羅的ではない) |
|---|---|
TypeError
|
パラメータが空である。 初期化データが無効。 応答フォーマットが無効。 " temporary"
セッションに永続ライセンスが提供された。
|
NotSupportedError
|
既存の MediaKeys オブジェクトが削除できない。Key System がサポートされていない。 初期化データタイプが Key System でサポートされていない。 セッションタイプが Key System でサポートされていない。 初期化データが Key System でサポートされていない。 操作が Key System でサポートされていない。 |
InvalidStateError
|
既存の MediaKeys オブジェクトが現時点では削除できない。セッションがすでに使用された。 セッションがまだ初期化されていない。 セッションが閉じられている。 |
QuotaExceededError
|
MediaKeys オブジェクトは追加の HTMLMediaElement で使用できない。この sessionId に対して未閉セッションがすでに存在する。 新しいセッションやライセンス要求を作成するためのリソースが不足している。 |
本節は、アルゴリズムを補足するセッション保存と永続化の概要を示します。
以下の要件は、Storage and Persistence の要件に加えて適用されます。
このオブジェクトの session type に対して Is persistent session type? アルゴリズムを実行した結果が
false であれば、ユーザーエージェントおよび CDM はセッションに関連する記録やデータ(ライセンス、鍵、record(s) of license destruction、Session ID を含む)をいかなる時点でも永続化してはならない(MUST
NOT)。
この節の残りは、Is persistent session type? アルゴリズムが
true を返すセッションタイプに適用されます。
CDM
は SHOULD NOT update()
が初めて呼ばれるまでは、Session ID を含むセッションデータを保存すべきではありません。特に、CDM は generateRequest()
アルゴリズムの間にセッションデータを保存すべきではありません(SHOULD
NOT)。これにより、アプリケーションはセッションの存在を把握し、最終的に削除する必要があることが分かります。
セッションがクリアされたとき(例: update() で record of license destruction
確認応答が処理された場合など)、そのセッションに関連する すべて のデータはクリアされなければなりません(MUST)。詳細は Persistent Data を参照。
CDM
は、あるセッションのデータが未閉じの MediaKeySession オブジェクト(任意の
Document
内)にしか存在しないことを保証しなければなりません(MUST)。言い換えれば、load() は、その sessionId
パラメータで指定されたセッションを表す MediaKeySession
が既に存在している場合(それを generateRequest()
で作成したオブジェクトがまだアクティブか、あるいは他のオブジェクトに load()
でロードされた場合)、必ず失敗しなければなりません(MUST)。すべての関連オブジェクトが closed なら、再度ロードすることができます(MAY)。
Is persistent session type? アルゴリズムが
true を返す型でセッションを作成するアプリケーションは、保存されたデータを後で remove()
で削除処理を開始し、その削除処理(メッセージのやりとりを含む場合がある)が正常に完了することを確認するべきです(SHOULD)。CDM
も適切にセッションを削除することがありますが、アプリケーションはこれに依存すべきではありません(SHOULD NOT)。
永続ストレージ対応時の追加考慮事項については、10. Security および 11. Privacy を参照してください。
この節では、Encrypted Media Extensions がサポートされている場合の HTMLMediaElement [HTML]
への追加および変更について規定します。
以下の内部値が HTMLMediaElement に追加されます:
attaching media keys(SHALL ブール値を持つ)。
encrypted block queue(SHALL 復号待ちの暗号化ブロックのキュー)。
decryption blocked waiting for key(SHALL ブール値を持つ)。
playback blocked waiting for key(SHALL ブール値を持つ)。
以下の変更が HTMLMediaElement の挙動に加えられます:
HTMLMediaElement が生成されるとき、attaching
media keys の値は SHALL false で初期化され、encrypted
block queue の値は SHALL 空で、decryption blocked waiting for
key の値は SHALL false で初期化され、playback blocked
waiting for key の値も SHALL false で初期化されます。
現在の再生位置
が通常再生の一部として再生方向に進む以外の方法で変更された場合、encrypted block queue の値は SHALL
空となり、decryption blocked waiting for key の値は SHALL
false で初期化され、playback blocked waiting for key の値も SHALL false に設定されます。
つまり、例えば メディアリソースのロード や シークの際にこれらの値をリセットすべきです。
[HTML] で規定された基準に加えて、HTMLMediaElement は、playback blocked
waiting for key の値が true の場合 blocked media element
と見なされます(SHALL)。
ユーザーエージェントが再生を開始する準備ができ、media data に暗号化ブロックが含まれる可能性のある指示に遭遇した場合、resource fetch algorithm の中で、ユーザーエージェントは SHALL Media Data May Contain Encrypted Blocks アルゴリズムを実行します。
一部のコンテナフォーマットでは、この指示は Initialization Data とは別です。
このアルゴリズムは、関連するコンテナデータのパース(Initialization Data Encountered アルゴリズムの実行を含む)後、デコードが開始する前に実行されます。
ユーザーエージェントが Initialization Data を media data の中で resource fetch algorithm の間に検出した場合、ユーザーエージェントは SHALL Initialization Data Encountered アルゴリズムを実行します。
一部のコンテナフォーマットは Initialization Data を含まない暗号化メディアデータをサポートしており、その場合このアルゴリズムはトリガーされません。
media data の暗号化ブロックが resource fetch algorithm の間に検出されるごとに、ユーザーエージェントは暗号化ブロックが検出された順に Encrypted Block Encountered アルゴリズムを SHALL 実行します。
この手順は、ユーザーエージェント実装が暗号化ブロック検出後、再生に必要になるまでの任意のタイミングで復号を行う柔軟性を提供します。
decryption blocked waiting for key の値が true の間に次のいずれかが発生した場合、ユーザーエージェントは SHALL Wait for Key アルゴリズムを実行します。
以下のように属性およびメソッドが追加されます。
プロミスを返すメソッドにおいて、すべてのエラーは返された Promise を拒否することで非同期に報告されます。これには [WEBIDL] の型マッピングエラーも含まれます。
アルゴリズムの手順は、プロミスが拒否されると常に中止されます。
WebIDL[Exposed=Window] partial interface HTMLMediaElement {
[SecureContext] readonly attribute MediaKeys? mediaKeys;
attribute EventHandler onencrypted;
attribute EventHandler onwaitingforkey;
[SecureContext] Promise<undefined> setMediaKeys (MediaKeys? mediaKeys);
};
mediaKeys 型 MediaKeys、readonly、nullable
このメディア要素で暗号化された media data
を復号する際に使用される MediaKeys。
onencrypted 型 EventHandler
イベントのイベントハンドラ。全ての encryptedHTMLMediaElement
でコンテンツ属性およびIDL属性として MUST サポートされなければなりません。
onwaitingforkey 型 EventHandler
イベントのイベントハンドラ。全ての waitingforkeyHTMLMediaElement でコンテンツ属性およびIDL属性として
MUST サポートされなければなりません。
setMediaKeys()
再生中のメディアデータの復号に使用する MediaKeys を指定します。
再生中に関連付けられた MediaKeys
オブジェクトをクリアまたは置換することのサポートは実装品質に依存します。多くの場合、悪いユーザー体験やプロミスの拒否につながります。
このメソッドが呼ばれたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:
このオブジェクトの attaching media keys 値が true なら、
で拒否されたプロミスを返します。
InvalidStateError
mediaKeys と mediaKeys
属性が同じオブジェクトなら、undefined で解決されたプロミスを返します。
このオブジェクトの attaching media keys 値を true にします。
promise を新しいプロミスとします。
次の手順を並行して実行します:
以下の条件がすべて成り立つ場合:
mediaKeys が null でない
mediaKeys で表される CDM インスタンスが他のメディア要素ですでに使用されている
ユーザーエージェントがこの要素でそれを使用できない
この場合はこのオブジェクトの attaching media keys 値を false にし、promise を
で拒否します。
QuotaExceededError
mediaKeys 属性が
null でない場合、次の手順を実行します:
ユーザーエージェントまたは CDM
が関連付け解除をサポートしない場合は、このオブジェクトの attaching media keys 値を false
にし、promise を
で拒否します。
NotSupportedError
現時点で関連付け解除できない場合は、このオブジェクトの attaching media keys 値を false
にし、promise を
で拒否します。
InvalidStateError
例えば一部の実装では再生中の解除を許可しません。
上記の手順が失敗した場合は、このオブジェクトの attaching media keys 値を false にし、promise を適切な error name で拒否します。
mediaKeys が null でない場合、次の手順を実行します:
mediaKeys で表される CDM インスタンスをメディア要素に関連付け、media data の復号に使用するようにします。
上記の手順が失敗した場合は次の手順を実行します:
mediaKeys
属性を null にします。
このオブジェクトの attaching media keys 値を false にします。
promise を適切な error name
で新しい DOMException
で拒否します。
タスクをキューして、メディア要素上で Attempt to Resume Playback If Necessary アルゴリズムを実行します。
mediaKeys 属性を
mediaKeys に設定します。
このオブジェクトの attaching media keys 値を false にします。
promise を undefined で解決します。
promise を返します。
MediaEncryptedEvent オブジェクトは イベントで使用されます。
encrypted
WebIDL[Exposed=Window]
interface MediaEncryptedEvent : Event {
constructor(DOMString type, optional MediaEncryptedEventInit eventInitDict = {});
readonly attribute DOMString initDataType;
readonly attribute ArrayBuffer? initData;
};
initDataType 型 DOMString、readonly
initData 属性に格納されています。
initData 型 ArrayBuffer、readonly、nullable
WebIDLdictionary MediaEncryptedEventInit : EventInit {
DOMString initDataType = "";
ArrayBuffer? initData = null;
};
MediaEncryptedEventInit
のメンバー
initDataType
型 DOMString、
デフォルト値 ""
initData
型 ArrayBuffer、
nullable、デフォルト値 null
この節は非規範的です。
| イベント名 | インターフェース | 発生条件 | 前提条件 |
|---|---|---|---|
encrypted
|
MediaEncryptedEvent
|
ユーザーエージェントが Initialization Data を media data で検出したとき。 |
要素の readyState
が
HAVE_METADATA
以上であること。
注
要素が再生中または再生済みの場合もあり得ます。 |
waitingforkey
|
Event
|
再生が鍵待ちでブロックされている。 |
readyState
が
HAVE_CURRENT_DATA
以下であること。
要素の playback blocked waiting
for key の値が新たに true になったとき。
|
「Media Data May Contain Encrypted Blocks」アルゴリズムは、ユーザーエージェントがメディアデータを再生する前に MediaKeys オブジェクトの指定を要求する場合に再生を一時停止します。
このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
もし media element の mediaKeys 属性が null
であり、実装が暗号化されている可能性のある media data
のデコード前に MediaKeys
オブジェクトの指定を要求する場合は、次の手順を実行します:
これらの手順は、アプリケーションが media data
を提供した後に setMediaKeys()
を呼んで MediaKeys
オブジェクトを提供するような場合に到達することがあります。CDM
の選択はパイプラインやデコーダに影響を与える可能性があるため、一部の実装では CDM が MediaKeys として setMediaKeys()
に渡されるまで、暗号化ブロックを含む可能性のあるメディアデータの再生を遅延させることがあります。
Wait for Key アルゴリズムを media element に対して実行します。
再生を再開するためのシグナルを待ちます。
「Initialization Data Encountered」アルゴリズムは、メディアデータ中で発見された イベントをキューします。
このアルゴリズムを実行する要求には、ターゲットの encryptedHTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
initDataType を空文字列とします。
initData を null とします。
もし media data が CORS-same-origin であり、かつ 混在コンテンツではない 場合、次の手順を実行します:
initDataType を、発見された Initialization Data の Initialization Data Type を表す文字列とします。
initData を Initialization Data とします。
メディア要素は「Upgradeable Content」を許可する場合がありますが、そのようなメディアデータからの Initialization Data をアプリケーションに公開してはなりません(MUST NOT)。
タスクをキューして、バブリングせずキャンセル不可の名前が
というイベントを encryptedMediaEncryptedEvent
インターフェースを使って作成し、type 属性を encrypted に、isTrusted を
true に初期化して media element 上でディスパッチします。
イベントインターフェース MediaEncryptedEvent は次を持ちます:
initDataType =
initDataTypeinitData =
initData
readyState
は変更されず、アルゴリズムは中止されません。 このイベントは単に情報を提供するものです。
initData
属性は、メディアデータが CORS-same-origin でない か、または 混在コンテンツ である場合は null
になります。アプリケーションは代替ソースから Initialization Data を取得することができます。
「Encrypted Block Encountered」アルゴリズムは、復号のために暗号化されたメディアデータのブロックをキューに入れ、可能であれば復号を試みます。
このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
block を暗号化されたメディアデータのブロックとします。
block を media element の encrypted block queue の末尾に追加します。
もし media element の decryption blocked waiting for key 値が
false であれば、Attempt to Decrypt
アルゴリズムを実行します。
「Attempt to Decrypt」アルゴリズムは、復号のためにキューに入れられているメディアデータの復号を試みます。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
もし media element の encrypted block queue が空であれば、この手順を中止します。
もし media element の mediaKeys 属性が null
でない場合、次の手順を実行します:
media keys をその属性が参照する MediaKeys オブジェクトとします。
cdm を media keys の cdm instance 値で表される CDM インスタンスとします。
もし cdm が何らかの理由でもはや使用不可能であれば、次の手順を実行します:
media data is corrupted の手順を resource fetch algorithm の対応箇所で実行します。
CDM
Unavailable アルゴリズムを、media keys
に対して、ハードウェアコンテキストのリセットの場合は理由を "hardware-context-reset"、それ以外の場合は
"internal-error"
として実行します。
この手順を中止します。
もし media keys によって作成された MediaKeySession
が少なくとも1つ存在し、それが closed でない場合、次の手順を実行します:
このチェックは、cdm の読み込みが完了し、対応する鍵が利用可能である前提条件を保証するためのものです。
block を media element の encrypted block queue の先頭のエントリとします。
block key ID を block の key ID とします。
key ID は一般にコンテナによって指定されます。
cdm を使用して次の手順を実行します:
available keys を、media keys によって作成されたセッション内の鍵の和集合とします。
block key を null とします。
もし available keys の中に block key ID に対応し、かつ usable for
decryption なものがあれば、当該鍵を含む MediaKeySession
オブジェクトを session とし、当該鍵を block key とします。
複数のセッションに対して block key ID に対応する usable for decryption な鍵が含まれている場合、どのセッションと鍵を使用するかは Key System に依存します。
もし前のステップの実行によって available keys の状態が変更された場合、影響を受けた各
session に対して、すべての key ID とそれに対応する適切な MediaKeyStatus
値を渡して、Update Key Statuses
アルゴリズムをキューするタスクを起動します。
もし block key が null でない場合、次の手順を実行します:
cdm を使って block を block key で復号します。
以下のリストの最初に一致する条件に従って処理します:
media data is corrupted の手順を resource fetch algorithm の対応箇所で実行します。
もし cdm がもはや使用不可能であれば、CDM
Unavailable アルゴリズムを media
keys に対して、ハードウェアコンテキストリセットの場合は "hardware-context-reset"、それ以外は
"internal-error"
の理由で実行します。
この手順を中止します。
block を media element の encrypted block queue の先頭から削除します。
復号済みブロックを通常どおり処理します。
つまり、そのブロックをデコードします。
このアルゴリズムの先頭に戻ります。
すべての復号の問題(例: 間違った鍵を使うなど)がここでの復号失敗を引き起こすわけではありません。そのような場合、ここではエラーが発生しないが、デコード中にエラーが発生する可能性があります。
そうでなければ、いかなるセッションにも block key ID の鍵が存在しないため、処理を継続します。
media element の decryption blocked waiting for key 値を
true に設定します。
この手順は、block に対して usable for decryption な鍵がない場合に到達します。
ユーザーエージェントが復号できないブロックに先行するブロックを(可能な限り、例えば完全なビデオフレーム全てなど)レンダリングした後、Wait for Key アルゴリズムを実行します。
このアルゴリズムをここで直接実行しないのは、実装が現在の再生位置より先にメディアデータを復号・デコードすることを許容し、その可視的挙動に影響を与えないようにするためです。
フレームベースの暗号化の場合、メディア要素がリソース取得アルゴリズムの一部としてフレームのデコードを試みるときに、以下のように実装できることがあります:
encrypted を false にします。
フレームが暗号化されているかどうかを検出します。
フレームをデコードします。
レンダリングのためにフレームを提供します。
「Wait for Key」アルゴリズムは
イベントをキューし、waitingforkeyreadyState
を更新します。 このアルゴリズムは、HTMLMediaElement
オブジェクトが potentially
playing であり、その readyState
が HAVE_FUTURE_DATA
以上のときにのみ呼び出すべきです。 このアルゴリズムを実行する要求にはターゲットの HTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
もし media element の playback blocked waiting for key 値が
true であれば、この手順を中止します。
media element の playback blocked waiting for key 値を true
に設定します。
上の手順の結果、メディア要素はまだでなければ blocked media element となり得ます。その場合、メディア要素は再生を停止します。
以下のリストの最初に一致する条件に従います:
media element の readyState
を HAVE_CURRENT_DATA
に設定します。
media element の readyState
を HAVE_METADATA
に設定します。
言い換えれば、現在の再生位置のビデオフレームやオーディオデータが非暗号化であったり正常に復号されたためにデコード済みであれば readyState
を HAVE_CURRENT_DATA
に設定します。そうでない場合、または以前はその状態だったが現在はデータが利用できない場合は readyState
を HAVE_METADATA
に設定します。
タスクをキューして、イベント発火
を行い、名前が のイベントを
media element に対して発火します。
waitingforkey
再生を一時停止します。
「Attempt to Resume Playback If Necessary」アルゴリズムは、メディア要素が鍵待ちでブロックされており、必要な鍵が現在 usable for decryption である場合に再生を再開します。
このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。
次の手順を実行します:
media element を指定された HTMLMediaElement オブジェクトとします。
もし media element の playback blocked waiting for key が
false であれば、この手順を中止します。
Attempt to Decrypt アルゴリズムを media element に対して実行します。
もしユーザーエージェントが current playback position を再生方向に進めることができるなら:
media element の decryption blocked waiting for key 値を
false に設定します。
media element の playback blocked waiting for key 値を
false に設定します。
上の手順の結果、メディア要素はもはや blocked media element でなくなる可能性があり、その結果として再生が再開されることがあります。
media element の readyState
を、状況に応じて HAVE_CURRENT_DATA、HAVE_FUTURE_DATA、または
HAVE_ENOUGH_DATA
に設定します。
HAVE_CURRENT_DATA
より先の状態や canplaythrough
イベントは、通常、現在の鍵以上の鍵の利用可能性を考慮しない(またはあまり考慮しない)ことに注意してください。
ready state の変更は、HTMLMediaElement
によるイベントの発火を引き起こすことがあります(詳細は こちら
を参照)。
この節は規範的ではありません。
CDM
によって処理されるメディアデータは、通常の方法(例えば CanvasRenderingContext2D
の
drawImage()
メソッドや AudioContext の
MediaElementAudioSourceNode
を用いる等)を通じてウェブプラットフォームの API から利用できないことがMAYあります。
本仕様はそのようなメディアデータの非利用可能性の条件を定義しませんが、もしメディアデータがそのような API を通じて利用できない場合、これらの API
はメディアデータがまったく存在しないかのように振る舞うことがMAYあります。
メディアレンダリングが UA によって行われない場合、例えばハードウェアベースのメディアパイプラインの場合、CSS トランスフォーム等の HTML のレンダリング機能のすべてが利用できないことがMAYあります。典型的な制約の一つとしては、ビデオメディアがウィンドウの辺に平行な辺を持ち、通常の向きに整った矩形領域のみに表示が制限されることがMAYあります。
このセクションでは、ユーザーエージェントおよび Key Systems(CDM やサーバーを含む)に対する、アルゴリズムで明示的に扱われていない可能性のある実装要件を定義します。ここおよび仕様全体の要件は、CDM がユーザーエージェントから分離されているか一部であるかにかかわらず、すべての実装に適用されます。
ユーザーエージェントの実装者は MUST、CDMs が、本仕様の機能を用いて保護付きメディアを再生するために合理的に必要とされる範囲を超える情報、ストレージ、またはシステム機能へアクセスしないことを保証しなければなりません。具体的には、CDM は SHALL NOT:
ユーザーエージェントを介して明示的に許可されている場合を除き、ローカルあるいはリモートのネットワークリソースへアクセスすること。
本仕様の機能を用いた保護付きメディアの再生のために合理的に必要とされる場合を除き、ストレージ(例:ディスクやメモリ)へアクセスすること。
CDM の状態および persistent data 以外のユーザーデータへアクセスすること。
本仕様の機能を用いた保護付きメディアの再生のために合理的に必要とされる場合を除き、ハードウェアコンポーネントやデバイスへアクセスすること。
ユーザーエージェントの実装者は上記の要件を満たすために様々な手法を用いることができます。例えば、自身で CDM を実装しているユーザーエージェント実装者は、上記を当該コンポーネントの設計要件として含めることができます。サードパーティの CDM を利用するユーザーエージェント実装者は、その CDM が禁止された情報やコンポーネントへアクセスできない制約された環境(例:"sandbox")で実行されることを保証することができます。
すべての CDM へのおよびそこからのメッセージおよび通信(例えば CDM とライセンスサーバー間の通信)は、MUST ユーザーエージェントを介して渡されなければなりません。CDM は MUST NOT 直接のアウト・オブ・バンドなネットワークリクエストを行ってはなりません。Direct Individualization MUST で説明されているものを除くすべてのメッセージおよび通信は、本仕様で定義された API を介してアプリケーションを通して渡されなければなりません。具体的には、アプリケーションに関する情報、origin に関する情報、あるいはコンテンツ固有の情報を含む通信、またはアプリケーションが指定した URL に送信される通信やその origin に基づく URL に送信される通信は、MUST 本仕様の API を経由して行われなければなりません。これにはすべてのライセンス交換メッセージが含まれます。
永続データは、CDM、またはその CDM を代表してユーザーエージェントが保存した、MediaKeys オブジェクトの破棄後も存在するすべてのデータを含みます。具体的には、識別子(Distinctive Identifier(s) を含む)、ライセンス、キー、キー ID、または
ライセンス破棄の記録 等を、CDM
またはその CDM を代表してユーザーエージェントが保存したものを指します。
アプリケーションやライセンスサーバーに見える形でメッセージや振る舞いに影響を与え得る Persistent Data は、origin 固有かつ browsing profile 固有の方法で保存されなければならず(MUST)、プライベートブラウジングセッションへ流出したり、そこから漏れてはいけません(MUST NOT)。具体的には(網羅的ではありませんが)、セッションデータ、ライセンス、鍵、per-origin 識別子は origin と browsing profile ごとに保存されなければなりません。
詳細は Session Storage and Persistence を参照してください。
Persistent Data を使用する実装は、そのデータが本仕様で定義された API 経由など外部から、またクライアントデバイス上でも回復不能になるようにユーザーがデータを消去できることをMUST 許容しなければなりません。
ユーザーエージェントは SHOULD 次のことを行うべきです:
Persistent Data をクッキー等の他のサイトデータと同様に扱う。具体的には:
閲覧履歴の消去機能の一部として Persistent Data を消去できるようにすること。
「すべてのデータを削除」機能に Persistent Data を含めること。
Persistent Data を他のサイトデータと同じ UI の場所に表示すること。
ユーザーが origin ごと、または browsing profile ごとに Persistent Data を消去できるようにすること(特に「このサイトを忘れる」機能の一部として、特定サイトに関連するクッキーやデータを削除できるようにすること)。
Persistent Data を消去する操作が十分に原子的であり、「クッキー復活(cookie resurrection)」のような、新しい識別子と古いものを別の残存データにより再関連付けできる状況を防ぐこと。
これらのインターフェースを、データの不完全な消去の可能性をユーザーが理解できるように提示し、クッキーや web storage などデータを永続化するすべての機能に関連するデータを同時に削除できるようにすること。
Key System を無効化・再有効化するためのインターフェースを、データの不完全な消去の可能性を理解させ、すべての永続ストレージ機能におけるデータを同時に削除できるように提示すること。
ユーザーが origin ごと、あるいはすべての origin に対して Persistent Data を特定に削除できるようにすること。
ユーザーエージェントは Persistent Data を潜在的に機微な情報として扱うべきです。これらの情報が流出するとユーザーのプライバシーが損なわれる可能性があります。そのため、ユーザーエージェントは Persistent Data が安全に保存されるようにし、データを削除する際は基盤となるストレージから速やかに削除されることをSHOULD 確保すべきです。
アプリケーションに公開される、あるいは CDM による使用などを通じて推測可能な値は、識別子として設計されていない場合でもクライアントやユーザーを特定するのに利用され得ます。本節はそのような懸念を回避または緩和するための要件を定義します。識別子に関する追加要件は Identifiers を参照してください。
アプリケーションに公開される、または推測可能なすべての Distinctive Values は、origin ごとおよび browsing profile ごとに固有でなければならない(MUST)。つまり、本仕様で定義された API を使用する一つの origin に対する値は、他の origin に対する値と異なるものでなければならず、また一つの browsing profile で使われる値は他のプロファイルで使われるものと異なるものでなければなりません。これらの値はプライベートブラウジングセッションへ漏れてはならず、そこから流出してはなりません。
オリジンやプロファイルをまたいだ値は、アプリケーションによって関連付け不可能(non-associable by applications)でなければなりません。すなわち、複数のオリジンやプロファイルからの値を相互に相関させて同一のクライアントやユーザーに由来するものと特定できてはなりません。オリジン独立またはプロファイル独立の値から per-origin 値を導出する実装は、上記の非関連付け性を保証する方法(非可逆性を持つ導出関数など)を用いなければなりません(MUST)。
Allow Persistent Data to Be Cleared の要件の結果として、アプリケーションに公開されたすべての永続化された値は、外部(本仕様で定義された API 経由等)およびクライアントデバイス上の双方で回復不能となるようにクリア可能でなければなりません(MUST)。
一度クリアされたら、新しい非関連付け可能な(non-associable by applications)値が、後で値が必要になったときに生成されなければなりません(MUST)。
実装による識別子の使用、特に Distinctive Identifier(s) や Distinctive Permanent Identifier(s) の利用はプライバシー上の懸念を引き起こします。本節はそのような懸念を回避または緩和するための要件を定義します。アプリケーションに公開される値に関する要件(Values Exposed to the Application)は、アプリケーションに公開される識別子にも適用されます。
要約すると:
Distinctive Identifiers や Permanent Identifiers の使用を制限または回避する。
Permanent Identifiers を除くすべての識別子は、Permanent Identifiers を除いて、MUST origin と profile ごとに一意であり、相関不能(non-associable)であり、クリア可能でなければならない。
すべての識別子は公開時に暗号化されるべきである(SHOULD)。
Distinctive Identifiers は、クライアント外に公開される際に暗号化され、origin と profile ごとに一意であり、かつクリア可能でなければならない(MUST)。
Distinctive Permanent Identifiers は、クライアント外に公開される際に暗号化されなければならず(MUST)、アプリケーションに公開されてはならない(MUST NOT)。
本仕様で定義された APIs の使用により生成される、上記で扱われていないすべての潜在的な識別子または Distinctive Values は、origin および profile ごとに一意であり、かつ クリア可能でなければなりません。これにはランダムな識別子、セッションデータ、 およびその他の CDM データが含まれますが、これらに限定されません。
実装は Distinctive Identifier(s) や Distinctive Permanent Identifier(s) の使用を避けるべきです(SHOULD)。
例えば、個々のクライアントではなく複数クライアントやデバイスのグループに適用される識別子や値を使用することが考えられます。
実装は、Distinctive Identifier(s) や Distinctive Permanent Identifier(s) を、特定の CDM インスタンスやセッションのポリシーを強制するためにのみ使用すべきです(SHOULD)。
例えば、"temporary" と
"persistent-license"
のセッションは異なる要件を持つかもしれません。
Distinctive Identifier(s) や Distinctive Permanent Identifier(s) を使用する実装は、それらを使用しないオプションをサポートすべきです(SHOULD)。そのようなサポートがある実装は、ユーザーがこのオプションを選択できる機能を公開するべきです(SHOULD)。
サポートされている場合、アプリケーションは distinctiveIdentifier
= "not-allowed"
を指定してこのモードを選択できます。こうしたオプションの選択は requestMediaKeySystemAccess()
の結果や、後続のセッションから生成されるライセンス要求に影響する可能性があります。
ユーザーにこの実装機能を選択させることで、より高いプライバシーを維持しながらコンテンツへアクセスできるようになる場合があります。
Distinctive Identifiers と Distinctive Permanent Identifiers は、クライアント外へ公開される際にメッセージ交換レベルで暗号化されなければなりません(MUST)。その他の識別子も、クライアント外へ公開される際にはメッセージ交換レベルで暗号化されるべきです(SHOULD)。暗号化は、識別子の暗号文の二つのインスタンスが復号鍵を持つエンティティのみによって関連付け可能(associable)であることを保証しなければなりません(MUST)。
識別子は次のような方法で公開され得ます:
イベントを介してアプリケーションに。
message
サーバーからのメッセージ内で、例えば update()
に渡されるものとして。
individualization の一部として。
CDM 必ず 暗号化キーがそのキーシステムに対して有効なサーバーに属していることを検証する必要があります。アプリケーションに公開される識別子については、これはサーバー証明書を使用して実装してもよいです。
Distinctive Permanent Identifiers を除くすべての識別子は、origin と browsing profile ごとに一意でなければなりません(MUST)。詳細は 8.4.1 Use Per-Origin Per-Profile Values を参照してください。
これは Distinctive Identifiers を含みますがこれに限定されません。
Distinctive Permanent Identifiers はアプリケーションやオリジンに公開してはならない(MUST NOT)。
実装がアプリケーションに公開するすべての識別子(Distinctive Identifiers を含む)、たとえ暗号化された形であっても、オリジン、browsing profiles、および 識別子のクリア を跨いでアプリケーションによって関連付けられない(non-associable by application)ものでなければなりません(MUST)。
そのような識別子について、複数のアプリケーションや関連するライセンスサーバー等が相関や関連付けを行えないことが求められます(MUST NOT)。
Allow Persistent Data to Be Cleared の要件の帰結として、Distinctive Values(Distinctive Permanent Identifiers を除く) は、外部やクライアントデバイス上の双方で回復不能となるようにクリア可能でなければなりません(MUST)。
Distinctive Identifier(s) を使用する実装は、ユーザーがその Distinctive Identifier(s) をクリアできるようにしなければなりません(MUST)。また、Distinctive Permanent Identifier(s) を使用する実装は、当該 Distinctive Permanent Identifier(s) に関連する値をユーザーがクリアできるようにしなければなりません(MUST)。
一度クリアされたら、新しい非関連付け可能な(non-associable by applications)値が、例えば Distinctive Identifiers のような値が再び必要になったときに生成されなければなりません(MUST)。
識別子、特に Distinctive Identifiers は、 個体化(individualization)またはプロビジョニングと呼ばれるプロセスを通じて生成または取得されることがあります。得られた識別子は MUST アプリケーションによって関連付けできない(non-associable by applications)ものであり、かつそれらの使用は MUST 単一の プロファイルの単一のオリジンにのみ公開されるものでなければなりません。 このプロセスは、識別子がクリアされた後などに、複数回実行されることが MAY あります。
このプロセスは MUST ユーザーエージェントが直接実行するdirectly by the user agent か、またはアプリケーションを通じて実行されなければなりません。両者の個体化の仕組み、フロー、および制約は以下の節で説明する通り異なります。どの方法が使用されるかは、CDM の実装と本仕様の要件(特に以下の要件)の適用によって決まります。
distinctiveIdentifier
は、Distinctive Identifiers および
Distinctive Permanent
Identifiers が個体化を含め使用できるかどうかを制御します。具体的には、そのような識別子は、distinctiveIdentifier
メンバーの値が "required" の場合にのみ使用され得ます。
Direct Individualization は CDM とオリジンやアプリケーションに依存しないサーバーとの間で行われます。サーバーはオリジン非依存ですが、個体化の結果により CDM は本仕様の他の要件に従ってオリジン固有の識別子を提供できるようになります。このプロセスはユーザーエージェントによって実行されなければならず(MUST)、本仕様で定義された API を使用してはなりません(MUST NOT)。
例えば、このプロセスはクライアントデバイスを初期化したり、ユーザーエージェントまたは CDM ベンダーがホストする事前に決められたサーバーと通信して、単一のブラウジングプロファイル のための クリア可能な per-origin 識別子を取得する場合があります。その際にクライアントデバイスのDistinctive Permanent Identifier(s) や他のPermanent Identifier(s) を使用することがあります。
そのような個体化では、すべてのメッセージ交換は次を満たさなければなりません:
MUST ユーザーエージェントが扱い、ユーザーエージェントのネットワークスタックを通じてユーザーエージェントによって実行されること。
MUST NOT CDM によって直接実行されないこと。
MUST NOT 本仕様で定義された API を通じてアプリケーションに渡されたり通過したりしないこと。
MUST オリジンやアプリケーションに依存しない URL に送信されること。
MUST すべての Distinctive Identifiers と Distinctive Permanent Identifiers を暗号化すること。
MUST TLS を使用すること。
実装は、オリジン、オリジン固有またはアプリケーション固有の情報、もしくはオリジンと関連付け可能な(associable)値を中央集権的サーバーに、たとえ暗号化された形であっても公開してはなりません。そうするとユーザーやデバイスが訪れたすべてのオリジンの中央記録が作成される可能性があるためです。
App-Assisted Individualization は CDM とアプリケーション(アプリケーションが選択したサーバーを含む)の間で行われ、オリジンごとの識別子を生成します。このプロセスは本仕様で定義された API を通じて実行されなければならず(MUST)、他の通信手段を用いてはなりません(MUST NOT)。他の API の使用と同様に、このプロセスは MAY 1 つ以上の Distinctive Identifier(s) を使用することがありますが、 MUST NOT Distinctive Permanent Identifier(s) や非オリジン固有の値を使用してはなりません(たとえ暗号化された形でも)。もし処理が 1つ以上の Distinctive Identifier(s) を使用する場合、結果の識別子は定義上 Distinctive Identifier にもなります。
そのような個体化では、すべてのメッセージ交換は次を満たさなければなりません:
MUST 本仕様で定義された API を介してアプリケーションに渡されるか、アプリケーションを通して渡されること。
SHALL 関連するすべての イベントに対してメッセージ種別 "messageindividualization-request"
を使用すること。
MUST NOT ユーザーエージェントによって実行されないこと。
MUST NOT CDM によって直接実行されないこと。
MUST NOT Distinctive Permanent Identifier(s) を含んだり使用したりしないこと。
MUST NOT 非オリジン固有のクライアント情報を含んではならないこと。
MUST 識別子要件 に従うこと。
これには origin と profile ごとに一意であること、クリア可能であること、および必要に応じて暗号化することが含まれます。
MUST NOT 実行可能なコードを CDM に提供してはならないこと。
関連付け可能(associable) な値、たとえば Distinctive Identifier(s) がプロセスで使用される場合、実装はたとえ暗号化された形であってもオリジンやオリジン固有、アプリケーション固有の情報、あるいはオリジンと関連付け可能な(associable) 値を中央サーバーに公開してはなりません。これによりユーザーやデバイスが訪れたすべてのオリジンの中央記録が作成される可能性があるためです。
適切な注意を払えば、そのような個体化は Direct Individualization よりも良好なプライバシーを提供することがありますが、Distinctive Identifier(s) を使用しない モデルほどではありません。そのような設計の利点を保持し、他のプライバシー問題を導入しないために、こうした実装やそれをサポートするアプリケーションは、個体化メッセージを中央サーバーやアプリケーション作成者が制御していない他のサーバーに先送りしたり委任したりすることを避けるべきです(SHOULD)。
実装は各 MediaKeySession オブジェクトで複数の鍵をサポートしなければなりません(MUST)。
複数の鍵をどのようにサポートするかの仕組みは実装の詳細ですが、アプリケーションおよび本仕様で定義された API から見て透明でなければなりません(MUST)。
実装は再生中の鍵間のシームレスな切替をサポートしなければなりません(MUST)。これには同一の MediaKeySession 内の鍵と、別の MediaKeySession オブジェクトにある鍵の両方が含まれます。
実装はサポートする任意の Initialization Data Type で生成されたライセンスを任意のコンテンツタイプで使用できるようにすることが SHOULD です。
そうでない場合、requestMediaKeySystemAccess()
アルゴリズムは、例えば MediaKeySystemConfiguration
のうちの一つが、initDataTypes
のいずれかがある videoCapabilities
と互換性がないとして拒否する可能性があります。
サポートされるコンテナに現れる可能性のある任意のサポートされた Initialization Data Type について、ユーザーエージェントはそれらのコンテナからその種の Initialization Data を抽出することを MUST サポートしなければなりません(initdata-encountered を参照)。
言い換えれば、ある Initialization Data Type のサポートを示すことは、CDM がライセンス要求を生成することをサポートすることと、コンテナ固有の型についてはユーザーエージェントがそのコンテナから抽出できることの両方を意味します。ただし、これは実装が任意のサポートされる Initialization Data を任意のサポートされるコンテンツタイプから解析できなければならない、という意味ではありません。
本節は本仕様の実装がサポートすべきコンテンツ(media resource)の特性を定義します。
メディアコンテナは暗号化されていてはならない(MUST
NOT)。本仕様はユーザーエージェントがメディアデータを復号することなしにメディアコンテナを解析できることに依存します。これには Encrypted Block
Encountered や Initialization Data Encountered
アルゴリズム、および HTMLMediaElement
の標準的な機能(例えば seeking)のサポートが含まれます。
すべてのトラックを含む Media resources は、コンテナ固有の「共通暗号化(common encryption)」仕様に従って暗号化およびパッケージ化される必要があります(MUST)。これにより鍵が提供されたときにコンテンツを完全に規定された互換的な方法で復号できるようになります。
Encrypted Media Extensions Stream Format Registry [EME-STREAM-REGISTRY] はそのようなストリーム形式への参照を提供します。
字幕、記述音声、トランスクリプトなどのインバンドのサポートコンテンツは暗号化されるべきではありません(SHOULD NOT)。
そのようなトラックの復号 — 特にユーザーエージェントに返せる形での復号 — は一般に実装でサポートされていません。したがって、そのようなトラックを暗号化すると、ユーザーエージェントの実装でアクセシビリティ機能に広く利用されることが妨げられます。
アクセシビリティ情報が利用可能な形で提供されることを確実にするために、インバンドのサポートコンテンツの暗号化をサポートする実装については: a) CDM は復号済みデータをユーザーエージェントに提供しなければならず(MUST)、b) ユーザーエージェントはそれを同等の非暗号化サポートコンテンツと同様に処理しなければなりません(例えば timed text tracks として公開するなど)(MUST)。
すべてのユーザーエージェントは MUST このセクションで説明される共通の キーシステム をサポートしなければなりません。
これは、完全にオープンソースであるユーザーエージェントを含め、すべてのユーザーエージェントでサポートが保証される共通の基本機能レベルが存在することを保証します。したがって、基本的な復号のみを必要とするコンテンツ提供者は、任意のコンテンツ保護プロバイダーと連携することなく、すべてのプラットフォームで動作する簡単なアプリケーションを構築できます。
"org.w3.clearkey" の キーシステム
は、平文のクリア(暗号化されていない)キーを使用してソースを復号します。追加のクライアント側コンテンツ保護は不要です。本 キーシステム は以下に記述します。
以下は クリアキー が キーシステム )固有の機能をどのようにサポートするかの説明です:
encryptionScheme:
実装は MUST
スキームをサポートし、他のスキームをサポートしてもよい(MAY)。
"cenc"
robustness:
空文字列のみがサポートされます。
distinctiveIdentifier:
"required"
はサポートされません。
persistentState:
アプリケーションが非 "temporary"
セッションを作成するつもりでない限り、"required"
ではありません。
"persistent-license"
MediaKeySessionType:
実装はこのタイプをサポートしてもよい(MAY)。
setServerCertificate()
メソッド: サポートされません。
getStatusForPolicy()
メソッド: 実装は常にプロミスを "usable"
と解決すべきです。
setMediaKeys()
メソッド: 実装は MediaKeys オブジェクトを複数の
HTMLMediaElement
に関連付けることをサポートしてもよい(MAY)。
以下は クリアキー が キーシステム 固有の動作をどのように実装するかの説明です:
generateRequest()
アルゴリズム:
生成される message は License Request Format に記載されたとおり UTF-8 でエンコードされた JSON オブジェクトです。
リクエストは sanitized init data からキーIDを抽出することによって生成されます。
"type" メンバの値は sessionType パラメータの値です。
sessionId 属性は 32
ビット整数で表現可能な数値です。
expiration 属性は常に
NaN です。
update()
アルゴリズム:
response パラメータは License Format に記載された JWK Set、または License Release Acknowledgement Format に記載された UTF-8 でエンコードされた JSON オブジェクトのいずれかです。
前者の場合、少なくとも音声/映像タイプに対して有効な長さの少なくとも一つの有効な JWK キーを含む有効な JWK Set でない場合、sanitized response は無効と見なされます。後者の場合、sanitized response は有効な JSON オブジェクトでない場合に無効と見なされます。
タイプが "persistent-license"
のセッションに対しては、
remove()
アルゴリズムにおいて、record of license destruction を反映する message は License Release Format に記載されたとおり UTF-8 でエンコードされた
JSON オブジェクトです。
keyStatuses 属性は最初、update()
によって提供されたすべてのキーID を含み、それらのステータスは "usable"
です。remove()
アルゴリズムが実行されると、keyStatuses
属性は空のリストに設定されます。
Initialization Data:
実装は登録された Initialization Data Types [EME-INITDATA-REGISTRY]
の任意の組み合わせをサポートしてもよい(MAY)。実装は "keyids" タイプ [EME-INITDATA-KEYIDS]
や、ユーザーエージェントがサポートするコンテンツタイプに適した他のタイプをサポートすることが推奨されます(SHOULD)。
本節では、 イベントの message
属性を通じてアプリケーションに提供されるライセンス要求のフォーマットについて説明します。
message
フォーマットは以下のメンバーを含む JSON オブジェクトです:
MediaKeySessionType。
ArrayBuffer の形で message
属性に含まれる場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8
でエンコードされます。アプリケーションは TextDecoder インターフェイスを使用して
ArrayBuffer の内容を JSON 文字列にデコードしてもよい(MAY)。
この節は規範ではありません。
以下の例は、2 つのキーID に対する一時ライセンスのライセンス要求です。(改行は読みやすさのためのものです。)
{
"kids": [
"LwVHf8JLtPrv2GUXFW2v_A",
"0DdtU9od-Bh5L3xbv0Xf_A"
],
"type": "temporary"
}
本節では、update() メソッドの
response パラメータを通じて提供されるライセンスのフォーマットについて説明します。
フォーマットは、復号に使用される対称鍵の表現を含む JSON Web Key (JWK) Set であり、JSON Web Key (JWK) 仕様 [RFC7517] に定義されます。
セット内の各 JWK について、パラメータ値は次のとおりです:
JSON オブジェクトはオプションの "type" メンバ値を持っていてもよく(MAY)、その場合は MediaKeySessionType
の値のいずれかでなければなりません(MUST)。指定されない場合、デフォルト値として "temporary" が使用されます。update() アルゴリズムはこの値を
sessionType と比較します。
update() メソッドに
ArrayBuffer として response パラメータで渡される場合、JSON 文字列は Encoding 仕様 [ENCODING]
に従って UTF-8 でエンコードされていなければなりません(MUST)。アプリケーションは TextEncoder インターフェイスを使用して
JSON 文字列をエンコードしてもよい(MAY)。
この節は規範ではありません。
以下の例は、単一の対称鍵を含む JWK Set です。(改行は読みやすさのためのものです。)
{
"keys": [{
"kty": "oct",
"k": "tQ0bJVWb6b0KPL6KtZIy_A",
"kid": "LwVHf8JLtPrv2GUXFW2v_A"
}],
"type": "temporary"
}
本節では、 イベントの message
属性を通じて提供されるライセンス解除メッセージのフォーマットについて説明します。
message
フォーマットは JSON オブジェクトです。タイプが "persistent-license"
のセッションの場合、オブジェクトは次のメンバを含める必要があります:
ArrayBuffer の形で message
属性に含まれる場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8
でエンコードされます。アプリケーションは TextDecoder インターフェイスを使用して
ArrayBuffer の内容を JSON 文字列にデコードしてもよい(MAY)。
この節は規範ではありません。
以下の例は、2 つのキーを含んでいた "persistent-license"
セッションのライセンス解除です。(改行は読みやすさのためのものです。)
{
"kids": [ "LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A" ]
}
本節では、update() メソッドの
response パラメータを通じて提供されるライセンス解除確認のフォーマットについて説明します。
フォーマットは次のメンバを含む JSON オブジェクトです:
update() メソッドに
ArrayBuffer として response パラメータで渡される場合、JSON 文字列は Encoding 仕様 [ENCODING]
に従って UTF-8 でエンコードされていなければなりません(MUST)。アプリケーションは TextEncoder インターフェイスを使用して
JSON 文字列をエンコードしてもよい(MAY)。
この節は規範ではありません。
以下の例は、2 つのキーID に対する一時ライセンスのライセンス要求です。(改行は読みやすさのためのものです。)
{
"kids": [
"LwVHf8JLtPrv2GUXFW2v_A",
"0DdtU9od-Bh5L3xbv0Xf_A"
]
}
この節は規範ではありません。
base64url とそれを扱う方法の詳細については、"Base64url Encoding" 用語定義および "Notes on implementing base64url encoding without padding" を [RFC7515] で参照してください。具体的には '=' パディングは存在せず、文字 '-' および '_' はそれぞれ '+' および '/' の代わりに使用されなければなりません(MUST)。
ユーザーエージェントと Key System の実装は MUST、
メディアデータ、Initialization Data、update() に渡されるデータ、ライセンス、
鍵データ、およびアプリケーションから提供されるその他すべてのデータを、信頼できないコンテンツかつ潜在的な攻撃ベクターとして考慮しなければなりません。これらは関連する脅威を軽減するために適切な安全策を講じ、当該データを安全に解析・復号などするよう注意を払う
MUST があります。ユーザーエージェントは SHOULD
データを CDM に渡す前に検証するべきです。
このような検証は、特に CDM が例えば DOM と同じ(サンドボックス化された)コンテキストで実行されない場合に重要です。
実装は MUST NOT として、アクティブコンテンツやアプリケーションの制御フローに影響を与える受動的なコンテンツを返してはなりません。
例えば、初期化データのようなメディアデータ由来の情報から得られた URL 等を公開するのは安全ではありません。これは
初期化データ が
generateRequest()
に渡される場合などに該当します。
使用する URL はアプリケーション側で決定する必要があります。messageType 属性は、
アプリケーションが該当する場合に一連の URL の中から選択するために使用できます。
ユーザーエージェントは、利用者に安全なウェブ閲覧手段を提供する責任があります。この責任は、サードパーティ由来の機能を含め、ユーザーエージェントが使用するいかなる機能にも適用されます。ユーザーエージェントの実装者は MUST、Key System 実装者から統合に伴うセキュリティ上の影響を適切に評価できるだけの十分な情報を入手しなければなりません。ユーザーエージェントの実装者は MUST、CDM 実装が利用者に対するセキュリティを提供するために、ユーザーエージェントが必要とする十分な制御を提供および/またはサポートすることを確保しなければなりません。ユーザーエージェントの実装者は MUST、CDM 実装がセキュリティ脆弱性発見時に迅速かつ積極的に更新されることを確実にしなければなりません。
完全にサンドボックス化されておらず、またはプラットフォーム機能を使用する CDM 実装が悪用されると、攻撃者がOSやプラットフォームの機能にアクセスしたり、権限を昇格させたり(例:systemやrootとして実行する)、ドライバー、カーネル、ファームウェア、ハードウェア等にアクセスしたりする可能性があります。そのような機能、ソフトウェア、ハードウェアは、敵対的なソフトウェアやウェブベースの攻撃に対して堅牢に設計されていない場合があり、特にユーザーエージェントと比べてセキュリティ修正が適用されない、あるいは更新が遅いことがあります。CDM 実装におけるセキュリティ脆弱性の修正が不足している、頻度が低い、または遅いことはリスクを高めます。そのような CDM 実装とそれらを公開する UAs は、セキュリティのあらゆる領域、例えば すべてのデータ の解析を含め、MUST 特に注意を払わなければなりません。
ユーザーエージェントは、クライアントの OS、プラットフォームおよび/またはハードウェアの一部であるか、あるいはそれらによって提供される CDM や基盤となる機構を使用する場合、特に入念であるべきです。
ユーザーエージェントが十分にサンドボックス化できない、またはその他の方法で十分に保護できない Key System をサポートすることを選択した場合、ユーザーエージェントは SHOULD として ユーザーに十分な情報を提供し、明示的な同意を得るべきです。
未認証のオリジンに権限を与えることは、ネットワーク攻撃者の存在下では任意のオリジンに権限を与えることと同等です。永続化された同意の悪用を参照してください。
このセクションは非規範的です。
想定されるネットワーク攻撃とその影響には次のようなものがあります:
DNS スプーフィング攻撃:あるホストが特定のドメイン(オリジン)を主張していても、 実際にそのドメインのものであるとは保証できません。
受動的ネットワーク攻撃:クライアントとサーバー間で送受信されるデータ(Distinctive Identifiers や Distinctive Permanent Identifiers を含む)が 他の主体によって閲覧されないことを保証できません。ユーザー追跡を参照してください。
能動的ネットワーク攻撃:ページに対して追加のスクリプトや iframe が注入されないことを保証できません(本仕様の API を正当に使用するページも、使用しないページも含む)。結果として:
本仕様で定義された API への呼び出しは任意のページに注入され得ます。
正当な目的でこれらの API を使用しているページからの呼び出しは改変され得ます。要求される機能の変更、呼び出しの変更や追加、データの変更や注入などが含まれます。入力データに対する攻撃と脆弱性も参照してください。
クライアントとサーバー間で送受信されるデータ(Distinctive Identifiers や Distinctive Permanent Identifiers を含む)が 他の主体によって閲覧および/または変更され得ます。ユーザー追跡を参照してください。
永続化された同意の悪用:本仕様で定義された API の使用を要求するホストが、 ユーザーが以前に同意を与えたホストと同一であると保証できない場合があります。結果として、未認証のオリジンに権限を与えることは、 ネットワーク攻撃者の存在下では任意のオリジンに権限を与えることと同等になります。
次の技術はリスクを緩和するのに役立ちます:
TLS を使用するアプリケーションは、ユーザー、そのユーザーの代理で動作するソフトウェア、そして同じドメインであることを示す証明書を持つ TLS を使用する他のページだけがそのアプリケーションと相互作用できることを確信できます。さらに、オリジン 固有の権限と安全なオリジンを組み合わせることで、 アプリケーションに付与された権限がネットワーク攻撃者に悪用されることを防げます。
本仕様で定義された API は安全なコンテキストでのみ公開されます。Secure Origin and Transport も参照してください。
ユーザーエージェントは MUST として混在コンテンツ [MIXED-CONTENT] を適切に扱い、「ブロッカブルコンテンツ」 [MIXED-CONTENT] をブロックして、 不安全なコンテンツへの露出を避ける必要があります。こうした露出は TLS の利用など他の緩和策を損なう可能性があります。
ユーザーエージェントは MAY として、さらにセキュリティを向上させるために「オプションでブロック可能なコンテンツ」も含めて すべての混在コンテンツをブロックすることを選択できます。これにより、信頼できないメディアデータが CDM に渡されるのを防げます(CDM に対する攻撃と脆弱性を参照)。
ユーザーエージェントは SHOULD として、ユーザーに十分な情報を提供し、明示的な同意を得るべきです。 これは、DOM コンテンツなど他のユーザーエージェント機能よりも大きなセキュリティ上の懸念を提示する可能性がある Key System に よるアクセス要求の前に行うべきです。
そのようなメカニズムは、正当な使用が後に悪意あるアクセスを可能にすることを避けるために、MUST として オリジン ごとに行われるべきであり、 また MUST としてブラウジングプロファイルごとに行われる必要があります(browsing profile を参照)。
本仕様で定義された API を安全なコンテキストに制限することにより、ネットワーク攻撃者が 未認証オリジンに付与された権限を悪用できないことが保証されます。永続化された同意の悪用も参照してください。
このセクションは非規範的です。
悪意のあるページは、正当なアプリケーションを iframe にホストして攻撃を隠蔽したり、使用元を偽装してユーザーに正当なコンテンツプロバイダからの利用であると思わせたりする可能性があります。 これは、セキュリティや プライバシーの理由 でユーザーに情報提供や同意を要求する実装にとって特に重要です。 ネットワーク攻撃 に加えて、攻撃者は iframe に正当な API 利用をホストすることで本仕様で定義された API の正当な利用を悪用しようとする可能性があります。 正当なアプリケーションが操作を行うことで、攻撃者は既存の付与済み権限(またはホワイトリスト)を再利用したり、正当なリクエストや使用に見せかけたりできます。
ユーザーに情報を提供したり同意を要求したりするユーザーエージェントは、セキュリティや プライバシーの理由 を含め、 UI と同意の永続化をトップレベルの オリジン と 本仕様で API を使用しているオリジンの組み合わせに基づいて行うべきです。これにより、リクエストを行っている主要なドキュメントがユーザーに示され、 ある(正当な)組み合わせに対して権限を永続化しても、悪意ある使用が見逃されないようにできます。
作者は SHOULD として、他の主体が自分のアプリケーションを iframe 内でホストすることを防止すべきです。
正当なアプリケーション設計上の理由でホストされる必要があるアプリケーションは、ホスティング文書が CDM に渡されるいかなるデータ
を提供すること(本仕様の API 経由またはメディアデータとして)を許可すべきではなく、
ホスティングフレームが本仕様で定義された API を呼び出すことを許可すべきではありません。
このセクションは非規範的です。
例えば geocities.com のように一つのホスト名を共有する異なる作者は、すべて一つの オリジン
を共有します。ユーザーエージェントは
パス名による API へのアクセス制限機能を提供していません。
共有ホストで本仕様の API を使用すると、ユーザーエージェントが実装するオリジンベースのセキュリティおよびプライバシー緩和策が損なわれます。 例えば、オリジンごとの Distinctive Identifiers は一つのホスト名上のすべての作者と共有され、永続化されたデータはホスト上の任意の作者によってアクセスおよび操作され得ます。 後者は特に、例えばそのデータの変更や削除によってユーザーの特定コンテンツに対する権利が失われる可能性がある場合に重要です。
たとえユーザーエージェントがパス制限機能を提供していたとしても、通常の DOM スクリプトセキュリティモデルにより、その保護は簡単に回避され、任意のパスからデータにアクセスされ得ます。
したがって、共有ホストの作者は本仕様で定義された API の使用を避けることが RECOMMENDED されます。なぜならそれによりユーザーエージェント側のオリジンベースのセキュリティおよびプライバシー緩和策が損なわれるためです。
ユーザーのデバイス上での Key System(s) の存在または使用は、多くのプライバシー上の問題を引き起こします。これらは主に二つのカテゴリに分けられます:(a) EME インターフェイス自体または Key System メッセージ内で開示され得るユーザー固有の情報、および (b) ユーザーのデバイス上に永続的に保存され得るユーザー固有の情報。
ユーザーエージェントは MUST として、ユーザーが自身のプライバシーを適切に制御できるようにする責任を負わなければなりません。ユーザーエージェントはサードパーティの CDM 実装と統合する可能性があるため、 CDM 実装者は、ユーザーエージェント実装者がユーザーのプライバシーを制御できるように適切な技術を実装するために十分な情報と制御手段を提供しなければなりません。以下に示す技術を含むがこれに限定されません。
EME および Key Systems によって開示される情報に関する懸念は二つのカテゴリに分かれます:(a) ユーザーエージェントやデバイスのフィンガープリント化の可能性に寄与し得る非特定情報に関する懸念、(b) 直接的に ユーザー追跡 に使用され得るユーザー固有の情報に関する懸念。
悪意のあるアプリケーションは、サポートされている Key Systems の検出や列挙、関連情報の取得によってユーザーやユーザーエージェントをフィンガープリント化できる可能性があります。適切なオリジン保護が提供されない場合、これには訪問したサイトの検出やそれらのサイトのために保存された情報の検出が含まれ得ます。特に、Key Systems は MUST として、キーやその他のデータを origins 間で共有してはなりません。
このセクションは非規範的です。
特にユーザーエージェントの外部に実装された CDM は、ウェブプラットフォームと同じ基本的な隔離を持たない場合があります。オリジン間での情報漏洩を避けるための措置を講じることが重要です。これにはメモリ内および保存データの両方が含まれます。これを怠ると、プライベートブラウジングセッションへの情報漏洩、browsing profiles 間(OS のユーザーアカウントを含む)や、異なるブラウザやアプリケーション間での漏洩につながる可能性があります。
このような問題を避けるために、ユーザーエージェントおよび CDM 実装は MUST 次のことを確実にする必要があります:
CDMs は、CDM インスタンスの概念を持ち、そのインスタンスが一対一で
MediaKeys オブジェクトに関連付けられていること。
キー、ライセンス、その他のセッションデータ、およびセッションの存在は、セッションを作成した
MediaKeys オブジェクトに関連付けられた
CDM インスタンスに限定されること。
セッションデータは、そのセッションを作成した
MediaKeys オブジェクトに関連付けられていない
メディア要素と共有されないこと。これには、例えばセッションのキーが、当該セッションを作成した
mediaKeys 属性が同じ
MediaKeys オブジェクトでない
メディア要素によって読み込まれたコンテンツの復号に使用されてはならないこと(MUST)。
適用される場合、永続化されたセッションデータは origin ごとに保存されること。
読み込めるのは要求元の origin によって保存されたデータのみであること。
CDM から、本仕様で明示的に記述されているものでもなく、他のウェブプラットフォームの API を通じてページが利用できるものでもない情報を、ユーザーの許可なしに抽出、導出、推測することは不可能であること。これは、CDM メッセージを含め、クライアントデバイス外部やアプリケーションに露出されるあらゆる情報に適用されます。
この要件で対象となる情報の種類には、以下を含むがこれらに限定されません:
位置情報(ジオロケーションを含む)
Distinctive Identifiers 以外の認証情報または識別子
OS アカウント名およびその他の潜在的な PII
類似の情報を含む可能性のあるローカルディレクトリパス
ローカルネットワークの詳細(例:デバイスのローカル IP アドレス)
ローカルデバイス(Bluetooth、USB、ユーザーメディアなどを含むがこれらに限定されない)
本仕様で定義された API に関連付けられていない、またはそれらの API により保存されていないユーザー状態
このセクションは非規範的です。
サードパーティのホスト(またはコンテンツを複数のサイトに配信できる広告主のような任意のエンティティ)は、Distinctive Identifier やライセンス、鍵、キーID、または records of license destruction を含む永続的なデータを、CDM によって、あるいはその代理で保存してユーザーを複数のセッション(origins や browsing profiles を含む)にわたって追跡し、ユーザーの活動や興味のプロファイルを構築する可能性があります。そのような追跡はウェブプラットフォームが提供するプライバシー保護を損ない、たとえば通常は不可能な高度にターゲティングされた広告を可能にするおそれがあります。ユーザーの実際の身元を把握しているサイト(認証済み資格情報を要求するコンテンツプロバイダや EC サイトなど)と結びつくと、純粋に匿名のウェブ利用しかない世界と比べて、抑圧的な集団が個人をより高精度に標的にすることを許してしまう可能性があります。
この仕様の API の実装を通じて取得され得るユーザーまたはクライアント固有の情報には次のものが含まれます:
訪問した origins(保存データやメモリ内データ、権限などを通じて)
表示したコンテンツ(保存されたまたはメモリ内のライセンス、鍵、キーID、records of license destruction 等を通じて)
この仕様は特に懸念を提示します。なぜなら、そのような情報は一般にユーザーエージェントの外部(および関連する browsing profile の保存)に保存されることが多く、しばしば CDM に保存されるためです。
ライセンスや records of license destruction の内容が Key System 固有であり、キーID が任意の値を含み得るため、これらのデータ項目はユーザーを特定する情報を保存するために悪用される可能性があります。
Key Systems は、デバイスまたはデバイスのユーザーのための永続的または半永続的な識別子をアクセスまたは作成する場合があります。場合によっては、これらの識別子は特定のデバイスに対して安全に結び付けられていることがあります。これらの識別子が Key System メッセージ内に存在する場合、デバイスやユーザーが追跡される可能性があります。以下の軽減策が適用されない場合、これは時間を通じたユーザー/デバイスの追跡や特定のデバイスの複数ユーザーの結び付けを含む可能性があります。
そのような識別子、特にクリアできないもの、非 origin 固有のもの、または permanent なものは、クッキー [COOKIES] や URL に埋め込まれたセッション識別子のような既存の手法がもたらす追跡影響を超える点に注意が必要です。
軽減されない場合、そのような追跡は Key System の設計に応じて三つの形態を取る可能性があります:
いずれの場合でも、そのような識別子は Key System を完全にサポートするサイトおよび/またはサーバー(したがって Key System メッセージを解釈できる)に対して利用可能となり、これらのサイトによる追跡を可能にすることが予想されます。
Key Systems によって公開される識別子が origin 固有でない場合、同じく Key System を完全にサポートする二つのサイトおよび/またはサーバーが共謀してユーザーを追跡する可能性があります。
あるコンテンツ項目に対する初期の Key System メッセージの一部が時間とともに変わらず、かつユーザー識別子に依存するような一貫した方法でユーザー識別子から導出された情報が Key System メッセージに含まれる場合、この情報は任意のアプリケーションによってデバイスやユーザーを時間を通じて追跡するために利用され得ます。
さらに、ある Key System が鍵やその他のデータを保存して origin 間で再利用できることを許す場合、二つの origin が共謀して共通の鍵にアクセスできるかどうかを記録することで一意のユーザーを追跡することが可能になるかもしれません。
最後に、Key Systems のユーザー制御のためのユーザーインターフェースが、HTTP セッション Cookie [COOKIES] や永続ストレージ内のデータと別々にデータを表示する場合、ユーザーはサイトの許可設定を変更したりデータを一方だけで削除したりする可能性が高くなります。これによりサイトは各種機能を互いに冗長なバックアップとして利用できるようになり、ユーザーのプライバシー保護の試みを無効化してしまいます。
サイトやその他の第三者によるユーザー追跡の可能性に加えて、ユーザーエージェントの実装者、CDM ベンダー、またはデバイスベンダーが、ユーザーが訪れる本仕様で定義された API を用いるサイトなど、ユーザーの活動や興味のプロファイルを構築する可能性があります。そのような追跡は、特にオリジンの分離に関連するウェブプラットフォームの残りのプライバシー保護を損ないます。
Distinctive Identifiers のような識別子は、CDM ベンダーが運営または提供するサーバーから、例えば individualization プロセスを通じて取得され得ます。そのプロセスには、Distinctive Permanent Identifier(s) を含むクライアント識別子の提供が含まれる場合があります。オリジンごとの識別子を生成するために、オリジンを表す値も提供され得ます。
そのような実装では、CDM ベンダーが、訪問したオリジンの数や新しい識別子が必要になった回数など、ユーザーの活動を追跡できる可能性があります。オリジンやオリジンと associable な値が識別子要求に提供されると、CDM ベンダーはユーザーが訪れたサイトやデバイスのユーザーを追跡できる可能性があります。
次のセクションでは、ユーザーの同意なしに追跡されるリスクを軽減する技術について説明します。
Key System 実装は、可能な限り Distinctive Identifiers および Distinctive Permanent Identifiers を使用することを避けるべきであり、 実装の堅牢性に意味のある寄与がある場合にのみ使用すべきです。詳細は Limit or Avoid use of Distinctive Identifiers and Permanent Identifiers を参照してください。
実装は MUST NOT として、Distinctive Permanent Identifiers をアプリケーションやオリジンに公開してはなりません。
Distinctive Identifiers を含む Key System メッセージは、タイムスタンプまたはノンスと共に暗号化され、 常に異なる Key System メッセージになるようにしなければなりません(MUST)。 これにより、Key System メッセージを用いた追跡は、その Key System を完全にサポートするサーバーによる場合を除き防止されます。詳細は Encrypt Identifiers を参照してください。
ユーザーエージェントは SHOULD として、Distinctive Identifiers や Key Systems によって保存されたデータの存在を、 HTTP セッションクッキー [COOKIES] と強く結びつけてユーザーに提示し、 「すべてのデータを削除」に含め、同じ UI 場所で表示すべきです。これによりユーザーがこれらの識別子を慎重に扱うことを促せます。ユーザーエージェントは SHOULD として、 Incomplete Clearing of Data を回避するようユーザーを支援すべきです。
origin(s) やオリジンに 関連付け可能な 値を、当該オリジンに無関係な individualization サーバーやその他の主体に提供してはなりません。実装がそのようなプロセスを使用する場合は、Individualization セクションの要件と推奨に従ってください。
アプリケーションに公開されるすべての Distinctive Values について、実装は各 origin および browsing profile ごとに異なる、アプリケーションから関連付けできない 値を使用しなければなりません(MUST)。詳細は 8.4.1 Use Per-Origin Per-Profile Values を参照してください。
これは特に Distinctive Identifier(s) を使用する 実装にとって重要です。8.5.3 Use Per-Origin Per-Profile Identifiers を参照してください。
アプリケーションやライセンスサーバーから見えてメッセージや挙動に影響を与え得る CDM によって使用される任意のデータは、origin および browsing profile ごとに分割される必要があり、かつプライベートブラウジングセッションへ漏洩してはならない(MUST)。これはメモリ上および永続化されたデータの両方に適用されます。具体的には、セッションデータ、ライセンス、キー、及びオリジンごとの識別子は MUST としてオリジンおよび browsing profile ごとに分離されるべきです。詳細は 8.3.1 Use origin-specific and browsing profile-specific Key System storage および 8.4.1 Use Per-Origin Per-Profile Values を参照してください。
ユーザーエージェントは MUST として、Distinctive Identifiers を含む任意の永続データをユーザーが消去できる機能を提供しなければなりません。詳細は Allow Persistent Data to Be Cleared を参照してください。
ユーザーエージェントは MAY として、ユーザーが設定可能な方法で、一定期間後に Distinctive Identifiers やその他の Key System データを自動的に削除することができます。
例えば、ユーザーエージェントはこれらのデータをセッションのみのストレージとして保存し、データへアクセス可能なすべての閲覧コンテキストが閉じられたときに削除するよう設定できるでしょう。
これにより、サイトはユーザーがサイト自身で認証した場合(購入やサービスへのサインインなど)にのみ複数セッションにわたって追跡できるようになり、追跡能力が制限されます。
しかしながら、こうした有効期限は、特に購入やレンタルしたコンテンツへのユーザーのアクセスを危険にさらす可能性があるため、ユーザーがその影響を十分に理解していない場合には注意が必要です。
ユーザーエージェントは MAY として、Key
Systems やその機能へのアクセスを、閲覧コンテキストのトップレベル Document の origin
に起源するスクリプトに限定することができます。例えば、requestMediaKeySystemAccess()
は、
iframe 内で実行される他のオリジンのページに対して特定の構成の要求を拒否する場合があります。
ユーザーエージェントは MUST として、Distinctive Identifier(s) または Distinctive Permanent Identifier(s) を使用する 前に、 ユーザーが十分に情報を与えられ、明示的な同意を与えることを確実にしなければなりません。
そのようなメカニズムは、正当な使用がその後の悪意あるアクセスを可能にしないようにするために、MUST としてオリジンごとに行われ、かつ MUST として browsing profile ごとに行われなければなりません。
本仕様で定義された API を安全なコンテキストに限定することは、ネットワーク攻撃者が未認証オリジンに付与された権限を悪用できないことを保証します。abuse of persisted consent も参照してください。
ユーザーエージェントは SHOULD として、Key System の有効化有無や、Key System による Distinctive Identifier(s) / Distinctive Permanent Identifier(s) の使用 を有効にするかどうかのグローバルな制御をユーザーに提供すべきです(Key System が対応している場合)。ユーザーエージェントは SHOULD として、Incomplete Clearing of Data を回避するようユーザーを支援すべきです。
ユーザーエージェントは MAY として、サイトが各 Key System(および/または特定の機能)を使用する前に、ユーザーが明示的にアクセスを許可することを要求することができます。ユーザーエージェントは SHOULD として、ユーザーがこの許可を一時的または恒久的に取り消せるようにすべきです。
ユーザーエージェントは MAY として、ユーザーがオリジンや Key Systems のブラックリストを共有できるようにすることができます。これにより、コミュニティが協力してプライバシーを保護することが可能になります。
これらの提案は、本仕様で定義された API を用いたユーザー追跡の単純な利用を防ぎますが、完全に遮断するものではありません。単一のオリジン内では、サイトはセッション中にユーザーを追跡し続け、得られたすべての情報をサイトが取得した識別情報(名前、クレジットカード番号、住所など)とともに第三者に渡すことが可能です。第三者が複数のサイトと協力してそのような情報を取得し、識別子が オリジンおよびプロファイルごとに一意でない 場合、プロファイルは依然として作成され得ます。
This section is non-normative.
Key Systems はユーザーのデバイス上に情報を保存する可能性があり、またユーザーエージェントが Key Systems のために情報を保存する場合があります。潜在的には、これは同じデバイスを使用する別のユーザーに対して、特定の origins が特定の Key System(つまり訪問したサイト)を使用したこと、あるいは Key System を使って復号されたコンテンツそのものに関する情報を明らかにする可能性があります。
もしあるオリジンによって保存された情報が他のオリジンのための Key System の動作に影響を与えるならば、あるサイトでユーザーが訪問したサイトや閲覧したコンテンツが別の(潜在的に悪意のある)サイトに明らかになる可能性があります。
クライアントデバイス上のある browsing profile のために保存された情報が、他の browsing profiles やブラウザのための Key System の動作に影響を与える場合、あるプロファイルで訪問したサイトや閲覧したコンテンツが別の browsing profile によって明らかにされたり相関可能になったりする可能性があり、これには異なる OS のユーザーアカウントや別のブラウザも含まれ得ます。
これらの懸念を緩和するための要件は、8.3 Persistent Data に定義されています。
This section is non-normative.
ユーザーが Distinctive Identifiers や保存されたデータを消去したり、Key System を無効化しようとする試みは、同時にすべての関連データや機能、クッキー [COOKIES] や他のサイトデータが消去・無効化されない場合に無効化される可能性があります。例えば:
ユーザーがクッキーや他の永続ストレージを消去しても、Distinctive Identifiers や Key Systems が保存したデータを同時に消去しない場合、サイトはこれらの機能を互いの冗長なバックアップとして使用してユーザーの試みを無効化できます。
ユーザーが Distinctive Identifiers を消去しても、Key Systems(永続セッションを含む)やクッキーおよび他の永続ストレージを同時に消去しない場合、サイトは残されたデータを使って古い識別子と新しい識別子を関連付けることができます。
ユーザーが特定の origin のために Key System を無効化しても、クッキーや他の永続ストレージを同時に消去しない場合、サイトは残された機能を使ってユーザーの試みを無効化できます。
ユーザーが Key System を無効化した後に再度有効化する場合、クッキーや他の永続ストレージ、Distinctive Identifiers、および Key Systems が保存したデータを同時に消去していなければ、サイトは無効化前のデータと再有効化後のデータや挙動を関連付けられる可能性があります。
これらの懸念を緩和するための推奨事項は、8.3 Persistent Data に定義されています。
ユーザーエージェントは、ユーザーの匿名性を保持したり閲覧履歴の記録がクライアント上に残らないようにすることを意図したモード(例:プライベートブラウジング)をサポートする場合があります。前節で議論したプライバシー上の懸念は、こうしたモードを利用するユーザーにとって特に重要になる可能性があります。
そのようなモードをサポートするユーザーエージェント実装者は、これらのモードで Key Systems へのアクセスを無効にすべきかどうかを慎重に検討することが SHOULD されます。例えば、そのようなモードは、MediaKeySystemAccess
オブジェクトの作成を禁止することがあり得ます。特に persistentState や
distinctiveIdentifier
をサポートまたは使用する構成を禁止する場合があります(これは CDM 実装の一部として、またはアプリケーションがそれらを "required"
と指定した場合のいずれでもあり得ます)。実装がそのような作成を禁止しない場合、使用を許可する前に当該モードの期待されるプライバシー特性に対する影響と潜在的な結果をユーザーに通知することが SHOULD されます。
本仕様で定義された API はセキュアなオリジン上でのみサポートされており、前節で議論した情報を保護します。識別子はさらに Encrypt Identifiers に規定されたとおりに暗号化されます。
アプリケーション(およびそれらが使用するサーバーを含む)は、CDM からのデータやメッセージを含むすべてのトラフィックについて、すべて安全なトランスポートを使用することが SHOULD されます。これには
イベントから渡される全データや、messageupdate()
へのデータなどが含まれますが、これらに限定されません。
すべてのユーザーエージェントは、ユーザーエージェントやアプリケーションがセキュアなオリジンと通信を強制したい場合に不安全なコンテンツや輸送への露出を避けるために、混在コンテンツ [MIXED-CONTENT] を適切に扱わなければなりません(MUST)。
非規範としてマークされた節のほかに、本仕様書のすべての作成ガイドライン、図、例、および注は非規範です。それ以外のすべてが規範です。
本ドキュメント内のキーワード MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULD, および SHOULD NOT は、すべて大文字で表示されている場合に限り、BCP 14 [RFC2119] [RFC8174] に記載されたとおりに解釈されます。
このセクションは非規範的です。
この節は、提案された拡張機能を用いたさまざまなユースケースに対する例示的な解決策を含んでいます。これらが唯一の解決策というわけではありません。例では video 要素を使用していますが、同じことはすべてのメディア要素に当てはまります。同期 XHR の使用のような場合には、拡張に焦点を当てるために例を簡略化しています。
この単純な例では、ソースファイルと平文ライセンス(clear-text license)がページ内にハードコードされています。作成されるセッションは常に一つだけです。
<script>
function onLoad() {
var video = document.getElementById('video');
if (!video.mediaKeys) {
navigator.requestMediaKeySystemAccess('org.w3.clearkey', [
{ initDataTypes: ['webm'],
videoCapabilities: [{ contentType: 'video/webm; codecs="vp8"' }] }
]).then(
function(keySystemAccess) {
var promise = keySystemAccess.createMediaKeys();
promise.catch(
console.error.bind(console, 'Unable to create MediaKeys')
);
promise.then(
function(createdMediaKeys) {
return video.setMediaKeys(createdMediaKeys);
}
).catch(
console.error.bind(console, 'Unable to set MediaKeys')
);
promise.then(
function(createdMediaKeys) {
var te = new TextEncoder();
var initData = te.encode( '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}');
var keySession = createdMediaKeys.createSession();
keySession.addEventListener("message", handleMessage, false);
return keySession.generateRequest('keyids', initData);
}
).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
);
}
}
function handleMessage(event) {
var keySession = event.target;
var te = new TextEncoder();
var license = te.encode('{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"temporary"}');
keySession.update(license).catch(
console.error.bind(console, 'update() failed')
);
}
</script>
<body onload='onLoad()'>
<video src='foo.webm' autoplay id='video'></video>
</body>
この例では、Key System の中でサポートされているものを requestMediaKeySystemAccess()
メソッドで選択し、
初期化データ を メディアデータ の "encrypted"
イベントから使ってライセンス要求を生成し、適切なライセンスサーバーへ送信します。サポートされる Key System の一つは serverCertificate を使用し、これは事前に提供されます。
<script>
var licenseUrl;
var serverCertificate;
// Returns a Promise<MediaKeys>.
function createSupportedKeySystem() {
someSystemOptions = [
{ initDataTypes: ['keyids', 'webm'],
audioCapabilities: [
{ contentType: 'audio/webm; codecs="opus"' },
{ contentType: 'audio/webm; codecs="vorbis"' }
],
videoCapabilities: [
{ contentType: 'video/webm; codecs="vp9"' },
{ contentType: 'video/webm; codecs="vp8"' }
]
}
];
clearKeyOptions = [
{ initDataTypes: ['keyids', 'webm'],
audioCapabilities: [
{ contentType: 'audio/webm; codecs="opus"' },
{ contentType: 'audio/webm; codecs="vorbis"' }
],
videoCapabilities: [
{ contentType: 'video/webm; codecs="vp9"',
robustness: 'foo' },
{ contentType: 'video/webm; codecs="vp9"',
robustness: 'bar' },
{ contentType: 'video/webm; codecs="vp8"',
robustness: 'bar' },
]
}
];
return navigator.requestMediaKeySystemAccess('com.example.somesystem', someSystemOptions).then(
function(keySystemAccess) {
// Not shown:
// 1. Use both attributes of keySystemAccess.getConfiguration().audioCapabilities[0]
// and both attributes of keySystemAccess.getConfiguration().videoCapabilities[0]
// to retrieve appropriate stream(s).
// 2. Set video.src.
licenseUrl = 'https://license.example.com/getkey';
serverCertificate = new Uint8Array([ ... ]);
return keySystemAccess.createMediaKeys();
}
).catch(
function(error) {
// Try the next key system.
navigator.requestMediaKeySystemAccess('org.w3.clearkey', clearKeyOptions).then(
function(keySystemAccess) {
// Not shown:
// 1. Use keySystemAccess.getConfiguration().audioCapabilities[0].contentType
// and keySystemAccess.getConfiguration().videoCapabilities[0].contentType
// to retrieve appropriate stream(s).
// 2. Set video.src.
licenseUrl = 'https://license.example.com/clearkey/request';
return keySystemAccess.createMediaKeys();
}
);
}
).catch(
console.error.bind(console, 'Unable to instantiate a key system supporting the required combinations')
);
}
function handleInitData(event) {
var video = event.target;
if (video.mediaKeysObject === undefined) {
video.mediaKeysObject = null; // Prevent entering this path again.
video.pendingSessionData = []; // Will store all initData until the MediaKeys is ready.
createSupportedKeySystem().then(
function(createdMediaKeys) {
video.mediaKeysObject = createdMediaKeys;
if (serverCertificate)
createdMediaKeys.setServerCertificate(serverCertificate);
for (var i = 0; i < video.pendingSessionData.length; i++) {
var data = video.pendingSessionData[i];
makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData);
}
video.pendingSessionData = [];
return video.setMediaKeys(createdMediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
}
addSession(video, event.initDataType, event.initData);
}
function addSession(video, initDataType, initData) {
if (video.mediaKeysObject) {
makeNewRequest(video.mediaKeysObject, initDataType, initData);
} else {
video.pendingSessionData.push({initDataType: initDataType, initData: initData});
}
}
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession();
keySession.addEventListener("message", licenseRequestReady, false);
keySession.generateRequest(initDataType, initData).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
function licenseRequestReady(event) {
var request = event.message;
var xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = event.target;
xmlhttp.open("POST", licenseUrl);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
var license = new Uint8Array(xmlhttp.response);
xmlhttp.keySession.update(license).catch(
console.error.bind(console, 'update() failed')
);
}
}
xmlhttp.send(request);
}
</script>
<video autoplay onencrypted='handleInitData(event)'></video>
暗号化イベントを MediaKeys 初期化中に処理する必要がない場合、初期化ははるかに簡単になります。これは、Initialization Data を別の方法で提供するか、あるいは MediaKeys オブジェクト作成後にソースを設定することで達成できます。この例は後者を行います。
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See the previous example for implementations of these functions.
function createSupportedKeySystem() { ... }
function makeNewRequest(mediaKeys, initDataType, initData) { ... }
function licenseRequestReady(event) { ... }
function handleInitData(event) {
makeNewRequest(mediaKeys, event.initDataType, event.initData);
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
video.src = 'foo.webm';
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id="v" autoplay onencrypted='handleInitData(event)'></video>
これは、すべてのイベントが使用されるより完全な例です。
handleMessage() は複数回呼び出される可能性があることに注意してください。複数往復が必要な場合の update() 呼び出しへの応答としてや、Key
System がメッセージを送信するその他の理由により呼ばれることがあります。
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See previous examples for implementations of these functions.
// createSupportedKeySystem() additionally sets renewalUrl.
function createSupportedKeySystem() { ... }
function handleInitData(event) { ... }
// This replaces the implementation in the previous example.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession();
keySession.addEventListener('message', handleMessage, false);
keySession.addEventListener('keystatuseschange', handlekeyStatusesChange, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.generateRequest(initDataType, initData).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(response);
keySession.update(license).catch(
function(err) {
console.error('update() failed: ' + err);
}
);
}
function sendMessage(type, message, keySession) {
var url = licenseUrl;
if (type == "license-renewal")
url = renewalUrl;
xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = keySession;
xmlhttp.open('POST', url);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
handleMessageResponse(xmlhttp.keySession, xmlhttp.response);
}
xmlhttp.send(message);
}
function handleMessage(event) {
sendMessage(event.messageType, event.message, event.target);
}
function handlekeyStatusesChange(event) {
// Evaluate the current state using one of the map-like methods exposed by
// event.target.keyStatuses.
// For example:
event.target.keyStatuses.forEach(function(status, keyId) {
switch (status) {
case "usable":
break;
case "expired":
// Report an expired key.
break;
case "status-pending":
// The status is not yet known. Consider the key unusable until the status is updated.
break;
default:
// Do something with |keyId| and |status|.
}
})
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id='v' src='foo.webm' autoplay></video>
この例では、将来の利用のために永続的なライセンスを要求して保存します。また、後でライセンスを取得したり破棄したりするための関数も提供します。
<script>
var licenseUrl;
var serverCertificate;
var mediaKeys;
// See the previous examples for implementations of these functions.
// createSupportedKeySystem() additionally sets persistentState: "required" in each options dictionary.
function createSupportedKeySystem() { ... }
function sendMessage(message, keySession) { ... }
function handleMessage(event) { ... }
// Called if the application does not have a stored sessionId for the media resource.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession("persistent-license");
keySession.addEventListener('message', handleMessage, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.generateRequest(initDataType, initData).then(
function() {
// Store this.sessionId in the application.
}.bind(keySession)
).catch(
console.error.bind(console, 'Unable to request a persistent license')
);
}
// Called if the application has a stored sessionId for the media resource.
function loadStoredSession(mediaKeys, sessionId) {
var keySession = mediaKeys.createSession("persistent-license");
keySession.addEventListener('message', handleMessage, false);
keySession.closed.then(
function(reason) {
console.log('Session', this.sessionId, 'closed, reason', reason);
}.bind(keySession)
);
keySession.load(sessionId).then(
function(loaded) {
if (!loaded) {
console.error('No stored session with the ID ' + sessionId + ' was found.');
// The application should remove its record of |sessionId|.
return;
}
}
).catch(
console.error.bind(console, 'Unable to load or initialize the stored session with the ID ' + sessionId)
);
}
// Called when the application wants to stop using the session without removing the stored license.
function closeSession(keySession) {
keySession.close();
}
// Called when the application wants to remove the stored license.
// The stored session data has not been completely removed until the promise returned by remove() is fulfilled.
// The remove() call may initiate a series of messages to/from the server that must be completed before this occurs.
function removeStoredSession(keySession) {
keySession.remove().then(
function() {
console.log('Session ' + this.sessionId + ' removed');
// The application should remove its record of this.sessionId.
}.bind(keySession)
).catch(
console.error.bind(console, 'Failed to remove the session')
);
}
// This replaces the implementation in the previous example.
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(response);
keySession.update(license).then(
function() {
// If this was the last required message from the server, the license is
// now stored. Update the application state as appropriate.
}
).catch(
console.error.bind(console, 'update() failed')
);
}
createSupportedKeySystem().then(
function(createdMediaKeys) {
mediaKeys = createdMediaKeys;
var video = document.getElementById("v");
if (serverCertificate)
mediaKeys.setServerCertificate(serverCertificate);
return video.setMediaKeys(mediaKeys);
}
).catch(
console.error.bind(console, 'Failed to create and initialize a MediaKeys object')
);
</script>
<video id='v' src='foo.webm' autoplay></video>
ライセンスに HDCP ポリシーが含まれるメディアがある場合、アプリケーションは事前フェッチの前にそのバージョンを確認できます。
const status = await video.mediaKeys.getStatusForPolicy({
minHdcpVersion: '1.4'
});
if (status === 'usable') {
// Pre-fetch HD content.
} else { // 'output-restricted'
// Pre-fetch SD content.
}
編集者は Aaron Colwell、Alex Russell、Anne van Kesteren、Bob Lund、Boris Zbarsky、Chris Needham、Chris Pearce、David Singer、Domenic Denicola、Frank Galligan、 Glenn Adams、Henri Sivonen、Jer Noble、Joe Steele、Joey Parrish、John Simmons、Mark Vickers、Pavel Pergamenshchik、Philip Jägenstedt、Pierre Lemieux、Robert O'Callahan、Ryan Sleevi、Steve Heffernan、Steven Robertson、Theresa O'Connor、Thomás Inskip、Travis Leithead、および Xiaohan Wang に対して、本仕様への貢献に感謝します。また、メーリングリストや Issue での参加を含め、本仕様に貢献した多くの他の方々にも感謝します。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: