--- a/encrypted-media/encrypted-media-wd.html Wed Aug 13 15:42:43 2014 -0700
+++ b/encrypted-media/encrypted-media-wd.html Fri Aug 15 13:20:40 2014 -0700
@@ -1,8 +1,14 @@
-<!DOCTYPE html SYSTEM "about:legacy-compat">
-<html>
+<!DOCTYPE html>
+<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Encrypted Media Extensions</title>
+
+ <script src="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/assets/scripts/bug-assist.js"></script>
+ <meta name="bug.product" content="HTML WG">
+ <meta name="bug.component" content="Encrypted Media Extensions">
+
+ <link rel="stylesheet" href="eme.css">
<style>
dt, dfn { font-weight: bold; font-style: normal; }
@@ -75,6 +81,23 @@
border-color: #52e052;
background: #e9fbe9;
}
+ .noteHeader {
+ font-weight: bold;
+ display: block;
+ color: #005a9c;
+ color: black;
+ padding-top: 0.5em;
+ }
+
+
+ pre.idl > div.issue {
+ white-space: normal;
+ margin-bottom: 0px;
+ margin-top: 0px;
+ font-family: "sans-serif";
+ }
+ pre.idl > div.issue :link { color: #0000EE; }
+ pre.idl > div.issue :visited { color: #551A8B; }
</style>
<style type="text/css">
div.nonnormative { color: green; margin: 2em 0 2em 0em; padding: 0.5em 1em; border: none; background: #DDFFDD; }
@@ -85,27 +108,29 @@
.non-normative em { font-style: normal;}
.non-normative var { font-style: normal;}
</style>
- <link rel="stylesheet" type="text/css" href="http://www.w3.org/StyleSheets/TR/W3C-WD">
+ <link rel="stylesheet" type="text/css" href="https://www.w3.org/StyleSheets/TR/w3c-wd.css">
</head>
<body>
<div class="head">
<p><a href="http://www.w3.org/"><img src="https://www.w3.org/Icons/w3c_home" alt="W3C" width="72" height="48"></a></p>
<h1>Encrypted Media Extensions</h1>
- <h2 id="draft-date">W3C Working Draft 13 February 2014</h2>
+ <h2 id="draft-date">W3C Working Draft 21 August 2014</h2>
<dl>
<dt>This Version:</dt>
- <dd><a href="http://www.w3.org/TR/2013/WD-encrypted-media-20140213/">http://www.w3.org/TR/2013/WD-encrypted-media-20140213/</a></dd>
+ <dd><a href="http://www.w3.org/TR/2014/WD-encrypted-media-20140821/">http://www.w3.org/TR/2014/WD-encrypted-media-20140821/</a></dd>
<dt>Latest Published Version:</dt>
<dd><a href="http://www.w3.org/TR/encrypted-media/">http://www.w3.org/TR/encrypted-media/</a></dd>
<dt>Latest editor's draft:</dt>
<dd><a href="http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html">http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html</a></dd>
<dt>Previous Versions:</dt>
+ <dd><a href="http://www.w3.org/TR/2014/WD-encrypted-media-20140218/">http://www.w3.org/TR/2014/WD-encrypted-media-20140218/</a></dd>
<dd><a href="http://www.w3.org/TR/2013/WD-encrypted-media-20130510/">http://www.w3.org/TR/2013/WD-encrypted-media-20130510/</a></dd>
<dd><a href="http://www.w3.org/TR/2013/WD-encrypted-media-20131022/">http://www.w3.org/TR/2013/WD-encrypted-media-20131022/</a></dd>
<dt>Editors:</dt>
<dd>David Dorwin, Google, Inc.</dd>
- <dd>Adrian Bateman, Microsoft Corporation</dd>
+ <dd>Jerry Smith, Microsoft Corporation</dd>
<dd>Mark Watson, Netflix, Inc.</dd>
+ <dd>Adrian Bateman, Microsoft Corporation (until May 2014)</dd>
<dt>Bug/Issue lists:</dt>
<dd>
<a href="http://w3.org/brief/MjY5">Bugzilla</a>, <a href="http://www.w3.org/html/wg/tracker/products/19">Tracker</a>
@@ -115,10 +140,10 @@
<dt>Test Suite:</dt>
<dd>None yet</dd>
</dl>
- </div>
<p class="copyright"><a href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> © 2014 <a href="http://www.w3.org/"><abbr title="World Wide Web Consortium">W3C</abbr></a><sup>®</sup> (<a href="http://www.csail.mit.edu/"><abbr title="Massachusetts Institute of Technology">MIT</abbr></a>, <a href="http://www.ercim.eu/"><abbr title="European Research Consortium for Informatics and Mathematics">ERCIM</abbr></a>, <a href="http://www.keio.ac.jp/">Keio</a>, <a href="http://ev.buaa.edu.cn/">Beihang</a>), All Rights Reserved. W3C <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>, <a href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> and <a href="http://www.w3.org/Consortium/Legal/copyright-documents">document use</a> rules apply.</p>
<hr>
+ </div>
<h2>Abstract</h2>
@@ -141,7 +166,7 @@
</em></p>
<p>Implementers should be aware that this specification is not stable. <strong>Implementers who are not taking part in the discussions are likely to find the specification changing out from under them in incompatible ways.</strong> Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation stage should join the mailing list mentioned below and take part in the discussions.</p>
<p>
- This document was published by the <a href="http://www.w3.org/html/wg/">HTML working group</a> as a Working Draft.
+ This document was published by the <a href="http://www.w3.org/html/wg/">HTML working group</a> as an Editor's Draft.
Please submit comments regarding this document by using the W3C's (<a href="https://www.w3.org/Bugs/Public/enter_bug.cgi?product=HTML%20WG&component=Encrypted%20Media%20Extensions">public bug database</a>) with the product set to <kbd>HTML WG</kbd> and the component set to
<kbd>Encrypted Media Extensions</kbd>.
If you cannot access the bug database, submit comments to <a href="mailto:public-html-media@w3.org">public-html-media@w3.org</a>
@@ -150,10 +175,10 @@
All feedback is welcome.
</p>
<p>
- Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated,
+ Publication as an Editor's Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated,
replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
</p>
- <p class="non-normative">Note: It is an open issue whether and how the spec should do more to encourage/ensure CDM-level interop. See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=20944">Bug 20944</a>.</p>
+ <p class="non-normative">Note: It is an open issue whether and how the specification should do more to encourage/ensure CDM-level interoperability. See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=20944">Bug 20944</a>.</p>
<p class="non-normative">Note: This specification contains sections for describing <a href="#security">security</a> and <a href="#privacy">privacy</a> considerations. These sections are not final and review is welcome.</p>
<p>
This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 W3C Patent Policy</a>.
@@ -173,9 +198,8 @@
</ul></li>
<li><a href="#extensions">2. Media Element Extensions</a></li>
<li><ul style="list-style-type:none">
- <li><a href="#error-codes">2.1. Errors</a></li>
- <li><a href="#session-state">2.2. MediaKeySession States</a></li>
- <li><a href="#media-element-restictions">2.3. Media Element Restrictions</a></li>
+ <li><a href="#exceptions">2.1. Exceptions</a></li>
+ <li><a href="#media-element-restictions">2.2. Media Element Restrictions</a></li>
</ul></li>
<li><a href="#events">3. Events</a></li>
<li><ul style="list-style-type:none">
@@ -184,24 +208,24 @@
</ul></li>
<li><a href="#algorithms">4. Algorithms</a></li>
<li><ul style="list-style-type:none">
- <li><a href="#algorithms-encrypted-stream">4.1. First Time a Key Reference is Encountered</a></li>
+ <li><a href="#algorithms-initdata-encountered">4.1. Initialization Data Encountered</a></li>
<li><a href="#algorithms-encrypted-block">4.2. Encrypted Block Encountered</a></li>
<li><a href="#algorithms-queue-message">4.3. Queue a "message" Event</a></li>
- <li><a href="#algorithms-session-close">4.4. Session Close</a></li>
+ <li><a href="#algorithms-queue-error">4.4. Queue an "error" Event</a></li>
+ <li><a href="#algorithms-keys-changed">4.5. Usable Keys Changed</a></li>
+ <li><a href="#algorithms-update-expiration">4.6. Update Expiration</a></li>
+ <li><a href="#algorithms-session-close">4.7. Session Close</a></li>
+ <li><a href="#algorithms-queue-waiting">4.8. Queue a "waiting" Event</a></li>
+ <li><a href="#algorithms-resume-playback">4.9. Attempt to Resume Playback If Necessary</a></li>
</ul></li>
<li><a href="#simple-decryption">5. Simple Decryption</a></li>
<li><ul style="list-style-type:none">
- <li><a href="#simple-decryption-clear-key">5.1. Clear Key</a></li>
+ <li><a href="#clear-key">5.1. Clear Key</a></li>
</ul></li>
<li><a href="#security">6. Security Considerations</a></li>
<li><a href="#privacy">7. Privacy Considerations</a></li>
- <li><a href="#containers">8. Container Guidelines</a></li>
- <li><ul style="list-style-type:none">
- <li><a href="#webm">8.1. WebM</a></li>
- <li><a href="#iso">8.2. ISO Base Media File Format</a></li>
- </ul></li>
- <li><a href="#examples">9. Examples</a></li>
- <li><a href="#revision-history">10. Revision History</a></li>
+ <li><a href="#examples">8. Examples</a></li>
+ <li><a href="#revision-history">9. Revision History</a></li>
</ul>
@@ -220,9 +244,8 @@
<p>Text in <span class="non-normative">this font and color</span> is non-normative.</p>
<h4 id="cdm">1.1.1. Content Decryption Module (CDM)</h4>
- <p><i>This section is non-normative.</i></p>
- <p>The Content Decryption Module (CDM) is a generic term for a part of or add-on to the user agent that provides functionality for one or more <a href="#key-system">Key Systems</a>.
- Implementations may or may not separate the implementations of CDMs and may or may not treat them as separate from the user agent.
+ <p>The Content Decryption Module (CDM) is a generic term for the client component that provides the functionality, including decryption, for one or more <a href="#key-system">Key Systems</a>.</p>
+ <p class="non-normative">Implementations may or may not separate the implementations of CDMs or treat them as separate from the user agent.
This is transparent to the API and application.
A user agent may support one or more CDMs.</p>
@@ -234,7 +257,7 @@
</p>
<p>A Key System string is always a reverse domain name. <span class="non-normative">For example, "com.example.somesystem".</span>
- Key System strings are compared using case-sensitive matching. <span class="non-normative">It is recommended that CDMs use simple lower-case ASCII key system strings.</span></p>
+ Key System strings are compared using case-sensitive matching. It is recommended that CDMs use simple lower-case ASCII key system strings.</p>
<p class="non-normative">
Within a given system ("somesystem" in the example), subsystems may be defined as determined by the key system provider.
@@ -243,537 +266,640 @@
</p>
<h4 id="key-session">1.1.3. Key Session</h4>
- <p>A Key Session, or simply Session, represents the lifetime of the key(s) it contains and associates all messages related to them.
+ <p>A Key Session, or simply Session, provides a context for message exchange with the CDM as a result of which key(s) are made available to be <a href="#cdm">CDM</a>.
Sessions are embodied as <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
Each Key session is associated with a single instance of <a href="#initialization-data">Initialization Data</a> provided in the <code><a href="#dom-createsession">createSession()</a></code> call.
</p>
+ <p>Each Key Session is associated with a single <code><a href="#dom-mediakeys">MediaKeys</a></code> object, and only <a href="#media-element">media elements</a> associated with that object may access key(s) associated with the session.
+ Other <code><a href="#dom-mediakeys">MediaKeys</a></code> objects, <a href="#cdm">CDM</a> instances, and media elements may <em>not</em> access the key session or use its key(s).
+ Key sessions and the keys they contain are no longer usable by the CDM for decryption when the <a href="#algorithms-session-close">session is closed</a>, including when the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object is destroyed.
+ </p>
<h4 id="session-id">1.1.4. Session ID</h4>
- <p>A Session ID is a unique string identifier generated by the user agent or CDM that can be used by the application to identify <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
+ <p>A Session ID is a unique string identifier generated by the user agent or <a href="#cdm">CDM</a> that can be used by the application to identify <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
<span class="non-normative">(The underlying content protection client or server do not necessarily need to support Session IDs.)</span>
</p>
- <p>A new Session ID is generated each time the user agent successfully initializes a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
- It must be valid before the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> enters the <code><a href="#dom-statepending">PENDING</a></code> or <code><a href="#dom-stateready">READY</a></code> states and the user agent fires the associated events.
- </p>
+ <p>A new Session ID is generated each time the user agent and CDM successfully create a new session.</p>
<p>Each Session ID shall be unique within the browsing context in which it was created.
<span class="non-normative">(Note: Some use cases may require that Session IDs be unique within the origin over time, including across browsing sessions.)</span>
</p>
- <h4 id="initialization-data">1.1.5. Initialization Data</h4>
- <p><i>This section is non-normative.</i></p>
- <p>Initialization Data is a generic term for container-specific data that is used by <a href="#cdm">Content Decryption Modules</a> to generate a key request.
- It should always allow unique identification of the key or keys needed to decrypt the content, possibly after being parsed by a CDM or server.
+ <h4 id="decryption-key">1.1.5. Key</h4>
+ <p>Unless otherwise stated, key refers to a decryption key that can be used to decrypt blocks within <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
+ Each such key is uniquely identified by a <a href="#decryption-key-id">key ID</a>.
+ A key is associated with the <a href="#key-session">session</a> used to provide it to the CDM. (The same key may be present in multiple sessions.)
+ Such keys may only be provided to the <a href="#cdm">CDM</a> via an <code><a href="#dom-update">update()</a></code> call. (They may later be loaded by <code><a href="#dom-loadsession">loadSession()</a></code> as part of the stored session data.)
+ </p>
+
+ <p>A key is considered <em>usable</em> if the CDM is certain the key is currently usable for decryption. <span class="non-normative">For example, a key is not usable if its license has expired.</span></p>
+
+ <h4 id="decryption-key-id">1.1.6. Key ID</h4>
+ <p>A <a href="#decryption-key">key</a> is associated with a key ID, which uniquely identifies a key.
+ The container specifies the ID of the key that can decrypt a block or set of blocks within the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
+ <a href="#initialization-data">Initialization Data</a> may contain key ID(s) to identify the keys that are needed to decrypt the media data.
+ However, there is no requirement that Initialization Data contain any or all key IDs used in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> or <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-resource">media resource</a>.
+ <a href="#license">Licenses</a> provided to the CDM associate each key with a key ID so the <a href="#cdm">CDM</a> can select the appropriate key when decrypting an encrypted block of media data.
</p>
- <p><a href="#key-system">Key Systems</a> usually require a block of initialization data containing information about the stream to be decrypted before they can construct a key request message.
- This block could be as simple as a key or content ID to send to a server or as complex as an opaque Key System-specific collection of data.
- This initialization information may be obtained in some application-specific way or may be stored with the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
- Container formats may provide for storage of such information, possibly for multiple <a href="#key-system">Key Systems</a> in a single media file.
+ <h4 id="license">1.1.7. License</h4>
+ <p>A license is key system-specific state information that includes one or more <a href="#decryption-key">key(s)</a> - each associated with a <a href="#decryption-key-id">key ID</a> - and potentially other information about key usage.</p>
+
+ <h4 id="initialization-data">1.1.8. Initialization Data</h4>
+ <p class="non-normative">
+ <a href="#key-system">Key Systems</a> usually require a block of initialization data containing information about the stream to be decrypted before they can construct a license request message.
+ This block could be a simple key or content ID or a more complex structure containing such information.
+ It should always allow unique identification of the key(s) needed to decrypt the content.
+ This initialization information may be obtained in some application-specific way or provided with the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
</p>
- <p>Initialization data found in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> is provided to the application in the <code><a href="#dom-initdata">initData</a></code> attribute of the <code><a href="#dom-needkey">needkey</a></code> event.
- This data has a container-specific format and is assumed to contain one or more generic or Key System-specific sets of initialization information.
+ <p>
+ Initialization Data is a generic term for container-specific data that is used by <a href="#cdm">CDMs</a> to generate a license request.
+ Initialization data found with the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> is provided to the application in the <code><a href="#dom-initdata">initData</a></code> attribute of the <code><a href="#dom-encrypted">encrypted</a></code> event.
</p>
- <h4 id="cross-origin-support">1.1.6. Cross Origin Support</h4>
- <p>During playback, embedded media data is exposed to script in the embedding origin. In order for the API to fire <code><a href="#dom-needkey">needkey</a></code>
+ <p>
+ The format of the initialization data depends upon the type of container, and containers may support more than one format
+ of initialization data. The <dfn id="initialization-data-type">initialization data type</dfn> is a string that indicates what
+ format the initialization data is provided in. Initialization data type strings are always matched case-sensitively. It is
+ recommended that initialization data type strings are lower-case ASCII strings.
+ </p>
+
+ <p>
+ The <a href="initdata-format-registry.html">Encrypted Media Extensions Stream Format and Initialization Data Format Registry</a>
+ provides the mapping from initialization data type string to the specification for each format.
+ </p>
+
+
+ <h4 id="cross-origin-support">1.1.9. Cross Origin Support</h4>
+ <p>During playback, embedded media data is exposed to script in the embedding origin. In order for the API to fire <code><a href="#dom-encrypted">encrypted</a></code>
and <code><a href="#dom-eventmessage">message</a></code> events, <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> must be <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-same-origin">CORS-same-origin</a> with the embedding page.
If <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> is cross-origin with the embedding document, authors should use the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#attr-media-crossorigin">crossorigin</a> attribute
on the <a href="#media-element">media element</a> and CORS headers on the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> response to make it <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-same-origin">CORS-same-origin</a>.
</p>
<h2 id="extensions">2. Media Element Extensions</h2>
- <p>We extend <dfn id="media-element" title="media element"><a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-element">media element</a></dfn> to allow decryption key acquisition to be handled in JavaScript.</p>
- <p class="non-normative">Note: For some <a href="#cdm">CDMs</a>, "key" and "key request" correspond to "license" and "license request", respectively.</p>
+ <p>We extend <dfn id="media-element" title="media element"><a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-element">media element</a></dfn> to allow decryption key acquisition to be handled by the application.</p>
<pre class="idl">
+enum <dfn id="dom-mediawaitingfor">MediaWaitingFor</dfn> { "<dfn id="dom-waitingfornone">none</dfn>", "<dfn id="dom-waitingfordata">data</dfn>", "<dfn id="dom-waitingforkey">key</dfn>" };
partial interface <dfn id="dom-htmlmediaelement">HTMLMediaElement</dfn> {
// Encrypted Media
- readonly attribute <a href="#dom-mediakeys">MediaKeys</a> <a href="#dom-attrmediakeys">mediaKeys</a>;
- void <a href="#dom-setmediakeys">setMediaKeys</a>(<a href="#dom-mediakeys">MediaKeys</a> mediaKeys);
+ readonly attribute <a href="#dom-mediakeys">MediaKeys</a>? <a href="#dom-attrmediakeys">mediaKeys</a>;
+ Promise<void> <a href="#dom-setmediakeys">setMediaKeys</a>(<a href="#dom-mediakeys">MediaKeys</a>? mediaKeys);
- attribute <a href="http://www.w3.org/TR/html5/webappapis.html#eventhandler">EventHandler</a> <a href="#dom-onneedkey">onneedkey</a>;
+ attribute <a href="http://www.w3.org/TR/html5/webappapis.html#eventhandler">EventHandler</a> <a href="#dom-onencrypted">onencrypted</a>;
+
+ readonly attribute <a href="#dom-mediawaitingfor">MediaWaitingFor</a> <a href="#dom-waitingfor">waitingFor</a>;
};
-[<a href="#dom-mediakeys-constructor">Constructor</a>(DOMString <a href="#key-system">keySystem</a>)]
+enum <dfn id="dom-istypesupportedresult">IsTypeSupportedResult</dfn> { "<dfn id="dom-istypesupportedresultempty"></dfn>" /* empty string */, "<dfn id="dom-istypesupportedresultmaybe">maybe</dfn>", "<dfn id="dom-istypesupportedresultprobably">probably</dfn>" };
+enum <dfn id="dom-sessiontype">SessionType</dfn> { "<dfn id="dom-sessiontypetemporary">temporary</dfn>", "<dfn id="dom-sessiontypepersistent">persistent</dfn>" };
interface <dfn id="dom-mediakeys">MediaKeys</dfn> {
readonly attribute DOMString <a href="#dom-keysystem">keySystem</a>;
- <a href="#dom-mediakeysession">MediaKeySession</a> <a href="#dom-createsession">createSession</a>(DOMString contentType, Uint8Array initData);
- <a href="#dom-mediakeysession">MediaKeySession</a> <a href="#dom-loadsession">loadSession</a>(DOMString sessionId);
+ Promise<<a href="#dom-mediakeysession">MediaKeySession</a>> <a href="#dom-createsession">createSession</a>(DOMString <a href="#initialization-data-type">initDataType</a>, (ArrayBuffer or ArrayBufferView) initData, optional <a href="#dom-sessiontype">SessionType</a> sessionType = "<a href="#dom-sessiontypetemporary">temporary</a>");
+ Promise<<a href="#dom-mediakeysession">MediaKeySession</a>> <a href="#dom-loadsession">loadSession</a>(DOMString sessionId);
+ Promise<void> <a href="#dom-setservercertificate">setServerCertificate</a>((ArrayBuffer or ArrayBufferView) serverCertificate);
- static bool <a href="#dom-istypesupported">isTypeSupported</a>(DOMstring <a href="#key-system">keySystem</a>, DOMString? contentType);
+ static Promise<<a href="#dom-mediakeys">MediaKeys</a>> <a href="#dom-create">create</a>(DOMString <a href="#key-system">keySystem</a>);
+
+ static <a href="#dom-istypesupportedresult">IsTypeSupportedResult</a> <a href="#dom-istypesupported">isTypeSupported</a>(DOMstring <a href="#key-system">keySystem</a>, optional DOMString <a href="#initialization-data-type">initDataType</a>, optional DOMString contentType, optional DOMString capability);
};
interface <dfn id="dom-mediakeysession">MediaKeySession</dfn> : <a href="http://www.w3.org/TR/dom/#eventtarget">EventTarget</a> {
- // error state
- readonly attribute <a href="#dom-mediakeyerror">MediaKeyError</a>? <a href="#dom-error">error</a>;
-
// session properties
- readonly attribute DOMString <a href="#dom-keysystem">keySystem</a>;
readonly attribute DOMString <a href="#dom-sessionid">sessionId</a>;
+ readonly attribute unrestricted double <a href="#dom-expiration">expiration</a>;
+ readonly attribute Promise<void> <a href="#dom-closed">closed</a>;
// session operations
- void <a href="#dom-update">update</a>(Uint8Array response);
- void <a href="#dom-release">release</a>();
+ Promise<void> <a href="#dom-update">update</a>((ArrayBuffer or ArrayBufferView) response);
+ Promise<void> <a href="#dom-close">close</a>();
+ Promise<void> <a href="#dom-remove">remove</a>();
+
+ Promise<sequence<ArrayBuffer>> <a href="#dom-getusablekeyids">getUsableKeyIds</a>();
};
+</pre>
-partial interface <dfn id="dom-htmlsourceelement">HTMLSourceElement</dfn> {
- attribute DOMString <a href="#dom-sourcekeysystem">keySystem</a>;
-};</pre>
+ <div class="note">
+<div class="noteHeader">Note</div>
+ <p>All errors are reported asynchronously by rejecting the returned Promise. This includes WebIDL type mapping errors.</p>
+ <p>The steps of an algorithm are always aborted when resolving or rejecting a promise.</p>
+ </div>
+
<p>The <dfn id="dom-attrmediakeys"><code>mediaKeys</code></dfn> attribute is the <code><a href="#dom-mediakeys">MediaKeys</a></code> being used when decrypting encrypted <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> for this <a href="#media-element">media element</a>.</p>
- <p>The <dfn id="dom-setmediakeys"><code>setMediaKeys(mediaKeys</code></dfn> method provides the <code><a href="#dom-mediakeys">MediaKeys</a></code> to use. When calling this method, the media element must run the following steps:</p>
+ <p>The <dfn id="dom-setmediakeys"><code>setMediaKeys(mediaKeys</code></dfn>) method provides the <code><a href="#dom-mediakeys">MediaKeys</a></code> to use when decrypting media data during playback. It must run the following steps:</p>
<ol>
- <li><p>If the <code><a href="#dom-mediakeys">MediaKeys</a></code> object is already in use and the user agent is unable to re-use it with this element, throw a <code><a href="http://www.w3.org/TR/dom/#dom-domexception-quota_exceeded_err">QUOTA_EXCEEDED_ERR</a></code> exception and abort these steps.</p></li>
- <li>Set the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute of the media element to <var>mediaKeys</var>.</li>
+ <li><p>If <var>mediaKeys</var> and the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute are the same object, return a resolved promise.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
+ <ol>
+ <li><p>If <var>mediaKeys</var> is not null, it is already in use by another media element, and the user agent is unable to use it with this element, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-QuotaExceededError">"QuotaExceededError"</a></code>.</p></li>
+ <li>
+<p>If the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute is not null, run the following steps:</p>
+ <ol>
+ <li><p>If the user agent or CDM do not support removing the association, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li><p>If the association cannot currently be removed <span class="non-normative">(i.e. during playback)</span>, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
+ <li><p>Stop using the CDM instance represented by the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute to decrypt <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> and remove the association with the media element.</p></li>
+ <li><p>If the preceding step failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ </ol>
+ </li>
+ <li>
+<p>If <var>mediaKeys</var> is not null, run the following steps:</p>
+ <ol>
+ <li><p>Associate the CDM instance represented by <var>mediaKeys</var> with the media element for decrypting <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.</p></li>
+ <li>
+<p>If the preceding step failed, run the following steps:</p>
+ <ol>
+ <li><p>Set the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute to null.</p></li>
+ <li><p>Reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ </ol>
+ </li>
+ <li>
+<p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to run the <a href="#algorithms-resume-playback">Attempt to Resume Playback If Necessary</a> algorithm on the media element.</p>
+ <p>The user agent may choose to skip this step if it knows resuming will fail <span class="non-normative">(i.e. <var>mediaKeys</var> has no sessions)</span>.</p>
+ </li>
+ </ol>
+ </li>
+ <li><p>Set the <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute to <var>mediaKeys</var>.</p></li>
+ <li><p>Resolve <var>promise</var>.</p></li>
+ </ol>
+ </li>
+ <li><p>Return <var>promise</var>.</p></li>
</ol>
+ <p class="non-normative">Note: Support for clearing or replacing the associated <code><a href="#dom-mediakeys">MediaKeys</a></code> object during playback is a quality of implementation issue. In many cases it will result in a bad user experience or rejected promise.</p>
<p class="non-normative">Note: As a best practice, applications should create a MediaKeys object and call <code><a href="#dom-setmediakeys">setMediaKeys()</a></code> before providing <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> (for example, setting the src attribute of the <a href="#media-element">media element</a>). This avoids potential delays in some implementations.</p>
- <p class="non-normative">Note: In some implementations, <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects created by <code><a href="#dom-createsession">createSession()</a></code> may not fire any events until the <code><a href="#dom-mediakeys">MediaKeys</a></code> object is associated with a media element with <code><a href="#dom-setmediakeys">setMediaKeys()</a></code>.</p>
+ <p class="non-normative">Note: In some implementations, <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects created by <code><a href="#dom-createsession">createSession()</a></code> may not fire any events until the <code><a href="#dom-mediakeys">MediaKeys</a></code> object is associated with a media element using <code><a href="#dom-setmediakeys">setMediaKeys()</a></code>.</p>
- <p>The <dfn id="dom-onneedkey"><code>onneedkey</code></dfn> event handler for the <code><a href="#dom-needkey">needkey</a></code> event must be supported by all HTMLMediaElements as both a content attribute and an IDL attribute.</p>
+ <p>The <dfn id="dom-onencrypted"><code>onencrypted</code></dfn> event handler for the <code><a href="#dom-encrypted">encrypted</a></code> event must be supported by all HTMLMediaElements as both a content attribute and an IDL attribute.</p>
- <p>The <dfn id="dom-mediakeys-constructor"><code>MediaKeys(<var title="true">keySystem</var>)</code></dfn> constructor must run the following steps:</p>
+ <p>The <dfn id="dom-waitingfor"><code>waitingFor</code></dfn> attribute indicates what the media element is waiting for, if anything (indicated by the <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-waiting">waiting</a></code> and <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-canplay">canplay</a></code> events). This is described in the <a href="#algorithms-encrypted-block">Encrypted Block Encountered</a> algorithm.</p>
+
+
+ <p>The <dfn id="dom-create"><code>create(keySystem)</code></dfn> method creates a new <code><a href="#dom-mediakeys">MediaKeys</a></code> object for <var title="true">keySystem</var>. It must run the following steps:</p>
<ol>
- <li><p>If <var title="true">keySystem</var> is null or an empty string, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
- <li><p>If <var title="true">keySystem</var> is not one of the user agent's supported <a href="#key-system">Key Systems</a>, throw a <code><a href="http://www.w3.org/TR/dom/#dom-domexception-not_supported_err">NOT_SUPPORTED_ERR</a></code> and abort these steps. Key system string comparison is case-sensitive.</p></li>
- <li>Create a new <code><a href="#dom-mediakeys">MediaKeys</a></code> object.
- <ol>
- <li><p>Let the <code><a href="#dom-keysystem">keySystem</a></code> attribute be <var title="true">keySystem</var>.</p></li>
- </ol>
- </li>
-
+ <li><p>If <var title="true">keySystem</var> is an empty string, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If <var title="true">keySystem</var> is not one of the <a href="#key-system">Key Systems</a> supported by the user agent, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>. String comparison is case-sensitive.</p></li>
+ <li><p>If <var title="true">keySystem</var> is not supported or not allowed on the <a href="http://www.w3.org/TR/html5/browsers.html#origin-0">origin</a> of the <code><a href="http://www.w3.org/TR/dom/#document">Document</a></code>, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
<li>
- <p>Schedule a task to execute the following steps:</p>
+<p>Run the following steps asynchronously:</p>
<ol>
<li><p>Let <var title="true">cdm</var> be the <a href="#cdm">content decryption module</a> corresponding to <var title="true">keySystem</var>.</p></li>
<li><p>Load and initialize the <var title="true">cdm</var> if necessary.</p></li>
+ <li><p>If <var title="true">cdm</var> fails to load or initialize, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+
<li>
- <dl class="switch">
- <dt>If <var title="true">cdm</var> fails to load or initialize</dt>
- <dd><ol>
- <li>
-<p>Create a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> = the appropriate <a href="#mediakeyerror-names">error name</a><br>
- <code><a href="#dom-systemcode">systemCode</a></code> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Store this new error object internally with the <code><a href="#dom-mediakeys">MediaKeys</a></code> instance being created. This will be used to fire an error against any session created for this instance.</p></li>
- </ol></dd>
- </dl>
+ <p>Let <var title="true">media keys</var> be a new <code><a href="#dom-mediakeys">MediaKeys</a></code> object, and initialize it as follows:</p>
+ <ol>
+ <li><p>Set the <code><a href="#dom-keysystem">keySystem</a></code> attribute to <var title="true">keySystem</var>.</p></li>
+ </ol>
</li>
+ <li><p>Resolve <var>promise</var> with <var title="true">media keys</var>.</p></li>
</ol>
</li>
-
- <li>Return the new <code><a href="#dom-mediakeys">MediaKeys</a></code> object to the caller.</li>
+ <li><p>Return <var>promise</var>.</p></li>
</ol>
- <p>The <dfn id="dom-keysystem"><code>keySystem</code></dfn> attribute is an identifier for the <a href="#key-system">Key System</a> being used.</p>
+ <p>The <dfn id="dom-keysystem"><code>keySystem</code></dfn> attribute identifies the <a href="#key-system">Key System</a> being used.</p>
- <p>The <dfn id="dom-createsession"><code>createSession(contentType, initData)</code></dfn> method must run the following steps:</p>
- <p class="non-normative">Note: The contents of <var title="true">initData</var> are container-specific <a href="#initialization-data">Initialization Data</a>.
- <var title="true">contentType</var> specifies the container type and thus how to interpret <var title="true">initData</var>.
+ <p>The <dfn id="dom-createsession"><code>createSession(initDataType, initData, sessionType)</code></dfn> method creates a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object for the <var title="true">initData</var>. It must run the following steps:</p>
+ <p class="non-normative">The contents of <var title="true">initData</var> are container-specific <a href="#initialization-data">Initialization Data</a>.
+ <var title="true">initDataType</var> is the <a href="#initialization-data-type">initialization data type</a> that indicates how to interpret <var title="true">initData</var>.
</p>
- <p class="non-normative">Note: MIME types usually include "audio/" or "video/", and these should be included in <var title="true">contentType</var> as appropriate.
- However, user agents and <a href="#cdm">CDMs</a> should not treat sessions created with "audio/" differently than those created with "video/".
+ <p class="non-normative">Note: User agents and <a href="#cdm">CDMs</a> should not treat sessions created with audio data differently than those created with video data.
That is, there is no such thing as an "audio session" or a "video session" - all sessions are used for all media streams processed by <var title="true">cdm</var>.
</p>
<ol>
- <li><p>If <var title="true">contentType</var> is null or an empty string, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
- <li><p>If <var title="true">initData</var> is null or an empty array, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
- <li><p>If <var title="true">contentType</var> contains a MIME type that is not supported or is not supported by the <code><a href="#dom-keysystem">keySystem</a></code>, throw a <code><a href="http://www.w3.org/TR/dom/#dom-domexception-not_supported_err">NOT_SUPPORTED_ERR</a></code> exception and abort these steps.</p></li>
-
- <li>Create a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
+ <li><p>If <var title="true">initDataType</var> is an empty string, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If <var title="true">initData</var> is an empty array, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is<code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If <var title="true">initDataType</var> is not an <a href="#initialization-data-type">initialization data type</a> supported by the <a href="#cdm">content decryption module</a> corresponding to the <code><a href="#dom-keysystem">keySystem</a></code>, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>. String comparison is case-sensitive.</p></li>
+ <li><p>If <var title="true">sessionType</var> is not supported by the <a href="#cdm">content decryption module</a> corresponding to the <code><a href="#dom-keysystem">keySystem</a></code>, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li><p>Let <var>init data</var> be a copy of the contents of the <var title="true">initData</var> parameter.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
<ol>
- <li><p>Let the <code><a href="#dom-keysystem">keySystem</a></code> attribute be <var title="true">keySystem</var>.</p></li>
- <li><p>Let the state of the session be <code><a href="#dom-statecreated">CREATED</a></code>.</p></li>
+ <li><p>Let <var title="true">request</var> be null.</p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
+ <li>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
+ <ol>
+ <li><p>If the <var>init data</var> is not valid for <var title="true">initDataType</var>, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If the <var>init data</var> is not supported by the <var title="true">cdm</var>, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li>
+<p>Let <var title="true">request</var> be a request <span class="non-normative">(e.g. a license request)</span> generated based on the <var>init data</var>, which is interpreteted per <var title="true">initDataType</var>, and <var title="true">sessionType</var>.</p>
+ <p>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypetemporary">temporary</a></code>", the request is for a temporary non-persisted license.
+ If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypepersistent">persistent</a></code>", the request is for a persistable session, possibly with a persistable license.</p>
+ <p>If <var title="true">sessionType</var> is <em>not</em> "<code><a href="#dom-sessiontypepersistent">persistent</a></code>", the CDM must <em>not</em> store a record of or data related to the session at any point.</p>
+ <p class="non-normative">Note: The license server may reject the requested type, but it should not issue a different type.</p>
+ <p><var title="true">cdm</var> must not use any stream-specific data, including <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>, not provided via the <var>init data</var>.</p>
+ </li>
+ </ol>
+ </li>
+ <li><p>Let the <var title="true">session ID</var> be a unique <a href="#session-id">Session ID</a> string. <span class="non-normative">It may be obtained from <var title="true">cdm</var>.</span></p></li>
+ <li>
+<p>Let <var title="true">session</var> be a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, and initialize it as follows:</p>
+ <ol>
+ <li><p>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">session ID</var>.</p></li>
+ <li><p>Let <code><a href="#dom-expiration">expiration</a></code> be <code>NaN</code>.</p></li>
+ <li><p>Let <code><a href="#dom-closed">closed</a></code> be a new promise.</p></li>
+ <li><p>Let the session type be <var title="true">sessionType</var>.</p></li>
+ </ol>
+ </li>
+ <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ <li><p>Add an entry for the value of the <code><a href="#dom-sessionid">sessionId</a></code> attribute to the <var title="true">list of active session IDs</var> for this object.</p></li>
+ <li><p>Run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <var title="true">session</var>, providing <var title="true">request</var> and <code>null</code>.</p></li>
+ <li><p>Resolve <var>promise</var> with <var title="true">session</var>.</p></li>
</ol>
</li>
-
+ <li><p>Return <var>promise</var>.</p></li>
+ </ol>
+
+ <p>The <dfn id="dom-loadsession"><code>loadSession(sessionId)</code></dfn> method creates a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object containing the data stored for the <var title="true">sessionId</var>. It must run the following steps:</p>
+ <ol>
+ <li><p>If the <a href="#cdm">content decryption module</a> corresponding to the <code><a href="#dom-keysystem">keySystem</a></code> attribute does not support loading previous sessions, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li><p>If <var title="true">sessionId</var> is an empty string, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
<li>
-<p>Schedule a task to initialize the session, providing <var title="true">contentType</var>, <var title="true">initData</var>, and the new object.</p>
- <p>The user agent will asynchronously execute the following steps in the task:</p>
+<p>Run the following steps asynchronously:</p>
<ol>
- <li><p>Wait for the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a> task to complete.</p></li>
- <li><p>
- If there is a <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> stored with the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that occurred because of an error during the loading the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a> task
- then <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object and abort these steps.
- </p></li>
- <li><p>Let <var title="true">request</var> be null.</p></li>
- <li><p>Let <var title="true">defaultURL</var> be null.</p></li>
- <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a>.</p></li>
<li>
-<p>Use <var title="true">cdm</var> to execute the following steps:</p>
+<p>If the <var title="true">list of active session IDs</var> for this object includes an entry for <var title="true">sessionId</var>, resolve <var>promise</var> with <code>null</code>.</p>
+ <p class="non-normative">In other words, do not create a session if a non-closed session already exists for this <var title="true">sessionId</var>.</p>
+ </li>
+ <li><p>Let <var title="true">expiration time</var> be <code>NaN</code>.</p></li>
+ <li><p>Let <var title="true">request</var> be null.</p></li>
+ <li><p>Let <var title="true">destination URL</var> be null.</p></li>
+ <li><p>Let <var title="true">origin</var> be the <a href="http://www.w3.org/TR/html5/browsers.html#origin-0">origin</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object's <code><a href="http://www.w3.org/TR/dom/#document">Document</a></code>.</p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
+ <li>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
<ol>
- <li>
-<p>Process <var title="true">contentType</var> and <var title="true">initData</var>.</p>
- <p class="non-normative">Note: <var title="true">contentType</var> should be used to determine how to interpret <var title="true">initData</var>.</p>
- </li>
+ <li><p>If there is no data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>, resolve <var>promise</var> with <code>undefined</code>.</p></li>
+ <li><p>Let <var title="true">session data</var> be the data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>.
+ This must not include data from other origin(s) or that is not associated with an origin.</p></li>
+ <li><p>Load the <var title="true">session data</var>.</p></li>
+ <li><p>If the <var title="true">session data</var> indicates an expiration time for the session, let <var title="true">expiration time</var> be the expiration time in milliseconds since 01 January 1970 UTC.</p></li>
<li>
-<p>If a message exchange <span class="non-normative">(e.g. a license request)</span> is required:</p>
+<p>If a message exchange is required:</p>
<ol>
- <li>
-<p>Let <var title="true">request</var> be a request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>.</p>
- <p><var title="true">cdm</var> must not use any stream-specific data, including <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>, not provided via <var title="true">initData</var>.</p>
- <p class="non-normative">Note: <var title="true">request</var> may be a request for multiple keys, depending on the <var title="true"><a href="#key-system">keySystem</a></var> and/or <var title="true">initData</var>. This is transparent to the application.</p>
- </li>
- <li><p>If <var title="true">initData</var> indicates a default URL relevant to <var title="true">keySystem</var>, let <var title="true">defaultURL</var> be that URL.</p></li>
+ <li><p>Let <var title="true">request</var> be a request generated by the <a href="#cdm">CDM</a> based on the <var title="true">session data</var>.</p></li>
+ <li><p>If the <var title="true">session data</var> indicates a destination URL for the request, let <var title="true">destination URL</var> be that URL. The URL may be validated and/or normalized.</p></li>
</ol>
</li>
</ol>
</li>
- <li><p>Let the <code><a href="#dom-sessionid">sessionId</a></code> attribute be a unique <a href="#session-id">Session ID</a> string. <span class="non-normative">It may be obtained from <var title="true">cdm</var>.</span></p></li>
- <li>
-<p>If any of the preceding steps in the task failed, run the following steps:</p>
- <ol>
- <li>
-<p>Create a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> = the appropriate <a href="#mediakeyerror-names">error name</a><br>
- <code><a href="#dom-systemcode">systemCode</a></code> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Set the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object's <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
- <li><p>Let the state of the session be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- <li><p>Abort the task.</p></li>
- </ol>
- </li>
- <li>
- <p>If the associated <a href="#media-element">media element(s)</a> are <a href="#waiting-for-a-key">waiting for a key</a>, <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to attempt to resume playback.</p>
- <p class="non-normative">In other words, resume playback if the necessary key is provided.</p>
- <p>The user agent may choose to skip this step if it knows resuming will fail <span class="non-normative">(i.e. no usable key was added)</span>.</p>
- </li>
<li>
-<p>Follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If <var title="true">request</var> is not null</dt>
- <dd>
- <p>Run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object with:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="#dom-message">message</a></code> = <var title="true">request</var><br>
- <code><a href="#dom-destinationurl">destinationURL</a></code> = <var title="true">defaultURL</var>
- </li></ul>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li><p>Let the state of the session be <code><a href="#dom-stateready">READY</a></code>.</p></li>
- <li>
- <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventready">ready</a></code> at the new object.</p>
- <p class="non-normative">Note: this step makes it possible for a MediaKeySession to transition from the CREATED state to the READY state.
- User agents might do this as an optimization but, even if this is done, all MediaKeySession instances must appear distinct regardless of the underlying implementation.</p>
- </li>
- </ol>
- </dd>
- </dl>
+<p>Let <var title="true">session</var> be a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, and initialize it as follows:</p>
+ <ol>
+ <li><p>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">sessionId</var>.</p></li>
+ <li><p>Let <code><a href="#dom-expiration">expiration</a></code> be <code>NaN</code>.</p></li>
+ <li><p>Let <code><a href="#dom-closed">closed</a></code> be a new promise.</p></li>
+ <li><p>Let the session type be "<code><a href="#dom-sessiontypepersistent">persistent</a></code>".</p></li>
+ </ol>
</li>
+ <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ <li><p>Add an entry for the value of the <code><a href="#dom-sessionid">sessionId</a></code> attribute to the <var title="true">list of active session IDs</var> for this object.</p></li>
+ <li>
+<p>If the loaded session contains usable keys, run the <a href="#algorithms-keys-changed">Usable Keys Changed</a> algorithm on the <var title="true">session</var>.</p>
+ <p>The algorithm may also be run later should additional processing be necessary to determine with certainty whether one or more keys is usable.</p>
+ </li>
+ <li><p>Run the <a href="#algorithms-update-expiration">Update Expiration</a> algorithm on the <var title="true">session</var>, providing <var title="true">expiration time</var>.</p></li>
+ <li><p>If <var title="true">request</var> is not null, run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <var title="true">session</var>, providing <var title="true">request</var> and <var title="true">destination URL</var>.</p></li>
+ <li><p>Resolve <var>promise</var> with <var title="true">session</var>.</p></li>
</ol>
</li>
- <li>
-<p>Return the new object to the caller.</p>
- <p class="non-normative">Note: User agents should always fire an event at the returned object in response to this call.
- For some implementations, it is possible - especially the first time a <a href="#key-system">Key System</a> is used - that the first event will be delayed significantly while the client is initialized, the user responds to permission requests, etc.
- Applications should expect and handle such delays.</p>
- </li>
+ <li><p>Return <var>promise</var>.</p></li>
</ol>
- <p>The <dfn id="dom-loadsession"><code>loadSession(sessionId)</code></dfn> method must run the following steps:</p>
+ <p id="server-certificate">The <dfn id="dom-setservercertificate"><code>setServerCertificate(serverCertificate)</code></dfn> method provides a server certificate to be used to encrypt messages to the license server. It must run the following steps:</p>
+ <p class="non-normative">The contents of <var title="true">serverCertificate</var> are <a href="#key-system">Key System</a>-specific.</p>
+ <p class="non-normative">Key systems that use such certificates should also support requesting the certificate from the server via an additional round trip. This simplifies interoperability for applications that are not designed to provide certificates to specific key systems.</p>
+
<ol>
- <li><p>If the <code><a href="#dom-keysystem">keySystem</a></code> does not support loading previous sessions, throw a <code><a href="http://www.w3.org/TR/dom/#dom-domexception-not_supported_err">NOT_SUPPORTED_ERR</a></code> exception and abort these steps.</p></li>
- <li><p>If <var title="true">sessionId</var> is null or an empty string, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
- <li>Create a new <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
+ <li><p>If <var title="true">serverCertificate</var> is an empty array, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If the <code><a href="#dom-keysystem">keySystem</a></code> does not support server certificates, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code>.</p></li>
+ <li><p>Let <var>certificate</var> be a copy of the contents of the <var title="true">serverCertificate</var> parameter.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
<ol>
- <li><p>Let the <code><a href="#dom-keysystem">keySystem</a></code> attribute be <var title="true">keySystem</var>.</p></li>
- <li><p>Let the state of the session be <code><a href="#dom-statecreated">CREATED</a></code>.</p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
+ <li><p>Use the <var title="true">cdm</var> to process <var>certificate</var>.</p></li>
+ <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ <li><p>Resolve <var>promise</var>.</p></li>
</ol>
</li>
+ <li><p>Return <var>promise</var>.</p></li>
+ </ol>
+
+ <p>The <dfn id="dom-istypesupported"><code>isTypeSupported(keySystem, initDataType, contentType, capability)</code></dfn> method returns whether <var title="true">keySystem</var> is supported with the <var title="true"><a href="#initialization-data-type">initDataType</a></var>, container and codec(s) specified by <var title="true">contentType</var>, and <var title="true">capability</var>.</p>
+ <div class="issue">
+<div class="issue-title"><span>Issue 1</span></div>
+<p class=""><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=25923">Bug 25923</a> - isTypeSupported() may be made asynchronous.</p>
+</div>
+ <div class="example">
+ <p>The following list shows some examples.</p>
+ <dl>
+ <dt>Returns whether the Some System <a href="#key-system">Key System</a> may be supported. Specific containers and codecs may or may not be supported with Some System.</dt>
+ <dd><pre class="code">MediaKeys.isTypeSupported("com.example.somesystem")</pre></dd>
+ <dt>Returns whether the Some System <a href="#key-system">Key System</a> may be supported and is capable of parsing the <a href="#initialization-data-type">initialization data type</a> format "keyids". Specific containers and codecs may or may not be supported with Some System.</dt>
+ <dd><pre class="code">MediaKeys.isTypeSupported("com.example.somesystem", "keyids")</pre></dd>
+ <dt>Returns whether the Some System <a href="#key-system">Key System</a> may be supported and is capable of parsing the <a href="#initialization-data-type">initialization data type</a> format <var title="true">initDataType</var>, the user agent is capable of demuxing the container specified by <var title="true">mimeType</var>, and the codec(s) specified by <var title="true">mimeType</var> are supported, all as specified by capability "foo".</dt>
+ <dd><pre class="code">MediaKeys.isTypeSupported("com.example.somesystem", <var title="true">initDataType</var>, <var title="true">mimeType</var>, "foo")</pre></dd>
+ <dt>Returns whether the user agent <em>probably</em> supports <a href="#clear-key">Clear Key</a> using the <a href="#initialization-data-type">initialization data type</a> format <var title="true">initDataType</var> and the container and codec(s) specified by <var title="true">mimeType</var>.</dt>
+ <dd><pre class="code">"probably" == MediaKeys.isTypeSupported("org.w3.clearkey", <var title="true">initDataType</var>, <var title="true">mimeType</var>)</pre></dd>
+ </dl>
+ </div>
+
+ <p>It must run the following steps:</p>
+
+ <ol>
+ <li><p>If <var title="true">keySystem</var> is an empty string or contains an unrecognized or unsupported <a href="#key-system">Key System</a>, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps. String comparison is case-sensitive.</p></li>
+ <li><p>If the <var title="true">keySystem</var> implementation is not available and usable, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li>
+<p>Follow the steps for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If <var title="true">keySystem</var> is a value that may be successfully passed to <code><a href="#dom-create">create()</a></code>
+</dt>
+ <dd>Let <var title="true">probably result</var> be "<code><a href="#dom-istypesupportedresultprobably">probably</a></code>".</dd>
+ <dt>Otherwise <span class="non-normative">(as may be the case for strings that are only used for discovery)</span>
+</dt>
+ <dd>Let <var title="true">probably result</var> be "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ </dl>
+ </li>
<li>
-<p>Schedule a task to initialize the session, providing <var title="true">sessionId</var> and the new object.</p>
- <p>The user agent will asynchronously execute the following steps in the task:</p>
+<p>If <var title="true">initDataType</var> was not provided, follow the steps for the first matching condition from the following list and abort these steps:</p>
+ <dl class="switch">
+ <dt>If the user agent is <em>not</em> confident that the <var title="true">keySystem</var> implementation is available and usable</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>Otherwise</dt>
+ <dd>Return <var title="true">probably result</var>.</dd>
+ </dl>
+ </li>
+
+ <li><p>If <var title="true">initDataType</var> is an empty string or contains an unrecognized or unsupported <a href="#initialization-data-type">initialization data type</a>, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps. String comparison is case-sensitive.</p></li>
+ <li><p>If <var title="true">initDataType</var> is not an <a href="#initialization-data-type">initialization data type</a> supported by the <var title="true">keySystem</var> implementation, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li><p>If the <var title="true">keySystem</var> implementation supporting <var title="true">initDataType</var> is not available and usable, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li>
+<p>If <var title="true">contentType</var> was not provided, follow the steps for the first matching condition from the following list and abort these steps:</p>
+ <dl class="switch">
+ <dt>If the user agent is <em>not</em> confident that the <var title="true">keySystem</var> implementation supporting <var title="true">initDataType</var> is available and usable</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>Otherwise</dt>
+ <dd>Return <var title="true">probably result</var>.</dd>
+ </dl>
+ </li>
+
+ <li><p>If <var title="true">contentType</var> is an empty string or contains an invalid or unrecognized MIME type, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li><p>Let <var title="true">container</var> be the container type specified by <var title="true">contentType</var>.</p></li>
+ <li><p>Let <var title="true">parameters</var> be the <a href="http://tools.ietf.org/html/rfc6381">RFC 6381</a> parameters, if any, specified by <var title="true">contentType</var>.</p></li>
+ <li><p>Let <var title="true">media types</var> be the set of media types specified by <var title="true">parameters</var>. <span class="non-normative">(For example, all of the codecs.)</span> It may be empty. The case-sensitivity of string comparisons is determined by the appropriate RFC or other specification. <span class="non-normative">(Case-sensitive string comparison is recommended because <a href="http://tools.ietf.org/html/rfc6381#section-3.3">RFC 6381</a> says, "Values are case sensitive" for some formats.)</span></p></li>
+ <li><p>If the user agent does not support <var title="true">container</var>, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps. The case-sensitivity of string comparisons is determined by the appropriate RFC. <span class="non-normative">(Per <a href="http://tools.ietf.org/html/rfc6838#section-4.2">RFC 6838</a>, "Both top-level type and subtype names are case-insensitive.")</span></p></li>
+ <li><p>If the user agent and <var title="true">keySystem</var> implementation do not support playback of encrypted <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> for all <var title="true">media types</var>, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li>
+<p>If <var title="true">capability</var> was not provided, follow the steps for the first matching condition from the following list and abort these steps:</p>
+ <dl class="switch">
+ <dt>If the user agent is <em>not</em> confident that the <var title="true">keySystem</var> implementation supporting <var title="true">initDataType</var> is available and usable to decrypt and enable playback of support playback of encrypted <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> for all <var title="true">media types</var>
+</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>If the user agent is <em>not</em> did not recognize one or more <var title="true">parameters</var>
+</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>Otherwise</dt>
+ <dd>Return <var title="true">probably result</var>.</dd>
+ </dl>
+ </li>
+
+ <li><p>If <var title="true">capability</var> is an empty string, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps.</p></li>
+ <li><p>If the <var title="true">keySystem</var> implementation does not support <var title="true">capability</var>, return the <a href="#dom-istypesupportedempty">empty string</a> and abort these steps. String comparison is case-sensitive.</p></li>
+ <li>
+<p>Follow the steps for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If the user agent is <em>not</em> confident that the <var title="true">keySystem</var> implementation supporting <var title="true">initDataType</var> is available and usable to decrypt and enable playback of support playback of encrypted <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> for all <var title="true">media types</var> as specified by <var title="true">capability</var>
+</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>If the user agent is <em>not</em> did not recognize one or more <var title="true">parameters</var>
+</dt>
+ <dd>Return "<code><a href="#dom-istypesupportedresultmaybe">maybe</a></code>".</dd>
+ <dt>Otherwise</dt>
+ <dd>Return <var title="true">probably result</var>.</dd>
+ </dl>
+ </li>
+ </ol>
+
+
+
+ <p>The <dfn id="dom-sessionid"><code>sessionId</code></dfn> attribute is the <a href="#session-id">Session ID</a> for this object and the associated key(s) or license(s).</p>
+
+ <p>The <dfn id="dom-expiration"><code>expiration</code></dfn> attribute is the time, in milliseconds since since 01 January, 1970 UTC, after which the key(s) in the session will no longer be usable to decrypt <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>, or <code>NaN</code> if no such time exists, as determined by the CDM.
+ </p>
+
+ <p>The <dfn id="dom-closed"><code>closed</code></dfn> attribute signals when object becomes closed as a result of the <a href="#algorithms-session-close">Session Close</a> algorithm being run.
+ This promise can only be fulfilled and is never rejected.</p>
+
+ <p>The <dfn id="dom-update"><code>update(response)</code></dfn> method provides messages, including licenses, to the CDM. It must run the following steps:</p>
+ <p class="non-normative">The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
+
+ <ol>
+ <li><p>If <var title="true">response</var> is an empty array, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>Let <var>message</var> be a copy of the contents of the <var title="true">response</var> parameter.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
<ol>
- <li><p>Wait for the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a> task to complete.</p></li>
- <li><p>
- If there is a <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> stored with the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that occurred because of an error during the loading the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a> task
- then <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object and abort these steps.
- </p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
<li><p>Let <var title="true">request</var> be null.</p></li>
- <li><p>Let <var title="true">destinationURL</var> be null.</p></li>
- <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a>.</p></li>
+ <li><p>Let <var title="true">destination URL</var> be null.</p></li>
<li>
-<p>Use <var title="true">cdm</var> to execute the following steps:</p>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
<ol>
- <li><p>Initialize the session with stored data for the <var title="true">sessionId</var>.</p></li>
+ <li><p>If the format of <var>message</var> is invalid in any way, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
<li>
-<p>If a message exchange <span class="non-normative">(e.g. a license request)</span> is required:</p>
+<p>Process <var>message</var>, following the stipulation for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypetemporary">temporary</a></code>" and <var>message</var> does not specify that session data, including any license, key(s), or similar session data it contains, should be stored</dt>
+ <dd>Continue processing <var>message</var>, not storing any session data.</dd>
+ <dt>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypepersistent">persistent</a></code>"</dt>
+ <dd>Continue processing <var>message</var>, storing the license, key(s), or similar session data contained in <var>message</var> as permitted or instructed by the license.</dd>
+ <dt>Otherwise</dt>
+ <dd>Reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</dd>
+ </dl>
+ <p class="non-normative">Note: When <var>message</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely cache the key and related data indexed by key ID.</p>
+ <p class="non-normative">Note: The replacement algorithm within a session is <a href="#key-system">Key System</a>-dependent.</p>
+ <p class="non-normative">Note: Keys from different sessions should be cached independently such that closing one session does not affect keys in other sessions, even if they have overlapping key IDs.</p>
+ <p class="non-normative">Note: It is recommended that CDMs support a standard and reasonably high minimum number of keys per <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, including a standard replacement algorithm, and a standard and reasonably high minimum number of <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
+ This enables a reasonable number of key rotation algorithms to be implemented across user agents and may reduce the likelihood of playback interruptions in use cases that involve various streams in the same element (i.e. adaptive streams, various audio and video tracks) using different keys.
+ </p>
+ </li>
+ <li>
+<p>If the set of usable keys changed, run the <a href="#algorithms-keys-changed">Usable Keys Changed</a> algorithm on the <var title="true">session</var>.</p>
+ <p>The algorithm may also be run later should additional processing be necessary to determine with certainty whether one or more keys is usable.</p>
+ </li>
+ <li><p>If the expiration time for the session changed, run the <a href="#algorithms-update-expiration">Update Expiration</a> algorithm on the <var title="true">session</var>, providing the new expiration time.</p></li>
+ <li>
+<p>If another message needs to be sent to the server, execute the following steps:</p>
<ol>
- <li><p>Let <var title="true">request</var> be a request generated by the <a href="#cdm">CDM</a> using <var title="true">sessionId</var>.</p></li>
- <li><p>If the stored data for <var title="true">sessionId</var> indicates a destination URL relevant to <var title="true">keySystem</var>, let <var title="true">destinationURL</var> be that URL.</p></li>
+ <li><p>Let <var title="true">request</var> be that message.</p></li>
+ <li><p>If there is a specific destination URL for the message, let <var title="true">destination URL</var> be that URL. The URL may be validated and/or normalized.</p></li>
</ol>
</li>
</ol>
</li>
- <li><p>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">sessionId</var></p></li>
+ <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ <li><p>If <var title="true">request</var> is not null, run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <var title="true">session</var>, providing <var title="true">request</var> and <var title="true">destination URL</var>.</p></li>
+ <li><p>Resolve <var>promise</var>.</p></li>
+ </ol>
+ </li>
+ <li><p>Return <var>promise</var>.</p></li>
+ </ol>
+
+ <p>The <dfn id="dom-close"><code>close()</code></dfn> method allows an application to indicate that it no longer needs the session and the CDM should release any resources associated with this object and close it.
+ <span class="non-normative">The returned promise is resolved when the request has been processed, and the <code><a href="#dom-closed">closed</a></code> attribute promise is resolved when the session is closed.</span>
+ It must run the following steps:</p>
+
+ <ol>
+ <li><p>If the <a href="#algorithms-session-close">Session Close</a> algorithm has been run on this object, return a resolved promise.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
+ <ol>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
<li>
-<p>If any of the preceding steps in the task failed, run the following steps:</p>
- <ol>
- <li>
-<p>Create a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> = the appropriate <a href="#mediakeyerror-names">error name</a><br>
- <code><a href="#dom-systemcode">systemCode</a></code> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Set the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object's <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
- <li><p>Let the state of the session be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- <li><p>Abort the task.</p></li>
- </ol>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
+ <ol>
+ <li>
+ <p>Process the close request.</p>
+ <p>Do not remove stored session data.</p>
+ </li>
+ <li><p>If the previous step caused the session to be closed, run the <a href="#algorithms-session-close">Session Close</a> algorithm on this object.</p></li>
+ </ol>
+ </li>
+ <li><p>Resolve <var>promise</var>.</p></li>
+ </ol>
+ </li>
+ <li><p>Return <var>promise</var>.</p></li>
+ </ol>
+
+ <p>The <dfn id="dom-remove"><code>remove()</code></dfn> method allows an application to remove stored session data associated with this object.
+ It must run the following steps:</p>
+
+ <ol>
+ <li><p>If the session type is not "<code><a href="#dom-sessiontypepersistent">persistent</a></code>", return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+ <li><p>If the <a href="#algorithms-session-close">Session Close</a> algorithm has been run on this object, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
+ <li>
+<p>Run the following steps asynchronously:</p>
+ <ol>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
+ <li>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
+ <ol>
+ <li>
+ <p>Process the remove request.</p>
+ <p>This may involve exchanging message(s) with the application.</p>
+ <p>Unless this step fails, the CDM must have cleared all stored session data associated with this object, including the <code><a href="#dom-sessionid">sessionId</a></code>, before proceeding to the next step.
+ <span class="non-normative">(A subsequent call to <code><a href="#dom-loadsession">loadSession()</a></code> with <code><a href="#dom-sessionid">sessionId</a></code> would fail because there is no data stored for the <var title="true">sessionId</var>.)</span>
+ </p>
+ </li>
+ </ol>
</li>
<li>
- <p>If the associated <a href="#media-element">media element(s)</a> are <a href="#waiting-for-a-key">waiting for a key</a>, <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to attempt to resume playback.</p>
- <p class="non-normative">In other words, resume playback if the necessary key is provided.</p>
- <p>The user agent may choose to skip this step if it knows resuming will fail <span class="non-normative">(i.e. no usable key was added)</span>.</p>
- </li>
- <li>
-<p>Follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If <var title="true">request</var> is not null</dt>
- <dd>
- <p>Run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object with:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="#dom-message">message</a></code> = <var title="true">request</var><br>
- <code><a href="#dom-destinationurl">destinationURL</a></code> = <var title="true">destinationURL</var>
- </li></ul>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li><p>Let the state of the session be <code><a href="#dom-stateready">READY</a></code>.</p></li>
- <li>
- <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventready">ready</a></code> at the new object.</p>
- </li>
- </ol>
- </dd>
- </dl>
+<p>Run the following steps asynchronously once the above step has completed:</p>
+ <ol>
+ <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p></li>
+ <li><p>Run the <a href="#algorithms-session-close">Session Close</a> algorithm on this object.</p></li>
+ <li><p>Resolve <var>promise</var>.</p></li>
+ </ol>
</li>
</ol>
</li>
- <li><p>Return the new object to the caller.</p></li>
+ <li><p>Return <var>promise</var>.</p></li>
</ol>
-
- <p>The <dfn id="dom-istypesupported"><code>isTypeSupported(keySystem, contentType)</code></dfn> method returns whether <var title="true">keySystem</var> is supported with the specified container and codec <var title="true">contentType</var>(s).</p>
- <div class="example">
- <p>The following list shows some examples.</p>
- <dl>
- <dt>Returns whether the Some System <a href="#key-system">Key System</a> is supported. Specific containers and codecs may or may not be supported with Some System.</dt>
- <dd><pre class="code">MediaKeys.isTypeSupported("com.example.somesystem")</pre></dd>
- <dt>Returns whether the Some System <a href="#key-system">Key System</a> is present and supports the container and codec(s) specified by <var title="true">mimeType</var>.</dt>
- <dd><pre class="code">MediaKeys.isTypeSupported("com.example.somesystem", <var title="true">mimeType</var>)</pre></dd>
- <dt>Returns whether the user agent supports <a href="#simple-decryption-clear-key">Clear Key</a> <a href="#simple-decryption">Simple Decryption</a> of the container and codec(s) specified by <var title="true">mimeType</var>.</dt>
- <dd><pre class="code">MediaKeys.isTypeSupported("org.w3.clearkey", <var title="true">mimeType</var>)</pre></dd>
- </dl>
- </div>
- <p>It must run the following steps:</p>
+ <p>The <dfn id="dom-getusablekeyids"><code>getUsableKeyIds()</code></dfn> method allows an application to get the key IDs for keys in the session that the CDM <em>knows</em> are currently usable to decrypt <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>. It must run the following steps:</p>
<ol>
- <li><p>If <var title="true">keySystem</var> is null or an empty string, return false and abort these steps.</p></li>
- <li><p>If <var title="true">keySystem</var> contains an unrecognized or unsupported <a href="#key-system">Key System</a>, return false and abort these steps. Key system string comparison is case-sensitive.</p></li>
- <li><p>If <var title="true">contentType</var> is null or an empty string, return true and abort these steps.</p></li>
- <li><p>If the <a href="#key-system">Key System</a> specified by <var title="true">keySystem</var> does not support decrypting the container and/or codec specified by <var title="true">contentType</var>, return false and abort these steps.</p></li>
- <li><p>Return true.</p></li>
- </ol>
-
- <p>The <dfn id="dom-error"><code>error</code></dfn> attribute is a <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> representing the current error state of the session. It is null if there is no error.</p>
-
- <p>The <dfn id="dom-sessionid"><code>sessionId</code></dfn> attribute is the <a href="#session-id">Session ID</a> for this object and the associated key(s) or license(s).</p>
-
- <p>The <dfn id="dom-update"><code>update(response)</code></dfn> method must run the following steps:</p>
- <p class="non-normative">Note: The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
-
- <ol>
- <li><p>If <var title="true">response</var> is null or an empty array, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
- <li><p>If the session is not in the <code><a href="#dom-statepending">PENDING</a></code> state, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code>.</p></li>
-
+ <li><p>Let <var>promise</var> be a new promise.</p></li>
<li>
-<p>Schedule a task to handle the call, providing <var title="true">response</var>.</p>
- <p>The user agent will asynchronously execute the following steps in the task:</p>
+<p>Run the following steps asynchronously:</p>
<ol>
- <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a>.</p></li>
- <li><p>Let <var title="true">request</var> be null.</p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
<li>
-<p>Use <var title="true">cdm</var> to execute the following steps:</p>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
<ol>
- <li>
-<p>Process <var title="true">response</var>.</p>
- <p class="non-normative">Note: When <var title="true">response</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely store the key and related data indexed by key ID.</p>
- <p class="non-normative">Note: The replacement algorithm within a session is <a href="#key-system">Key System</a>-dependent.</p>
- <p class="non-normative">Note: Keys from different sessions should be stored independently such that closing one session does not affect keys in other sessions, even if they have overlapping key IDs.</p>
- <p class="non-normative">Note: It is recommended that CDMs support a standard and reasonably high minimum number of keys per <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, including a standard replacement algorithm, and a standard and reasonably high minimum number of <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
- This enables a reasonable number of key rotation algorithms to be implemented across user agents and may reduce the likelihood of playback interruptions in use cases that involve various streams in the same element (i.e. adaptive streams, various audio and video tracks) using different keys.
- </p>
- </li>
- <li><p>If another message needs to be sent to the server, let <var title="true">request</var> be that message.</p></li>
+ <li><p>Let <var title="true">usable key ids</var> be a list of the key IDs for keys in the session that the CDM <em>knows</em> are currently usable to decrypt <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>. <var title="true">usable key ids</var> must not contain IDs for keys that <em>may not</em> currently be usable. Each element must be unique.</p></li>
</ol>
</li>
<li>
-<p>If any of the preceding steps in the task failed, run the following steps:</p>
- <ol>
- <li>
-<p>Create a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> = the appropriate <a href="#mediakeyerror-names">error name</a><br>
- <code><a href="#dom-systemcode">systemCode</a></code> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Set the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object's <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
- <li><p>Let the state of the session be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- <li><p>Abort the task.</p></li>
- </ol>
- </li>
- <li>
- <p>If the associated <a href="#media-element">media element(s)</a> are <a href="#waiting-for-a-key">waiting for a key</a>, <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to attempt to resume playback.</p>
- <p class="non-normative">In other words, resume playback if the necessary key is provided.</p>
- <p>The user agent may choose to skip this step if it knows resuming will fail <span class="non-normative">(i.e. no usable key was added)</span>.</p>
+ <p>If the preceding step failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a> and that has an appropriate message.</p>
</li>
<li>
-<p>Follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If <var title="true">request</var> is not null</dt>
- <dd>
- <p>Run the <a href="#algorithms-queue-message">Queue a "message" Event</a> algorithm on the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object with:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="#dom-message">message</a></code> = <var title="true">request</var><br>
- <code><a href="#dom-destinationurl">destinationURL</a></code> = null
- </li></ul>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li><p>Let the state of the session be <code><a href="#dom-stateready">READY</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventready">ready</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- </ol>
- </dd>
- </dl>
- </li>
- </ol>
- </li>
- </ol>
-
- <p>The <dfn id="dom-release"><code>release()</code></dfn> method allows an application to indicate to the system that it may release any resources associated with the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. It must run the following steps:</p>
-
- <ol>
- <li><p>If the state of the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> is <code><a href="#dom-stateclosed">CLOSED</a></code> then abort these steps.</p></li>
- <li><p>If the state of the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> is <code><a href="#dom-stateerror">ERROR</a></code>, throw an <code><a href="http://www.w3.org/TR/dom/#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code> exception and abort these steps.</p></li>
- <li>
-<p>Schedule a task to handle the call.</p>
- <p>The user agent will asynchronously execute the following steps in the task:</p>
- <ol>
- <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a>.</p></li>
- <li>
-<p>Use <var title="true">cdm</var> to execute the following steps:</p>
- <ol>
- <li>
- <p>Process the release request.</p>
- <p class="non-normative">Note: the release() method is intended to act as a hint to the user agent that the application believes the MediaKeySession is no longer needed.
- However, the CDM determines whether resources can now be released.</p>
- </li>
- <li><p>If the previous step caused the session to be closed, run the <a href="#algorithms-session-close">Session Close</a> algorithm for the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>.</p></li>
- </ol>
+ <p>Resolve <var>promise</var> with a new Sequence object, each element of which contains one element of <var title="true">usable key ids</var>.</p>
</li>
</ol>
</li>
</ol>
- <p>The <dfn id="dom-sourcekeysystem"><code>keySystem</code></dfn> attribute of <code><a href="#dom-htmlsourceelement">HTMLSourceElement</a></code> specifies the <a href="#key-system">Key System</a> to be used with the <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-resource">media resource</a></code>. The <code><a href="#dom-sourcekeysystem">keySystem</a></code> attribute must be supported by all HTMLSourceElement as both an IDL attribute and also a content attribute named <dfn id="dom-sourcecontentkeysystem"><code>keysystem</code></dfn>.
- The <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-algorithm">resource selection algorithm</a> is modified to check the <code><a href="#dom-sourcekeysystem">keySystem</a></code> attribute after the existing <em>step 5</em> of the <em>Otherwise</em> branch of <em>step 6</em>:
+ <h3 id="exceptions">2.1. Exceptions</h3>
+ <p id="error-names">The methods report errors by rejecting the returned promise with a <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code>.
+ The following <a href="http://www.w3.org/TR/dom/#error-names">DOMException names from DOM4</a> are used in the algorithms.
+ Causes specified specified in the algorithms are listed alongside each name, though these names may be used for other reasons as well.
</p>
- <ol start="6">
- <li><p>⌛ If <var title="">candidate</var> has a <code><a href="#dom-sourcekeysystem">keySystem</a></code> attribute whose value represents a <a href="#key-system">Key System</a> that the user agent knows it cannot use with <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#attr-source-type">type</a></code>, then end the <a href="http://www.w3.org/TR/html5/webappapis.html#synchronous-section">synchronous section</a>, and jump down to the <i title="">failed</i> step below.</p></li>
- </ol>
-
- <h3 id="error-codes">2.1. Errors</h3>
- <h4 id="mediakeyerror">2.1.1. Interface</h4>
- <pre class="idl">
-
-[<a href="#dom-mediakeyerror-constructor">Constructor</a>(DOMString <a href="#mediakeyerror-names">name</a>, unsigned long <a href="#dom-systemcode">systemCode</a>, optional DOMString message = "")]
-interface <dfn id="dom-mediakeyerror">MediaKeyError</dfn> : <a href="http://www.w3.org/TR/dom/#interface-domerror">DOMError</a> {
- readonly attribute unsigned long <a href="#dom-systemcode">systemCode</a>;
-};
-</pre>
-
- <div class="impl">
- <p>The <dfn id="dom-mediakeyerror-constructor"><code>MediaKeys(<var title="true">keySystem</var>)</code></dfn> constructor must return a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> whose <code><a href="#dom-systemcode">systemCode</a></code> attribute is initialized to <var title="true">systemCode</var> and inherited attributes are initialized by passing <var title="true">name</var> and <var title="true">message</var> to the <code><a href="http://www.w3.org/TR/dom/#dom-domerror">DOMError</a></code> constructor.</p>
- <p>The <dfn id="dom-systemcode"><code>systemCode</code></dfn> attribute of a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object is a <a href="#key-system">Key System</a>-dependent status code for the error that occurred.
- <span class="non-normative">This allows a more granular status to be returned than the more general <a href="#mediakeyerror-names">name</a>.</span>
- It should be 0 if there is no associated status code or such status codes are not supported by the Key System.
- </p>
- </div>
-
- <h4 id="mediakeyerror-names">2.1.2. Error Names</h4>
-
- <p>The <dfn id="error-names-table">error names table</dfn> below lists all the allowed error names for the <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> attribute along with a description.
- In addition, any of the standard <a href="http://www.w3.org/TR/dom/#error-names-0">error names</a> are allowed.</p>
-
- <div class="issue">
-<div class="issue-title"><span>Issue 1</span></div>
-<p class=""><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=21798">Bug 21798</a> - The additional error names are yet to be defined.</p>
-</div>
-
- <h3 id="session-state">2.2 MediaKeySession States</h3>
- <p><i>This section is non-normative.</i></p>
- <p>Each <code><a href="#dom-mediakeysession">MediaKeySession</a></code> maintains an internal state that determines what events may be fired.</p>
- <h4 id="session-state-list">2.2.1 MediaKeySession State Definitions</h4>
- <p>The following table describes the possible states:</p>
<table>
- <thead>
- <tr>
- <th>State name</th>
- <th>Description</th>
- </tr>
- </thead>
<tbody>
<tr>
- <td><dfn id="dom-statecreated"><code>CREATED</code></dfn></td>
- <td>The <code><a href="#dom-mediakeysession">MediaKeySession</a></code> has been created with a <code><a href="#dom-createsession">createSession()</a></code> call.</td>
+ <th>Name</th>
+ <th>Possible Causes (non-exhaustive)</th>
</tr>
<tr>
- <td><dfn id="dom-statepending"><code>PENDING</code></dfn></td>
- <td>A <code><a href="#dom-eventmessage">message</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. A call to <code><a href="#dom-update">update()</a></code> is expected next. The <a href="#media-element">media element</a> may block waiting for a key if encrypted data is encountered.</td>
+ <td><dfn id="dfn-NotSupportedError"><code>NotSupportedError</code></dfn></td>
+ <td>
+ The existing MediaKeys object cannot be removed.<br>
+ The key system is not supported.<br>
+ The key system is not supported on insecure origins.<br>
+ The initialization data type is not supported by the key system.<br>
+ The session type is not supported by the key system.<br>
+ The initialization data is not supported by the key system.<br>
+ The operation is not supported by the key system.
+ </td>
</tr>
<tr>
- <td><dfn id="dom-stateready"><code>READY</code></dfn></td>
- <td>A <code><a href="#dom-eventready">ready</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. The <a href="#media-element">media element</a> should not need to block waiting for a key if encrypted data associated with this session is encountered.</td>
+ <td><dfn id="dfn-InvalidStateError"><code>InvalidStateError</code></dfn></td>
+ <td>The existing MediaKeys object cannot be removed at this time.<br>
+ The session is closed.
+ </td>
</tr>
<tr>
- <td><dfn id="dom-stateerror"><code>ERROR</code></dfn></td>
- <td>A <code><a href="#dom-eventerror">error</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. The <code><a href="#dom-error">error</a></code> attribute of the session holds information about the most recent error.</td>
+ <td><dfn id="dfn-InvalidAccessError"><code>InvalidAccessError</code></dfn></td>
+ <td>
+ The parameter is empty.<br>
+ Invalid initialization data.<br>
+ The operation is not supported on sessions of this type.<br>
+ Invalid response format.<br>
+ A persistent license was provided for a "temporary" session.
+ </td>
</tr>
<tr>
- <td><dfn id="dom-stateclosed"><code>CLOSED</code></dfn></td>
- <td>A <code><a href="#dom-eventclose">close</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. No further events will be fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>.</td>
+ <td><dfn id="dfn-QuotaExceededError"><code>QuotaExceededError</code></dfn></td>
+ <td>The MediaKeys object cannot be used with additional HTMLMediaElements.</td>
</tr>
</tbody>
</table>
-
-
- <h4 id="session-state-transitions">2.2.2 MediaKeySession State Transitions</h4>
- <p>The following diagram shows the possible state transitions and the events fired when changing state:</p>
- <p><img src="session_state.svg" width="631" height="408" alt="State transition diagram"></p>
-
- <h3 id="media-element-restictions">2.3 Media Element Restrictions</h3>
+
+ <h3 id="media-element-restictions">2.2 Media Element Restrictions</h3>
<p><i>This section is non-normative.</i></p>
<p>Media data processed by a CDM may not be available through Javascript APIs in the usual way (for example using the CanvasRenderingContext2D drawImage() method and the AudioContext MediaElementAudioSourceNode).
This specification does not define conditions for such non-availability of media data, however, if media data is not available to Javascript APIs then these APIs may behave as if no media data was present at all.</p>
@@ -784,35 +910,37 @@
<h3 id="event-definitions">3.1. Event Definitions</h3>
<pre class="idl">
-[Constructor(DOMString type, optional <a href="#dom-mediakeyneededeventinit">MediaKeyNeededEventInit</a> eventInitDict)]
-interface <dfn id="dom-mediakeyneededevent">MediaKeyNeededEvent</dfn> : <a href="http://www.w3.org/TR/dom/#event">Event</a> {
- readonly attribute DOMString <a href="#dom-contenttype">contentType</a>;
- readonly attribute Uint8Array? <a href="#dom-initdata">initData</a>;
+[Constructor(DOMString type, optional <a href="#dom-mediaencryptedeventinit">MediaEncryptedEventInit</a> eventInitDict)]
+interface <dfn id="dom-mediaencryptedevent">MediaEncryptedEvent</dfn> : <a href="http://www.w3.org/TR/dom/#event">Event</a> {
+ readonly attribute DOMString <a href="#dom-initdatatype">initDataType</a>;
+ readonly attribute ArrayBuffer? <a href="#dom-initdata">initData</a>;
};
-dictionary <dfn id="dom-mediakeyneededeventinit">MediaKeyNeededEventInit</dfn> : <a href="http://www.w3.org/TR/dom/#eventinit">EventInit</a> {
- DOMString <a href="#dom-contenttype">contentType</a>;
- Uint8Array? <a href="#dom-initdata">initData</a>;
-};</pre>
+dictionary <dfn id="dom-mediaencryptedeventinit">MediaEncryptedEventInit</dfn> : <a href="http://www.w3.org/TR/dom/#eventinit">EventInit</a> {
+ DOMString <a href="#dom-initdatatype">initDataType</a> = "";
+ ArrayBuffer? <a href="#dom-initdata">initData</a> = null;
+};
+</pre>
<pre class="idl">
[Constructor(DOMString type, optional <a href="#dom-mediakeymessageeventinit">MediaKeyMessageEventInit</a> eventInitDict)]
interface <dfn id="dom-mediakeymessageevent">MediaKeyMessageEvent</dfn> : <a href="http://www.w3.org/TR/dom/#event">Event</a> {
- readonly attribute Uint8Array <a href="#dom-message">message</a>;
+ readonly attribute ArrayBuffer <a href="#dom-message">message</a>;
readonly attribute DOMString? <a href="#dom-destinationurl">destinationURL</a>;
};
dictionary <dfn id="dom-mediakeymessageeventinit">MediaKeyMessageEventInit</dfn> : <a href="http://www.w3.org/TR/dom/#eventinit">EventInit</a> {
- Uint8Array <a href="#dom-message">message</a>;
- DOMString? <a href="#dom-destinationurl">destinationURL</a>;
-};</pre>
+ ArrayBuffer <a href="#dom-message">message</a> = ArrayBuffer();
+ DOMString? <a href="#dom-destinationurl">destinationURL</a> = null;
+};
+</pre>
<dl class="domintro">
<dt>
-<var title="">event</var> . <code><a href="#dom-contenttype">contentType</a></code>
+<var title="">event</var> . <code><a href="#dom-initdatatype">initDataType</a></code>
</dt>
<dd>
- <p>Returns the MIME type of the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> related to the event.</p>
+ <p>Returns a string indicating the <a href="#initialization-data-type">initialization data type</a> of the <a href="#initialization-data">Initialization Data</a> related to the event.</p>
</dd>
<dt>
<var title="">event</var> . <code><a href="#dom-initdata">initData</a></code>
@@ -824,31 +952,29 @@
<var title="">event</var> . <code><a href="#dom-message">message</a></code>
</dt>
<dd>
- <p>Returns the message <span class="non-normative">(i.e. key request)</span> to send.</p>
+ <p>Returns the message <span class="non-normative">(i.e. license request)</span> to send.</p>
</dd>
<dt>
<var title="">event</var> . <code><a href="#dom-destinationurl">destinationURL</a></code>
</dt>
<dd>
- <p>Returns the URL to send the <code><a href="#dom-message">message</a></code> to.</p>
+ <p>Returns the URL to which the <code><a href="#dom-message">message</a></code> should be sent.</p>
</dd>
</dl>
<div class="impl">
- <p>The <dfn id="dom-contenttype"><code>contentType</code></dfn> attribute contains the MIME type of the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> specific to the event. The format of the <code><a href="#dom-initdata">initData</a></code> will depend on the <code><a href="#dom-contenttype">contentType</a></code>.</p>
- <p class="non-normative">Note: MIME types usually include "audio/" or "video/", and user agents should include these in <var title="true">contentType</var> as appropriate.
- However, either variant may be returned for any stream of a given MIME type, and this is does not reflect the type(s) of stream(s) in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
- Applications processing this attribute should handle all such variants.
- </p>
+ <p>The <dfn id="dom-initdatatype"><code>initDataType</code></dfn> attribute contains a string indicating the <a href="#initialization-data-type">initialization data type</a> specific to the event. The format of the <code><a href="#dom-initdata">initData</a></code> will vary according to the <code><a href="#dom-initdatatype">initDataType</a></code>.</p>
<p>The <dfn id="dom-initdata"><code>initData</code></dfn> attribute contains <a href="#initialization-data">Initialization Data</a> specific to the event.</p>
<p>The <dfn id="dom-message"><code>message</code></dfn> attribute contains a message from the CDM. Messages are Key System-specific. <span class="non-normative">In most cases, it should be sent to a key server.</span></p>
- <p>The <dfn id="dom-destinationurl"><code>destinationURL</code></dfn> is the URL to send the <code><a href="#dom-message">message</a></code> to.
- An application <em>may</em> override this.
- <span class="non-normative">In some cases, it may have been provided by the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.</span>
+ <p>The <dfn id="dom-destinationurl"><code>destinationURL</code></dfn> is the URL to which the <code><a href="#dom-message">message</a></code> should be sent.
It may be null.
+ An application <em>may</em> choose not to send the message to this URL.
+ Implementations may validate and/or normalize the URL, which could result in a value that is different from the original or null. Applications should not assume that the value of this attribute will be identical across implementations.
</p>
+ <p>Events are constructed as defined in <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#constructing-events">Constructing events</a>, in [DOM4].</p>
</div>
<h3 id="event-summary">3.2. Event Summary</h3>
+ <p><i>This section is non-normative.</i></p>
<p>The following event is fired at <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code>.</p>
<table>
@@ -862,12 +988,9 @@
</thead>
<tbody>
<tr>
- <td><dfn id="dom-needkey"><code>needkey</code></dfn></td>
- <td><code><a href="#dom-mediakeyneededevent">MediaKeyNeededEvent</a></code></td>
- <td>
- The user agent needs a key or license to begin or continue playback.
- <br><span class="non-normative"><br>It may have encountered <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> that may/does require decryption to load or play OR need a new key/license to continue playback.</span>
- </td>
+ <td><dfn id="dom-encrypted"><code>encrypted</code></dfn></td>
+ <td><code><a href="#dom-mediaencryptedevent">MediaEncryptedEvent</a></code></td>
+ <td>The user agent encounters <a href="#initialization-data">Initialization Data</a> in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.</td>
<td>
<code title="dom-media-readyState"><a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-readystate">readyState</a></code> is equal to <code title="dom-media-HAVE_METADATA"><a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-have_metadata">HAVE_METADATA</a></code> or greater.
<span class="non-normative">It is possible that the element is playing or has played.</span>
@@ -883,41 +1006,21 @@
<th>Event name</th>
<th>Interface</th>
<th>Dispatched when...</th>
- <th>Preconditions</th>
</tr>
</thead>
<tbody>
<tr>
- <td><dfn id="dom-eventerror"><code>error</code></dfn></td>
+ <td><dfn id="dom-eventkeyschange"><code>keyschange</code></dfn></td>
<td><code><a href="http://www.w3.org/TR/dom/#event">Event</a></code></td>
- <td>An error occurs in the session. The session moves to the <code><a href="#dom-stateerror">ERROR</a></code> state.</td>
- <td></td>
+ <td>There has been a change in usable keys.</td>
</tr>
<tr>
<td><dfn id="dom-eventmessage"><code>message</code></dfn></td>
<td><code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code></td>
<td>
A message has been generated <span class="non-normative">(and likely needs to be sent to a server)</span>.
- <span class="non-normative">For example, a key request has been generated as the result of a <code><a href="#dom-createsession">createSession()</a></code> call or another message must be sent in response to an <code><a href="#dom-update">update()</a></code> call.</span>
- The session moves to the <code><a href="#dom-statepending">PENDING</a></code> state.
+ <span class="non-normative">For example, a license request has been generated as the result of a <code><a href="#dom-createsession">createSession()</a></code> call or another message must be sent in response to an <code><a href="#dom-update">update()</a></code> call.</span>
</td>
- <td></td>
- </tr>
- <tr>
- <td><dfn id="dom-eventready"><code>ready</code></dfn></td>
- <td><code><a href="http://www.w3.org/TR/dom/#event">Event</a></code></td>
- <td>
- The CDM currently has all the information it needs to use keys/licenses from this session. The session moves to the <code><a href="#dom-stateready">READY</a></code> state.
- </td>
- <td></td>
- </tr>
- <tr>
- <td><dfn id="dom-eventclose"><code>close</code></dfn></td>
- <td><code><a href="http://www.w3.org/TR/dom/#event">Event</a></code></td>
- <td>
- The session is no longer needed. The session moves to the <code><a href="#dom-stateclosed">CLOSED</a></code> state.
- </td>
- <td></td>
</tr>
</tbody>
</table>
@@ -925,20 +1028,26 @@
<h2 id="algorithms">4. Algorithms</h2>
- <h3 id="algorithms-encrypted-stream">4.1. First Time a Key Reference is Encountered</h3>
- <p>The following steps are run when the <a href="#media-element">media element</a> encounters a source that may contain encrypted blocks or streams during the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a>:</p>
+ <h3 id="algorithms-initdata-encountered">4.1. Initialization Data Encountered</h3>
+ <p>The following steps are run when the <a href="#media-element">media element</a> encounters <a href="#initialization-data">Initialization Data</a> in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> during the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a>:</p>
<ol>
+ <li><p>Let <var title="">initDataType</var> be the empty string.</p></li>
<li><p>Let <var title="">initData</var> be null.</p></li>
- <li><p>If <a href="#initialization-data">Initialization Data</a> was encountered and if the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> is <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-same-origin">CORS-same-origin</a>, let <var title="">initData</var> be that initialization data.</p></li>
<li>
- <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-needkey">needkey</a></code> at the <a href="#media-element">media element</a>.</p>
- <p>The event is of type <code><a href="#dom-mediakeyneededevent">MediaKeyNeededEvent</a></code> and has:</p>
+ <p>If the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> is <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-same-origin">CORS-same-origin</a>, run the following steps:</p>
+ <ol>
+ <li><p>Let <var title="">initDataType</var> be the string representing the <a href="#initialization-data-type">initialization data type</a> of that initialization data.</p></li>
+ <li><p>Let <var title="">initData</var> be that initialization data.</p></li>
+ </ol>
+ </li>
+ <li>
+ <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-encrypted">encrypted</a></code> at the <a href="#media-element">media element</a>.</p>
+ <p>The event is of type <code><a href="#dom-mediaencryptedevent">MediaEncryptedEvent</a></code> and has:</p>
<ul style="list-style-type:none"><li>
- <code><a href="#dom-contenttype">contentType</a></code> = the MIME type of the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> container format<br>
+ <code><a href="#dom-initdatatype">initDataType</a></code> = <var title="">initDataType</var><br>
<code><a href="#dom-initdata">initData</a></code> = <var title="">initData</var>
</li></ul>
- <p class="non-normative">Firing this event allows the application to begin acquiring the key process before it is needed.</p>
<p class="non-normative">Note that <code title="dom-media-readyState"><a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-media-readystate">readyState</a></code> is <em>not</em> changed and no algorithms are aborted. This event merely provides information.</p>
<p class="non-normative">Note that if the media is not <a href="http://www.w3.org/TR/html5/infrastructure.html#cors-same-origin">CORS-same-origin</a> then the initData will be null. This allows applications that can retrieve initData from an alternative source to continue. Applications with no way to retrieve initData may wish to consider aborting playback in this case.</p>
</li>
@@ -951,72 +1060,73 @@
<ol>
<li>
+<p>If the media element's <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute is not null, run the following steps:</p>
+ <ol>
+ <li><p>Let <var title="true">media keys</var> be the <code><a href="#dom-mediakeys">MediaKeys</a></code> object referenced by that atribute.</p></li>
+ <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded during the <a href="#dom-mediakeys-create">initialization</a> of the <var title="true">media keys</var>.</p></li>
+ <li>
+<p>If there is at least one <code><a href="#dom-mediakeysession">MediaKeySession</a></code> created by the <var title="true">media keys</var> on which the <a href="#algorithms-session-close">Session Close</a> algorithm has not been run, run the following steps:</p>
+ <p class="non-normative">This check ensures the <var title="true">cdm</var> has finished loading and is a prequisite for a matching key being available.</p>
+ <ol>
+ <li><p>Let the <var title="true">block key ID</var> be the key ID of the current block <span class="non-normative">(as specified by the container)</span>.</p></li>
+ <li>
+<p>Use the <var title="true">cdm</var> to execute the following steps:</p>
+ <ol>
+ <li><p>Let <var title="true">available keys</var> be the union of keys in sessions that were created by the <var title="true">media keys</var>.</p></li>
+ <li>
<p>Follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If the media element's <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute is not null:</dt>
- <dd>Run the following steps:
- <ol>
- <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in the <a href="#dom-mediakeys-constructor"><code>MediaKeys</code> constructor</a>.</p></li>
- <li>
-<p>If <var title="true">cdm</var> has at least one <code><a href="#dom-mediakeysession">MediaKeySession</a></code> in the <code><a href="#dom-statepending">PENDING</a></code> or <code><a href="#dom-stateready">READY</a></code> state, run the following steps:</p>
- <p class="non-normative">This check ensures the <var title="true">cdm</var> has finished loading and is a prequisite for a matching key being available.</p>
- <ol>
- <li><p>Let <var title="true">block key ID</var> be be the key ID for the current block.</p></li>
- <li>
-<p>Use <var title="true">cdm</var> to decrypt the block by following the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If any session has a usable key for <var title="">block key ID</var>
-</dt>
- <dd>Run the following steps:
- <ol>
- <li>
+ <dl class="switch">
+ <dt>If any of the <var title="true">available keys</var> corresponds to the <var title="">block key ID</var> and is usable</dt>
+ <dd>Run the following steps:
+ <ol>
+ <li>
<p>Let <var title="">block key</var> be the matching key.</p>
- <p class="non-normative">Note: If multiple sessions contain a <em>usable</em> key for <var title="">block key ID</var>, which session is used is <a href="#key-system">Key System</a>-dependent.</p>
- </li>
- <li>
-<p>Use <var title="true">cdm</var> to decrypt the block using <var title="">block key</var> by following the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If decryption fails</dt>
- <dd>Abort the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a>, run the steps to report a <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-mediaerror-media_err_decode">MEDIA_ERR_DECODE</a></code> error, and abort these steps.</dd>
- <dt>Otherwise</dt>
- <dd>Abort these steps and process the decrypted block as normal. <span class="non-normative">(Decode the block.)</span>
-</dd>
- </dl>
- <p class="non-normative">Note: Not all decryption problems (i.e. using the wrong key) will result in a decryption failure. In such cases, no error is fired here but one may be fired during decode.</p>
- </li>
- </ol>
- </dd>
- <dt>If any session has an unusable key for <var title="">block key ID</var>
-</dt>
- <dd>Run the following steps:
- <ol>
- <li><p>Let <var title="">session</var> be the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object for the session with an unusable key.</p></li>
- <li>
-<p>Create a new <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="http://www.w3.org/TR/dom/#dom-domerror-name">name</a></code> = the appropriate <a href="#mediakeyerror-names">error name</a><br>
- <code><a href="#dom-systemcode">systemCode</a></code> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Set <var title="">session</var>'s <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
- <li><p>Let the state of <var title="">session</var> be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventerror">error</a></code> at <var title="">session</var>.</p></li>
- </ol>
- </dd>
- <dt><span class="non-normative">Otherwise (there is no key for <var title="true">block key ID</var> in any session)</span></dt>
- <dd><span class="non-normative">Continue.</span></dd>
- </dl>
+ <p class="non-normative">Note: If multiple sessions contain a <em>usable</em> key for the <var title="">block key ID</var>, which key to use is <a href="#key-system">Key System</a>-dependent.</p>
+ </li>
+ <li><p>Use the <var title="true">cdm</var> to decrypt the block using <var title="">block key</var>.</p></li>
+ <li>
+<p>Follow the steps for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If decryption fails</dt>
+ <dd>Abort the media element's <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a>, run the steps to report a <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#dom-mediaerror-media_err_decode">MEDIA_ERR_DECODE</a></code> error, and abort these steps.</dd>
+ <dt>Otherwise</dt>
+ <dd>Run the following steps:
+ <ol>
+ <li><p>If the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the media element is "<code><a href="#dom-waitingforkey">key</a></code>", set the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the media element to "<code><a href="#dom-waitingfornone">none</a></code>".</p></li>
+ <li><p>Abort these steps and process the decrypted block as normal. <span class="non-normative">(Decode the block.)</span></p></li>
+ </ol>
+ </dd>
+ </dl>
+ <p class="non-normative">Note: Not all decryption problems (i.e. using the wrong key) will result in a decryption failure. In such cases, no error is fired here but one may be fired during decode.</p>
+ </li>
+ </ol>
+ </dd>
+ <dt>If any of the <var title="true">available keys</var> corresponds to the <var title="">block key ID</var> and is unusable</dt>
+ <dd>Run the following steps:
+ <ol>
+ <li><p>Let <var title="true">session</var> be the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object associated with that session.</p></li>
+ <li><p>Run the <a href="#algorithms-queue-error">Queue an "error" Event</a> algorithm on the <var title="true">session</var>, providing the appropriate <a href="#error-names">error name</a>.</p></li>
+ <li><p>Abort these steps.</p></li>
+ </ol>
+ </dd>
+ <dt class="non-normative">Otherwise (there is no key for the <var title="true">block key ID</var> in any session)</dt>
+ <dd class="non-normative">Continue.</dd>
+ </dl>
+ </li>
+ </ol>
</li>
</ol>
- </li>
- </ol>
- </dd>
- </dl>
+ </li>
+ </ol>
</li>
<li>
- <p>Abort these steps and wait for a signal to resume playback.</p>
- <p class="non-normative">There is no usable key for the block.</p>
- <p class="non-normative">If playback stops because the stream cannot be decrypted when the <a href="#media-element">media element</a> is <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#potentially-playing">potentially playing</a></code>, the media element is said to be <a href="#waiting-for-a-key">waiting for a key</a>.</p>
+ <p><span class="non-normative">There is no usable key for the block.</span>
+ Run the following steps:
+ </p>
+ <ol>
+ <li><p>Run the <a href="#algorithms-queue-waiting">Queue a "waiting" Event</a> algorithm on the media element.</p></li>
+ <li><p>Wait for a signal to resume playback.</p></li>
+ </ol>
</li>
</ol>
@@ -1038,44 +1148,115 @@
</ol>
</div>
- <p>The following paragraph is added to <a href="http://www.w3.org/TR/html5/embedded-content-0.html#playing-the-media-resource">Playing the media resource</a>.</p>
- <ul style="list-style-type:none">
- <li>A <a href="#media-element">media element</a> is said to be <dfn id="waiting-for-a-key">waiting for a key</dfn> when
- it would be <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#potentially-playing">potentially playing</a></code> but
- the user agent has reached a point in the <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-resource">media resource</a></code> that must be decrypted for the resource to continue and the <a href="#cdm">CDM</a> does not have the necessary key.
- </li>
- <li class="non-normative">The media element leaves this state when seeking but could re-enter it if the same conditions exist.</li>
+
+ <p>The following steps are added to readyState change algorithms in <a href="http://www.w3.org/TR/html5/embedded-content-0.html#playing-the-media-resource">Playing the media resource</a>:</p>
+ <ul>
+ <li>If a readyState change queues a task to fire a <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-waiting">waiting</a></code> event, the user agent must also set the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the Media Element to "<code><a href="#dom-waitingfordata">data</a></code>".</li>
+ <li>If a readyState change queues a task to fire a <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-canplay">canplay</a></code> event, the user agent must also set the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the Media Element to "<code><a href="#dom-waitingfornone">none</a></code>".</li>
</ul>
- <p>At any point while decrypting content, the user agent may determine that a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> is no longer needed. It should run the <a href="#algorithms-session-close">Session Close</a> algorithm on the session.</p>
-
<h3 id="algorithms-queue-message">4.3. Queue a "message" Event</h3>
<p>The Queue a "message" Event algorithm is run when the CDM needs to queue a message event to a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
- Requests to run this algorithm include a target <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, a <var title="true">request</var>, and a <var title="true">destinationURL</var>.
- The following steps are run:</p>
+ Requests to run this algorithm include a target <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, a <var title="true">request</var>, and a <var title="true">destination URL</var>.
+ </p>
+ <p>The following steps are run:</p>
<ol>
- <li><p>Let <var title="true">session</var> be the specified <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- <li><p>Let the state of <var title="true">session</var> be <code><a href="#dom-statepending">PENDING</a></code>.</p></li>
+ <li><p>Let the <var title="true">session</var> be the specified <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
<li>
- <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventmessage">message</a></code> at <var title="true">session</var>.</p>
+ <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventmessage">message</a></code> at the <var title="true">session</var>.</p>
<p>The event is of type <code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code> and has:</p>
<ul style="list-style-type:none"><li>
<code><a href="#dom-message">message</a></code> = the specified <var title="true">request</var><br>
- <code><a href="#dom-destinationurl">destinationURL</a></code> = the specified <var title="true">destinationURL</var>
+ <code><a href="#dom-destinationurl">destinationURL</a></code> = the specified <var title="true">destination URL</var>
</li></ul>
</li>
</ol>
-
- <h3 id="algorithms-session-close">4.4. Session Close</h3>
- <p>The following steps are run when the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> closes:</p>
+ <h3 id="algorithms-queue-error">4.4. Queue an "error" Event</h3>
+ <div class="issue">
+<div class="issue-title"><span>Issue 2</span></div>
+<p class=""><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=26372">Bug 26372</a> - There is currently no mechanism for reporting errors and other events not related to a specific method call.</p>
+</div>
+ <h3 id="algorithms-keys-changed">4.5. Usable Keys Changed</h3>
+ <p>The Usable Keys Changed algorithm is run when the CDM changes the set of keys in the session that may be used for decryption.
+ This can happen as the result of an <code><a href="#dom-update">update()</a></code> call or some other event.
+ Requests to run this algorithm include a target <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
+ </p>
+ <p>The following steps are run:</p>
<ol>
- <li><p>Implementations may clear the internal state associated with the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>, including keys and licences, to release resources but are not required to do so.</p></li>
- <li><p>Let the state of the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> be <code><a href="#dom-stateclosed">CLOSED</a></code>.</p></li>
- <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventclose">close</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
+ <li><p>Let the <var title="true">session</var> be the associated <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
+ <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-eventkeyschange">keyschange</a></code> at the <var title="true">session</var>.</p></li>
+ <li>
+<p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to run the <a href="#algorithms-resume-playback">Attempt to Resume Playback If Necessary</a> algorithm on each of the <a href="#media-element">media element(s)</a> whose <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute is the MediaKeys object that created the <var title="true">session</var>.</p>
+ <p>The user agent may choose to skip this step if it knows resuming will fail <span class="non-normative">(i.e. no additional keys became available)</span>.</p>
+ </li>
</ol>
- <p class="non-normative">Note: Keys in other sessions should be unaffected, even if they have overlapping key IDs.</p>
+
+ <h3 id="algorithms-update-expiration">4.6. Update Expiration</h3>
+ <p>The Update Expiration algorithm is run when the CDM changes the expiration time of a session.
+ This can happen as the result of an <code><a href="#dom-update">update()</a></code> call or some other event.
+ Requests to run this algorithm include a target <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object and the new expiration time, which may be <code>NaN</code>.
+ </p>
+ <p>The following steps are run:</p>
+ <ol>
+ <li><p>Let the <var title="true">session</var> be the associated <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
+ <li><p>Let <var title="true">expiration time</var> be <code>NaN</code>.</p></li>
+ <li><p>If the new expiration time is not <code>NaN</code>, let <var title="true">expiration time</var> be the new expiration time in milliseconds since 01 January 1970 UTC.</p></li>
+ <li><p>Set the <var title="true">session</var>'s <code><a href="#dom-expiration">expiration</a></code> attribute to <var title="true">expiration time</var>.</p></li>
+ </ol>
+
+ <h3 id="algorithms-session-close">4.7. Session Close</h3>
+ <p>The Session Close algorithm is run when the CDM closes the session associated with a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p>
+ <p class="non-normative">The CDM may close a session at any point, such as in response to a <code><a href="#dom-close">close()</a></code> call, when the session is no longer needed, or when system resources are lost.
+ Keys in other sessions should be unaffected, even if they have overlapping key IDs.
+ </p>
+ <p>The following steps are run:</p>
+ <ol>
+ <li><p>Let the <var title="true">session</var> be the associated <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
+ <li><p>Remove the entry for the value of the <var title="true">session</var>'s <code><a href="#dom-sessionid">sessionId</a></code> attribute from the <var title="true">list of active session IDs</var> for the MediaKeys object that created the <var title="true">session</var>.</p></li>
+ <li><p>Let <var>promise</var> be the <code><a href="#dom-closed">closed</a></code> attribute of the <var title="true">session</var>.</p></li>
+ <li><p>Resolve <var>promise</var>.</p></li>
+ </ol>
+
+ <h3 id="algorithms-queue-waiting">4.8. Queue a "waiting" Event</h3>
+ <p>The Queue a "waiting" Event algorithm is run when the CDM needs to queue a waiting event to a <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code> object.
+ Requests to run this algorithm include a target <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code> object.
+ </p>
+ <p>The following steps are run:</p>
+ <ol>
+ <li><p>Let the <var title="true">media element</var> be the specified <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code> object.</p></li>
+ <li>
+<p>If the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the <var title="true">media element</var> is not "<code><a href="#dom-waitingforkey">key</a></code>", run the following steps:</p>
+ <ol>
+ <li><p>Set the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the <var title="true">media element</var> to "<code><a href="#dom-waitingforkey">key</a></code>".</p></li>
+ <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-waiting">waiting</a></code> at the <var title="true">media element</var>.</p></li>
+ </ol>
+ </li>
+ <li><p>Suspend playback.</p></li>
+ </ol>
+
+ <h3 id="algorithms-resume-playback">4.9. Attempt to Resume Playback If Necessary</h3>
+ <p>The Attempt to Resume Playback If Necessary algorithm is run when one or more keys becomes available.
+ If playback is blocked waiting for a key, it resumes playback if a necessary key has been provided.
+ Requests to run this algorithm include a target <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code> object.
+ </p>
+
+ <p>The following steps are run:</p>
+ <ol>
+ <li><p>Let the <var title="true">media element</var> be the specified <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code> object.</p></li>
+ <li><p>If the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the <var title="true">media element</var> is not "<code><a href="#dom-waitingforkey">key</a></code>", abort these steps.</p></li>
+ <li><p>Attempt to resume the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a> by running the <a href="#algorithms-encrypted-block">Encrypted Block Encountered</a> algorithm.</p></li>
+ <li>
+<p>If the user agent can advance the <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#current-playback-position">current playback position</a></code> in the <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#direction-of-playback">direction of playback</a></code>, run the following steps:</p>
+ <ol>
+ <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">Queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-canplay">canplay</a></code> at the <var title="true">media element</var>.</p></li>
+ <li><p>If the <code><a href="#dom-paused">paused</a></code> attribute on the <var title="true">media element</var> is false, <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-playing">playing</a></code> at the <var title="true">media element</var>.</p></li>
+ </ol>
+ <p>Otherwise, the <code><a href="#dom-waitingfor">waitingFor</a></code> attribute on the <var title="true">media element</var> must not be "<code><a href="#dom-waitingfornone">none</a></code>".</p>
+ </li>
+ </ol>
+
<h2 id="simple-decryption">5. Simple Decryption</h2>
<p>All user agents must support the simple decryption capabilities described in this section regardless of whether they support a more advanced <a href="#cdm">CDM</a>.
@@ -1083,81 +1264,201 @@
Thus, content providers that need only basic protection can build simple applications that will work on all platforms without needing to work with any content protection providers.</span>
</p>
- <h3 id="simple-decryption-clear-key">5.1. Clear Key</h3>
- <p>The "org.w3.clearkey" <a href="#key-system">Key System</a> indicates a plain-text clear (unencrypted) key will be used to decrypt the source.
+ <span id="simple-decryption-clear-key"></span>
+ <h3 id="clear-key">5.1. Clear Key</h3>
+ <p>The "org.w3.clearkey" <a href="#key-system">Key System</a> uses plain-text clear (unencrypted) key(s) to decrypt the source.
No additional client-side content protection is required.
- Use of this Key System is described below.
+ This Key System is described below.
</p>
- <p>The <var title="true">keySystem</var> parameter and <code><a href="#dom-keysystem">keySystem</a></code> attributes are always <code>"org.w3.clearkey"</code>.
- The <code><a href="#dom-sessionid">sessionId</a></code> string is numerical.</p>
+ <h4 id="clear-key-capabilities">5.1.1. Capabilities</h4>
+ <p>The following describe how Clear Key supports key system-specific capabilities:</p>
+ <ul>
+ <li><p>The <code><a href="#dom-setmediakeys">setMediaKeys()</a></code> method: Implementations may support associating the <code><a href="#dom-mediakeys">MediaKeys</a></code> object with more than one <code><a href="#dom-htmlmediaelement">HTMLMediaElement</a></code>.</p></li>
+ <li><p>The <code><a href="#dom-setservercertificate">setServerCertificate()</a></code> method: Not supported.</p></li>
+ <li><p>The <code><a href="#dom-istypesupported">isTypeSupported()</a></code> method: There are no supported <var title="true">capability</var> values.</p></li>
+ <li><p>The "<code><a href="#dom-sessiontypepersistent">persistent</a></code>" <code><a href="#dom-sessiontype">SessionType</a></code>, including the <code><a href="#dom-loadsession">loadSession()</a></code> and <code><a href="#dom-remove">remove()</a></code> methods: Implementations may support these.</p></li>
+ </ul>
+
+ <h4 id="clear-key-behavior">5.1.2. Behavior</h4>
+ <p>The following describe how Clear Key implements key system-specific behaviors:</p>
+ <ul>
+ <li>
+<p>In the <code><a href="#dom-createsession">createSession()</a></code> algorithm:</p>
+ <ul>
+ <li><p>The generated <var title="true">request</var> is a JSON object encoded in UTF-8 as described in <a href="#clear-key-request-format">License Request Format</a>.</p></li>
+ <li><p>The request is generated by extracting the key IDs from the <var>init data</var>.</p></li>
+ <li><p>The "type" member value is the value of the <var title="true">sessionType</var> parameter.</p></li>
+ </ul>
+ </li>
+ <li><p>The <code><a href="#dom-sessionid">sessionId</a></code> attribute is a numerical value representable by a 32-bit integer.</p></li>
+ <li><p>The <code><a href="#dom-expiration">expiration</a></code> attribute is always <code>NaN</code>.</p></li>
+ <li>
+<p>In the <code><a href="#dom-update">update()</a></code> algorithm:</p>
+ <ul>
+ <li><p>The <var title="true">response</var> parameter is a JWK Set as described in <a href="#clear-key-license-format">License Format</a>.</p></li>
+ <li><p><var>message</var> is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the media type.</p></li>
+ </ul>
+ </li>
+ <li><p>The <code><a href="#dom-getusablekeyids">getUsableKeyIds()</a></code> method always returns all key IDs that have been provided via <code><a href="#dom-update">update()</a></code>.</p></li>
+ <li><p><a href="#initialization-data">Initialization Data</a>: Implementations may support any combination of <a href="initdata-format-registry.html">registered and Initialization Data types</a>.
+ Implementations should support the "<a href="keyids-format.html%20">keyids</a>" type and other types appropriate for content types supported by the user agent.
+ </p></li>
+ </ul>
- <p>The <code><a href="#dom-initdata">initData</a></code> attribute of the <code><a href="#dom-needkey">needkey</a></code> event and the <var title="true">initData</var> parameter of <code><a href="#dom-createsession">createSession()</a></code> are the same container-specific <a href="#initialization-data">Initialization Data</a> format and values.
- <span class="non-normative">
- If supported, these values should provide some type of identification of the content or key that could be used to look up the key (since there is no defined logic for parsing it).
- For containers that support a simple key ID, it should be a binary array containing the raw key ID.
- For other containers, it may be some other opaque blob or null.</span>
+ <h4 id="clear-key-request-format">5.1.3. License Request Format</h4>
+ <p>This section describes the format of the license request provided to the application via the <code><a href="#dom-message">message</a></code> attribute of the <a href="#dom-eventmessage">message</a> event.</p>
+
+ <p>The format is a JSON object containing the following members:</p>
+ <dl>
+ <dt>"kids"</dt>
+ <dd>An array of <a href="#decryption-key-id">key IDs</a>. Each element of the array is the base64url encoding of the octet sequence containing the key ID value.</dd>
+ <dt>"type"</dt>
+ <dd>The requested <code><a href="#dom-sessiontype">SessionType</a></code>
+</dd>
+ </dl>
+
+ <p>When contained in the ArrayBuffer <code><a href="#dom-message">message</a></code> attribute of a <code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code> object, the JSON string is encoded in UTF-8 as specified in the <a href="http://www.w3.org/TR/encoding/">Encoding</a> specification.
+ Applications may decode the contents of the ArrayBuffer to a JSON string using the <a href="http://www.w3.org/TR/encoding/#interface-textdecoder">TextDecoder interface</a>.
</p>
- <p>The <code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code> generated by <code><a href="#dom-createsession">createSession()</a></code> has:</p>
- <ul style="list-style-type:none"><li>
- <code><a href="#dom-message">message</a></code> = a container-specific value extracted from the <var title="true">initData</var> parameter of <code><a href="#dom-createsession">createSession()</a></code>. null if <var title="true">initData</var> was null or a value could not be extracted.<br>
- <code><a href="#dom-destinationurl">destinationURL</a></code> = value of the default URL if present in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> and null otherwise.
- </li></ul>
+ <h5 id="clear-key-request-format-example">5.1.3.1. Example</h5>
+ <p><i>This section is non-normative.</i></p>
+ <p>The following example is a license request for a temporary license for two key IDs. (Line breaks are for readability only.)</p>
+ <pre class="example">
+{
+ "kids":
+ [
+ "67ef0gd8pvfd0",
+ "77ef0gd8pvfd0"
+ ],
+ "type":"<a href="#dom-sessiontypetemporary">temporary</a>"
+}
+</pre>
- <p>The <var title="true">response</var> parameter of <code><a href="#dom-update">update()</a></code> should be a JSON Web Key (JWK) representation of the symmetric key to be used for decryption, as defined in the <a href="http://tools.ietf.org/html/draft-ietf-jose-json-web-key">IETF Internet-draft JSON Web Key (JWK) specification</a>. The JSON string is encoded into the Uint8Array parameter using <a href="http://www.w3.org/TR/html5/infrastructure.html#ascii-compatible-character-encoding">ASCII-compatible character encoding</a>.</p>
- <p>When the JWK 'key type' ("kty") member value is 'octet sequence' ("oct"), the 'key value' ("k") member will be a base64 encoding of the octet sequence containing the symmetric key value.</p>
- <p>For example, the following contains a single symmetric key represented as a JWK, designated as being for use with the AES Key Wrap algorithm (line breaks for readability, only).</p>
+ <h4 id="clear-key-license-format">5.1.4. License Format</h4>
+ <p>This section describes the format of the license to be provided via the <var title="true">response</var> parameter of the <code><a href="#dom-update">update()</a></code> method.</p>
- <div class="example">
- <pre class="code">
+ <p>The format is a JSON Web Key (JWK) Set containing representation of the symmetric key to be used for decryption, as defined in the <a href="http://tools.ietf.org/html/draft-ietf-jose-json-web-key">IETF Internet-draft JSON Web Key (JWK) specification</a>.</p>
+
+ <p>For each JWK in the set, the parameter values are as follows:</p>
+ <dl>
+ <dt>"kty" (key type)</dt>
+ <dd>"oct" (octet sequence)</dd>
+ <dt>"alg" (algorithm)</dt>
+ <dd>"A128KW" (AES key wrap using a 128-bit key)</dd>
+ <dt>"k" (key value)</dt>
+ <dd>The base64url encoding of the octet sequence containing the symmetric <a href="#decryption-key">key</a> value</dd>
+ <dt>"kid" (key ID)</dt>
+ <dd>The base64url encoding of the octet sequence containing the <a href="#decryption-key-id">key ID</a> value</dd>
+ </dl>
+
+ <p>The JSON object may have an optional "type" member value, which may be any of the <code><a href="#dom-sessiontype">SessionType</a></code> values.
+ If not specified, the default value of "<code><a href="#dom-sessiontypetemporary">temporary</a></code>" is used.
+ The <code><a href="#dom-update">update()</a></code> algorithm compares this value to the <var title="true">sessionType</var>.
+ </p>
+
+ <p>When passed to the <code><a href="#dom-update">update()</a></code> method as the ArrayBuffer <var title="true">response</var> parameter, the JSON string must be encoded in UTF-8 as specified in the <a href="http://www.w3.org/TR/encoding/">Encoding</a> specification.
+ Applications may encode the JSON string using the <a href="http://www.w3.org/TR/encoding/#interface-textencoder">TextEncoder interface</a>.
+ </p>
+
+
+ <h5 id="clear-key-license-format-example">5.1.4.1. Example</h5>
+ <p><i>This section is non-normative.</i></p>
+ <p>The following example is a JWK Set containing a single symmetric key. (Line breaks are for readability only.)</p>
+ <pre class="example">
{
"keys":
[{
"kty":"oct",
"alg":"A128KW",
- "kid":"67ef0gd8pvfd0=",
"k":"GawgguFyGrWKav7AX4VKUg"
- }]
+ "kid":"67ef0gd8pvfd0",
+ }],
+ "type":"<a href="#dom-sessiontypetemporary">temporary</a>"
}</pre>
- </div>
+
+
+ <h4 id="using-base64url">5.1.5. Using base64url</h4>
+ <p><i>This section is non-normative.</i></p>
+ <p>For more information on base64url and working with it, see the Base64url Encoding entry in the <a href="http://tools.ietf.org/html/draft-ietf-jose-json-web-signature#section-2">Terminology section</a> and <a href="http://tools.ietf.org/html/draft-ietf-jose-json-web-signature#appendix-C">Notes on implementing base64url encoding without padding</a> of the JSON Web Signature (JWS) specification.
+ Specifically, there is no '=' padding, and the characters '-' and '_' must be used instead of '+' and '/', respectively.
+ </p>
+
<h2 id="security">6. Security Considerations</h2>
<div class="nonnormative">
- <div class="issue">
-<div class="issue-title"><span>Issue 2</span></div>Note: This section is not final and review is welcome.</div>
+ <p>User Agent and Key System implementations must consider <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>, <a href="#initialization-data">Initialization Data</a>, responses (i.e. data passed to <code><a href="#dom-update">update()</a></code>), licenses, key data, and all other data provided by the application as untrusted content and potential attack vectors.
+ They must use appropriate safeguards to mitigate any associated threats and take care to safely parse, decrypt, etc. such data.
+ User Agents may want to validate data before passing it to the CDM, especially if the CDM does not run in the same (sandboxed) context as the DOM (i.e. rendering).
+ </p>
+ <p>Implementations should not return active content or passive content that affects program control flow to the application.
+ For example, it is not safe to expose URLs or other information that may have come from media data, such as is the case for the Initialization Data passed to <code><a href="#dom-createsession">createSession()</a></code>.
+ An exception is made for information extracted from a license or other messages from the license server, which is assumed to be trusted by the application.
+ (This requires that the application be responsible for determining the location of the license or the URL of the license server.)
+ For example, a license may include a destination URL to receive renewal requests.
+ </p>
+ <p>Applications should validate any URLs or other "instructions" provided by the user agent (or CDM).
+ Specifically, applications should validate that any <code><a href="#dom-destinationurl">destinationURL</a></code> value represents a trusted and expected origin and path.
+ A restrictive whitelist, possibly using strict patterns, is recommended.
+ Applications should reject URLs that do not have a secure origin (e.g. HTTPS).
+ </p>
+ <p>User Agents are responsible for providing users with a secure way to browse the web. Since User Agents may integrate with third party CDM implementations, CDM implementers must provide sufficient information and controls to user agent implementers to enable them to properly asses the security implications of integrating with the Key System.</p>
+ <p>Note: Unsandboxed CDMs (or CDMs that use platform features) and UAs that use them must be especially careful in all areas of security, including parsing of key and media data, etc. due to the potential for compromises to provide access to OS/platform features, interact with or run as root, access drivers, kernel, firmware, hardware, etc., all of which may not be written to be robust against hostile software or web-based attacks. Additionally, CDMs may not be updated with security fixes as frequently, especially when part of the OS, platform or hardware.</p>
- <p>Key system implementations must consider initialization data, key data and media data as potential attack vectors and must take care to safely parse, decrypt etc. initialization data, key data and media data. User Agents may want to validate data before passing it to the CDM, especially if the CDM does not run in the same (sandboxed) context as the DOM (i.e. rendering). </p>
- <p>User Agents should treat key data and media data as untrusted content and use appropriate safeguards to mitigate any associated threats.</p>
- <p>User Agents are responsible for providing users with a secure way to browse the web. Since User Agents may integrate with third party CDM implementations, CDM implementers must provide sufficient information and controls to user agent implementers to enable them to properly asses the security implications of integrating with the Key System.</p>
- <p>Note: unsandboxed CDMs (or CDMs that use platform features) and UAs that use them must be especially careful in all areas of security, including parsing of key and media data, etc. due to the potential for compromises to provide access to OS/platform features, interact with or run as root, access drivers, kernel, firmware, hardware, etc., all of which may not be written to be robust against hostile software or web-based attacks. Additionally, CDMs may not be updated with security fixes as frequently, especially when part of the OS, platform or hardware.</p>
+ <p>User agents may choose to only support the EME APIs and/or specific Key Systems (i.e. based on privacy and security risks) on secure origins.
+ This is especially important if a user agent chooses to support a Key System implementation that cannot be sufficiently sandboxed or otherwise secured.
+ Such user agents should also properly handle <a href="https://w3c.github.io/webappsec/specs/mixedcontent/">Mixed Content</a> to avoid potential exposure to insecure content.
+ See also <a href="#privacy-secureorigin">Use Secure Origin and Transport</a>.
+ </p>
+ <p>If a user agent chooses to support a Key System implementation that cannot be sufficiently sandboxed or otherwise secured, the user agent should ensure that users are fully informed and/or give explicit consent before loading or invoking it.
+ See also <a href="#privacy-prompts">User Alerts / Prompts</a>.
+ </p>
+
</div>
+
+
<h2 id="privacy">7. Privacy Considerations</h2>
<div class="nonnormative">
- <div class="issue">
-<div class="issue-title"><span>Issue 3</span></div>Note: This section is not final and review is welcome.</div>
-
<p>The presence or use of Key Systems on a user's device raises a number of privacy issues, falling into two categories: (a) user-specific information that may be disclosed by the EME interface itself, or within messages from Key Systems and (b) user-specific information that may be persistently stored on the users device.</p>
<p>User Agents should take responsibility for providing users with adequate control over their own privacy. Since User Agents may integrate with third party CDM implementations, CDM implementers must provide sufficient information and controls to user agent implementers to enable them to implement appropriate techniques to ensure users have control over their privacy, including but not limited to the techniques described below.</p>
- <h3 id="privacy-disclosure">7.1. Information disclosed by EME and Key Systems</h3>
+ <h3 id="privacy-disclosure">7.1. Information Disclosed by EME and Key Systems</h3>
<p>Concerns regarding information disclosed by EME and Key Systems fall into two categories, concerns about non-specific information that may nevertheless contribute to the possibility of fingerprinting a user agent or device and user-specific information that may be used directly for user tracking.</p>
<h4 id="privacy-fingerprinting">7.1.1 Fingerprinting</h4>
- <p>Malicious applications may be able to fingerprint users or user agents by detecting or enumerating the list of key systems that are supported and related information. If proper origin protections are not provided this could include detection of sites that have been visited and information stored for those sites. In particular, Key Systems should not share key or other data between sites that are not CORS-same-origin.</p>
+ <p>Malicious applications may be able to fingerprint users or user agents by detecting or enumerating the list of Key Systems that are supported and related information. If proper origin protections are not provided this could include detection of sites that have been visited and information stored for those sites. In particular, Key Systems should not share key or other data between sites that are not CORS-same-origin.</p>
- <h4 id="privacy-tracking">7.1.2 Tracking</h4>
+ <h4 id="privacy-leakage">7.1.2 Information Leakage</h4>
+ <p>CDMs, especially those implemented outside the user agent, may not have the same fundamental isolations as the web platform.
+ It is important that steps be taken to avoid information leakage, especially across origins.
+ This includes both in-memory and stored data.
+ Failure to do so could lead to information leakage to/from Incognito/Private Browsing sessions, across profiles, and even across different operating system user accounts.
+ </p>
+
+ <p>To avoid such issues, user agent and CDM implementations should ensure that:</p>
+ <ul>
+ <li>CDMs have a concept of a CDM instance that is associated 1:1 with a MediaKeys object.</li>
+ <li>Keys, licenses, other session data, and the presence of sessions are restricted to the CDM instance associated with the MediaKeys object that created the session.</li>
+ <li>Session data is not shared between MediaKeys objects or CDM instances.</li>
+ <li>Session data is not shared with media elements not associated with the MediaKeys object that created the session. Among other things, this means a session's keys may not be used to decrypt content loaded by a media element whose <code><a href="#dom-attrmediakeys">mediaKeys</a></code> attribute is not the MediaKeys object.</li>
+ <li>MediaKeys objects and the underlying implementation do not expose information outside the origin.</li>
+ <li>Persisted session data, if applicable, is stored on a per-origin basis.</li>
+ <li>Only data stored by the requesting origin may be loaded.</li>
+ </ul>
+
+ <h4 id="privacy-tracking">7.1.3 Tracking</h4>
<p>User-specific information may be obtained over the EME API in two ways: through detection of stored keys and through Key System messages.</p>
<p>Key Systems may access or create persistent or semi-persistent identifiers for a device or user of a device. In some cases these identifiers may be bound to a specific device in a secure manner. If these identifiers are present in Key System messages, then devices and/or users may be tracked. If the mitigations below are not applied this could include both tracking of users / devices over time and associating multiple users of a given device. If not mitigated, such tracking may take three forms depending on the design of the Key System:</p>
<ul>
- <li>in all cases, such identifiers are expected to be available to sites and/or servers that fully support the Key System (and thus can interpret Key System messages) enabling tracking by such sites.</li>
- <li>if identifiers exposed by Key Systems are not origin-specific, then two sites and/or servers that fully support the Key System may collude to track the user</li>
- <li>if a Key System messages contains information derived from a user identifier in a consistent manner, for example such that a portion of the initial Key System message for a specific content item does not change over time and is dependent on the user identifier, then this information could be used by any application to track the device or user over time.</li>
+ <li>In all cases, such identifiers are expected to be available to sites and/or servers that fully support the Key System (and thus can interpret Key System messages) enabling tracking by such sites.</li>
+ <li>If identifiers exposed by Key Systems are not origin-specific, then two sites and/or servers that fully support the Key System may collude to track the user</li>
+ <li>If a Key System messages contains information derived from a user identifier in a consistent manner, for example such that a portion of the initial Key System message for a specific content item does not change over time and is dependent on the user identifier, then this information could be used by any application to track the device or user over time.</li>
</ul>
<p>If a Key System permits keys to be stored and to be re-used between origins, then it may be possible for two origins to collude and track a unique user by recording their ability to access a common key.</p>
@@ -1171,8 +1472,10 @@
<dt>Use of (non-reversible) per-origin identifiers</dt>
<dd>The user / device identifier exposed by a Key System may be different for each origin, either by allocation of different identifiers for different origins or by use of a non-reversible origin-specific mapping from an origin-independent identifier.</dd>
- <dt>Encryption of user identifiers</dt>
- <dd>User identifiers in Key System messages could be encrypted, together with a timestamp or nonce, such that the Key System messages are always different. This would prevent the use of Key System messages for tracking except by applications fully supporting the Key System.</dd>
+ <dt id="identifier-encryption">Encryption of user identifiers</dt>
+ <dd>User identifiers in Key System messages could be encrypted, together with a timestamp or nonce, such that the Key System messages are always different. This would prevent the use of Key System messages for tracking except by applications fully supporting the Key System.
+ This may be implemented using a <a href="#server-certificate">server certificate</a>.
+ </dd>
<dt>Site-specific white-listing of access to each Key System</dt>
<dd>User agents could require the user to explicitly authorize access by each site to each Key System. User agents should enable users to revoke this authorization either temporarily or permanently.</dd>
@@ -1183,25 +1486,29 @@
<dt>Shared blacklists</dt>
<dd>User agents may allow users to share their Key System domain blacklists. This would allow communities to act together to protect their privacy.</dd>
- <dt>User alerts / prompts</dt>
- <dd>User Agents could ensure that users are fully informed and / or give explicit consent before identifiers are exposed in messages from Key Systems.</dd>
+ <dt id="privacy-prompts">User Alerts / Prompts</dt>
+ <dd>User Agents should ensure that users are fully informed and/or give explicit consent before identifiers are exposed in messages from Key Systems.
+ Such alerts and consent should be per origin to avoid valid uses enabling subsequent malicious access.
+ User agents that consider such alerts or consent appropriate should only support such Key Systems on secure origins (see <a href="#privacy-secureorigin">Use Secure Origin and Transport</a>), especially if they allow such consent to be persisted.
+ (Granting permissions to unauthenticated origins is equivalent to granting the permissions to any origin in the presence of a network attacker.)
+ </dd>
<dt>User controls to disable Key Systems or Key System use of identifiers</dt>
- <dd>User Agents could provide users with a global control of whether a Key System is enabled / disabled and / or whether Key System use of user / device identifiers is enabled or disabled (if supported by the Key System).</dd>
+ <dd>User Agents could provide users with a global control of whether a Key System is enabled / disabled and/or whether Key System use of user / device identifiers is enabled or disabled (if supported by the Key System).</dd>
</dl>
<p>While these suggestions prevent trivial use of this feature for user tracking, they do not block it altogether. Within a single domain, a site can continue to track the user during a session, and can then pass all this information to a third party along with any identifying information (names, credit card numbers, addresses) obtained by the site. If a third party cooperates with multiple sites to obtain such information, and if identifiers are not per-origin, then a profile can still be created.</p>
<p>It is important to note that identifiers that are non-clearable, non-origin-specific or hardware-bound exceed the tracking impact of existing techniques such as Cookies or session identifiers embedded in URLs.</p>
<p>Thus, in addition to the various mitigations described above, if a browser supports a mode of operation intended to preserve user anonymity, then User Agent implementers should carefully consider whether access to Key Systems should be disabled in this mode.</p>
- <h3 id="privacy-storedinfo">7.2. Information stored on user devices</h3>
+ <h3 id="privacy-storedinfo">7.2. Information Stored on User Devices</h3>
<p>Key Systems may store information on a user's device, or user agents may store information on behalf of Key Systems. Potentially, this could reveal information about a user to another user of the same device, including potentially the origins that have used a particular Key System (i.e. sites visited) or even the content that has been decrypted using a Key System.</p>
<p>If information stored by one origin affects the operation of the Key System for another origin, then potentially the sites visited or content viewed by a user on one site may be revealed to another, potentially malicious, site.</p>
<p>There are a number of techniques that can be used to mitigate these privacy risk to users:</p>
<dl>
<dt>Origin-specific Key System storage</dt>
- <dd>User agents may require that some or all of the Key System's persistently stored data is stored in an origin-specific way.</dd>
+ <dd>User agents may require that some or all of the Key System's persistently stored data is stored in an origin-specific way. Session data, licenses, and keys that are persistently stored should be stored per-origin.</dd>
<dt>User deletion of Key System storage</dt>
<dd>User agents may present the user with a way to delete Key System storage for a specific origin or all origins.</dd>
@@ -1212,67 +1519,25 @@
<dt>Encryption or obfuscation of Key System stored data</dt>
<dd>User agents should treat data stored by Key Systems as potentially sensitive; it is quite possible for user privacy to be compromised by the release of this information. To this end, user agents should ensure that such data is securely stored and when deleting data, it is promptly deleted from the underlying storage.</dd>
</dl>
+
+ <p>User agent and CDM implementations that allow the CDM to persist data should:</p>
+ <ul>
+ <li>Ensure it is restricted to the origin for which it was created.</li>
+ <li>Ensure it is restricted to the current profile and does not leak to or from Incognito/Private Browsing sessions.</li>
+ <li>Allow the user to clear it, preferably by origin.</li>
+ <li>Treat it like other site data, including presenting it along with cookies, including it in "remove all data", and presenting it in the same UI locations.</li>
+ </ul>
+
+ <h3 id="privacy-secureorigin">7.3. Use Secure Origin and Transport</h3>
+ <p>In order to protect identifiers and other information discussed in previous sections, user agents may choose to only support the EME APIs and/or specific Key Systems (i.e. based on privacy and security risks) on secure origins.
+ This is especially important if a user agent chooses to support a Key System implementation that exposes identifiers or other such information without effectively anonymizing it in transit (i.e. without <a href="#identifier-encryption">encrypting identifiers</a>).
+ </p>
+ <p>Regardless of user agent limitations, applications should use secure transport (e.g. HTTPS) for all traffic containing messages from the CDM (i.e. all data passed from <code><a href="#dom-eventmessage">message</a></code> events and to <code><a href="#dom-update">update()</a></code>).</p>
+ <p>All user agents should properly handle <a href="https://w3c.github.io/webappsec/specs/mixedcontent/">Mixed Content</a> to avoid exposure to insecure content or transport when the user agent or application wish to enforce secure origin and transport.</p>
</div>
- <h2 id="containers">8. Container Guidelines</h2>
- <p>This document describes behavior independent of specific media containers.
- The following sections provide container-specific details for implementations that choose to support those containers.
- </p>
-
- <h3 id="webm">8.1 WebM</h3>
- <div class="nonnormative">
- <p>This section defines the stream format and Initialization Data for implementations that choose to support <a href="http://www.webmproject.org/code/specs/container/">WebM</a>.</p>
-
- <h4 id="webm-stream-format">8.1.1.Stream Format </h4>
- <p><a href="http://wiki.webmproject.org/encryption/webm-encryption-rfc">Encrypted WebM streams</a> are encrypted at the block level with AES-128 CTR encryption.
- The container shall include appropriate values within the <a href="http://matroska.org/technical/specs/index.html#ContentEncryption">ContentEncryption</a> element.
- </p>
-
- <p>WebM streams may be partially encrypted, both at the <a href="http://matroska.org/technical/specs/index.html#LevelTrack">Track</a> level and the block level.
- In the former case, a subset of Tracks in the stream have a <a href="http://matroska.org/technical/specs/index.html#ContentEncryption">ContentEncryption</a> element.
- In the latter case, a subset of the blocks within a Track containing a <a href="http://matroska.org/technical/specs/index.html#ContentEncryption">ContentEncryption</a> element are marked as encrypted.</p>
-
- <h4 id="webm-detect-encrypt">8.1.2. Detecting Encryption</h4>
- <p>When a WebM <a href="http://matroska.org/technical/specs/index.html#LevelTrack">Track</a> is parsed, the presence of a <a href="http://matroska.org/technical/specs/index.html#ContentEncKeyID">ContentEncKeyID</a> element shall indicate that the stream is potentially encrypted. Each time a new value is encountered in a ContentEncKeyID element, the <a href="#algorithms-encrypted-stream">First Time a Key Reference is Encountered</a> algorithm shall be invoked with the value in that element as <var title="">initData</var>.</p>
-
- <p><a href="#algorithms-encrypted-block">Encrypted blocks</a> are those marked encrypted by the <a href="http://wiki.webmproject.org/encryption/webm-encryption-rfc#TOC-4.6-Signal-Byte-Format">Signal Byte.</a></p>
-
- <h4 id="webm-init-data">8.1.3. Initialization Data and Events</h4>
- <p><a href="#initialization-data">Initialization Data</a> in <a href="#events">events</a> is always a key ID, which is the <a href="http://matroska.org/technical/specs/index.html#ContentEncKeyID">ContentEncKeyID</a> of the current <a href="http://matroska.org/technical/specs/index.html#LevelTrack">Track</a>.
- The current Track is the one being parsed or that contains the block being decrypted.
- </p>
- <p>Events only contain a single key ID.
- However, if supported by the key system, multiple key IDs may be bundled by the application before requesting a key and multiple key ID-key pairs may be returned by the license server.
- </p>
-
- <p>An event will be fired for each new key ID (in <a href="http://matroska.org/technical/specs/index.html#ContentEncKeyID">ContentEncKeyID</a>) encountered for which a key is not already known.</p>
- </div>
-
- <h3 id="iso">8.2 ISO Base Media File Format</h3>
- <div class="nonnormative">
- <div class="issue">
-<div class="issue-title"><span>Issue 4</span></div>Note: There is an open issue about how initialization data should be extracted from ISO BMFF content. See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=17673">Bug 17673</a>.</div>
- <p>This section defines the stream format and initialization data for ISO Base media File Format (ISOBMFF) content.</p>
-
- <h4 id="iso-stream-format">8.2.1 Stream format</h4>
- <p>The stream format is dependent upon the protection scheme, as defined in the scheme type box ('schm').</p>
- <p>For example, under the common encryption ("cenc") protection scheme, ISOBMFF content is encrypted at the sample level with AES-128 CTR encryption, according to ISO/IEC 23001-7:2012, "Information technology - MPEG system technologies - Part 7: Common encryption in ISO base media file format files". This protection method enables multiple Key Systems to decrypt the same media content.</p>
-
- <h4 id="iso-detect-encrypt">8.2.2 Detecting Encryption</h4>
- <p>Protection scheme signaling conforms with ISO/IEC 14496-12. When protection has been applied, the stream type will be transformed to 'encv' for video or 'enca' for audio, with a scheme information box ('sinf') added to the sample entry in the sample description box ('stsd'). The scheme information box ('sinf') will contain a scheme type box ('schm') with a scheme_type field set to the 4CC value of the protection scheme.</p>
- <p>Additionally, if the protection scheme is common encryption ("cenc"), the "encrypted block" is a sample. Determining whether a sample is encrypted depends on the corresponding track encryption box ('tenc') and the sample group associated with the sample. In this case the default encryption state of a sample is defined by the IsEncrypted flag in the associated track encryption box ('tenc'). This default state may be modified by the IsEncrypted flag in the Sample Group Description Box ('sgpd'), pointed to by an index in the Sample to Group Box ('sbgp').</p>
- <p>For complete information about "cenc" see ISO/IEC 23001-7:2012.</p>
-
- <h4 id="iso-init-data">8.2.3 Initialization Data and Events</h4>
- <p>For ISOBMFF the InitData begins with a the protection scheme information box ('sinf'). The 'sinf' includes the scheme type box ('schm'), giving the scheme_type, and the scheme information box ('schi').</p>
- <p>If this scheme_type is common encryption ("cenc"), the scheme information box will also contain the track encryption box ('tenc'), giving the defaults for IsEncrypted, IV_size and KID for that track. In addition, one or more protection system specific heder boxes ('pssh') will be concatenated after the 'sinf' box.</p>
- <p>In a file encrypted with common encryption, each key is identified by a Key ID and each encrypted sample is associated with the Key ID of the key needed to decrypt it. This association is signaled either through the specification of a default Key ID in the track encryption box ('tenc') or by assigning the sample to a Sample Group, the definition of which specifies a Key ID. Common encryption files may contain a mixture of encrypted and unencrypted samples. Playback of unencrypted samples should not be impeded by unavailability of the keys needed to decrypt other samples in the same file or track.</p>
- <p>Note that if there is already an active Key System CDM and the key storage for that Key System already contains the key associated with the Key ID, there is no need to generate a needkey event.</p>
- </div>
-
-
- <h2 id="examples">9. Examples</h2>
+ <h2 id="examples">8. Examples</h2>
<p><i>This section and its subsections are non-normative.</i></p>
<p>This section contains example solutions for various use cases using the proposed extensions.
These are not the only solutions to these use cases.
@@ -1280,143 +1545,75 @@
In some cases, such as using synchronous XHR, the examples are simplified to keep the focus on the extensions.
</p>
- <h3 id="example-source-and-key-known" class="exampleheader">9.1. Source and Key Known at Page Load (Clear Key)</h3>
- <p class="exampledescription">In this simple example, the source file and <a href="#simple-decryption-clear-key">clear-text key</a> are hard-coded in the page.</p>
- <p class="exampledescription">This example is very simple because it does not care when the key has been added or associating that event with the <code><a href="#dom-update">update()</a></code> call. It also does not handle errors.</p>
+ <h3 id="example-source-and-key-known" class="exampleheader">8.1. Source and Key Known at Page Load (Clear Key)</h3>
+ <p class="exampledescription">In this simple example, the source file and <a href="#clear-key">clear-text license</a> are hard-coded in the page.
+ Only one session will ever be created.</p>
- <div class="example">
- <pre class="code">
+ <pre class="example">
<script>
function load() {
var video = document.getElementById("video");
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- video.<a href="#dom-setmediakeys">setMediaKeys</a>(new <a href="#dom-mediakeys">MediaKeys</a>("org.w3.clearkey"));
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- throw "Could not create MediaKeys";
-
- var keySession = video.<a href="#dom-attrmediakeys">mediaKeys</a>.<a href="#dom-createsession">createSession</a>();
- if (!keySession)
- throw "Could not create key session";
-
- keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+ if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>) {
+ var promise = <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>("org.w3.clearkey");
+ promise.catch(
+ console.error.bind(console, "Unable to create MediaKeys")
+ );
+ promise.then(
+ function(createdMediaKeys) {
+ return video.<a href="#dom-setmediakeys">setMediaKeys</a>(createdMediaKeys);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to set MediaKeys")
+ );
+ promise.then(
+ function(createdMediaKeys) {
+ var initData = new Uint8Array([ ... ]);
+ return createdMediaKeys.<a href="#dom-createsession">createSession</a>("webm", initData);
+ }
+ ).then(
+ function(keySession) {
+ keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create key session")
+ );
+ }
}
function handleMessage(event) {
var keySession = event.target;
- var key = new Uint8Array([ ... ]);
- keySession.<a href="#dom-update">update</a>(key);
+ var license = new Uint8Array([ ... ]);
+ keySession.<a href="#dom-update">update</a>(license).catch(
+ console.error.bind(console, "update() failed")
+ );
}
</script>
<body onload="load()">
<video src="foo.webm" autoplay id="video"></video>
-</body></pre>
- </div>
-
- <h3 id="example-source-known-but-key-not-known" class="exampleheader">9.2. Source Known but Key Not Known at Page Load</h3>
- <p class="exampledescription">In this case, the <a href="#initialization-data">Initialization Data</a> is contained in the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>.
- If this was not the case, <code>handleKeyNeeded()</code> could obtain and provide it instead of getting it from the event.</p>
-
- <h4 id="example-clear-key" class="exampleheader">9.2.1. Clear Key</h4>
- <p class="exampledescription">This solution uses the <a href="#simple-decryption-clear-key">Clear Key</a> <a href="#simple-decryption">Simple Decryption</a>.</p>
- <p class="exampledescription">As with the previous example, this one is very simple because it does not care when the key has been added or handle errors.</p>
-
- <div class="example">
- <pre class="code">
-<script>
- function handleKeyNeeded(event) {
- var video = event.target;
-
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- video.<a href="#dom-setmediakeys">setMediaKeys</a>(new <a href="#dom-mediakeys">MediaKeys</a>("org.w3.clearkey"));
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- throw "Could not create MediaKeys";
-
- var keySession = video.<a href="#dom-attrmediakeys">mediaKeys</a>.<a href="#dom-createsession">createSession</a>(event.<a href="#dom-contenttype">contentType</a>, event.<a href="#dom-initdata">initData</a>);
- if (!keySession)
- throw "Could not create key session";
-
- keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
- }
-
- function handleMessage(event) {
- var keySession = event.target;
- var message = event.<a href="#dom-message">message</a>;
-
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.open("POST", "http://.../getkey");
- xmlhttp.onreadystatechange = function() {
- if(xmlhttp.readyState==4) {
- var key = new Uint8Array(xmlhttp.response);
- keySession.<a href="#dom-update">update</a>(key);
- }
- }
- xmlhttp.send(message);
- }
-</script>
+</body>
+</pre>
-<video src="foo.webm" autoplay on<a href="#dom-needkey">needkey</a>="handleKeyNeeded(event)"></video></pre>
- </div>
-
- <h4 id="example-other-cdm" class="exampleheader">9.2.2. Other Key System</h4>
- <p class="exampledescription">This solution uses more advanced decryption from a fictitious <a href="#cdm">content decryption module</a> called Some System.</p>
-
- <div class="example">
- <pre class="code">
-<script>
- function handleKeyNeeded(event) {
- var video = event.target;
-
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- video.<a href="#dom-setmediakeys">setMediaKeys</a>(new <a href="#dom-mediakeys">MediaKeys</a>("com.example.somesystem.1_0"));
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- throw "Could not create MediaKeys";
-
- var keySession = video.<a href="#dom-attrmediakeys">mediaKeys</a>.<a href="#dom-createsession">createSession</a>(event.<a href="#dom-contenttype">contentType</a>, event.<a href="#dom-initdata">initData</a>);
- if (!keySession)
- throw "Could not create key session";
-
- keySession.addEventListener("<a href="#dom-eventmessage">message</a>", licenseRequestReady, false);
- }
-
- function licenseRequestReady(event) {
- var keySession = event.target;
- var request = event.<a href="#dom-message">message</a>;
- if (!request)
- throw "Could not create license request";
-
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.open("POST", "http://.../getkey");
- xmlhttp.onreadystatechange = function() {
- if(xmlhttp.readyState==4) {
- var license = new Uint8Array(xmlhttp.response);
- keySession.<a href="#dom-update">update</a>(license);
- }
- }
- xmlhttp.send(request);
- }
-</script>
-
-<video src="foo.webm" autoplay on<a href="#dom-needkey">needkey</a>="handleKeyNeeded(event)"></video></pre>
- </div>
-
- <h3 id="examples-selecting-key-system" class="exampleheader">9.3. Selecting a Supported Key System</h3>
- <p class="exampledescription">Below is an example of detecting supported <a href="#key-system">Key System</a> using the <code><a href="#dom-istypesupported">isTypeSupported()</a></code> and selecting one.
+ <h3 id="example-selecting-key-system" class="exampleheader">8.2. Selecting a Supported Key System and Using Initialization Data from the "encrypted" Event</h3>
+ <p class="exampledescription">This example selects a supported <a href="#key-system">Key System</a> using the <code><a href="#dom-istypesupported">isTypeSupported()</a></code> method then uses
+ the <a href="#initialization-data">Initialization Data</a> from the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> to generate the license request and send it to the appropriate license server.
+ One of the supported key systems uses a serverCertificate, which is provided proactively.
</p>
- <div class="example">
- <pre class="code">
+ <pre class="example">
<script>
var keySystem;
var licenseUrl;
+ var serverCertificate;
function selectKeySystem() {
- if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.example.somesystem", "video/webm; codecs='vp8, vorbis'")) {
+ if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.example.somesystem", "webm", "video/webm; codecs='vp8, vorbis'")) {
licenseUrl = "https://license.example.com/getkey"; // OR "https://example.<My Video Site domain>"
keySystem = "com.example.somesystem";
- } else if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.foobar", "video/webm; codecs='vp8, vorbis'")) {
+ serverCertificate = new Uint8Array([ ... ]);
+ } else if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.foobar", "webm", "video/webm; codecs='vp8, vorbis'")) {
licenseUrl = "https://license.foobar.com/request";
keySystem = "com.foobar";
} else {
@@ -1424,110 +1621,302 @@
}
}
- function handleKeyNeeded(event) {
+ function handleInitData(event) {
var video = event.target;
-
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>) {
+ if (video.mediaKeysObject === undefined) {
selectKeySystem();
- video.<a href="#dom-setmediakeys">setMediaKeys</a>(new <a href="#dom-mediakeys">MediaKeys</a>(keySystem));
- }
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- throw "Could not create MediaKeys";
+ video.mediaKeysObject = null; // Prevent entering this path again.
+ video.pendingSessionData = []; // Will store all initData until the MediaKeys is ready.
+ <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>(keySystem).then(
+ function(createdMediaKeys) {
+ video.mediaKeysObject = createdMediaKeys;
- var keySession = video.<a href="#dom-attrmediakeys">mediaKeys</a>.<a href="#dom-createsession">createSession</a>(event.<a href="#dom-contenttype">contentType</a>, event.<a href="#dom-initdata">initData</a>);
- if (!keySession)
- throw "Could not create key session";
+ if (serverCertificate)
+ createdMediaKeys.<a href="#dom-setservercertificate">setServerCertificate</a>(serverCertificate);
- keySession.addEventListener("<a href="#dom-eventmessage">message</a>", licenseRequestReady, false);
+ for (var i = 0; i < video.pendingSessionData.length; i++) {
+ var data = video.pendingSessionData[i];
+ createSession(video.mediaKeysObject, data.initDataType, data.initData);
+ }
+ video.pendingSessionData = [];
+
+ return video.<a href="#dom-setmediakeys">setMediaKeys</a>(createdMediaKeys);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or use new MediaKeys")
+ );
+ }
+ addSession(video, event.<a href="#dom-initdatatype">initDataType</a>, event.<a href="#dom-initdata">initData</a>);
}
-
+
+ function addSession(video, initDataType, initData) {
+ if (video.mediaKeysObject) {
+ createSession(video.mediaKeysObject, initDataType, initData);
+ } else {
+ video.pendingSessionData.push({initDataType: initDataType, initData: initData});
+ }
+ }
+
+ function createSession(mediaKeys, initDataType, initData) {
+ mediaKeys.<a href="#dom-createsession">createSession</a>(initDataType, initData).then(
+ function(keySession) {
+ keySession.addEventListener("<a href="#dom-eventmessage">message</a>", licenseRequestReady, false);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or initialize key session")
+ );
+ }
+
function licenseRequestReady(event) {
- var keySession = event.target;
var request = event.<a href="#dom-message">message</a>;
- if (!request)
- throw "Could not create license request";
var xmlhttp = new XMLHttpRequest();
+ xmlhttp.keySession = event.target;
xmlhttp.open("POST", licenseUrl);
xmlhttp.onreadystatechange = function() {
- if(xmlhttp.readyState==4) {
+ if (xmlhttp.readyState == 4) {
var license = new Uint8Array(xmlhttp.response);
- keySession.<a href="#dom-update">update</a>(license);
+ xmlhttp.keySession.<a href="#dom-update">update</a>(license).catch(
+ console.error.bind(console, "update() failed")
+ );
}
}
xmlhttp.send(request);
}
</script>
-<video src="foo.webm" autoplay on<a href="#dom-needkey">needkey</a>="handleKeyNeeded(event)"></video></pre>
- </div>
+<video src="foo.webm" autoplay on<a href="#dom-encrypted">encrypted</a>="handleInitData(event)"></video>
+</pre>
- <h3 id="example-using-all-events" class="exampleheader">9.4. Using All Events</h3>
+ <h3 id="example-mediakeys-before-source" class="exampleheader">8.3. Create MediaKeys Before Loading Media</h3>
+ <p class="exampledescription">Initialization is much simpler if encrypted events do not need to be handled during MediaKeys initialization.
+ This can be accomplished either by providing the <a href="#initialization-data">Initialization Data</a> in other ways or setting the source after the MediaKeys object has been created.
+ This example does the latter.
+ </p>
+
+ <pre class="example">
+<script>
+ var keySystem;
+ var licenseUrl;
+ var serverCertificate;
+ var mediaKeys;
+
+ // See the previous example for implementations of these functions.
+ function selectKeySystem() { ... }
+ function createSession(mediaKeys, initDataType, initData) { ... }
+ function licenseRequestReady(event) { ... }
+
+ function handleInitData(event) {
+ createSession(mediaKeys, event.<a href="#dom-initdatatype">initDataType</a>, event.<a href="#dom-initdata">initData</a>);
+ }
+
+ selectKeySystem();
+ <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>(keySystem).then(
+ function(createdMediaKeys) {
+ mediaKeys = createdMediaKeys;
+ var video = document.getElementById("v");
+ video.src = "foo.webm";
+ if (serverCertificate)
+ mediaKeys.<a href="#dom-setservercertificate">setServerCertificate</a>(serverCertificate);
+ return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or initialize key session")
+ );
+</script>
+
+<video id="v" autoplay on<a href="#dom-encrypted">encrypted</a>="handleInitData(event)"></video>
+</pre>
+
+ <h3 id="example-using-all-events" class="exampleheader">8.4. Using All Events</h3>
<p class="exampledescription">This is a more complete example showing all events being used.</p>
<p class="exampledescription">Note that <code>handleMessage()</code> could be called multiple times, including in response to the <code><a href="#dom-update">update()</a></code> call if multiple round trips are required and for any other reason the Key System might need to send a message.</p>
- <div class="example">
- <pre class="code">
+ <pre class="example">
<script>
var keySystem;
var licenseUrl;
+ var serverCertificate;
+ var mediaKeys;
- function handleMessageResponse() {
- var license = new Uint8Array(xmlhttp.response);
- this.keySession.<a href="#dom-update">update</a>(license);
+ // See previous examples for implementations of these functions.
+ function selectKeySystem() { ... }
+ function handleInitData(event) { ... }
+
+ // This replaces the implementation in the previous example.
+ function createSession(mediaKeys, initDataType, initData) {
+ mediaKeys.<a href="#dom-createsession">createSession</a>(initDataType, initData).then(
+ function(keySession) {
+ keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+ keySession.addEventListener("<a href="#dom-eventkeyschange">keyschange</a>", handleKeysChange, false);
+ keySession.<a href="#dom-closed">closed</a>.then(
+ console.log.bind(console, "Session closed")
+ );
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or initialize key session")
+ );
}
-
+
+ function handleMessageResponse(keySession, response) {
+ var license = new Uint8Array(response);
+ keySession.<a href="#dom-update">update</a>(license).catch(
+ function(err) {
+ console.error("update() failed: " + err);
+ }
+ );
+ }
+
function sendMessage(message, keySession) {
xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = keySession;
- xmlhttp.onreadystatechange = handleMessageResponse;
xmlhttp.open("POST", licenseUrl);
+ xmlhttp.onreadystatechange = function() {
+ if (xmlhttp.readyState == 4)
+ handleMessageResponse(xmlhttp.keySession, xmlhttp.response);
+ }
xmlhttp.send(message);
}
function handleMessage(event) {
- var keySession = event.target;
- var message = event.<a href="#dom-message">message</a>;
- if (!message)
- throw "Invalid key message";
-
- sendMessage(message, keySession);
+ sendMessage(event.<a href="#dom-message">message</a>, event.target);
}
- function handleReady(event) {
- // Do some bookkeeping with event.target.<a href="#dom-sessionid">sessionId</a> if necessary.
+ function handleKeysChange(event) {
+ event.target.<a href="#dom-getusablekeyids">getUsableKeyIds</a>().then(
+ function(keyIdSequence) {
+ // Process keyIdSequence and respond appropriately.
+ }
+ ).catch(
+ console.error.bind(console, "Failed handling usable keys change")
+ );
}
function handleError(event) {
- // Report event.target.error.name and event.target.error.<a href="#dom-systemcode">systemCode</a>,
- // and do some bookkeeping with event.target.<a href="#dom-sessionid">sessionId</a> if necessary.
+ // Report and do some bookkeeping with event.target.<a href="#dom-sessionid">sessionId</a> if necessary.
}
- function handleKeyNeeded(event) {
- var video = event.target;
-
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>) {
- selectKeySystem(); // See previous example for implementation.
- video.<a href="#dom-setmediakeys">setMediaKeys</a>(new <a href="#dom-mediakeys">MediaKeys</a>(keySystem));
+ selectKeySystem();
+ <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>(keySystem).then(
+ function(createdMediaKeys) {
+ mediaKeys = createdMediaKeys;
+ var video = document.getElementById("v");
+ video.src = "foo.webm";
+ if (serverCertificate)
+ mediaKeys.<a href="#dom-setservercertificate">setServerCertificate</a>(serverCertificate);
+ return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
}
- if (!video.<a href="#dom-attrmediakeys">mediaKeys</a>)
- throw "Could not create MediaKeys";
-
- var keySession = video.<a href="#dom-attrmediakeys">mediaKeys</a>.<a href="#dom-createsession">createSession</a>(event.<a href="#dom-contenttype">contentType</a>, event.<a href="#dom-initdata">initData</a>);
- if (!keySession)
- throw "Could not create key session";
-
- keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
- keySession.addEventListener("<a href="#dom-eventready">ready</a>", handleReady, false);
- keySession.addEventListener("<a href="#dom-eventerror">error</a>", handleError, false);
- }
+ ).catch(
+ console.error.bind(console, "Unable to create or use new MediaKeys")
+ );
</script>
-<video src="foo.webm" autoplay on<a href="#dom-needkey">needkey</a>="handleKeyNeeded(event)"></video></pre>
- </div>
+<video id="v" autoplay on<a href="#dom-encrypted">encrypted</a>="handleInitData(event)"></video>
+</pre>
+
+ <h3 id="example-stored-license" class="exampleheader">8.5. Stored License</h3>
+ <p class="exampledescription">This example requests a persistent license for future use and stores it. It also provides functions for later retrieving the license and for destroying it.</p>
+
+ <pre class="example">
+<script>
+ var keySystem;
+ var licenseUrl;
+ var serverCertificate;
+ var mediaKeys;
+
+ // See the previous examples for implementations of these functions.
+ function selectKeySystem() { ... }
+ function sendMessage(message, keySession) { ... }
+ function handleMessage(event) { ... }
+ function handleError(event) { ... }
+
+ // Called if the application does not have a stored sessionId for the media resource.
+ function createSession(mediaKeys, initDataType, initData) {
+ mediaKeys.<a href="#dom-createsession">createSession</a>(initDataType, initData, "persistent").then(
+ function(keySession) {
+ keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+ keySession.<a href="#dom-closed">closed</a>.then(
+ function() {
+ console.log("Session " + this.sessionId + " closed");
+ }.bind(keySession)
+ );
+ // Store keySession.<a href="#dom-sessionid">sessionId</a> in the application.
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or initialize a persistable key session")
+ );
+ }
+
+ // Called if the application has a stored sessionId for the media resource.
+ function loadStoredSession(mediaKeys, sessionId) {
+ mediaKeys.<a href="#dom-loadsession">loadSession</a>(sessionId).then(
+ function(keySession) {
+ if (!keySession) {
+ console.error("No stored session with the ID " + sessionId + " was found.");
+ // The application should remove its record of |sessionId|.
+ return;
+ }
+ keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+ keySession.<a href="#dom-closed">closed</a>.then(
+ console.log.bind(console, "Session closed")
+ );
+ }
+ ).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.<a href="#dom-close">close</a>();
+ }
+
+ // 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.<a href="#dom-remove">remove</a>().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.<a href="#dom-update">update</a>(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")
+ );
+ }
+
+ selectKeySystem();
+ <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>(keySystem).then(
+ function(createdMediaKeys) {
+ mediaKeys = createdMediaKeys;
+ var video = document.getElementById("v");
+ if (serverCertificate)
+ mediaKeys.<a href="#dom-setservercertificate">setServerCertificate</a>(serverCertificate);
+ return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
+ }
+ ).catch(
+ console.error.bind(console, "Unable to create or use new MediaKeys")
+ );
+</script>
+
+<video id="v" src="foo.webm" autoplay></video>
+</pre>
- <h2 id="revision-history">10. Revision History</h2>
+ <h2 id="revision-history">9. Revision History</h2>
<table>
<thead>
<tr>
@@ -1537,6 +1926,18 @@
</thead>
<tbody>
<tr>
+ <td><a href="https://dvcs.w3.org/hg/html-media/raw-file/9842af174b80/encrypted-media/encrypted-media.html">14 April 2014</a></td>
+ <td>Use promises.</td>
+ </tr>
+ <tr>
+ <td><a href="http://dvcs.w3.org/hg/html-media/raw-file/ef65c237d053/encrypted-media/encrypted-media.html">1 April 2014</a></td>
+ <td>Moved Container Guidelines to the <a href="initdata-format-registry.html">Encrypted Media Extensions Stream Format and Initialization Data Format Registry</a>.</td>
+ </tr>
+ <tr>
+ <td><a href="http://dvcs.w3.org/hg/html-media/raw-file/11245f9516cf/encrypted-media/encrypted-media.html">3 February 2014</a></td>
+ <td>Produced candidate WD.</td>
+ </tr>
+ <tr>
<td>17 September 2013</td>
<td>Produced candidate WD.</td>
</tr>