[EME] Bug 20622 - SessionID may be assigned asynchronously in MediaKeys.createSession
Includes the following changes to the createSession() algorithm:
* Use "message exchange" and "request" instead of "key request".
* Explicitly determine whether a message exchange is required and allow errors
to occur in the not required case.
* sessionId is set asynchronously and possibly as part of or after determining
whether a request is necessary and generating it. It must be set before firing
keymessage or keyready.
Also updated the Session ID definition and added a definition for Key Session.
--- a/encrypted-media/encrypted-media.html Mon Oct 28 12:54:32 2013 -0700
+++ b/encrypted-media/encrypted-media.html Mon Oct 28 12:58:16 2013 -0700
@@ -204,23 +204,26 @@
Key System providers should keep in mind that these will be used for comparison and discovery, so they should be easy to compare and the structure should remain reasonably simple.
</p>
-
- <h4 id="session-id">1.1.3. Session ID</h4>
- <p>A Session ID is a string ID that can be used to associate calls related to a key/license lifetime, starting with the request.
- <span class="non-normative">It is a local binding between a request and key/license.
- It does not associate keys or licenses for different streams (i.e. audio and video).</span>
- It is generated by the user agent/CDM and provided to the application in the <code><a href="#dom-keymessage">keymessage</a></code> event.
- <span class="non-normative">(Session IDs need not necessarily be supported by the underlying content protection client or server.)</span>
+ <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.
+ 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>A new Session ID will be generated each time <code><a href="#dom-createsession">createSession()</a></code> successfully creates a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.
- The user agent/CDM manage the lifetime of Session IDs.
- All Session IDs are cleared from the <a href="#media-element">media element</a> when a load occurs, although the CDM may retain them for longer periods.
+ <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.
+ <span class="non-normative">(The underlying content protection client or server do not necessarily need to support Session IDs.)</span>
</p>
- <p>Each SessionID shall be unique within the browsing context in which it was created. If secure proof of key release is supported each Session ID shall
- be unique within the origin. Note that this last requirement implies that Session IDs shall be unique over time including across browsing sessions.</p>
- <h4 id="initialization-data">1.1.4. Initialization Data</h4>
+ <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-pending">PENDING</a></code> or <code><a href="#dom-ready">READY</a></code> states and the user agent fires the associated events.
+ </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.
@@ -236,7 +239,7 @@
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>
- <h4 id="cross-origin-support">1.1.5. Cross Origin Support</h4>
+ <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>
and <code><a href="#dom-keymessage">keymessage</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
@@ -353,7 +356,6 @@
<li>Create a new <code><a href="#dom-mediakeysession">MediaKeySession</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>
- <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 generated by <var title="true">cdm</var>.</span></p></li>
<li><p>Let the state of the session be <code><a href="#dom-created">CREATED</a></code>.</p></li>
</ol>
</li>
@@ -366,44 +368,57 @@
</p></li>
<li>
-<p>Schedule a task to generate a key request, providing <var title="true">type</var>, <var title="true">initData</var>, and the new object.</p>
+<p>Schedule a task to initialize the session, providing <var title="true">type</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>
<ol>
<li><p>Let <var title="true">defaultURL</var> be null.</p></li>
+ <li><p>Let <var title="true">request</var> be null.</p></li>
<li>
-<p>Use <var title="true">cdm</var> to generate a key request and follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If a request is successfully generated</dt>
- <dd>
- <ol>
- <li>
-<p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided. The <var title="true">key request</var> may be empty if the <a href="#cdm">CDM</a> does not need a message exchange.</p>
- <p>Note: <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"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
- </li>
- <li><p>If <var title="true">initData</var> contains a default URL for <var title="true">keySystem</var>, let <var title="true">defaultURL</var> be that URL.</p></li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd><ol>
- <li>
+<p>Use <var title="true">cdm</var> to process <var title="true">type</var> and <var title="true">initData</var>.</p>
+ <ol>
+ <li><p>Determine whether a message exchange <span class="non-normative">(e.g. a license request)</span> is required.</p></li>
+ <li>
+<p>Follow the steps for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If a message exchange is required</dt>
+ <dd>
+ <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>Note: <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"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
+ <p class="non-normative"><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> contains a default URL for <var title="true">keySystem</var>, let <var title="true">defaultURL</var> be that URL.</p></li>
+ </ol>
+ </dd>
+ <dt>Otherwise</dt>
+ <dd>Continue.</dd>
+ </dl>
+ </li>
+ <li>
+<p><i>Error</i>: If any of the preceding processing steps failed</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="#dom-code">code</a></code> = the appropriate <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> code<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-keyerror">keyerror</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
- <li><p>Abort the task.</p></li>
- </ol></dd>
- </dl>
+ <ul style="list-style-type:none"><li>
+ <code><a href="#dom-code">code</a></code> = the appropriate <code><a href="#dom-mediakeyerror">MediaKeyError</a></code> code<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-keyerror">keyerror</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
+ <li><p>Abort the task.</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>Follow the steps for the first matching condition from the following list:</p>
<dl class="switch">
- <dt>If the <var title="true">key request</var> is not empty</dt>
+ <dt>If <var title="true">request</var> is not null</dt>
<dd>
<ol>
<li><p>Let the state of the session be <code><a href="#dom-pending">PENDING</a></code>.</p></li>
@@ -411,14 +426,13 @@
<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-keymessage">keymessage</a></code> at the new object.</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> = <var title="true">key request</var><br>
+ <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>
- <p class="non-normative">Note: <code><a href="#dom-message">message</a></code> 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>
</ol>
</dd>
- <dt>If the <var title="true">key request</var> is empty</dt>
+ <dt>Otherwise</dt>
<dd>
<ol>
<li><p>Let the state of the session be <code><a href="#dom-ready">READY</a></code>.</p></li>
--- a/encrypted-media/encrypted-media.xml Mon Oct 28 12:54:32 2013 -0700
+++ b/encrypted-media/encrypted-media.xml Mon Oct 28 12:58:16 2013 -0700
@@ -201,23 +201,26 @@
Key System providers should keep in mind that these will be used for comparison and discovery, so they should be easy to compare and the structure should remain reasonably simple.
</p>
-
- <h4 id="session-id">1.1.3. Session ID</h4>
- <p>A Session ID is a string ID that can be used to associate calls related to a key/license lifetime, starting with the request.
- <span class="non-normative">It is a local binding between a request and key/license.
- It does not associate keys or licenses for different streams (i.e. audio and video).</span>
- It is generated by the user agent/CDM and provided to the application in the <coderef>keymessage</coderef> event.
- <span class="non-normative">(Session IDs need not necessarily be supported by the underlying content protection client or server.)</span>
+ <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.
+ Sessions are embodied as <coderef>MediaKeySession</coderef> objects.
+ Each Key session is associated with a single instance of <a href="#initialization-data">Initialization Data</a> provided in the <methodref>createSession</methodref> call.
</p>
- <p>A new Session ID will be generated each time <methodref>createSession</methodref> successfully creates a <coderef>MediaKeySession</coderef> object.
- The user agent/CDM manage the lifetime of Session IDs.
- All Session IDs are cleared from the <a href="#media-element">media element</a> when a load occurs, although the CDM may retain them for longer periods.
+ <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 <coderef>MediaKeySession</coderef> objects.
+ <span class="non-normative">(The underlying content protection client or server do not necessarily need to support Session IDs.)</span>
</p>
- <p>Each SessionID shall be unique within the browsing context in which it was created. If secure proof of key release is supported each Session ID shall
- be unique within the origin. Note that this last requirement implies that Session IDs shall be unique over time including across browsing sessions.</p>
- <h4 id="initialization-data">1.1.4. Initialization Data</h4>
+ <p>A new Session ID is generated each time the user agent successfully initializes a <coderef>MediaKeySession</coderef> object.
+ It must be valid before the <coderef>MediaKeySession</coderef> enters the <coderef>PENDING</coderef> or <coderef>READY</coderef> states and the user agent fires the associated events.
+ </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>
<non-normative-section/>
<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.
@@ -233,7 +236,7 @@
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>
- <h4 id="cross-origin-support">1.1.5. Cross Origin Support</h4>
+ <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 <coderef>needkey</coderef>
and <coderef>keymessage</coderef> events, <videoanchor name="media-data">media data</videoanchor> must be <cors-same-origin/> with the embedding page.
If <videoanchor name="media-data">media data</videoanchor> is cross-origin with the embedding document, authors should use the <videoanchor name="attr-media-crossorigin">crossorigin</videoanchor> attribute
@@ -348,7 +351,6 @@
<li>Create a new <coderef>MediaKeySession</coderef> object.
<ol>
<li><p>Let the <coderef>keySystem</coderef> attribute be <var title="true">keySystem</var>.</p></li>
- <li><p>Let the <coderef>sessionId</coderef> attribute be a unique <a href="#session-id">Session ID</a> string. <span class="non-normative">It may be generated by <var title="true">cdm</var>.</span></p></li>
<li><p>Let the state of the session be <coderef>CREATED</coderef>.</p></li>
</ol>
</li>
@@ -360,40 +362,51 @@
then <queue-a-task/> to <fire-a-simple-event/> named <coderef>keyerror</coderef> at the <coderef>MediaKeySession</coderef> object and abort these steps.
</p></li>
- <li><p>Schedule a task to generate a key request, providing <var title="true">type</var>, <var title="true">initData</var>, and the new object.</p>
+ <li><p>Schedule a task to initialize the session, providing <var title="true">type</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>
<ol>
<li><p>Let <var title="true">defaultURL</var> be null.</p></li>
- <li><p>Use <var title="true">cdm</var> to generate a key request and follow the steps for the first matching condition from the following list:</p>
- <dl class="switch">
- <dt>If a request is successfully generated</dt>
- <dd>
- <ol>
- <li><p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided. The <var title="true">key request</var> may be empty if the <a href="#cdm">CDM</a> does not need a message exchange.</p>
- <p>Note: <var title="true">cdm</var> must not use any stream-specific data, including <videoanchor name="media-data">media data</videoanchor>, not provided via <var title="true">initData</var>.</p>
- <p class="non-normative"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
- </li>
- <li><p>If <var title="true">initData</var> contains a default URL for <var title="true">keySystem</var>, let <var title="true">defaultURL</var> be that URL.</p></li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd><ol>
- <li><p>Create a new <coderef>MediaKeyError</coderef> object with the following attributes:</p>
- <ul style="list-style-type:none"><li>
- <coderef>code</coderef> = the appropriate <coderef>MediaKeyError</coderef> code<br></br>
- <coderef>systemCode</coderef> = a Key System-specific value, if provided, and 0 otherwise
- </li></ul>
- </li>
- <li><p>Set the <coderef>MediaKeySession</coderef> object's <coderef>error</coderef> attribute to the error object created in the previous step.</p></li>
- <li><p>Let the state of the session be <coderef prefix="state">ERROR</coderef>.</p></li>
- <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keyerror</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
- <li><p>Abort the task.</p></li>
- </ol></dd>
- </dl>
+ <li><p>Let <var title="true">request</var> be null.</p></li>
+ <li><p>Use <var title="true">cdm</var> to process <var title="true">type</var> and <var title="true">initData</var>.</p>
+ <ol>
+ <li><p>Determine whether a message exchange <span class="non-normative">(e.g. a license request)</span> is required.</p></li>
+ <li><p>Follow the steps for the first matching condition from the following list:</p>
+ <dl class="switch">
+ <dt>If a message exchange is required</dt>
+ <dd>
+ <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>Note: <var title="true">cdm</var> must not use any stream-specific data, including <videoanchor name="media-data">media data</videoanchor>, not provided via <var title="true">initData</var>.</p>
+ <p class="non-normative"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
+ <p class="non-normative"><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> contains a default URL for <var title="true">keySystem</var>, let <var title="true">defaultURL</var> be that URL.</p></li>
+ </ol>
+ </dd>
+ <dt>Otherwise</dt>
+ <dd>Continue.</dd>
+ </dl>
+ </li>
+ <li><p><i>Error</i>: If any of the preceding processing steps failed</p>
+ <ol>
+ <li><p>Create a new <coderef>MediaKeyError</coderef> object with the following attributes:</p>
+ <ul style="list-style-type:none"><li>
+ <coderef>code</coderef> = the appropriate <coderef>MediaKeyError</coderef> code<br></br>
+ <coderef>systemCode</coderef> = a Key System-specific value, if provided, and 0 otherwise
+ </li></ul>
+ </li>
+ <li><p>Set the <coderef>MediaKeySession</coderef> object's <coderef>error</coderef> attribute to the error object created in the previous step.</p></li>
+ <li><p>Let the state of the session be <coderef prefix="state">ERROR</coderef>.</p></li>
+ <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keyerror</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
+ <li><p>Abort the task.</p></li>
+ </ol>
+ </li>
+ </ol>
</li>
+ <li><p>Let the <coderef>sessionId</coderef> 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>Follow the steps for the first matching condition from the following list:</p>
<dl class="switch">
- <dt>If the <var title="true">key request</var> is not empty</dt>
+ <dt>If <var title="true">request</var> is not null</dt>
<dd>
<ol>
<li><p>Let the state of the session be <coderef>PENDING</coderef>.</p></li>
@@ -401,14 +414,13 @@
<p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keymessage</coderef> at the new object.</p>
<p>The event is of type <coderef>MediaKeyMessageEvent</coderef> and has:</p>
<ul style="list-style-type:none"><li>
- <coderef>message</coderef> = <var title="true">key request</var><br></br>
+ <coderef>message</coderef> = <var title="true">request</var><br></br>
<coderef>destinationURL</coderef> = <var title="true">defaultURL</var>
</li></ul>
- <p class="non-normative">Note: <coderef>message</coderef> 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>
</ol>
</dd>
- <dt>If the <var title="true">key request</var> is empty</dt>
+ <dt>Otherwise</dt>
<dd>
<ol>
<li><p>Let the state of the session be <coderef>READY</coderef>.</p></li>