暗号化メディア拡張機能

W3C 作業草案

この文書の詳細情報
このバージョン:
https://www.w3.org/TR/2025/WD-encrypted-media-2-20250821/
最新公開バージョン:
https://www.w3.org/TR/encrypted-media-2/
最新編集者草案:
https://w3c.github.io/encrypted-media/
履歴:
https://www.w3.org/standards/history/encrypted-media-2/
コミット履歴
実装報告:
https://w3c.github.io/test-results/encrypted-media/all.html
最新勧告:
https://www.w3.org/TR/2017/REC-encrypted-media-20170918/
編集者:
Joey Parrish (Google Inc.)
Greg Freedman (Netflix Inc.)
以前の編集者:
Mark Watson (Netflix Inc.) (2019年9月まで)
David Dorwin (Google Inc.) (2017年9月まで)
Jerry Smith (Microsoft Corporation) (2017年9月まで)
Adrian Bateman (Microsoft Corporation) (2014年5月まで)
フィードバック:
GitHub w3c/encrypted-media (プルリクエスト, 新規 issue, オープン issue)
public-media-wg@w3.org 件名 [encrypted-media-2] … メッセージトピック … (アーカイブ)

概要

この仕様は、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 の公開以降、二つの新機能が追加されました:

その他の機能の追加は Media Working Group の対象外です。編集上の更新に加え、本仕様へのその他の実質的な変更は、本仕様に対する保守上の問題に対処しています:

以前のバージョン以降の変更の完全な一覧については、コミット履歴 を参照してください。

この文書は Media Working Group により、Recommendation track を用いて Working Draft として公開されました。

Working Draft としての公開は、W3C およびそのメンバーによる支持を意味するものではありません。

これは草案文書であり、いつでも更新、置換、廃止される可能性があります。本文書を進行中の作業以外の目的で引用することは適切ではありません。

この文書は、W3C Patent Policy の下で運営されるグループによって作成されました。

W3C は、グループの成果物に関連して行われた特許開示の公開リストを維持しています。該当ページには特許の開示方法についての指示も含まれています。個人が、当該個人が本質的請求(Essential Claim(s))を含むと信じる特許を実際に知っている場合、その情報は W3C 特許方針セクション6 に従って開示しなければなりません。

この文書は 2025年8月18日付の W3C プロセス文書 に従って管理されています。

1. 導入

このセクションは非規範的です。

この仕様はスクリプトがコンテンツ保護メカニズムを選択し、ライセンス/鍵交換を制御し、カスタムのライセンス管理アルゴリズムを実行できるようにします。各ユースケースごとに各ユーザーエージェント側でクライアント改変を要求することなく、幅広いユースケースをサポートします。これにより、コンテンツ提供者はすべてのデバイス向けに単一のアプリケーションソリューションを開発できます。

サポートされるコンテンツはコンテナ固有の「共通暗号化」仕様に従って暗号化され、キーシステム間での利用を可能にします。サポートされるコンテンツはコンテナ自体は暗号化されていないため、メタデータをアプリケーションに提供でき、他の HTMLMediaElement の機能との互換性を維持します。

実装者は、本仕様で記述されているセキュリティおよびプライバシーの脅威と懸念に対する緩和策に注意を払うべきです。特に、セキュリティおよびプライバシー要件は Key System とその実装のセキュリティおよびプライバシー特性を把握していないと満たせません。8. Implementation Requirements には基盤となる Key System 実装の統合および使用に関するセキュリティとプライバシーの条項が含まれています。10. Security は入力データやネットワーク攻撃など外部からの脅威に焦点を当てています。11. Privacy はユーザー固有の情報の取り扱いと、ユーザーが自身のプライバシーを適切に制御できるようにすることに焦点を当てています。

この仕様はメディアデータの供給元に依存しませんが、多くの実装が Media Source Extensions [MEDIA-SOURCE] 経由で提供されるメディアデータの復号のみをサポートしていることに著者は注意すべきです。

API を用いて実装された一般的なスタックの例を以下に示します。この図は一例のフローを示しており、他の API 呼び出しやイベントの組み合わせも可能です。

提案された API を使用して実装された汎用スタック

2. 定義

コンテンツ復号モジュール(CDM)

コンテンツ復号モジュール(CDM)は、1 つ以上の Key Systems に対して復号を含む機能を提供するクライアント側のコンポーネントです。

実装は CDM の実装とユーザーエージェントの実装を分離する場合と分離しない場合があります。本仕様ではこれは API とアプリケーションに対して透過的です。

Key System

Key System は復号メカニズムおよび/またはコンテンツ保護プロバイダを指す一般的な用語です。Key System 文字列は Key System を一意に識別します。これらはユーザーエージェントによって CDM を選択したり、鍵に関連するイベントの発生源を特定するために使用されます。ユーザーエージェントは MUSTCommon 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

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

Session ID は CDM によって生成される一意の文字列識別子で、アプリケーションが MediaKeySession オブジェクトを識別するために使用できます。

ユーザーエージェントと CDM が新しいセッションを正常に作成するたびに、新しい Session ID が生成されます。

各 Session ID は、作成されたブラウジングコンテキスト内で一意でなければなりません(SHALL)。Is persistent session type? アルゴリズムが true を返すセッションタイプについては、Session ID はオリジン内で時間を越えて、一貫して一意でなければなりません(MUST)、閲覧セッションを跨いでも含みます。

基盤となるコンテンツ保護プロトコルは必ずしも Session ID をサポートする必要はありません。

Key

特に明記されない限り、key は media data 内のブロックを復号するために使用される復号キーを指します。各キーは key ID によって一意に識別されます。キーはそれを session に提供するために使用された CDM に関連付けられます。(同じキーが複数のセッションに存在する場合があります。)そのような鍵は update() 呼び出しを通じてのみ CDM に提供されなければなりません(MUST)。(後で保存されたセッションデータの一部として load() によって読み込まれる場合があります。)

著者は、意味のある異なるポリシーを強制する必要がある各ストリーム集合を別個のキー(および key ID)で暗号化することを推奨します(SHOULD)。例えば、二つのビデオ解像度間でポリシーが異なる可能性がある場合、ある解像度を含むストリームは他の解像度を含むストリームを暗号化するのに使用されたキーと同じキーで暗号化してはいけません。音声ストリームが暗号化される場合、音声はビデオストリームと同じキーを使用すべきではありません(SHOULD NOT)。これはクライアント間での強制と互換性を保証する唯一の方法です。

Usable For Decryption

キーが復号に使用可能と見なされるのは、CDM が当該キーが現在 1 個以上の media data のブロックを復号するために使用可能であると確信できる場合です。

例えば、ライセンスが期限切れの場合、そのキーは復号に使用できません。ライセンスが期限切れでない場合でも、出力保護などの使用条件が現在満たされていない場合は、そのキーは復号に使用できません。

Key ID

key はバイト列である key ID に関連付けられ、キーを一意に識別します。コンテナは media data 内のブロックまたはブロック集合を復号できるキーの ID を指定します。Initialization Data はメディアデータを復号するために必要なキーを識別するための key ID を含んでいてもよい(MAY)。しかし、Initialization Data にメディアデータやメディアリソースで使用されるすべての key ID が含まれることを要求するものではありません。LicensesCDM に提供されると、各キーは key ID に関連付けられ、CDM が暗号化されたメディアデータのブロックを復号する際に適切なキーを選択できるようになります。

Known Key

キーがセッションに「既知」であるとは、CDM のセッション実装がそのキーについて何らかの情報を含んでいる(特に key ID)ことを指し、実際のキーの値が既知であるかどうか、またはそのキーが使用可能かどうかは問いません。既知のキーは keyStatuses 属性を通じて公開されます。

キーは、例えば expiration によって使用不能になった場合や、削除されたが record of license destruction が利用可能な場合でも、既知と見なされます。キーは明示的にセッションから削除され、かつライセンス解除メッセージが確認されるときにのみ未知になります。

例えば、update() 呼び出しが以前キーを含んでいたライセンスを置換するような新しいライセンスを提供し、その新しいライセンスにそのキーが含まれていない場合、キーは未知になる可能性があります。

License

ライセンスはキーシステム固有の状態情報で、一つ以上の key(s)(各々が key ID に関連付けられる)および鍵利用に関する他の情報を含む場合があります。

Initialization Data

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 属性としてアプリケーションに encrypted イベントで提供します。ユーザーエージェントはその時点で Initialization Data を保存したり、その 内容 を使用してはなりません(MUST NOT)。アプリケーションは Initialization DataCDMgenerateRequest() を通じて提供します。ユーザーエージェントは他の手段で Initialization DataCDM に提供してはなりません(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 Value

二つ以上の識別子または他の値は、同一であるか、あるいは合理的な時間と労力で相関または関連付けることが可能である場合、互いに「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 の例には次が含まれますがこれに限定されません:

Distinctive Value は通常ユーザーやクライアントデバイスに固有ですが、絶対的に一意である必要はありません。例えば少数のユーザー間で共有される値でも識別的でありうる場合があります。

Permanent Identifier

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 は、クライアント外の任意の主体がウェブプラットフォーム上でユーザーが期待する以上に値を相関・関連付けできる値(不透明または暗号化形式を含む)です(例:クッキーや他のサイトデータを越えた相関)。例えば、ある値がオリジンやブラウジングプロファイル、閲覧セッションを跨いで外部の主体によって相関可能である場合、これは Distinctive Identifier と見なされます。これは個別化(individualization)要求に共通の値が含まれていたり、個別化要求で提供された値が中央サーバ(例:個別化サーバ)によって相関可能である場合に起こり得ます。

アプリケーションに露出される Distinctive Identifiers は、暗号化形式であっても、識別子要件(暗号化、オリジン・プロファイルごとの一意性、消去可能性など)に従わなければなりません(MUST)。

Distinctive Identifier の生成や使用は本仕様の API の使用によってトリガーされますが、その識別子をアプリケーションに提供する必要はありません(ただし Distinctive Permanent Identifiers は決してアプリケーションに提供されるべきではありません)。

distinctiveIdentifier は Distinctive Identifiers の使用可否を制御します。具体的には、Distinctive Identifiers が使用できるのは、distinctiveIdentifier メンバーが MediaKeySystemAccess の生成に使用された値が "required" の場合に限られることを示します。

Distinctive Identifier は次のすべての基準を満たす値、データ断片、所持の示唆、または観測可能な振る舞いやタイミングです:

  • 識別的であること(distinctive)

    Distinctive Identifier は通常ユーザーやクライアントデバイスに固有ですが、厳密に一意である必要はありません。例えば少数のユーザー間で共有される識別子でも識別的でありえます。

  • それ自体、あるいはそれに関する情報や派生値がクライアント外に(暗号化形式であっても)露出されること。これにはアプリケーションやライセンス、individualization サーバ、その他のサーバへの提供が含まれます。

  • 次の一つ以上の性質を持つこと:

    • それが一つ以上の Distinctive Permanent Identifier から派生していること。

    • その値を生成したプロセス(生成、individualization、プロビジョニングなど)が一つ以上の Distinctive Permanent Identifier または他の Distinctive Identifier を使ったか、関連していること。

    • それは 消去可能(clearable) だが、クッキーなどのサイトデータと一緒には消去されないこと。

      例えば OS レベルの外部メカニズムを介する場合などです。

    アプリケーションに露出される値について規範的に禁止される他の性質には次が含まれますがこれに限定されません:

    規範的に禁止されるそのような値の例には次が含まれますがこれに限定されません:

    • すべてのオリジンで使用される単一のハードウェアベースの値。

    • すべてのオリジンで使用される単一のランダムベースの値。

    • すべてのオリジンで使用される単一の個別化プロセス(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 ユーザーアカウント名)から導出された値。

  • CDM バイナリや CDM が使用する他のファイルに埋め込まれた一意の値から導出された値。

Distinctive Identifier でない例には次が含まれます:

  • インストールベースが大きい場合、ある CDM バージョンのすべてのコピーで共有される公開鍵。

  • 一意だが一つのセッションでのみ使用されるノンスやエフェメラルキー。

  • 外部に露出しない値(個別化や類似の方法を含めて)で、クライアント外に派生形や類似の形で露出されないもの。

  • 例えばビデオパイプラインと CDM 間の認証で使用されるデバイス固有キーのように、CDM がそれらの認証をアプリケーションに流さず、代わりに Distinctive Identifier を構成しないキーを用いて新たな認証を行う場合。

  • クッキー等と共に完全に消去可能であり、その後中央サーバ(例えば個別化サーバ)によっても相関され得ない(non-associable)新しい値に置き換えられる値、かつ以下のいずれかを満たすもの。

    • 生成に Distinctive Permanent Identifier や Distinctive Identifier が関与していないこと。

    • システムからの入力なしに生成されたランダム値であること。

    • サーバから提供された値であり、他の Distinctive Identifier の使用や知識を伴わないこと。

Use of Distinctive Identifiers and Distinctive Permanent Identifiers

実装、設定、インスタンス、またはオブジェクトが 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" の場合にのみ使用できることを示します。

Cross Origin Limitations

再生中、埋め込まれたメディアデータは埋め込み元の origin のスクリプトに晒されます。API が Initialization Dataencrypted イベントで提供するためには、media data は埋め込みページと CORS-same-origin でなければなりません(MUST)。メディアデータが埋め込み文書とクロスオリジンである場合、著者は crossOrigin 属性を HTMLMediaElement に設定し、メディアデータのレスポンスに CORS ヘッダを付与して CORS-same-origin にするべきです(SHOULD)。

Mixed Content Limitations

再生中、埋め込まれたメディアデータは埋め込み元の origin のスクリプトに晒されます。API が Initialization Dataencrypted イベントで提供するためには、media data は Mixed Content であってはなりません(MUST NOT)[MIXED-CONTENT]。

Time

時刻(Time)は ECMAScript の Time Values and Time Range に表現されるものと同等でなければなりません(MUST)。

該当する時刻が存在しない、または時刻が不確定である場合、Time は NaN をとります。Infinity の値を持つべきではありません。

Time は通常ミリ秒精度の時刻を表しますが、それだけでは十分な定義ではありません。定義された Time Values and Time Range 参照が他の重要な要件を追加します。

Expiration Time

キーがもはや usable for decryption ではなくなる時刻を指します。

Browsing Profile

与えられたマシン上のユーザーエージェントは、アプリケーションに可視な状態やデータに関して独立して振る舞うことが期待される様々なコンテキストやモード、一時的状態で実行できる場合があります。特に、保存されたすべてのデータは独立していることが期待されます。本仕様ではそのような独立したコンテキストやモードを「Browsing Profiles」と呼びます。

そのような独立コンテキストの例としては、ユーザーエージェントが異なる OS ユーザーアカウントで実行されている場合や、単一アカウントで複数の独立プロファイルを定義する機能をユーザーエージェントが提供している場合などがあります。

3. キーシステムへのアクセスの取得

このセクションでは、Key System へのアクセスを取得する仕組みを定義します。リクエストに機能を含めることで、機能検出も可能になります。

アルゴリズムの手順は、プロミスが拒否されると常に中止されます。

3.1 Permissions Policy の統合

requestMediaKeySystemAccess() は、文字列 encrypted-media によって識別される ポリシー制御機能 です。 その デフォルト許可リスト'self' です [PERMISSIONS-POLICY].

3.3 MediaKeySystemConfiguration 辞書

WebIDLenum MediaKeysRequirement {
  "required",
  "optional",
  "not-allowed"
};

MediaKeysRequirement 列挙型は以下のように定義されます:

列挙型の説明
required
requestMediaKeySystemAccess() の呼び出しで使用した場合
返されるオブジェクトはこの機能を MUST サポートしなければなりません。
MediaKeySystemAccess オブジェクトによって返された場合
オブジェクトによって生成された CDM インスタンスはこの機能を使用してもよい(MAY)。
optional
requestMediaKeySystemAccess() の呼び出しで使用した場合
返されるオブジェクトはこの機能をサポート・使用してもよい(MAY)。
MediaKeySystemAccess オブジェクトによって返された場合
この値はそのようなオブジェクトに存在することはできず、MUST NOT 存在してはなりません。
not-allowed
requestMediaKeySystemAccess() の呼び出しで使用した場合
返されるオブジェクトはこの機能を使用せず、かつ MUST NOT いかなる時点でも使用してはなりません。
MediaKeySystemAccess オブジェクトによって返された場合
オブジェクトによって生成された CDM インスタンスはこの機能を MUST NOT 使用してはなりません。
WebIDLdictionary MediaKeySystemConfiguration {
  DOMString                               label = "";
  sequence<DOMString>                     initDataTypes = [];
  sequence<MediaKeySystemMediaCapability> audioCapabilities = [];
  sequence<MediaKeySystemMediaCapability> videoCapabilities = [];
  MediaKeysRequirement                    distinctiveIdentifier = "optional";
  MediaKeysRequirement                    persistentState = "optional";
  sequence<DOMString>                     sessionTypes;
};

辞書 MediaKeySystemConfiguration は以下のメンバーを持ちます:

labelDOMString、デフォルト値 ""
オプションのラベルで、MediaKeySystemConfigurationgetConfiguration() メソッドで返される際に保持されます。 MediaKeySystemAccess のメソッドです。
initDataTypessequence<DOMString>、デフォルト値 []
サポートされる Initialization Data Type 名のリストです。このオブジェクトの Initialization Data Type 機能は、リストが空または他のすべてのメンバーと共にサポートされる値が1つ以上含まれていればサポートされていると見なされます(アルゴリズムで判定)。列の値は空文字列であってはなりません(MUST)。
audioCapabilitiessequence<MediaKeySystemMediaCapability>、デフォルト値 []
サポートされる音声タイプと機能のペアのリストです。このオブジェクトの音声機能はリストが空か他のすべてのメンバーと共にサポートされる値が1つ以上含まれていればサポートされていると見なされます(アルゴリズムで判定)。値間に競合がある場合は、先の値が選択されます。空リストは音声機能がサポートされないことを示します。この場合、videoCapabilities メンバーは空であってはなりません。
videoCapabilitiessequence<MediaKeySystemMediaCapability>、デフォルト値 []
サポートされる映像タイプと機能のペアのリストです。このオブジェクトの映像機能はリストが空か他のすべてのメンバーと共にサポートされる値が1つ以上含まれていればサポートされていると見なされます(アルゴリズムで判定)。値間に競合がある場合は、先の値が選択されます。空リストは映像機能がサポートされないことを示します。この場合、audioCapabilities メンバーは空であってはなりません。
distinctiveIdentifierMediaKeysRequirement、デフォルト値 "optional"
Distinctive Identifier(s) の使用が必要かどうか。

このメンバーが "not-allowed" の場合、実装はこの構成から生成されたいかなるオブジェクトの処理において Distinctive Identifier(s) または Distinctive Permanent Identifier(s) の使用MUST NOT 行ってはなりません。

persistentStateMediaKeysRequirement、デフォルト値 "optional"
状態の永続化機能が必要かどうかを示します。これにはセッションデータやその他の種類の状態が含まれます。

このメンバーが "not-allowed" の場合、CDM はこのオブジェクトの originDocument、アプリケーションに関連するいかなる状態も永続化してはなりません(MUST NOT)。

このメンバーに関して、永続状態にはキーシステム実装が管理する永続的な一意識別子(Distinctive Identifiers)は含みません。distinctiveIdentifier がこの要件を個別に反映します。

永続状態がサポートされない場合は、"temporary" セッションのみ作成可能です。

"temporary" セッションでは、状態の保存の必要性や可能性はキーシステム実装依存であり、使用される機能によって異なる場合があります。

"temporary" 以外のセッションを作成したいアプリケーションは、 requestMediaKeySystemAccess() 呼び出し時にこのメンバーを "required" に設定すべきです。

sessionTypessequence<DOMString>
サポートされなければならない MediaKeySessionType のリストです。すべての値がサポートされている必要があります。

このメンバーが辞書に 存在しない [Infra] 状態で requestMediaKeySystemAccess() に渡された場合、[ "temporary" ] が設定されているものとして扱われます。

実装はこの辞書にメンバーを追加すべきではありません(SHOULD NOT)。もし追加する場合、型は MediaKeysRequirement にしなければならず(MUST)、デフォルト値は "optional" とすることが推奨されます(RECOMMENDED)。これにより最も幅広いアプリケーションとクライアントの組み合わせをサポートできます。

ユーザーエージェント実装が認識しない辞書メンバーは [WEBIDL] に従い無視され、requestMediaKeySystemAccess() アルゴリズムで考慮されません。アプリケーションが非標準的な辞書メンバーを使用する場合、ユーザーエージェント実装がそのような辞書メンバーを含む構成を拒否することを前提にしてはなりません(MUST NOT)。

この辞書は CDM に状態やデータを渡すために使用してはなりません(MUST NOT)。

3.4 MediaKeySystemMediaCapability 辞書

WebIDLdictionary MediaKeySystemMediaCapability {
  DOMString contentType = "";
  DOMString? encryptionScheme = null;
  DOMString robustness = "";
};

3.4.1 辞書 MediaKeySystemMediaCapability のメンバー

contentTypeDOMString、デフォルト値 ""

MIMEタイプメディアリソースの)。

アプリケーションは、MIMEタイプが明示的にコーデックやコーデック制約(たとえば [RFC6381])を指定することを 推奨 します(SHOULD)。これらがコンテナによって規範的に暗示されない限りです。

encryptionSchemeDOMString、デフォルト値 null

content type に関連付けられる暗号化方式。値が null または存在しない場合、アプリケーションが特定の暗号化方式を要求しないことをユーザーエージェントに示し、そのためいかなる暗号化方式でも許容されます。

このフィールドを認識しているアプリケーションは、必要な暗号化方式を指定すべきです(SHOULD)。異なる暗号化方式は一般的に互換性がありません。アプリケーションが「いかなる方式でも可」とするのは非現実的ですが、デフォルトの null と null の「任意」としての解釈は、未認識アプリや古いユーザーエージェントへのポリフィルの道を提供します。

空文字列は null や未指定とは異なり、認識できない暗号化方式として扱われます。

encryptionScheme のよく知られた値:

  • cenc: "cenc" モード。 [CENC] 4.2a節。AES-CTRモードのフルサンプルおよび動画NALサブサンプル暗号化。
  • cbcs: "cbcs" モード。 [CENC] 4.2d節。AES-CBCモードの部分動画NALパターン暗号化。動画の場合、仕様では様々な暗号化パターンを許容しています。
  • cbcs-1-9: "cbcs" モードと同じですが、動画について暗号化:スキップパターンが 1:9 となっており、[CENC] 10.4.2節の推奨です。
robustnessDOMString、デフォルト値 ""

content type に関連付けられる堅牢性レベル。空文字列の場合、コンテンツタイプの復号およびデコードができる能力であれば何でも許容されます。

実装は CDM を、MediaKeySystemAccess オブジェクトの構成で指定された堅牢性レベルを少なくともサポートするように設定しなければなりません(MUST)。MediaKeys オブジェクトの生成に使用されます。CDM の正確な設定は実装依存であり、実装は構成内の最高堅牢性レベルを使うように設定してもよい(MAY)、より高い堅牢性レベルが利用可能であってもです。空文字列のみ指定された場合、実装はサポートする最低堅牢性レベルを使うように設定してもよいです(MAY)。

アプリケーションは想定外のクライアント非互換性を避けるために必要な堅牢性レベルを指定するべきです(SHOULD)。

このオブジェクトが表す機能がサポートされているとみなされるためには、contentType は空文字列であってはならず(MUST NOT)、値全体(すべてのコーデックを含む)が robustness とともにサポートされていなければなりません(MUST)。

受け入れ可能なコーデックが複数ある場合は、各コーデックごとにこの辞書の別インスタンスを使用してください。

4. MediaKeySystemAccess インターフェース

MediaKeySystemAccess オブジェクトは Key System へのアクセスを提供します。

WebIDL[Exposed=Window, SecureContext] interface MediaKeySystemAccess {
  readonly attribute DOMString keySystem;
  MediaKeySystemConfiguration  getConfiguration ();
  Promise<MediaKeys>           createMediaKeys ();
};

4.1 属性

keySystemDOMString、readonly
使用される Key System を識別します。

4.2 メソッド

getConfiguration()

requestMediaKeySystemAccess() アルゴリズムによって選択されたサポートされる構成オプションの組み合わせを返します。

返されるオブジェクトは、最初に満たされた MediaKeySystemConfiguration 構成(+暗黙のデフォルト)からなる非厳密な部分集合です。これは requestMediaKeySystemAccess() の呼び出しに渡され、その呼び出しで解決されたプロミスに対応します。その単一構成で指定されていない機能(暗黙のデフォルト以外)は含まれず、Key System 実装のすべての機能を必ずしも反映しません。構成内のすべての値は任意の組み合わせで使用できます。型 MediaKeysRequirement のメンバーは、どの組み合わせでその機能が要求されるかを反映します。これらは "optional" の値にはなりません。

このメソッドが呼び出された際、ユーザーエージェントは次の手順を 必ず実行しなければなりません:

  1. このオブジェクトの configuration の値を返します。

    このメソッドが呼び出されるたびに configuration から新しいオブジェクトが作成・初期化されます。

    encryptionScheme がアプリケーションによって指定されなかった場合でも、累積された configuration には値 nullencryptionScheme フィールドが含まれていなければならず(MUST)、ポリフィルがユーザーエージェントのフィールドサポートを特定値指定せずに検出できるようにします。

createMediaKeys()

keySystem 用の新しい MediaKeys オブジェクトを作成します。

このメソッドが呼び出された際、ユーザーエージェントは次の手順を 必ず実行しなければなりません:

  1. promise を新しいプロミスとして作成します。

  2. 次の手順を並行して実行します:

    1. configuration をこのオブジェクトの configuration の値とします。

    2. use distinctive identifier を、configurationdistinctiveIdentifier メンバーの値が "required" なら true、そうでなければ false とします。

    3. persistent state allowed を、configurationpersistentState メンバーの値が "required" なら true、そうでなければ false とします。

    4. 必要ならこのオブジェクトの cdm implementation の値で表される Key System 実装をロード・初期化します。

    5. instance をこのオブジェクトの cdm implementation の値で表される Key System 実装の新しいインスタンスとします。

    6. configuration を使って instanceKey System 機能の有効化・無効化・選択に初期化します。

    7. use distinctive identifierfalse の場合、instanceDistinctive Identifier(s) および Distinctive Permanent Identifier(s) を使用 できないようにします。

    8. persistent state allowedfalse の場合、instance がこのオブジェクトの originDocument、アプリケーションに関連するいかなる状態も永続化できないようにします。

    9. 直前のいずれかの手順が失敗した場合、新しい DOMException(名前は適切な エラー名)で promise を拒否します。

    10. media keys を新しい MediaKeys オブジェクトとし、以下のように初期化します:

      1. use distinctive identifier の値を media keys の値として設定します。

      2. persistent state allowed の値を media keys の値として設定します。

      3. supported session types の値を configurationsessionTypes メンバーの値とします。

      4. cdm implementation の値をこのオブジェクトの cdm implementation の値とします。

      5. cdm instance の値を instance とします。

    11. promisemedia keys で解決します。

  3. promise を返します。

5. MediaKeys インターフェース

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 固有の証明です。このセッションタイプのサポートは 任意 です。

このタイプのセッションは、このオブジェクトを生成した MediaKeySystemAccess オブジェクトに関係付けられた構成の persistentState が "required" に設定されている場合にのみ作成できます。セッションは Session ID を使用して、update() が成功裏に呼ばれた後、ロード可能でなければなりません。message のタイプ "license-release" を含むメッセージが、remove() が呼ばれたときに生成され、その記録が update() に渡された応答によって確認されるまで送出され続けます。

そのようなセッションのために永続化されたデータが不要になったときに削除する責任はアプリケーションにあります。詳細は 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);
};

5.1 メソッド

createSession()

新しい MediaKeySession オブジェクトを返します。

sessionType パラメータは返されるオブジェクトの挙動に影響します。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの supported session types 値が sessionType を含まない場合、throw [WEBIDL] として NotSupportedError を投げます。

    sessionType に対して Is persistent session type? アルゴリズムが true を返す値は、このオブジェクトの persistent state allowed 値が false の場合に失敗します。

  2. 実装が現在の状態で MediaKeySession 操作をサポートしていない場合、throw [WEBIDL] として InvalidStateError を投げます。

    一部の実装では、この MediaKeySession アルゴリズムを実行するために、まずこの MediaKeys オブジェクトを setMediaKeys() を使ってメディア要素に関連付ける必要がある場合があります。この手順は、そのような珍しい挙動を検出することで、その後の操作実行前に検出できるようにするものです。

  3. session を新しい MediaKeySession オブジェクトとし、次のように初期化します:

    1. sessionId 属性を空文字列とします。

    2. expiration 属性を NaN とします。

    3. closed 属性を新しいプロミスとします。

    4. key status を新しい空の MediaKeyStatusMap オブジェクトとし、次のように初期化します:

      1. size 属性を 0 とします。

    5. session type の値を sessionType とします。

    6. uninitialized の値を true とします。

    7. callable の値を false とします。

    8. closing or closed の値を false とします。

    9. use distinctive identifier の値をこのオブジェクトの use distinctive identifier 値とします。

    10. cdm implementation の値をこのオブジェクトの cdm implementation とします。

    11. cdm instance の値をこのオブジェクトの cdm instance とします。

  4. session を返します。

getStatusForPolicy()

指定された MediaKeysPolicy に対する MediaKeyStatus を返します。

WebIDLdictionary MediaKeysPolicy {
    DOMString minHdcpVersion;
};

MediaKeysPolicy 辞書はオプションのプロパティのみからなるオブジェクトです。各プロパティはポリシー要件を表します。ポリシーは、すべての要件に基づいて CDM が復号済みメディアデータの表示を許可する場合に満たされたと見なされます。

HDCP ポリシーは minHdcpVersion で表されます。システムが指定された HDCP バージョン以上を有効にできる場合、ポリシーは "usable" の MediaKeyStatus をもたらします。[EME-HDCP-VERSION-REGISTRY] は minHdcpVersion の値と HDCP 仕様との対応を提供します。

HDCP 状況の判定は、再生中に CDM がそのような制限を強制するのと同じ方法で行うべきです。こうすることで、アプリケーション開発者は再生を開始するために取得すべきコンテンツを最適化するための合理的なヒントを得られます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. If policy存在する 辞書メンバー がない場合、TypeError で拒否されたプロミスを返します。
  2. promise を新しいプロミスとします。

  3. タスクをキューして、次の手順を実行します:

    1. policy の各 辞書メンバー に対して次の手順を実行します:

      1. もしキーが MediaKeysPolicy の有効なメンバーでないか、値の型が間違っている場合、promiseTypeError で拒否してこれらの手順を中止します。

    2. policy の各 辞書メンバー に対して次の手順を実行します:

      1. もし CDM がその MediaKeyStatus を判定できない場合、promiseNotSupportedError で拒否してこれらの手順を中止します。

    3. policy の各 辞書メンバー に対して次の手順を実行します:

      1. もし CDM がその辞書メンバーに対して復号済みメディアデータの表示をブロックするなら、promise を "output-restricted" で解決します。

    4. promise を "usable" で解決します。

  4. promise を返します。

setServerCertificate()

ライセンスサーバーへのメッセージを暗号化するために使用されるサーバー証明書を提供します。

そのような証明書を使用する Key Systems は、サーバーから証明書を要求するために "Queue a "message" Event" アルゴリズムをサポートしなければなりません。

このメソッドは、必要になった場合に CDM が証明書を要求する追加の往復を回避するために、サーバー証明書を事前に実装に渡すことを可能にします。最適化を目的としており、アプリケーションはこれを必ず使用する必要はありません。

サーバー証明書の内容は Key System 固有です。実行可能なコードを含んではいけません(MUST NOT)。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. このオブジェクトの cdm implementation 値で表される Key System 実装がサーバー証明書をサポートしていない場合、false で解決されたプロミスを返します。

  2. もし serverCertificate が空の配列であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  3. certificateserverCertificate パラメータの内容のコピーとします。

  4. promise を新しいプロミスとします。

  5. 次の手順を並行して実行します:

    1. sanitized certificatecertificate の検証および/またはサニタイズされたバージョンとします。

      ユーザーエージェントは証明書を CDM に渡す前に十分に検証すべきです。これには、値が妥当な範囲内であることの確認、無関係なデータやフィールドの削除、事前解析、サニタイズ、あるいは完全にサニタイズされたバージョンの生成が含まれる場合があります。ユーザーエージェントはフィールドの長さや値が妥当であることを確認すべきです。未知のフィールドは拒否または削除すべきです。

    2. このオブジェクトの cdm instance を使って sanitized certificate を処理します。

    3. 前述の手順が失敗した場合、適切な エラー名 を持つ新しい DOMExceptionpromise を拒否します。

    4. promisetrue で解決します。

  6. promise を返します。

5.2 アルゴリズム

5.2.1 Is persistent session type?

Is persistent session type? アルゴリズムは、指定されたセッションタイプが何らかの永続化をサポートするかどうかを判定するために実行されます。このアルゴリズムを実行するリクエストには MediaKeySessionType の値が含まれます。

次の手順が実行されます:

  1. session type を指定された MediaKeySessionType の値とします。

  2. 次のリストの session type の値に対応する手順に従います:

    "temporary"
    Return false.
    "persistent-license"
    Return true.

5.2.2 CDM Unavailable

CDM unavailable アルゴリズムは、MediaKeySession オブジェクトをすべて閉じるために実行されます。対象は MediaKeys オブジェクト(media keys)に関連付けられたものです。これは CDM インスタンスが利用不可能になった場合に実行されます。このアルゴリズムを実行するリクエストには MediaKeySessionClosedReason の値が含まれます。

次の手順が実行されます:

  1. reason を指定された MediaKeySessionClosedReason の値とします。

  2. media keys によって生成され、この時点で closed でない各 MediaKeySession に対して、タスクをキューし、そのセッションで Session Closed アルゴリズムを reason を使って実行します。

5.3 Storage and Persistence

本節では、ストレージおよび永続化に関連する一般的な要件について説明します。

もし 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 を参照してください。

6. MediaKeySession インターフェース

MediaKeySession オブジェクトはキーセッションを表します。

MediaKeySession オブジェクトは、そのオブジェクトの closed 属性が解決済みである場合に限り closed と見なされます。

ユーザーエージェントは、CDM 状態変化の監視 アルゴリズムを、MediaKeySession オブジェクトごとに、そのオブジェクトが closed でない限り継続的に実行しなければなりません。CDM 状態変化の監視 アルゴリズムは、メインイベントループと並列して実行されなければならない(MUST)が、本仕様で並列実行と定義されている他の手続きと並行して実行してはなりません。

MediaKeySession オブジェクトは、もしそのオブジェクトが closed でなく、かつそれを生成した MediaKeys オブジェクトが引き続きアクセス可能である場合、破棄されてはならず(SHALL)、イベントを受け取り続けなければなりません。そうでない場合、もはやアクセス可能でない MediaKeySession オブジェクトは更なるイベントを受け取ってはならず(SHALL NOT)、破棄されてもよい(MAY)。

上記の規則は、すべての 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 インスタンス上で新しいセッションを作成してはなりません(MUST NOT)。
closed-by-application アプリケーションがセッションの close() メソッドを明示的に呼び出してセッションを閉じたためです。
release-acknowledged CDM が record of license destruction の確認応答を受け取ったためセッションが閉じられました。
hardware-context-reset CDM の元のハードウェアコンテキストがリセットされたためセッションが閉じられました。この場合、ユーザーエージェントはアプリケーションが当該 MediaKeys インスタンス上で新しいセッションを作成できるようにしなければなりません(MUST)。

これはデバイスのハイバネーション、モニター設定の変更など多くの理由で発生する可能性があり、その正確な理由は実装依存です。

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 ();
};

6.1 属性

sessionIdDOMString、readonly

このオブジェクトおよび関連する鍵やライセンスの Session ID

expirationunrestricted double, readonly

セッション内のすべての鍵の expiration time、またはそのような時刻が存在しない場合やライセンスが明示的に期限切れにならないと CDM が判断した場合は NaN

この値は、ウィンドウの開始を引き起こすようなアクションが発生したときのように、セッションの有効期間中に変更されることがある(MAY)。

closedPromise<MediaKeySessionClosedReason>, readonly

Session Closed アルゴリズムの実行によりオブジェクトが closed になったときに通知します。このプロミスは満たされることのみ可能で、拒否されることはありません。

keyStatusesMediaKeyStatusMap, readonly

セッションに key IDs と、そのキーに対応する現在の状態を示す読み取り専用マップへの参照。各エントリは一意の key ID を持たなければならない(MUST)。

マップのエントリおよびその値はイベントループが回るたびに更新され得る。マップは決して不整合や部分的更新の状態になってはならない(MUST NOT)が、アクセス間にイベントループが回ると変化する可能性はある。Key ID は load()update() の結果として追加されることがある。既存の鍵に関する知識を削除する(または既存の鍵セットを新しいセットに置き換える)ような update() の呼び出しにより Key ID は削除され得る。Key ID が有効期限切れなどで使用不能になったために削除されてはならない(MUST NOT)。その代わりに、例えば "expired" のような適切な状態が付与されなければならない(MUST)。

古いプラットフォームの中には key IDs を公開しない Key System 実装があり、準拠するユーザーエージェント実装を提供することが不可能な場合がある。相互運用性を最大化するため、そうした CDM を公開するユーザーエージェント実装はこのメンバーを次のように実装することを SHOULD 推奨する: 非空のリストが適切である場合、例えばこのオブジェクトが表す key session に鍵が含まれる可能性がある場合、マップを 1 バイトの key ID 0 と、このオブジェクトの集約された状態に最も適切な MediaKeyStatus を持つ単一のペアで埋める。

onkeystatuseschangeEventHandler

keystatuseschange イベントのイベントハンドラ。

onmessageEventHandler

message イベントのイベントハンドラ。

6.2 Methods

generateRequest()

initData に基づくライセンス要求を生成します。アルゴリズムが成功してプロミスが解決された場合、タイプが "license-request" または "individualization-request" の message が常にキューされます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの closing or closed 値が true であれば、InvalidStateError で拒否されたプロミスを返します。

  2. もしこのオブジェクトの uninitialized 値が false であれば、InvalidStateError で拒否されたプロミスを返します。

  3. このオブジェクトの uninitialized 値を false にします。

  4. もし initDataType が空文字列であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  5. もし initData が空の配列であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  6. もしこのオブジェクトの cdm implementation 値で表される Key System 実装が initDataTypeInitialization Data Type としてサポートしていない場合、NotSupportedError で拒否されたプロミスを返します。文字列比較は大文字小文字を区別します。

  7. init datainitData パラメータの内容のコピーとします。

  8. session type をこのオブジェクトの session type とします。

  9. promise を新しいプロミスとします。

  10. 次の手順を並行して実行します:

    1. もし init datainitDataType に対して有効でない場合、promise を新しく作成した TypeError で拒否します。

    2. sanitized init datainit data の検証およびサニタイズされたバージョンとします。

      ユーザーエージェントは Initialization Data を CDM に渡す前に徹底的に検証しなければなりません(MUST)。これにはフィールドの長さや値が妥当であることの確認、値が合理的な範囲内であることの検証、無関係・未サポート・未知のデータやフィールドの削除が含まれます。ユーザーエージェントは Initialization Data を事前解析・サニタイズし、完全にサニタイズされたバージョンを生成することが RECOMMENDED です。もし initDataType で指定されるフォーマットが複数エントリをサポートする場合、ユーザーエージェントは CDM に不要なエントリを削除することを SHOULD します。ユーザーエージェントは Initialization Data 内のエントリの並び替えを行ってはなりません(MUST NOT)。

    3. もし直前の手順が失敗した場合、promise を新しく作成した TypeError で拒否します。

    4. もし sanitized init data が空であれば、NotSupportedErrorpromise を拒否します。

    5. session id を空文字列とします。

    6. message を null とします。

    7. message type を null とします。

    8. cdm をこのオブジェクトの cdm instance 値で表される CDM インスタンスとします。

    9. cdm を使用して次の手順を実行します:

      1. もし sanitized init datacdm によってサポートされていなければ、promiseNotSupportedError で拒否します。

      2. 次のリストから session type の値に対応する手順に従います:

        "temporary"

        requested license type を一時的で永続化不可のライセンスとします。

        Note

        返されるライセンスは永続化できず、それに関連する情報を永続化することを要求してはなりません。

        "persistent-license"

        requested license type を永続化可能なライセンスとします。

      3. session id を一意な Session ID 文字列とします。

        もし session type に対して Is persistent session type? アルゴリズムを実行した結果が true であれば、この ID はこのオブジェクトの origin 内で、ドキュメントやブラウジングセッションを跨いで一意でなければなりません(MUST)。

      4. もし sanitized init data に基づいて requested license type のライセンス要求を生成できる場合:
        1. message を、sanitized init datainitDataType に従って解釈して生成された requested license type のライセンス要求とします。

          cdmsanitized init data で提供されていないストリーム固有のデータ(media data を含む)を使用してはなりません(MUST NOT)。

          cdm はこの時点でセッションデータ(セッション ID を含む)を保存してはならないことが SHOULD NOT とされます。詳細は Session Storage and Persistence を参照してください。

        2. message type を "license-request" とします。

        それ以外
        1. message を、sanitized init data に基づいて requested license type のライセンス要求を生成する前に処理する必要のある要求とします。

          後続の update() 呼び出しにおいて、CDMinitDataType に従って解釈された sanitized init data に基づいて requested license type のライセンス要求を生成しなければなりません(MUST)。

        2. message typemessage の型に合わせて設定します。これは "license-request" または "individualization-request" のいずれかです。

    10. Queue a task を使って次の手順を実行します:

      1. もし前段のいずれかの手順がリソース不足のために失敗したなら、promiseQuotaExceededError で拒否します。

      2. もし前段のいずれかの手順がその他の理由で失敗したなら、適切な error name を名前に持つ新しい DOMExceptionpromise を拒否します。

      3. sessionId 属性を session id に設定します。

      4. このオブジェクトの callable 値を true に設定します。

      5. promiseundefined で解決します。

      6. Queue a "message" Event アルゴリズムを session 上で実行し、message typemessage を提供します。

  11. promise を返します。

load()

指定されたセッションに保存されているデータをこのオブジェクトにロードします。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの closing or closed 値が true であれば、InvalidStateError で拒否されたプロミスを返します。

  2. もしこのオブジェクトの uninitialized 値が false であれば、InvalidStateError で拒否されたプロミスを返します。

  3. このオブジェクトの uninitialized 値を false にします。

  4. もし sessionId が空文字列であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  5. もしこのオブジェクトの session type に対して Is persistent session type? アルゴリズムを実行した結果が false であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  6. origin をこのオブジェクトの origin とします。

  7. promise を新しいプロミスとします。

  8. 次の手順を並行して実行します:

    1. sanitized session IDsessionId の検証および/またはサニタイズされたバージョンとします。

      Note

      ユーザーエージェントは sessionId を CDM に渡す前に徹底的に検証するべきです。最低でも長さや値が妥当であること(例えば数十文字より長くない、英数字である、等)を確認すべきです。

    2. もし直前の手順が失敗した、または sanitized session ID が空であれば、新しく作成した TypeErrorpromise を拒否します。

    3. もしこのオブジェクトの MediaKeySession の中で、このオブジェクトの Document に属し、かつ sessionId 属性が sanitized session ID である閉じられていないセッションが存在する場合、promiseQuotaExceededError で拒否します。

      Note

      言い換えれば、このブラウジングコンテキスト内ですでに閉じられていないセッション(タイプに関わらず)がこの sanitized session ID を持つ場合はセッションを作成してはなりません。

    4. expiration timeNaN とします。

    5. message を null とします。

    6. message type を null とします。

    7. cdm をこのオブジェクトの cdm instance 値で表される CDM インスタンスとします。

    8. cdm を使用して次の手順を実行します:

      1. もし originsanitized session ID のデータが存在しない場合、promisefalse で解決してこれらの手順を中止します。

      2. もし保存されたセッションの session type が現在のこのオブジェクトの session type と異なる場合、promise を新しく作成した TypeError で拒否します。

      3. session dataorigin に保存されている sanitized session ID 用のデータとします。このデータは他の origin のデータや origin に関連付けられていないデータを含んではなりません(MUST NOT)。

      4. もしどの MediaKeySession オブジェクトも閉じられておらず、かつその session data を表すものが任意の Document に存在する場合、promiseQuotaExceededError で拒否します。

        Note

        言い換えれば、任意のブラウジングコンテキスト内ですでに非閉じられた永続セッションがこの sanitized session ID について存在する場合はセッションを作成してはなりません。

      5. session data をロードします。

      6. もし session data がセッションの expiration time を示しているなら、expiration time をその期限時刻にします。

      7. もしメッセージを送信する必要があるなら、次の手順を実行します:

        1. messagesession data に基づいて生成されたメッセージとします。

        2. message type をそのメッセージに適切な MediaKeyMessageType とします。

    9. Queue a task を使って次の手順を実行します:

      1. もし前段のいずれかの手順が失敗したなら、適切な error namepromise を拒否します。

      2. sessionId 属性を sanitized session ID に設定します。

      3. このオブジェクトの callable 値を true に設定します。

      4. もしロードされたセッションがいかなる鍵に関する情報(known keys)を含むなら、各鍵の key ID と適切な MediaKeyStatus を渡して、Update Key Statuses アルゴリズムを session 上で実行します。

        もし鍵の状態を確定するために追加処理が必要であれば、"status-pending" を使用します。1 つ以上の鍵に対する追加処理が完了したら、実際の状態で再度 Update Key Statuses アルゴリズムを実行します。

      5. Update Expiration アルゴリズムを session 上で実行し、expiration time を提供します。

      6. promisetrue で解決します。

      7. もし message が null でなければ、Queue a "message" Event アルゴリズムを session 上で実行し、message typemessage を提供します。

  9. promise を返します。

update()

ライセンスを含むメッセージを CDM に提供します。

response パラメータは CDM に提供されるメッセージを含みます。内容は Key System 固有です。実行可能なコードを含んではなりません(MUST NOT)。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの closing or closed 値が true であれば、InvalidStateError で拒否されたプロミスを返します。

  2. もしこのオブジェクトの callable 値が false であれば、InvalidStateError で拒否されたプロミスを返します。

  3. もし response が空の配列であれば、新しく作成した TypeError で拒否されたプロミスを返します。

  4. response copyresponse パラメータの内容のコピーとします。

  5. promise を新しいプロミスとします。

  6. 次の手順を並行して実行します:

    1. sanitized responseresponse copy の検証および/またはサニタイズされたバージョンとします。

      Note

      ユーザーエージェントは CDM に渡す前に response を徹底的に検証するべきです。これには値が合理的な範囲内にあることの検証、無関係なデータやフィールドの削除、事前解析、サニタイズ、完全にサニタイズされたバージョンの生成などが含まれ得ます。フィールドの長さや値が妥当であることを確認し、未知のフィールドは拒否または削除するべきです。

    2. もし直前の手順が失敗した、または sanitized response が空であれば、promise を新しく作成した TypeError で拒否します。

    3. message を null とします。

    4. message type を null とします。

    5. session closed を false とします。

    6. cdm をこのオブジェクトの cdm instance 値で表される CDM インスタンスとします。

    7. cdm を使用して次の手順を実行します:

      1. もし sanitized response の形式が何らかの方法で無効であれば、promise を新しく作成した TypeError で拒否します。

      2. sanitized response を処理し、以下のリストの最初に一致する条件に従って処理を行います:

        もし sanitized response がライセンスまたは鍵を含む場合
        Note

        これには初期ライセンス、更新ライセンス、ライセンス更新メッセージが含まれます。

        sanitized response を処理し、以下のリストの最初に一致する条件に従います:

        もし sessionType が "temporary" であり、かつ sanitized response が含むセッションデータ(ライセンス、鍵、類似のセッションデータを含む)が保存されるべきであると指定していない場合

        sanitized response を処理し、セッションデータを保存しません。

        もし sessionType が "persistent-license" であり、かつ sanitized response が永続化可能なライセンスを含む場合

        sanitized response を処理し、sanitized response に含まれるライセンス/鍵および関連するセッションデータを保存します。そのようなデータはこのオブジェクトの origin のみがアクセスできるように保存されなければなりません(MUST)。

        それ以外

        promise を新しく作成した TypeError で拒否します。

        詳細は Session Storage and Persistence も参照してください。

        各セッションの状態情報(鍵を含む)は、あるセッションを閉じても他のセッションの観測可能な状態に影響を与えないように保存されなければなりません(MUST)。たとえそれらが重複する key ID を含んでいてもです。

        Note

        sanitized response が鍵や関連データを含む場合、cdm は通常それらを鍵 ID でインデックスされた(メモリ内の)データとして格納するでしょう。

        Note

        セッション内での置換アルゴリズムは Key System に依存します。

        Note

        CDM 実装は、各 MediaKeySession オブジェクトあたりの標準的かつ十分に大きな最小鍵数、標準的な置換アルゴリズム、および標準的かつ十分に大きな最小セッション数をサポートすることが RECOMMENDED です。これによりユーザーエージェント間で鍵ローテーションアルゴリズムの実装が容易になり、同一要素で複数ストリームが存在するケース(適応ストリームや異なる音声/映像トラックなど)で再生中断の可能性を減らせます。

        もし sanitized responserecord of license destruction の確認応答を含み、かつ sessionType が "persistent-license" である場合

        次の手順を実行します:

        1. key session を閉じ、当該オブジェクトに関連する すべて の保存されたセッションデータ(sessionIdrecord of license destruction を含む)を消去します。

          Note

          その後にこのオブジェクトの load() を当該オブジェクトの sessionId の値で呼んでも失敗することになります(そのセッション ID に対するデータが存在しないため)。

        2. session closed を true に設定します。

        それ以外

        sanitized response を処理し、セッションデータを保存しません。

        Note

        例えば sanitized response が別の message イベントを生成するために用いられる情報を含む場合があります。この場合、sessionType に対して内容を検証する必要はありません。

      3. もしメッセージを送信する必要があるなら、次の手順を実行します:

        1. message をそのメッセージとします。

        2. message type をそのメッセージに適切な MediaKeyMessageType とします。

    8. Queue a task を使って次の手順を実行します:

      1. もし session closed が true なら:

        このオブジェクト上で Session Closed アルゴリズムを理由 "release-acknowledged" で実行します。

        それ以外

        次の手順を実行します:

        1. もしこのオブジェクトに対して CDM によって知られている鍵の集合が変更された、または任意の鍵の状態が変化した場合、各既知鍵の key ID と適切な MediaKeyStatus を渡して、Update Key Statuses アルゴリズムを session 上で実行します。

          鍵の状態を確定するために追加処理が必要な場合は "status-pending" を使用します。追加処理が完了したら、実際の状態で再度 Update Key Statuses を実行します。

        2. もしセッションの expiration time が変化していれば、Update Expiration アルゴリズムを session 上で実行し、新しい expiration time を提供します。

        3. もし前段のいずれかの手順が失敗したなら、適切な error name を名前に持つ新しい DOMExceptionpromise を拒否します。

        4. もし message が null でなければ、Queue a "message" Event アルゴリズムを session 上で実行し、message typemessage を提供します。

      2. promiseundefined で解決します。

  7. promise を返します。

close()

アプリケーションがもはやセッションを必要としないことを示します。CDM はセッションに関連するリソースを解放し、セッションを閉じるべきです。保存されたデータは解放や消去されるべきではありません。

Note

返されるプロミスはリクエストの処理が完了したときに解決され、セッションが閉じられたときには closed 属性プロミスが "closed-by-application" で解決されます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの closing or closed 値が true であれば、undefined で解決されたプロミスを返します。

  2. もしこのオブジェクトの callable 値が false であれば、InvalidStateError で拒否されたプロミスを返します。

  3. promise を新しいプロミスとします。

  4. このオブジェクトの closing or closed 値を true に設定します。

  5. 次の手順を並行して実行します:

    1. cdm をこのオブジェクトの cdm instance 値で表される CDM インスタンスとします。

    2. cdm を使用してこのオブジェクトに関連する key session を閉じます。

      Note

      キーセッションを閉じると、明示的に保存されていないライセンスや鍵が破棄されます。

    3. Queue a task を使って次の手順を実行します:

      1. promiseundefined で解決します。

      2. このオブジェクト上で Session Closed アルゴリズムを理由 "closed-by-application" で実行します。

  6. promise を返します。

remove()

セッションに関連するすべてのライセンスおよび鍵を削除します。永続セッションタイプ の場合、リリースメッセージの確認応答が update() によって処理されると、セッションタイプごとに定義される他のセッションデータも消去されます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. もしこのオブジェクトの closing or closed 値が true であれば、InvalidStateError で拒否されたプロミスを返します。

  2. もしこのオブジェクトの callable 値が false であれば、InvalidStateError で拒否されたプロミスを返します。

  3. promise を新しいプロミスとします。

  4. 次の手順を並行して実行します:

    1. cdm をこのオブジェクトの cdm instance 値で表される CDM インスタンスとします。

    2. message を null とします。

    3. message type を null とします。

    4. cdm を使用して次の手順を実行します:

      1. もしセッションに関連するライセンスや鍵が存在する場合:

        1. セッションに関連するライセンスや鍵を破棄します。

          Note

          これはそれらがメモリ内にあろうと永続ストアにあろうと、ライセンスおよび/または鍵が破壊されることを意味します。

        2. このオブジェクトの session type の値に対するリストの手順に従います:

          "temporary"

          次の手順を続行します。

          "persistent-license"
          1. record of license destruction を当該オブジェクトが表すライセンスのための record of license destruction とします。

          2. record of license destruction を保存します。

          3. messagerecord of license destruction を含むかそれを反映するメッセージとします。

    5. Queue a task を使って次の手順を実行します:

      1. Update Key Statuses アルゴリズムを session 上で実行し、セッション内のすべての key ID に対して "released" の MediaKeyStatus 値を提供します。

      2. Update Expiration アルゴリズムを session 上で実行し、NaN を提供します。

      3. もし前段のいずれかの手順が失敗したなら、適切な error name を名前に持つ新しい DOMExceptionpromise を拒否します。

      4. message type を "license-release" にします。

      5. promiseundefined で解決します。

      6. もし messagenull でなければ、Queue a "message" Event アルゴリズムを session 上で実行し、message typemessage を提供します。

  5. promise を返します。

6.3 MediaKeyStatusMap インターフェース

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);
};

6.3.1 属性

sizeunsigned long, readonly

known keys の数。

6.3.2 メソッド

has()

keyId で識別される鍵の状態が既知であれば true を返します。

get()

keyId で識別される鍵の MediaKeyStatus を返すか、 その鍵の状態が既知でなければ undefined を返します。

このインターフェースは、entrieskeysvaluesforEach および @@iterator メソッドを iterable により提供します [WebIDL]。

反復対象となる値のペアは、すべての known keys に対して形成された (key ID, 対応する MediaKeyStatus) のスナップショットであり、 key ID によってソートされています。key ID の比較は次のように行われます: 長さが m の key ID A と長さが nBm <= n に割り当てられている)について、A の方が小さい (A < B) のは、Am オクテットが 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;
};

6.4.1 属性

messageTypeMediaKeyMessageType, readonly
メッセージの種類。

実装はアプリケーションにメッセージタイプの処理を要求してはなりません(MUST NOT)。実装はメッセージを区別しないアプリケーションをサポートしなければならず(MUST)、メッセージタイプの処理を強制してはなりません(MUST NOT)。 具体的には、Key Systems はすべての種類のメッセージを単一の URL に渡すことをサポートしなければなりません(MUST)。

この属性は、メッセージを解析せずにアプリケーションがメッセージを区別できるようにするためのものです。これはオプションのアプリケーションやサーバーの最適化を可能にすることを意図していますが、アプリケーションはこれを使用する必要はありません。

messageArrayBuffer, readonly

CDM からのメッセージ。メッセージは Key System 固有です。

6.4.2 MediaKeyMessageEventInit

WebIDLdictionary MediaKeyMessageEventInit : EventInit {
  required MediaKeyMessageType messageType;
  required ArrayBuffer         message;
};
6.4.2.1 辞書 MediaKeyMessageEventInit のメンバー
messageTypeMediaKeyMessageType
メッセージの種類。
messageArrayBuffer
メッセージ。

6.5 Event Summary

この節は非規範的です。

イベント名 インターフェース 発生条件
keystatuseschange Event セッション内の鍵やその状態に変化があったとき。
message MediaKeyMessageEvent CDM がセッションのためにメッセージを生成したとき。

6.6 アルゴリズム

6.6.1 「message」イベントをキューする

「message」イベントをキューするアルゴリズムは、MediaKeySession オブジェクトに対してメッセージイベントをキューします。 このアルゴリズムを実行する要求には、ターゲットとなる MediaKeySession オブジェクト、message type、および message が含まれます。

message は暗号化された形であっても Distinctive Permanent Identifier(s) を含んではいけません(MUST NOT)。また、もし該当の MediaKeySession オブジェクトの use distinctive identifier 値が false の場合、message は暗号化された形であっても Distinctive Identifier(s) を含んではいけません(MUST NOT)。

次の手順を実行します:

  1. session を指定された MediaKeySession オブジェクトとします。

  2. タスクをキューして、バブリングせずキャンセル不可能な名前が message というイベントを作成し、MediaKeyMessageEvent インターフェースを用いてそのイベントを生成し、type 属性を message に、isTrusted 属性を true に初期化し、それを session に対してディスパッチします。

    イベントインターフェース MediaKeyMessageEvent は次を持ちます:

6.6.2 鍵の状態を更新する

鍵の状態を更新するアルゴリズムは、known 鍵の集合や、1つ以上の鍵の状態を MediaKeySession に対して更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession オブジェクトと、key ID とそれに対応する MediaKeyStatus の対の列が含まれます。

このアルゴリズムは常にタスク内で実行されます。

次の手順を実行します:

  1. session を該当する MediaKeySession オブジェクトとします。

  2. input statuses を、key ID とそれに対応する MediaKeyStatus の対の列とします。

  3. statusessessionkeyStatuses 属性とします。

  4. statuses の内容を置き換えるために次の手順を実行します:

    1. statuses を空にします。

    2. input statuses の各対について以下を行います。

      1. pair をその対とします。

      2. pair の key ID に対するエントリを statuses に挿入し、pairMediaKeyStatus 値を設定します。

    この手順の効果は、sessionkeyStatuses 属性の内容が既存の参照を無効にすることなく置き換えられる、ということです。この置換はスクリプトの観点から原子操作です。つまり、スクリプトは決して部分的にしか埋められていない状態を観測してはなりません(MUST NOT)。

  5. タスクをキューして、イベントを発火 する処理を実行し、名前が keystatuseschange のイベントを session に対して発火します。

  6. タスクをキューして、各メディア要素について mediaKeys 属性がこの session を作成した MediaKeys オブジェクトである場合に、Attempt to Resume Playback If Necessary アルゴリズムを実行します。

6.6.3 有効期限を更新する

有効期限を更新するアルゴリズムは、expiration timeMediaKeySession に対して更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession オブジェクトと、新しい有効期限(NaN である場合があります)が含まれます。

このアルゴリズムは常にタスク内で実行されます。

次の手順を実行します:

  1. session を該当する MediaKeySession オブジェクトとします。

  2. expiration timeNaN とします。

  3. 新しい有効期限が NaN でないなら、expiration time をその値とします。

  4. sessionexpiration 属性を、time として表現された expiration time に設定します。

6.6.4 セッションが閉じられた

セッションが閉じられたアルゴリズムは、MediaKeySession の状態を、key sessionCDM によって閉じられた後に更新します。このアルゴリズムを実行する要求には、ターゲットの MediaKeySession オブジェクトと、MediaKeySessionClosedReason が含まれます。

このアルゴリズムは常にタスク内で実行されます。

セッションが閉じられると、当該セッションに関連するライセンスや鍵はメディアデータの復号に利用できなくなります。すべての MediaKeySession のメソッドは失敗し、このアルゴリズム実行後はこのオブジェクトに対してさらにイベントがキューされることはありません。

CDM は、セッションが不要になったときやシステムリソースが失われたときなど、任意の時点でセッションを閉じることがあります。その場合、Monitor for CDM State Changes アルゴリズムが変化を検出してこのアルゴリズムを実行します。

他のセッション内の鍵は、たとえ重複する key ID を持っていても影響を受けてはなりません(MUST)。

このアルゴリズム実行後、当該アルゴリズムによってキューされたイベントハンドラは実行されますが、それ以降はさらにイベントをキューすることはできません。その結果、セッションを閉じたことにより CDM がメッセージを送信することはできなくなります。

次の手順を実行します:

  1. session を該当する MediaKeySession オブジェクトとします。

  2. promisesessionclosed 属性とします。

  3. もし promise が既に解決されているなら、この手順を中止します。

  4. sessionclosing or closed 値を true に設定します。

  5. Update Key Statuses アルゴリズムを session 上で空の列を提供して実行します。

  6. Update Expiration アルゴリズムを session 上で NaN を提供して実行します。

  7. promise を与えられた理由で解決します。

6.6.5 CDM の状態変化を監視する

CDM の状態変化を監視するアルゴリズムは、CDM 状態の変化に伴って必要となる手順を実行します。

このアルゴリズムは、他のアルゴリズムで扱われていない CDM の状態変化にのみ適用されます。たとえば、update() はメッセージ、鍵状態の変化、または有効期限の変化をもたらすことがありますが、それらはすべて当該アルゴリズム内で処理されます。

このアルゴリズムは常にメインイベントループと並列して実行されます。

次の手順を実行します:

  1. sessionMediaKeySession オブジェクトとします。

  2. cdmsessioncdm instance 値で表される CDM インスタンスとします。

  3. もし cdm にまだ送信されていない送信メッセージがあるなら、タスクをキューして次の手順を実行します:

    1. message typemessage をメッセージの種類とメッセージにそれぞれ設定します。

    2. 「message」イベントをキューする アルゴリズムを実行し、sessionmessage typemessage を渡します。

  4. もし cdmsession に対して known な鍵の集合を変更したか、あるいは 1つ以上の鍵の状態を変更したなら、タスクをキューして次の手順を実行します:

    1. statuses を、sessionknown な各鍵につき 1 対の key ID と MediaKeyStatus 値を含むリストとします。

    2. 鍵の状態を更新する アルゴリズムを実行し、sessionstatuses を渡します。

  5. もし cdmsessionexpiration time を変更したなら、タスクをキューして次の手順を実行します:

    1. expiration timesession の新しい有効期限とします。

    2. 有効期限を更新する アルゴリズムを実行し、sessionexpiration time を渡します。

  6. もし cdmsession を閉じたなら、タスクをキューして、セッションが閉じられた アルゴリズムを適切な MediaKeySessionClosedReason 値で session に対して実行します。

  7. もし cdm がハードウェアコンテキストリセットにより利用不能になったなら、タスクをキューして、CDM Unavailable アルゴリズムを理由 "hardware-context-reset" で実行します。

  8. もし cdm が他の理由で利用不能になったなら、タスクをキューして、CDM Unavailable アルゴリズムを理由 "internal-error" で実行します。

6.7 例外

メソッドは、返されたプロミスを 単純例外 [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 に対して未閉セッションがすでに存在する。
新しいセッションやライセンス要求を作成するためのリソースが不足している。

6.8 セッションの保存と永続化

本節は、アルゴリズムを補足するセッション保存と永続化の概要を示します。

以下の要件は、Storage and Persistence の要件に加えて適用されます。

このオブジェクトの session type に対して Is persistent session type? アルゴリズムを実行した結果が false であれば、ユーザーエージェントおよび CDM はセッションに関連する記録やデータ(ライセンス、鍵、record(s) of license destructionSession ID を含む)をいかなる時点でも永続化してはならない(MUST NOT)。

この節の残りは、Is persistent session type? アルゴリズムが true を返すセッションタイプに適用されます。

CDMSHOULD NOT update() が初めて呼ばれるまでは、Session ID を含むセッションデータを保存すべきではありません。特に、CDMgenerateRequest() アルゴリズムの間にセッションデータを保存すべきではありません(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 を参照してください。

7. HTMLMediaElement 拡張

この節では、Encrypted Media Extensions がサポートされている場合の HTMLMediaElement [HTML] への追加および変更について規定します。

以下の内部値が HTMLMediaElement に追加されます:

以下の変更が HTMLMediaElement の挙動に加えられます:

プロミスを返すメソッドにおいて、すべてのエラーは返された 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);
};

7.1 属性

mediaKeysMediaKeys、readonly、nullable

このメディア要素で暗号化された media data を復号する際に使用される MediaKeys

onencryptedEventHandler

encrypted イベントのイベントハンドラ。全ての HTMLMediaElement でコンテンツ属性およびIDL属性として MUST サポートされなければなりません。

onwaitingforkeyEventHandler

waitingforkey イベントのイベントハンドラ。全ての HTMLMediaElement でコンテンツ属性およびIDL属性として MUST サポートされなければなりません。

7.2 メソッド

setMediaKeys()

再生中のメディアデータの復号に使用する MediaKeys を指定します。

再生中に関連付けられた MediaKeys オブジェクトをクリアまたは置換することのサポートは実装品質に依存します。多くの場合、悪いユーザー体験やプロミスの拒否につながります。

このメソッドが呼ばれたとき、ユーザーエージェントは次の手順を 必ず 実行しなければなりません:

  1. このオブジェクトの attaching media keys 値が true なら、InvalidStateError で拒否されたプロミスを返します。

  2. mediaKeysmediaKeys 属性が同じオブジェクトなら、undefined で解決されたプロミスを返します。

  3. このオブジェクトの attaching media keys 値を true にします。

  4. promise を新しいプロミスとします。

  5. 次の手順を並行して実行します:

    1. 以下の条件がすべて成り立つ場合:

      • mediaKeys が null でない

      • mediaKeys で表される CDM インスタンスが他のメディア要素ですでに使用されている

      • ユーザーエージェントがこの要素でそれを使用できない

      この場合はこのオブジェクトの attaching media keys 値を false にし、promiseQuotaExceededError で拒否します。

    2. mediaKeys 属性が null でない場合、次の手順を実行します:

      1. ユーザーエージェントまたは CDM が関連付け解除をサポートしない場合は、このオブジェクトの attaching media keys 値を false にし、promiseNotSupportedError で拒否します。

      2. 現時点で関連付け解除できない場合は、このオブジェクトの attaching media keys 値を false にし、promiseInvalidStateError で拒否します。

        例えば一部の実装では再生中の解除を許可しません。

      3. mediaKeys 属性で表される CDM インスタンスの利用を停止し、メディア要素との関連付けも解除します。

      4. 上記の手順が失敗した場合は、このオブジェクトの attaching media keys 値を false にし、promise を適切な error name で拒否します。

    3. mediaKeys が null でない場合、次の手順を実行します:

      1. mediaKeys で表される CDM インスタンスをメディア要素に関連付け、media data の復号に使用するようにします。

      2. 上記の手順が失敗した場合は次の手順を実行します:

        1. mediaKeys 属性を null にします。

        2. このオブジェクトの attaching media keys 値を false にします。

        3. promise を適切な error name で新しい DOMException で拒否します。

      3. タスクをキューして、メディア要素上で Attempt to Resume Playback If Necessary アルゴリズムを実行します。

    4. mediaKeys 属性を mediaKeys に設定します。

    5. このオブジェクトの attaching media keys 値を false にします。

    6. promiseundefined で解決します。

  6. promise を返します。

MediaEncryptedEvent オブジェクトは encrypted イベントで使用されます。

WebIDL[Exposed=Window]
interface MediaEncryptedEvent : Event {
    constructor(DOMString type, optional MediaEncryptedEventInit eventInitDict = {});
    readonly        attribute DOMString    initDataType;
    readonly        attribute ArrayBuffer? initData;
};

7.3.1 属性

initDataTypeDOMString、readonly
このイベントに含まれる Initialization Data Type を示します。Initialization DatainitData 属性に格納されています。
initDataArrayBuffer、readonly、nullable
このイベントの Initialization Data

7.3.2 MediaEncryptedEventInit

WebIDLdictionary MediaEncryptedEventInit : EventInit {
  DOMString    initDataType = "";
  ArrayBuffer? initData = null;
};
7.3.2.1 辞書 MediaEncryptedEventInit のメンバー
initDataTypeDOMString、 デフォルト値 ""
Initialization Data Type
initDataArrayBuffer、 nullable、デフォルト値 null
Initialization Data

7.4 イベント概要

この節は非規範的です。

イベント名 インターフェース 発生条件 前提条件
encrypted MediaEncryptedEvent ユーザーエージェントが Initialization Datamedia data で検出したとき。 要素の readyStateHAVE_METADATA 以上であること。

要素が再生中または再生済みの場合もあり得ます。

waitingforkey Event 再生が鍵待ちでブロックされている。 readyStateHAVE_CURRENT_DATA 以下であること。 要素の playback blocked waiting for key の値が新たに true になったとき。

7.5 アルゴリズム

7.5.1 Media Data May Contain Encrypted Blocks

「Media Data May Contain Encrypted Blocks」アルゴリズムは、ユーザーエージェントがメディアデータを再生する前に MediaKeys オブジェクトの指定を要求する場合に再生を一時停止します。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. もし media elementmediaKeys 属性が null であり、実装が暗号化されている可能性のある media data のデコード前に MediaKeys オブジェクトの指定を要求する場合は、次の手順を実行します:

    これらの手順は、アプリケーションが media data を提供した後に setMediaKeys() を呼んで MediaKeys オブジェクトを提供するような場合に到達することがあります。CDM の選択はパイプラインやデコーダに影響を与える可能性があるため、一部の実装では CDMMediaKeys として setMediaKeys() に渡されるまで、暗号化ブロックを含む可能性のあるメディアデータの再生を遅延させることがあります。

    1. Wait for Key アルゴリズムを media element に対して実行します。

    2. 再生を再開するためのシグナルを待ちます。

7.5.2 Initialization Data Encountered

「Initialization Data Encountered」アルゴリズムは、メディアデータ中で発見された encrypted イベントをキューします。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. initDataType を空文字列とします。

  3. initData を null とします。

  4. もし media dataCORS-same-origin であり、かつ 混在コンテンツではない 場合、次の手順を実行します:

    1. initDataType を、発見された Initialization Data の Initialization Data Type を表す文字列とします。

    2. initData を Initialization Data とします。

    メディア要素は「Upgradeable Content」を許可する場合がありますが、そのようなメディアデータからの Initialization Data をアプリケーションに公開してはなりません(MUST NOT)。

  5. タスクをキューして、バブリングせずキャンセル不可の名前が encrypted というイベントを MediaEncryptedEvent インターフェースを使って作成し、type 属性を encrypted に、isTrustedtrue に初期化して media element 上でディスパッチします。

    イベントインターフェース MediaEncryptedEvent は次を持ちます:

    readyState は変更されず、アルゴリズムは中止されません。 このイベントは単に情報を提供するものです。

    initData 属性は、メディアデータが CORS-same-origin でない か、または 混在コンテンツ である場合は null になります。アプリケーションは代替ソースから Initialization Data を取得することができます。

7.5.3 Encrypted Block Encountered

「Encrypted Block Encountered」アルゴリズムは、復号のために暗号化されたメディアデータのブロックをキューに入れ、可能であれば復号を試みます。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. block を暗号化されたメディアデータのブロックとします。

  3. blockmedia elementencrypted block queue の末尾に追加します。

  4. もし media elementdecryption blocked waiting for key 値が false であれば、Attempt to Decrypt アルゴリズムを実行します。

7.5.4 Attempt to Decrypt

「Attempt to Decrypt」アルゴリズムは、復号のためにキューに入れられているメディアデータの復号を試みます。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. もし media elementencrypted block queue が空であれば、この手順を中止します。

  3. もし media elementmediaKeys 属性が null でない場合、次の手順を実行します:

    1. media keys をその属性が参照する MediaKeys オブジェクトとします。

    2. cdmmedia keyscdm instance 値で表される CDM インスタンスとします。

    3. もし cdm が何らかの理由でもはや使用不可能であれば、次の手順を実行します:

      1. media data is corrupted の手順を resource fetch algorithm の対応箇所で実行します。

      2. CDM Unavailable アルゴリズムを、media keys に対して、ハードウェアコンテキストのリセットの場合は理由を "hardware-context-reset"、それ以外の場合は "internal-error" として実行します。

      3. この手順を中止します。

    4. もし media keys によって作成された MediaKeySession が少なくとも1つ存在し、それが closed でない場合、次の手順を実行します:

      このチェックは、cdm の読み込みが完了し、対応する鍵が利用可能である前提条件を保証するためのものです。

      1. blockmedia elementencrypted block queue の先頭のエントリとします。

      2. block key IDblock の key ID とします。

        key ID は一般にコンテナによって指定されます。

      3. cdm を使用して次の手順を実行します:

        1. available keys を、media keys によって作成されたセッション内の鍵の和集合とします。

        2. block key を null とします。

        3. もし available keys の中に block key ID に対応し、かつ usable for decryption なものがあれば、当該鍵を含む MediaKeySession オブジェクトを session とし、当該鍵を block key とします。

          複数のセッションに対して block key ID に対応する usable for decryption な鍵が含まれている場合、どのセッションと鍵を使用するかは Key System に依存します。

        4. もし前のステップの実行によって available keys の状態が変更された場合、影響を受けた各 session に対して、すべての key ID とそれに対応する適切な MediaKeyStatus 値を渡して、Update Key Statuses アルゴリズムをキューするタスクを起動します。

        5. もし block key が null でない場合、次の手順を実行します:

          1. cdm を使って blockblock key で復号します。

          2. 以下のリストの最初に一致する条件に従って処理します:

            もし復号が失敗した場合
            1. media data is corrupted の手順を resource fetch algorithm の対応箇所で実行します。

            2. もし cdm がもはや使用不可能であれば、CDM Unavailable アルゴリズムを media keys に対して、ハードウェアコンテキストリセットの場合は "hardware-context-reset"、それ以外は "internal-error" の理由で実行します。

            3. この手順を中止します。

            それ以外
            1. blockmedia elementencrypted block queue の先頭から削除します。

            2. 復号済みブロックを通常どおり処理します。

              つまり、そのブロックをデコードします。

            3. このアルゴリズムの先頭に戻ります。

            すべての復号の問題(例: 間違った鍵を使うなど)がここでの復号失敗を引き起こすわけではありません。そのような場合、ここではエラーが発生しないが、デコード中にエラーが発生する可能性があります。

          そうでなければ、いかなるセッションにも block key ID の鍵が存在しないため、処理を継続します。

  4. media elementdecryption blocked waiting for key 値を true に設定します。

    この手順は、block に対して usable for decryption な鍵がない場合に到達します。

    ユーザーエージェントが復号できないブロックに先行するブロックを(可能な限り、例えば完全なビデオフレーム全てなど)レンダリングした後、Wait for Key アルゴリズムを実行します。

    このアルゴリズムをここで直接実行しないのは、実装が現在の再生位置より先にメディアデータを復号・デコードすることを許容し、その可視的挙動に影響を与えないようにするためです。

フレームベースの暗号化の場合、メディア要素がリソース取得アルゴリズムの一部としてフレームのデコードを試みるときに、以下のように実装できることがあります:

  1. encrypted を false にします。

  2. フレームが暗号化されているかどうかを検出します。

    フレームが暗号化されている場合
    上記の手順を実行します。
    それ以外
    続行します。
  3. フレームをデコードします。

  4. レンダリングのためにフレームを提供します。

7.5.5 Wait for Key

「Wait for Key」アルゴリズムは waitingforkey イベントをキューし、readyState を更新します。 このアルゴリズムは、HTMLMediaElement オブジェクトが potentially playing であり、その readyStateHAVE_FUTURE_DATA 以上のときにのみ呼び出すべきです。 このアルゴリズムを実行する要求にはターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. もし media elementplayback blocked waiting for key 値が true であれば、この手順を中止します。

  3. media elementplayback blocked waiting for key 値を true に設定します。

    上の手順の結果、メディア要素はまだでなければ blocked media element となり得ます。その場合、メディア要素は再生を停止します。

  4. 以下のリストの最初に一致する条件に従います:

    もし直近の current playback position に対するデータが利用可能である場合

    media elementreadyStateHAVE_CURRENT_DATA に設定します。

    それ以外

    media elementreadyStateHAVE_METADATA に設定します。

    言い換えれば、現在の再生位置のビデオフレームやオーディオデータが非暗号化であったり正常に復号されたためにデコード済みであれば readyStateHAVE_CURRENT_DATA に設定します。そうでない場合、または以前はその状態だったが現在はデータが利用できない場合は readyStateHAVE_METADATA に設定します。

  5. タスクをキューして、イベント発火 を行い、名前が waitingforkey のイベントを media element に対して発火します。

  6. 再生を一時停止します。

7.5.6 Attempt to Resume Playback If Necessary

「Attempt to Resume Playback If Necessary」アルゴリズムは、メディア要素が鍵待ちでブロックされており、必要な鍵が現在 usable for decryption である場合に再生を再開します。 このアルゴリズムを実行する要求には、ターゲットの HTMLMediaElement オブジェクトが含まれます。

次の手順を実行します:

  1. media element を指定された HTMLMediaElement オブジェクトとします。

  2. もし media elementplayback blocked waiting for keyfalse であれば、この手順を中止します。

  3. Attempt to Decrypt アルゴリズムを media element に対して実行します。

  4. もしユーザーエージェントが current playback position を再生方向に進めることができるなら:

    1. media elementdecryption blocked waiting for key 値を false に設定します。

    2. media elementplayback blocked waiting for key 値を false に設定します。

      上の手順の結果、メディア要素はもはや blocked media element でなくなる可能性があり、その結果として再生が再開されることがあります。

    3. media elementreadyState を、状況に応じて HAVE_CURRENT_DATAHAVE_FUTURE_DATA、または HAVE_ENOUGH_DATA に設定します。

      HAVE_CURRENT_DATA より先の状態や canplaythrough イベントは、通常、現在の鍵以上の鍵の利用可能性を考慮しない(またはあまり考慮しない)ことに注意してください。

      ready state の変更は、HTMLMediaElement によるイベントの発火を引き起こすことがあります(詳細は こちら を参照)。

7.6 メディア要素の制約

この節は規範的ではありません。

CDM によって処理されるメディアデータは、通常の方法(例えば CanvasRenderingContext2DdrawImage() メソッドや AudioContextMediaElementAudioSourceNode を用いる等)を通じてウェブプラットフォームの API から利用できないことがMAYあります。 本仕様はそのようなメディアデータの非利用可能性の条件を定義しませんが、もしメディアデータがそのような API を通じて利用できない場合、これらの API はメディアデータがまったく存在しないかのように振る舞うことがMAYあります。

メディアレンダリングが UA によって行われない場合、例えばハードウェアベースのメディアパイプラインの場合、CSS トランスフォーム等の HTML のレンダリング機能のすべてが利用できないことがMAYあります。典型的な制約の一つとしては、ビデオメディアがウィンドウの辺に平行な辺を持ち、通常の向きに整った矩形領域のみに表示が制限されることがMAYあります。

8. 実装要件

この節は、アルゴリズムで明示的に扱われていないかもしれない実装要件(ユーザーエージェントおよび Key Systems、および CDM やサーバーを含む)を定義します。ここおよび仕様全体の要件は、CDM がユーザーエージェントの外部にあるか内部に組み込まれているかにかかわらず、すべての実装に適用されます。

8.1 CDM 制約

ユーザーエージェントの実装者は、CDM が、本仕様の機能を用いた保護されたメディアの再生に合理的に必要とされる範囲を超える情報、ストレージ、またはシステム能力へアクセスしないことをMUST 確実にしなければなりません。具体的には、CDMSHALL NOT 次を行ってはなりません:

ユーザーエージェントの実装者は上記要件を満たすために様々な手法を用いることができます。例えば、自身で CDM を実装する実装者は、そのコンポーネントに上記を設計要件として組み込むことができます。サードパーティの CDM を利用する実装者は、それが禁止された情報やコンポーネントへアクセスできない制約付き環境(例えば「サンドボックス」)で実行されることを保証することができます。

8.2 メッセージおよび通信

CDM との間のすべてのメッセージおよび通信(CDM とライセンスサーバーの間のものなど)は、ユーザーエージェントを経由して渡されなければならない(MUST)。CDM は直接のアウトオブバンドなネットワークリクエストを行ってはならない(MUST NOT)。Direct Individualization で記述されたもの以外のすべてのメッセージと通信は、本仕様で定義された API を通じてアプリケーションを経由して渡されなければならない(MUST)。具体的には、アプリケーションが指定した URL に送信されるかその origin に基づく、アプリケーション固有、origin 固有、コンテンツ固有の情報を含む通信や、ライセンス交換メッセージはすべて API を経由しなければなりません。

8.3 永続データ

Persistent Data には、CDM、または CDM を代表してユーザーエージェントが保存する、MediaKeys オブジェクトの破棄後も残るすべてのデータが含まれます。具体的には、識別子(Distinctive Identifier(s) を含む)、ライセンス、鍵、鍵 ID、あるいは records of license destruction などが該当します。これらは CDM または CDM を代表してユーザーエージェントによって保存されます。

8.3.1 オリジン特有かつブラウジングプロファイル特有の Key System ストレージを使用すること

アプリケーションやライセンスサーバーに見える形でメッセージや振る舞いに影響を与え得る Persistent Data は、origin 固有かつ browsing profile 固有の方法で保存されなければならず(MUST)、プライベートブラウジングセッションへ流出したり、そこから漏れてはいけません(MUST NOT)。具体的には(網羅的ではありませんが)、セッションデータ、ライセンス、鍵、per-origin 識別子は originbrowsing profile ごとに保存されなければなりません。

詳細は Session Storage and Persistence を参照してください。

8.3.2 永続データの削除を許可すること

Persistent Data を使用する実装は、そのデータが本仕様で定義された API 経由など外部から、またクライアントデバイス上でも回復不能になるようにユーザーがデータを消去できることをMUST 許容しなければなりません。

ユーザーエージェントは SHOULD 次のことを行うべきです:

  • Persistent Data をクッキー等の他のサイトデータと同様に扱う。具体的には:

    • クッキーとともに 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 を特定に削除できるようにすること。

8.3.3 永続データを暗号化または難読化すること

ユーザーエージェントは Persistent Data を潜在的に機微な情報として扱うべきです。これらの情報が流出するとユーザーのプライバシーが損なわれる可能性があります。そのため、ユーザーエージェントは Persistent Data が安全に保存されるようにし、データを削除する際は基盤となるストレージから速やかに削除されることをSHOULD 確保すべきです。

8.4 アプリケーションに公開される値に関する要件

アプリケーションに公開される、あるいは CDM による使用などを通じて推測可能な値は、識別子として設計されていない場合でもクライアントやユーザーを特定するのに利用され得ます。本節はそのような懸念を回避または緩和するための要件を定義します。識別子に関する追加要件は Identifiers を参照してください。

8.4.1 オリジンごと・プロファイルごとの値を使用すること

アプリケーションに公開される、または推測可能なすべての Distinctive Values は、origin ごとおよび browsing profile ごとに固有でなければならない(MUST)。つまり、本仕様で定義された API を使用する一つの origin に対する値は、他の origin に対する値と異なるものでなければならず、また一つの browsing profile で使われる値は他のプロファイルで使われるものと異なるものでなければなりません。これらの値はプライベートブラウジングセッションへ漏れてはならず、そこから流出してはなりません。

オリジンやプロファイルをまたいだ値は、アプリケーションによって関連付け不可能(non-associable by applications)でなければなりません。すなわち、複数のオリジンやプロファイルからの値を相互に相関させて同一のクライアントやユーザーに由来するものと特定できてはなりません。オリジン独立またはプロファイル独立の値から per-origin 値を導出する実装は、上記の非関連付け性を保証する方法(非可逆性を持つ導出関数など)を用いなければなりません(MUST)。

8.4.2 値の消去を許可すること

Allow Persistent Data to Be Cleared の要件の結果として、アプリケーションに公開されたすべての永続化された値は、外部(本仕様で定義された API 経由等)およびクライアントデバイス上の双方で回復不能となるようにクリア可能でなければなりません(MUST)。

一度クリアされたら、新しい非関連付け可能な(non-associable by applications)値が、後で値が必要になったときに生成されなければなりません(MUST)。

8.5 識別子要件

実装による識別子の使用、特に 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)。

  • 本仕様で定義された API の使用に伴って生成される潜在的な識別子や Distinctive Values はすべて、origin と profile ごとに一意であり、かつクリア可能でなければならない(MUST)。これはランダム識別子、セッションデータ、その他の CDM データなどを含みますが、これらに限定されません。

8.5.1 目立つ識別子および永久識別子の使用を制限または回避すること

  • 実装は 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() の結果や、後続のセッションから生成されるライセンス要求に影響する可能性があります。

    ユーザーにこの実装機能を選択させることで、より高いプライバシーを維持しながらコンテンツへアクセスできるようになる場合があります。

8.5.2 識別子を暗号化すること

Distinctive IdentifiersDistinctive Permanent Identifiers は、クライアント外へ公開される際にメッセージ交換レベルで暗号化されなければなりません(MUST)。その他の識別子も、クライアント外へ公開される際にはメッセージ交換レベルで暗号化されるべきです(SHOULD)。暗号化は、識別子の暗号文の二つのインスタンスが復号鍵を持つエンティティのみによって関連付け可能(associable)であることを保証しなければなりません(MUST)。

識別子は次のような方法で公開され得ます:

  • message イベントを介してアプリケーションに。

  • サーバーからのメッセージ内で、例えば update() に渡されるものとして。

  • individualization の一部として。

CDM は、暗号化鍵がその Key System に対して有効なサーバーに属していることを検証しなければなりません(MUST)。アプリケーションに公開される識別子については、これは サーバー証明書 を用いて実装され得ます(MAY)。

サーバーは、識別子をそれを送った CDM 以外のエンティティに公開してはなりません(MUST NOT)。

具体的には、識別子をアプリケーションに提供したり、CDM に対するメッセージに平文で含めてはなりません。識別子やメッセージを暗号化し、その特定の CDM のみが復号できるようにすることでこれを達成できます。

これは次を意味します:

  • デバイス固有またはユーザー固有の鍵で作られる署名は、同じプレーンテキストであっても各署名が異なっていなければならない(MUST)。

  • デバイス固有またはユーザー固有の鍵に関連する識別子、鍵、証明書は、ライセンスや individualization サーバー向けに暗号化されなければならない(MUST)。

  • ライセンスサーバーから CDM へのメッセージは、意図された復号鍵の識別子(例えば対象の復号鍵の ID)など受信者固有の識別子を暗号封筒の外側に露出してはならない(MUST NOT)。

8.5.3 オリジンごと・プロファイルごとの識別子を使用すること

Distinctive Permanent Identifiers を除くすべての識別子は、originbrowsing profile ごとに一意でなければなりません(MUST)。詳細は 8.4.1 Use Per-Origin Per-Profile Values を参照してください。

これは Distinctive Identifiers を含みますがこれに限定されません。

Distinctive Permanent Identifiers はアプリケーションやオリジンに公開してはならない(MUST NOT)。

8.5.4 非紐付け可能な識別子を使用すること

実装がアプリケーションに公開するすべての識別子(Distinctive Identifiers を含む)、たとえ暗号化された形であっても、オリジン、browsing profiles、および 識別子のクリア を跨いでアプリケーションによって関連付けられない(non-associable by application)ものでなければなりません(MUST)。

そのような識別子について、複数のアプリケーションや関連するライセンスサーバー等が相関や関連付けを行えないことが求められます(MUST NOT)。

8.5.5 識別子の消去を許可すること

Allow Persistent Data to Be Cleared の要件の帰結として、Distinctive ValuesDistinctive 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)。

8.6 個別化

識別子、特に 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" の場合にのみ使用され得ます。

8.6.1 直接個別化

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 IdentifiersDistinctive Permanent Identifiers を暗号化すること。

  • MUST TLS を使用すること。

実装は、オリジン、オリジン固有またはアプリケーション固有の情報、もしくはオリジンと関連付け可能な(associable)値を中央集権的サーバーに、たとえ暗号化された形であっても公開してはなりません。そうするとユーザーやデバイスが訪れたすべてのオリジンの中央記録が作成される可能性があるためです。

8.6.2 アプリ支援個別化

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 関連するすべての message イベントに対してメッセージ種別 "individualization-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)。

8.7 複数鍵のサポート

実装は各 MediaKeySession オブジェクトで複数の鍵をサポートしなければなりません(MUST)。

複数の鍵をどのようにサポートするかの仕組みは実装の詳細ですが、アプリケーションおよび本仕様で定義された API から見て透明でなければなりません(MUST)。

実装は再生中の鍵間のシームレスな切替をサポートしなければなりません(MUST)。これには同一の MediaKeySession 内の鍵と、別の MediaKeySession オブジェクトにある鍵の両方が含まれます。

8.8 初期化データ型のサポート

8.8.1 生成されるライセンスはコンテンツタイプに依存しない

実装はサポートする任意の Initialization Data Type で生成されたライセンスを任意のコンテンツタイプで使用できるようにすることが SHOULD です。

そうでない場合、requestMediaKeySystemAccess() アルゴリズムは、例えば MediaKeySystemConfiguration のうちの一つが、initDataTypes のいずれかがある videoCapabilities と互換性がないとして拒否する可能性があります。

8.8.2 メディアデータからの抽出をサポートする

サポートされるコンテナに現れる可能性のある任意のサポートされた Initialization Data Type について、ユーザーエージェントはそれらのコンテナからその種の Initialization Data を抽出することを MUST サポートしなければなりません(initdata-encountered を参照)。

言い換えれば、ある Initialization Data Type のサポートを示すことは、CDM がライセンス要求を生成することをサポートすることと、コンテナ固有の型についてはユーザーエージェントがそのコンテナから抽出できることの両方を意味します。ただし、これは実装が任意のサポートされる Initialization Data を任意のサポートされるコンテンツタイプから解析できなければならない、という意味ではありません。

8.9 サポートされるメディア

本節は本仕様の実装がサポートすべきコンテンツ(media resource)の特性を定義します。

8.9.1 暗号化されていないコンテナ

メディアコンテナは暗号化されていてはならない(MUST NOT)。本仕様はユーザーエージェントがメディアデータを復号することなしにメディアコンテナを解析できることに依存します。これには Encrypted Block EncounteredInitialization Data Encountered アルゴリズム、および HTMLMediaElement の標準的な機能(例えば seeking)のサポートが含まれます。

8.9.2 相互運用可能に暗号化されている

すべてのトラックを含む Media resources は、コンテナ固有の「共通暗号化(common encryption)」仕様に従って暗号化およびパッケージ化される必要があります(MUST)。これにより鍵が提供されたときにコンテンツを完全に規定された互換的な方法で復号できるようになります。

Encrypted Media Extensions Stream Format Registry [EME-STREAM-REGISTRY] はそのようなストリーム形式への参照を提供します。

8.9.3 バンド内サポートコンテンツは暗号化されていない

字幕、記述音声、トランスクリプトなどのインバンドのサポートコンテンツは暗号化されるべきではありません(SHOULD NOT)。

そのようなトラックの復号 — 特にユーザーエージェントに返せる形での復号 — は一般に実装でサポートされていません。したがって、そのようなトラックを暗号化すると、ユーザーエージェントの実装でアクセシビリティ機能に広く利用されることが妨げられます。

アクセシビリティ情報が利用可能な形で提供されることを確実にするために、インバンドのサポートコンテンツの暗号化をサポートする実装については: a) CDM は復号済みデータをユーザーエージェントに提供しなければならず(MUST)、b) ユーザーエージェントはそれを同等の非暗号化サポートコンテンツと同様に処理しなければなりません(例えば timed text tracks として公開するなど)(MUST)。

9. 共通キーシステム

すべてのユーザーエージェントは MUST このセクションで説明される共通の キーシステム をサポートしなければなりません。

これは、完全にオープンソースであるユーザーエージェントを含め、すべてのユーザーエージェントでサポートが保証される共通の基本機能レベルが存在することを保証します。したがって、基本的な復号のみを必要とするコンテンツ提供者は、任意のコンテンツ保護プロバイダーと連携することなく、すべてのプラットフォームで動作する簡単なアプリケーションを構築できます。

9.1 クリアキー

"org.w3.clearkey"キーシステム は、平文のクリア(暗号化されていない)キーを使用してソースを復号します。追加のクライアント側コンテンツ保護は不要です。本 キーシステム は以下に記述します。

9.1.1 能力

以下は クリアキーキーシステム )固有の機能をどのようにサポートするかの説明です:

9.1.2 動作

以下は クリアキーキーシステム 固有の動作をどのように実装するかの説明です:

  • generateRequest() アルゴリズム:

    • 生成される messageLicense 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 を反映する messageLicense 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)。

9.1.3 ライセンス要求フォーマット

本節では、message イベントの message 属性を通じてアプリケーションに提供されるライセンス要求のフォーマットについて説明します。

フォーマットは以下のメンバーを含む JSON オブジェクトです:

"kids"
key ID の配列。配列の各要素はキーID 値を含むオクテット列の base64url エンコーディングです。
"type"
要求された MediaKeySessionType

ArrayBuffer の形で message 属性に含まれる場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8 でエンコードされます。アプリケーションは TextDecoder インターフェイスを使用して ArrayBuffer の内容を JSON 文字列にデコードしてもよい(MAY)。

9.1.3.1

この節は規範ではありません。

以下の例は、2 つのキーID に対する一時ライセンスのライセンス要求です。(改行は読みやすさのためのものです。)

{
  "kids": [
    "LwVHf8JLtPrv2GUXFW2v_A",
    "0DdtU9od-Bh5L3xbv0Xf_A"
  ],
  "type": "temporary"
}

9.1.4 ライセンスフォーマット

本節では、update() メソッドの response パラメータを通じて提供されるライセンスのフォーマットについて説明します。

フォーマットは、復号に使用される対称鍵の表現を含む JSON Web Key (JWK) Set であり、JSON Web Key (JWK) 仕様 [RFC7517] に定義されます。

セット内の各 JWK について、パラメータ値は次のとおりです:

"kty" (鍵タイプ)
"oct"(オクテット列)。
"k" (鍵値)
対称 key 値を含むオクテット列の base64url エンコーディング。
"kid" (キーID)
key ID 値を含むオクテット列の base64url エンコーディング。

JSON オブジェクトはオプションの "type" メンバ値を持っていてもよく(MAY)、その場合は MediaKeySessionType の値のいずれかでなければなりません(MUST)。指定されない場合、デフォルト値として "temporary" が使用されます。update() アルゴリズムはこの値を sessionType と比較します。

update() メソッドに ArrayBuffer として response パラメータで渡される場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8 でエンコードされていなければなりません(MUST)。アプリケーションは TextEncoder インターフェイスを使用して JSON 文字列をエンコードしてもよい(MAY)。

9.1.4.1

この節は規範ではありません。

以下の例は、単一の対称鍵を含む JWK Set です。(改行は読みやすさのためのものです。)

{
  "keys": [{
    "kty": "oct",
    "k": "tQ0bJVWb6b0KPL6KtZIy_A",
    "kid": "LwVHf8JLtPrv2GUXFW2v_A"
  }],
  "type": "temporary"
}

9.1.5 ライセンス解除フォーマット

本節では、message イベントの message 属性を通じて提供されるライセンス解除メッセージのフォーマットについて説明します。

フォーマットは JSON オブジェクトです。タイプが "persistent-license" のセッションの場合、オブジェクトは次のメンバを含める必要があります:

"kids"
key IDの配列。配列の各要素はキーID 値を含むオクテット列の base64url エンコーディングです。

ArrayBuffer の形で message 属性に含まれる場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8 でエンコードされます。アプリケーションは TextDecoder インターフェイスを使用して ArrayBuffer の内容を JSON 文字列にデコードしてもよい(MAY)。

9.1.5.1 ライセンス破棄の記録を反映する例のメッセージ

この節は規範ではありません。

以下の例は、2 つのキーを含んでいた "persistent-license" セッションのライセンス解除です。(改行は読みやすさのためのものです。)

{
  "kids": [ "LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A" ]
}

9.1.6 ライセンス解除確認フォーマット

本節では、update() メソッドの response パラメータを通じて提供されるライセンス解除確認のフォーマットについて説明します。

フォーマットは次のメンバを含む JSON オブジェクトです:

"kids"
key IDの配列。配列の各要素はキーID 値を含むオクテット列の base64url エンコーディングです。

update() メソッドに ArrayBuffer として response パラメータで渡される場合、JSON 文字列は Encoding 仕様 [ENCODING] に従って UTF-8 でエンコードされていなければなりません(MUST)。アプリケーションは TextEncoder インターフェイスを使用して JSON 文字列をエンコードしてもよい(MAY)。

9.1.6.1

この節は規範ではありません。

以下の例は、2 つのキーID に対する一時ライセンスのライセンス要求です。(改行は読みやすさのためのものです。)

{
  "kids": [
    "LwVHf8JLtPrv2GUXFW2v_A",
    "0DdtU9od-Bh5L3xbv0Xf_A"
  ]
}

9.1.7 base64url の使用

この節は規範ではありません。

base64url とそれを扱う方法の詳細については、"Base64url Encoding" 用語定義および "Notes on implementing base64url encoding without padding" を [RFC7515] で参照してください。具体的には '=' パディングは存在せず、文字 '-' および '_' はそれぞれ '+' および '/' の代わりに使用されなければなりません(MUST)。

10. セキュリティ

10.1 入力データに対する攻撃と脆弱性

ユーザーエージェントおよび Key System 実装は MUST として、 メディアデータ初期化データupdate() に渡されるデータ、 ライセンス、鍵データ、およびアプリケーションによって提供されるその他すべてのデータを、 信頼されないコンテンツかつ潜在的な攻撃ベクトルとして考慮しなければなりません。適切な安全対策を講じ、 これらのデータを安全に解析・復号化などするよう注意する必要があります。ユーザーエージェントは、 SHOULD として CDM に渡す前にデータを検証するべきです。

そのような検証は、例えば DOM と同じ(サンドボックス化された)コンテキストで CDM が動作していない場合に特に重要です。

実装は MUST NOT として、アクティブコンテンツやアプリケーションの制御フローに影響を与える受動的なコンテンツを返してはなりません。

例えば、初期化データのようなメディアデータ由来の情報から得られた URL 等を公開するのは安全ではありません。これは 初期化データgenerateRequest() に渡される場合などに該当します。 使用する URL はアプリケーション側で決定する必要があります。messageType 属性は、 アプリケーションが該当する場合に一連の URL の中から選択するために使用できます。

10.2 CDM に対する攻撃と脆弱性

ユーザーエージェントは、ユーザーが安全にウェブを閲覧できる方法を提供する責任があります。この責任は、サードパーティ由来の機能を含む、 ユーザーエージェントが使用するあらゆる機能に適用されます。ユーザーエージェント実装者は MUST として、 Key System 実装者から十分な情報を取得し、 Key System と統合することのセキュリティ上の影響を適切に評価できるようにしなければなりません。 ユーザーエージェント実装者は MUST として、CDM 実装がユーザーエージェント側でユーザーのセキュリティを提供するために十分な制御を提供およびサポートすることを確実にする必要があります。 また、CDM 実装がセキュリティ脆弱性発生時に迅速かつ積極的に更新されることを保証しなければなりません。

サンドボックス化されていない、あるいはプラットフォーム機能を使用する CDM 実装を悪用されると、 攻撃者が OS やプラットフォーム機能にアクセスしたり、権限昇格(例: system や root として実行)を行ったり、 ドライバ、カーネル、ファームウェア、ハードウェア等へアクセスできる可能性があります。これらの機能やソフトウェア、ハードウェアは 敵対的なソフトウェアやウェブベースの攻撃に対して堅牢に設計されていない場合があり、ユーザーエージェントに比べてセキュリティ修正が提供されない、 あるいは遅い可能性があります。CDM 実装に対する修正の欠如、頻度の低さ、遅さはリスクを高めます。 そのような CDM 実装およびそれらを公開する UA は、すべてのデータ の解析を含むあらゆるセキュリティ領域で特に慎重でなければなりません。

ユーザーエージェントは、クライアント OS、プラットフォームおよび/またはハードウェアの一部である、あるいはそれらによって提供される CDM や基盤となる仕組みを使用する際には特に注意を払うべきです。

ユーザーエージェントが十分にサンドボックス化できない、またはその他の方法で十分に保護できない Key System をサポートすることを選択した場合、ユーザーエージェントは SHOULD として ユーザーに十分な情報を提供し、明示的な同意を得るべきです。

未認証のオリジンに権限を与えることは、ネットワーク攻撃者の存在下では任意のオリジンに権限を与えることと同等です。永続化された同意の悪用を参照してください。

10.3 ネットワーク攻撃

10.3.1 想定される攻撃

このセクションは非規範的です。

想定されるネットワーク攻撃とその影響には次のようなものがあります:

  • DNS スプーフィング攻撃:あるホストが特定のドメイン(オリジン)を主張していても、 実際にそのドメインのものであるとは保証できません。

  • 受動的ネットワーク攻撃:クライアントとサーバー間で送受信されるデータ(Distinctive IdentifiersDistinctive Permanent Identifiers を含む)が 他の主体によって閲覧されないことを保証できません。ユーザー追跡を参照してください。

  • 能動的ネットワーク攻撃:ページに対して追加のスクリプトや iframe が注入されないことを保証できません(本仕様の API を正当に使用するページも、使用しないページも含む)。結果として:

    • 本仕様で定義された API への呼び出しは任意のページに注入され得ます。

    • 正当な目的でこれらの API を使用しているページからの呼び出しは改変され得ます。要求される機能の変更、呼び出しの変更や追加、データの変更や注入などが含まれます。入力データに対する攻撃と脆弱性も参照してください。

    • クライアントとサーバー間で送受信されるデータ(Distinctive IdentifiersDistinctive Permanent Identifiers を含む)が 他の主体によって閲覧および/または変更され得ます。ユーザー追跡を参照してください。

  • 永続化された同意の悪用:本仕様で定義された API の使用を要求するホストが、 ユーザーが以前に同意を与えたホストと同一であると保証できない場合があります。結果として、未認証のオリジンに権限を与えることは、 ネットワーク攻撃者の存在下では任意のオリジンに権限を与えることと同等になります。

10.3.2 緩和策

次の技術はリスクを緩和するのに役立ちます:

TLS を使用する

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 を安全なコンテキストに制限することにより、ネットワーク攻撃者が 未認証オリジンに付与された権限を悪用できないことが保証されます。永続化された同意の悪用も参照してください。

10.4 iframe による攻撃

10.4.1 想定される攻撃

このセクションは非規範的です。

悪意のあるページは、正当なアプリケーションを iframe にホストして攻撃を隠蔽したり、使用元を偽装してユーザーに正当なコンテンツプロバイダからの利用であると思わせたりする可能性があります。 これは、セキュリティや プライバシーの理由 でユーザーに情報提供や同意を要求する実装にとって特に重要です。 ネットワーク攻撃 に加えて、攻撃者は iframe に正当な API 利用をホストすることで本仕様で定義された API の正当な利用を悪用しようとする可能性があります。 正当なアプリケーションが操作を行うことで、攻撃者は既存の付与済み権限(またはホワイトリスト)を再利用したり、正当なリクエストや使用に見せかけたりできます。

10.4.2 緩和策

ユーザーに情報を提供したり同意を要求したりするユーザーエージェントは、セキュリティや プライバシーの理由 を含め、 UI と同意の永続化をトップレベルの オリジン と 本仕様で API を使用しているオリジンの組み合わせに基づいて行うべきです。これにより、リクエストを行っている主要なドキュメントがユーザーに示され、 ある(正当な)組み合わせに対して権限を永続化しても、悪意ある使用が見逃されないようにできます。

作者は SHOULD として、他の主体が自分のアプリケーションを iframe 内でホストすることを防止すべきです。 正当なアプリケーション設計上の理由でホストされる必要があるアプリケーションは、ホスティング文書が CDM に渡されるいかなるデータ を提供すること(本仕様の API 経由またはメディアデータとして)を許可すべきではなく、 ホスティングフレームが本仕様で定義された API を呼び出すことを許可すべきではありません。

10.5 クロスディレクトリ攻撃

このセクションは非規範的です。

例えば geocities.com のように一つのホスト名を共有する異なる作者は、すべて一つの オリジン を共有します。ユーザーエージェントは パス名による API へのアクセス制限機能を提供していません。

共有ホストで本仕様の API を使用すると、ユーザーエージェントが実装するオリジンベースのセキュリティおよびプライバシー緩和策が損なわれます。 例えば、オリジンごとの Distinctive Identifiers は一つのホスト名上のすべての作者と共有され、永続化されたデータはホスト上の任意の作者によってアクセスおよび操作され得ます。 後者は特に、例えばそのデータの変更や削除によってユーザーの特定コンテンツに対する権利が失われる可能性がある場合に重要です。

たとえユーザーエージェントがパス制限機能を提供していたとしても、通常の DOM スクリプトセキュリティモデルにより、その保護は簡単に回避され、任意のパスからデータにアクセスされ得ます。

したがって、共有ホストの作者は本仕様で定義された API の使用を避けることが RECOMMENDED されます。なぜならそれによりユーザーエージェント側のオリジンベースのセキュリティおよびプライバシー緩和策が損なわれるためです。

11. プライバシー

ユーザーのデバイス上での Key System(s) の存在または使用は、多くのプライバシー上の問題を引き起こします。これらは主に二つのカテゴリに分けられます:(a) EME インターフェイス自体または Key System メッセージ内で開示され得るユーザー固有の情報、および (b) ユーザーのデバイス上に永続的に保存され得るユーザー固有の情報。

ユーザーエージェントは MUST として、ユーザーが自身のプライバシーを適切に制御できるようにする責任を負わなければなりません。ユーザーエージェントはサードパーティの CDM 実装と統合する可能性があるため、 CDM 実装者は、ユーザーエージェント実装者がユーザーのプライバシーを制御できるように適切な技術を実装するために十分な情報と制御手段を提供しなければなりません。以下に示す技術を含むがこれに限定されません。

11.1 EME および Key Systems によって開示される情報

EME および Key Systems によって開示される情報に関する懸念は二つのカテゴリに分かれます:(a) ユーザーエージェントやデバイスのフィンガープリント化の可能性に寄与し得る非特定情報に関する懸念、(b) 直接的に ユーザー追跡 に使用され得るユーザー固有の情報に関する懸念。

11.2 フィンガープリンティング

悪意のあるアプリケーションは、サポートされている Key Systems の検出や列挙、関連情報の取得によってユーザーやユーザーエージェントをフィンガープリント化できる可能性があります。適切なオリジン保護が提供されない場合、これには訪問したサイトの検出やそれらのサイトのために保存された情報の検出が含まれ得ます。特に、Key SystemsMUST として、キーやその他のデータを origins 間で共有してはなりません。

11.3 情報漏洩

11.3.1 懸念事項

このセクションは非規範的です。

特にユーザーエージェントの外部に実装された CDM は、ウェブプラットフォームと同じ基本的な隔離を持たない場合があります。オリジン間での情報漏洩を避けるための措置を講じることが重要です。これにはメモリ内および保存データの両方が含まれます。これを怠ると、プライベートブラウジングセッションへの情報漏洩、browsing profiles 間(OS のユーザーアカウントを含む)や、異なるブラウザやアプリケーション間での漏洩につながる可能性があります。

11.3.2 緩和策

そのような問題を避けるために、ユーザーエージェントおよび CDM 実装は MUST として次を確保しなければなりません:

  • CDMs は、CDM インスタンスの概念を持ち、そのインスタンスが一対一で MediaKeys オブジェクトに関連付けられていること。

  • キー、ライセンス、その他のセッションデータ、およびセッションの存在は、セッションを作成した MediaKeys オブジェクトに関連付けられた CDM インスタンスに制限されること。

  • セッションデータが MediaKeys オブジェクトや CDM インスタンス間で共有されないこと。

  • セッションデータが、そのセッションを作成した MediaKeys オブジェクトに関連付けられていないメディア要素と共有されないこと。これには、あるセッションのキーが、そのセッションを作成した mediaKeys 属性を持たないメディア要素によって読み込まれたコンテンツを復号するために使用されてはならない、ということが含まれます。

  • MediaKeys オブジェクトおよび基盤となる実装が、origin の外部に情報を露出しないこと。

  • 永続化されたセッションデータが存在する場合、それが origin ごとに保存されること。

  • 読み込めるのは要求元の origin によって保存されたデータのみであること。

  • CDM から、またはこの仕様で明示的に記述されていない情報や、ユーザーの許可なしにウェブプラットフォームの他の API を通じてページに利用可能でない情報を抽出、派生、推測することが不可能であること。これは、CDM メッセージ中の情報を含め、クライアントデバイスまたはアプリケーションの外部に露出するあらゆる情報に適用されます。

    この要件で扱われる情報の種類には、次のものが含まれますがこれに限定されません:

    • 位置情報(ジオロケーションを含む)

    • Distinctive Identifiers 以外の認証情報や識別子

    • OS アカウント名その他の PII の可能性がある情報

    • ローカルのディレクトリパス(類似の情報を含む可能性があります)

    • ローカルネットワークの詳細(例:デバイスのローカル IP アドレス)

    • Bluetooth、USB、ユーザーメディアなどを含むローカルデバイス

    • 本仕様で定義された API の結果として関連付けられていない、または保存されていないユーザーステート

11.4 ユーザー追跡

11.4.1 懸念事項

このセクションは非規範的です。

サードパーティのホスト(または広告主のように複数のサイトにコンテンツを配布できる任意の主体)は、Distinctive Identifier や、CDM によって保存されたライセンス、キー、キー ID、または records of license destruction のような永続データを利用して、複数のセッション(originsbrowsing profiles を跨ぐ場合を含む)にわたりユーザーを追跡し、ユーザーの活動や興味のプロファイルを構築する可能性があります。そのような追跡はウェブプラットフォームが提供するプライバシー保護を損ない、例えば通常は不可能な高度にターゲティングされた広告を可能にすることがあります。ユーザーの実際の身元を知るサイト(認証された資格情報を要求するコンテンツプロバイダや e コマースサイトなど)と組み合わせると、匿名のウェブ利用しかなかった場合よりも個人を高い精度で特定して標的にすることが可能になります。

本仕様の API の実装を通じて取得され得るユーザーまたはクライアント固有の情報には次のものが含まれます:

本仕様は、これらの情報が一般的にユーザーエージェントの外部(および関連するbrowsing profile 保存領域)に保存され、しばしば CDM に置かれるため、特に懸念されます。

ライセンスの内容や records of license destructionKey System 固有であり、キー ID が任意の値を含む可能性があることから、これらのデータ項目はユーザー識別情報を格納するために悪用され得ます。

Key Systems は、デバイスまたはデバイスのユーザーのための永続的または準永続的な識別子をアクセスまたは作成する可能性があります。場合によっては、これらの識別子が特定のデバイスに対して安全にバインドされることがあります。これらの識別子が Key System メッセージ内に存在する場合、デバイスやユーザーが追跡される可能性があります。以下の緩和策が適用されない場合、これには時間を通じたユーザー/デバイスの追跡や、特定のデバイスの複数ユーザーの関連付けが含まれる可能性があります。

特に、消去不可能でオリジン固有でない、またはpermanent な識別子は、クッキーや URL に埋め込まれたセッション識別子といった既存手法よりも追跡効果が大きくなる点に注意することが重要です。

緩和されない場合、こうした追跡は Key System の設計に応じて三つの形式を取る可能性があります:

  • いずれの場合でも、こうした識別子は Key System を完全にサポートするサイトやサーバーから利用可能であり(したがって Key System メッセージを解釈できる)、そのようなサイトによる追跡を可能にすると予想されます。

  • Key Systems によって公開される識別子がオリジン固有でない場合、二つのサイトやサーバーが共謀してユーザーを追跡する可能性があります。

  • Key System メッセージがユーザー識別子から一貫した方法で派生した情報を含む場合(例えば、特定のコンテンツ項目に対する最初の Key System メッセージの一部が時間とともに変化せず、ユーザー識別子に依存するような場合)、その情報は任意のアプリケーションによってデバイスやユーザーを時間を通じて追跡するために使用され得ます。

さらに、Key System がキーやその他のデータをオリジン間で保存および再利用可能にすることを許可する場合、二つのオリジンが共謀して共通のキーへアクセスできることを記録することで固有のユーザーを追跡できる可能性があります。

最後に、Key Systems のユーザー向け制御用 UI が HTTP セッションクッキー [COOKIES] や永続ストレージ内のデータと別にデータを提示する場合、ユーザーはサイトの許可を変更したりデータを一方だけで削除したりする可能性が高くなります。これにより、サイトは各機能を互いの冗長バックアップとして使用し、ユーザーのプライバシー保護の試みを無効にすることができます。

サイトや他のサードパーティによる追跡の可能性に加えて、ユーザーエージェント実装者、CDM ベンダー、またはデバイスベンダーが、ユーザーが訪れる本仕様で定義された API を使用するサイトなど、ユーザーの活動や興味のプロファイルを構築する可能性があります。このような追跡は、特にオリジンの隔離に関連するウェブプラットフォームのプライバシー保護を損ないます。

CDM ベンダーが運営または提供するサーバー(例えば individualization プロセスを通じて)から識別子(例:Distinctive Permanent Identifier(s) を含む)が取得され得ることがあります。オリジンごとの識別子を生成するために、オリジンを表す値が提供される場合もあります。

そのような実装では、CDM ベンダーは、訪問したオリジンの数や新しい識別子が必要とされた回数など、ユーザーの活動を追跡できる可能性があります。オリジンやオリジンに関連付け可能な値が識別子要求に提供される場合、CDM ベンダーはユーザーが訪れたサイトやデバイスのユーザーを追跡することができます。

次のセクションでは、ユーザーの同意なしに追跡されるリスクを軽減する可能性のある手法について説明します。

11.4.2 緩和策

Do not use Distinctive Identifiers or Distinctive Permanent Identifiers

Key System 実装は、可能な限り Distinctive Identifiers および Distinctive Permanent Identifiers を使用することを避けるべきであり、 実装の堅牢性に意味のある寄与がある場合にのみ使用すべきです。詳細は Limit or Avoid use of Distinctive Identifiers and Permanent Identifiers を参照してください。

Do not expose Distinctive Permanent Identifiers to the application

実装は MUST NOT として、Distinctive Permanent Identifiers をアプリケーションやオリジンに公開してはなりません。

Encrypt Distinctive Identifiers

Distinctive Identifiers を含む Key System メッセージは、タイムスタンプまたはノンスと共に暗号化され、 常に異なる Key System メッセージになるようにしなければなりません(MUST)。 これにより、Key System メッセージを用いた追跡は、その Key System を完全にサポートするサーバーによる場合を除き防止されます。詳細は Encrypt Identifiers を参照してください。

Treat Distinctive Identifiers and Key System stored data like cookies / web storage

ユーザーエージェントは SHOULD として、Distinctive IdentifiersKey Systems によって保存されたデータの存在を、 HTTP セッションクッキー [COOKIES] と強く結びつけてユーザーに提示し、 「すべてのデータを削除」に含め、同じ UI 場所で表示すべきです。これによりユーザーがこれらの識別子を慎重に扱うことを促せます。ユーザーエージェントは SHOULD として、 Incomplete Clearing of Data を回避するようユーザーを支援すべきです。

Do not expose per-origin information to unrelated entities

origin(s) やオリジンに 関連付け可能な 値を、当該オリジンに無関係な individualization サーバーやその他の主体に提供してはなりません。実装がそのようなプロセスを使用する場合は、Individualization セクションの要件と推奨に従ってください。

Use non-associable per-origin per-profile values and identifiers

アプリケーションに公開されるすべての 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 を参照してください。

Use origin-specific and browsing profile-specific Key System storage

アプリケーションやライセンスサーバーから見えてメッセージや挙動に影響を与え得る 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 を参照してください。

Provide user deletion of persistent data, including Distinctive Identifiers

ユーザーエージェントは MUST として、Distinctive Identifiers を含む任意の永続データをユーザーが消去できる機能を提供しなければなりません。詳細は Allow Persistent Data to Be Cleared を参照してください。

Expire stored data

ユーザーエージェントは MAY として、ユーザーが設定可能な方法で、一定期間後に Distinctive Identifiers やその他の Key System データを自動的に削除することができます。

例えば、ユーザーエージェントはこれらのデータをセッションのみのストレージとして保存し、データへアクセス可能なすべての閲覧コンテキストが閉じられたときに削除するよう設定できるでしょう。

これにより、サイトはユーザーがサイト自身で認証した場合(購入やサービスへのサインインなど)にのみ複数セッションにわたって追跡できるようになり、追跡能力が制限されます。

しかしながら、こうした有効期限は、特に購入やレンタルしたコンテンツへのユーザーのアクセスを危険にさらす可能性があるため、ユーザーがその影響を十分に理解していない場合には注意が必要です。

Block third-party access

ユーザーエージェントは MAY として、Key Systems やその機能へのアクセスを、閲覧コンテキストのトップレベル Documentorigin に起源するスクリプトに限定することができます。例えば、requestMediaKeySystemAccess() は、 iframe 内で実行される他のオリジンのページに対して特定の構成の要求を拒否する場合があります。

ユーザーエージェントは MUST として、Distinctive Identifier(s) または Distinctive Permanent Identifier(s) を使用する 前に、 ユーザーが十分に情報を与えられ、明示的な同意を与えることを確実にしなければなりません。

そのようなメカニズムは、正当な使用がその後の悪意あるアクセスを可能にしないようにするために、MUST としてオリジンごとに行われ、かつ MUST として browsing profile ごとに行われなければなりません。

本仕様で定義された API を安全なコンテキストに限定することは、ネットワーク攻撃者が未認証オリジンに付与された権限を悪用できないことを保証します。abuse of persisted consent も参照してください。

Provide user controls to disable Key Systems or Key System use of identifiers

ユーザーエージェントは SHOULD として、Key System の有効化有無や、Key System による Distinctive Identifier(s) / Distinctive Permanent Identifier(s) の使用 を有効にするかどうかのグローバルな制御をユーザーに提供すべきです(Key System が対応している場合)。ユーザーエージェントは SHOULD として、Incomplete Clearing of Data を回避するようユーザーを支援すべきです。

Require site-specific whitelisting of access to each Key System

ユーザーエージェントは MAY として、サイトが各 Key System(および/または特定の機能)を使用する前に、ユーザーが明示的にアクセスを許可することを要求することができます。ユーザーエージェントは SHOULD として、ユーザーがこの許可を一時的または恒久的に取り消せるようにすべきです。

Use shared blacklists

ユーザーエージェントは MAY として、ユーザーがオリジンや Key Systems のブラックリストを共有できるようにすることができます。これにより、コミュニティが協力してプライバシーを保護することが可能になります。

Note

これらの提案は、本仕様で定義された API を用いたユーザー追跡の単純な利用を防ぎますが、完全に遮断するものではありません。単一のオリジン内では、サイトはセッション中にユーザーを追跡し続け、得られたすべての情報をサイトが取得した識別情報(名前、クレジットカード番号、住所など)とともに第三者に渡すことが可能です。第三者が複数のサイトと協力してそのような情報を取得し、識別子が オリジンおよびプロファイルごとに一意でない 場合、プロファイルは依然として作成され得ます。

11.5 ユーザーのデバイスに保存される情報

11.5.1 懸念事項

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 のユーザーアカウントや別のブラウザも含まれ得ます。

11.5.2 緩和策

これらの懸念を緩和するための要件は、8.3 Persistent Data に定義されています。

11.6 不完全なデータ消去

11.6.1 懸念事項

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 が保存したデータを同時に消去していなければ、サイトは無効化前のデータと再有効化後のデータや挙動を関連付けられる可能性があります。

11.6.2 緩和策

これらの懸念を緩和するための推奨事項は、8.3 Persistent Data に定義されています。

11.7 プライベートブラウジングモード

ユーザーエージェントは、ユーザーの匿名性を保持したり閲覧履歴の記録がクライアント上に残らないようにすることを意図したモード(例:プライベートブラウジング)をサポートする場合があります。前節で議論したプライバシー上の懸念は、こうしたモードを利用するユーザーにとって特に重要になる可能性があります。

そのようなモードをサポートするユーザーエージェント実装者は、これらのモードで Key Systems へのアクセスを無効にすべきかどうかを慎重に検討することが SHOULD されます。例えば、そのようなモードは、MediaKeySystemAccess オブジェクトの作成を禁止することがあり得ます。特に persistentStatedistinctiveIdentifier をサポートまたは使用する構成を禁止する場合があります(これは CDM 実装の一部として、またはアプリケーションがそれらを "required" と指定した場合のいずれでもあり得ます)。実装がそのような作成を禁止しない場合、使用を許可する前に当該モードの期待されるプライバシー特性に対する影響と潜在的な結果をユーザーに通知することが SHOULD されます。

11.8 セキュアなオリジンと通信

本仕様で定義された API はセキュアなオリジン上でのみサポートされており、前節で議論した情報を保護します。識別子はさらに Encrypt Identifiers に規定されたとおりに暗号化されます。

アプリケーション(およびそれらが使用するサーバーを含む)は、CDM からのデータやメッセージを含むすべてのトラフィックについて、すべて安全なトランスポートを使用することが SHOULD されます。これには message イベントから渡される全データや、update() へのデータなどが含まれますが、これらに限定されません。

すべてのユーザーエージェントは、ユーザーエージェントやアプリケーションがセキュアなオリジンと通信を強制したい場合に不安全なコンテンツや輸送への露出を避けるために、混在コンテンツ [MIXED-CONTENT] を適切に扱わなければなりません(MUST)。

12. 適合性

非規範としてマークされた節のほかに、本仕様書のすべての作成ガイドライン、図、例、および注は非規範です。それ以外のすべてが規範です。

本ドキュメント内のキーワード MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULD, および SHOULD NOT は、すべて大文字で表示されている場合に限り、BCP 14 [RFC2119] [RFC8174] に記載されたとおりに解釈されます。

13.

このセクションは非規範的です。

この節は、提案された拡張機能を用いたさまざまなユースケースに対する例示的な解決策を含んでいます。これらが唯一の解決策というわけではありません。例では video 要素を使用していますが、同じことはすべてのメディア要素に当てはまります。同期 XHR の使用のような場合には、拡張に焦点を当てるために例を簡略化しています。

13.1 ページ読み込み時にソースと鍵が既知の場合(Clear Key)

この単純な例では、ソースファイルと平文ライセンス(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>

13.2 サポートされている Key System を選択し、"encrypted" イベントからの初期化データを使用する

この例では、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>

13.3 メディア読み込み前に MediaKeys を作成する

暗号化イベントを 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>

13.4 すべてのイベントを使用する例

これは、すべてのイベントが使用されるより完全な例です。

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>

13.5 保存されたライセンス

この例では、将来の利用のために永続的なライセンスを要求して保存します。また、後でライセンスを取得したり破棄したりするための関数も提供します。

<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>

13.6 HDCP ポリシーを考慮したメディアの事前フェッチ

ライセンスに HDCP ポリシーが含まれるメディアがある場合、アプリケーションは事前フェッチの前にそのバージョンを確認できます。

const status = await video.mediaKeys.getStatusForPolicy({
  minHdcpVersion: '1.4'
});

if (status === 'usable') {
  // Pre-fetch HD content.
} else {  // 'output-restricted'
  // Pre-fetch SD content.
}

14. 謝辞

編集者は 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 での参加を含め、本仕様に貢献した多くの他の方々にも感謝します。

A. 参考文献

A.1 規範的参考文献

[COOKIES]
HTTP State Management Mechanism。A. Barth。IETF。2011年4月。提案規格。URL: https://httpwg.org/specs/rfc6265.html
[dom]
DOM Standard。Anne van Kesteren。WHATWG。 Living Standard。URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript Language Specification。 Ecma International。URL: https://tc39.es/ecma262/multipage/
[EME-INITDATA-KEYIDS]
"keyids" Initialization Data Format。Joey Parrish; Greg Freedman。W3C。2024年8月20日。W3C Working Group Note。 URL: https://www.w3.org/TR/eme-initdata-keyids/
[EME-INITDATA-REGISTRY]
Encrypted Media Extensions Initialization Data Format Registry。Joey Parrish; Greg Freedman。W3C。2024年7月18日。DRY。 URL: https://www.w3.org/TR/eme-initdata-registry/
[ENCODING]
Encoding Standard。Anne van Kesteren。 WHATWG。Living Standard。URL: https://encoding.spec.whatwg.org/
[HTML]
HTML Standard。Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters。WHATWG。Living Standard。URL: https://html.spec.whatwg.org/multipage/
[Infra]
Infra Standard。Anne van Kesteren; Domenic Denicola。WHATWG。Living Standard。URL: https://infra.spec.whatwg.org/
[mimesniff]
MIME Sniffing Standard。Gordon P. Hemsley。WHATWG。Living Standard。URL: https://mimesniff.spec.whatwg.org/
[MIXED-CONTENT]
Mixed Content。Emily Stark; Mike West; Carlos IbarraLopez。W3C。2023年2月23日。CRD。URL: https://www.w3.org/TR/mixed-content/
[PERMISSIONS-POLICY]
Permissions Policy。Ian Clelland。W3C。2025年8月6日。W3C Working Draft。URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels。S. Bradner。IETF。1997年3月。Best Current Practice。URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC6381]
The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types。R. Gellens; D. Singer; T. Hansen。IETF。2011年8月。提案規格。URL: https://www.rfc-editor.org/rfc/rfc6381
[RFC7517]
JSON Web Key (JWK)。M. Jones。 IETF。2015年5月。提案規格。URL: https://www.rfc-editor.org/rfc/rfc7517
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words。B. Leiba。IETF。2017年5月。Best Current Practice。URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard。Edgar Chen; Timothy Gu。 WHATWG。Living Standard。URL: https://webidl.spec.whatwg.org/

A.2 情報参考文献

[CENC]
ISO/IEC 23001-7:2016, Information technology — MPEG systems technologies — Part 7: Common encryption in ISO Base Media File Format files。ISO/IEC。国際標準。URL: https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1
[EME-HDCP-VERSION-REGISTRY]
Encrypted Media Extensions HDCP Version Registry。Joey Parrish; Greg Freedman。W3C。2024年7月18日。DRY。URL: https://www.w3.org/TR/eme-hdcp-version-registry/
[EME-STREAM-REGISTRY]
Encrypted Media Extensions Stream Format Registry。Joey Parrish; Greg Freedman。W3C。2024年7月18日。DRY。URL: https://www.w3.org/TR/eme-stream-registry/
[MEDIA-SOURCE]
Media Source Extensions™。Jean-Yves Avenard; Mark Watson。W3C。2025年4月17日。W3C Working Draft。URL: https://www.w3.org/TR/media-source-2/
[RFC6838]
Media Type Specifications and Registration Procedures。N. Freed; J. Klensin; T. Hansen。IETF。2013年1月。Best Current Practice。URL: https://www.rfc-editor.org/rfc/rfc6838
[RFC7515]
JSON Web Signature (JWS)。M. Jones; J. Bradley; N. Sakimura。IETF。2015年5月。提案規格。URL: https://www.rfc-editor.org/rfc/rfc7515
[webaudio]
Web Audio API。Paul Adenot; Hongchan Choi。W3C。2021年6月17日。W3C Recommendation。URL: https://www.w3.org/TR/webaudio-1.0/