[EME] Bug 26575 - Copied createSession() and moved loadSession() to MediaKeySession.
authorDavid Dorwin <ddorwin@google.com>
Mon, 25 Aug 2014 11:40:20 -0700
changeset 401 ec33087ef0db
parent 400 9a94854a5999
child 402 19ef12173afb
[EME] Bug 26575 - Copied createSession() and moved loadSession() to MediaKeySession.

No algorithm or other changes yet.
encrypted-media/encrypted-media.html
encrypted-media/encrypted-media.xml
--- a/encrypted-media/encrypted-media.html	Mon Aug 18 14:23:59 2014 -0700
+++ b/encrypted-media/encrypted-media.html	Mon Aug 25 11:40:20 2014 -0700
@@ -104,7 +104,7 @@
     <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 Editor's Draft 18 August 2014</h2>
+      <h2 id="draft-date">W3C Editor's Draft 25 August 2014</h2>
       <dl>
         <dt>This Version:</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>
@@ -350,7 +350,6 @@
   readonly attribute DOMString <a href="#dom-keysystem">keySystem</a>;
 
   Promise&lt;<a href="#dom-mediakeysession">MediaKeySession</a>&gt; <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&lt;<a href="#dom-mediakeysession">MediaKeySession</a>&gt; <a href="#dom-loadsession">loadSession</a>(DOMString sessionId);
   Promise&lt;void&gt; <a href="#dom-setservercertificate">setServerCertificate</a>((ArrayBuffer or ArrayBufferView) serverCertificate);
 
   static Promise&lt;<a href="#dom-mediakeys">MediaKeys</a>&gt; <a href="#dom-create">create</a>(DOMString <a href="#key-system">keySystem</a>);
@@ -364,6 +363,10 @@
   readonly attribute unrestricted double <a href="#dom-expiration">expiration</a>;
   readonly attribute Promise&lt;void&gt; <a href="#dom-closed">closed</a>;
 
+  // session initialization
+  Promise&lt;<a href="#dom-mediakeysession">MediaKeySession</a>&gt; <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&lt;<a href="#dom-mediakeysession">MediaKeySession</a>&gt; <a href="#dom-loadsession">loadSession</a>(DOMString sessionId);
+
   // session operations
   Promise&lt;void&gt; <a href="#dom-update">update</a>((ArrayBuffer or ArrayBufferView) response);
   Promise&lt;void&gt; <a href="#dom-close">close</a>();
@@ -518,67 +521,6 @@
       <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>
-    <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=26575">Bug 26575</a> - MediaKeySession creation may be separated from loading the session.</p>
-</div>
-    <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>Run the following steps asynchronously:</p>
-        <ol>
-          <li>
-<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>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 is required:</p>
-                <ol>
-                  <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 <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 <var>promise</var>.</p></li>
-    </ol>
-
     <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>
@@ -706,6 +648,125 @@
     <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-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>
+    <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=26575">Bug 26575</a> - MediaKeySession creation may be separated from generating a license request.</p>
+</div>
+    <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: 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">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 <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>
+    <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=26575">Bug 26575</a> - MediaKeySession creation may be separated from loading the session.</p>
+</div>
+    <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>Run the following steps asynchronously:</p>
+        <ol>
+          <li>
+<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>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 is required:</p>
+                <ol>
+                  <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 <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 <var>promise</var>.</p></li>
+    </ol>
+
     <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>
 
--- a/encrypted-media/encrypted-media.xml	Mon Aug 18 14:23:59 2014 -0700
+++ b/encrypted-media/encrypted-media.xml	Mon Aug 25 11:40:20 2014 -0700
@@ -103,7 +103,7 @@
     <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 Editor's Draft 18 August 2014</h2>
+      <h2 id="draft-date">W3C Editor's Draft 25 August 2014</h2>
       <dl>
         <dt>This Version:</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>
@@ -347,7 +347,6 @@
   readonly attribute DOMString <precoderef>keySystem</precoderef>;
 
   Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>createSession</premethodref>(DOMString <a href="#initialization-data-type">initDataType</a>, (ArrayBuffer or ArrayBufferView) initData, optional <precoderef>SessionType</precoderef> sessionType = "<precoderef prefix="sessiontype">temporary</precoderef>");
-  Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>loadSession</premethodref>(DOMString sessionId);
   Promise&lt;void&gt; <premethodref>setServerCertificate</premethodref>((ArrayBuffer or ArrayBufferView) serverCertificate);
 
   static Promise&lt;<precoderef>MediaKeys</precoderef>&gt; <premethodref>create</premethodref>(DOMString <a href="#key-system">keySystem</a>);
@@ -361,6 +360,10 @@
   readonly attribute unrestricted double <precoderef>expiration</precoderef>;
   readonly attribute Promise&lt;void&gt; <precoderef>closed</precoderef>;
 
+  // session initialization
+  Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>createSession</premethodref>(DOMString <a href="#initialization-data-type">initDataType</a>, (ArrayBuffer or ArrayBufferView) initData, optional <precoderef>SessionType</precoderef> sessionType = "<precoderef prefix="sessiontype">temporary</precoderef>");
+  Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>loadSession</premethodref>(DOMString sessionId);
+
   // session operations
   Promise&lt;void&gt; <premethodref>update</premethodref>((ArrayBuffer or ArrayBufferView) response);
   Promise&lt;void&gt; <premethodref>close</premethodref>();
@@ -501,58 +504,6 @@
       <li><p>Return <var>promise</var>.</p></li>
     </ol>
 
-    <p>The <methoddfn name="loadSession">loadSession(<var title="true">sessionId</var>)</methoddfn> method creates a new <coderef>MediaKeySession</coderef> object containing the data stored for the <var title="true">sessionId</var>. It must run the following steps:</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=26575">Bug 26575</a> - MediaKeySession creation may be separated from loading the session.</p></div>
-    <ol>
-      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to the <coderef>keySystem</coderef> attribute does not support loading previous sessions, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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><dom4ref name="exception-domexception">DOMException</dom4ref></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>Run the following steps asynchronously:</p>
-        <ol>
-          <li><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 <coderef>MediaKeys</coderef> object's <code><dom4ref name="document">Document</dom4ref></code>.</p></li>
-          <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <methodref>create</methodref>.</p></li>
-          <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
-            <ol>
-              <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><!-- "undefined" per https://github.com/w3ctag/promises-guide#rejections-should-be-used-for-exceptional-situations. -->
-              <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 is required:</p>
-                <ol>
-                  <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 <var title="true">session</var> be a new <coderef>MediaKeySession</coderef> object, and initialize it as follows:</p>
-            <ol>
-              <li><p>Set the <coderef>sessionId</coderef> attribute to <var title="true">sessionId</var>.</p></li>
-              <li><p>Let <coderef>expiration</coderef> be <code>NaN</code>.</p></li>
-              <li><p>Let <coderef>closed</coderef> be a new promise.</p></li>
-              <li><p>Let the session type be "<coderef prefix="sessiontype">persistent</coderef>".</p></li>
-            </ol>
-          </li>
-          <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <coderef>sessionId</coderef> 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 <var>promise</var>.</p></li>
-    </ol>
-
     <p id="server-certificate">The <methoddfn name="setServerCertificate">setServerCertificate(<var title="true">serverCertificate</var>)</methoddfn> 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>
@@ -665,6 +616,109 @@
     <p>The <codedfn>closed</codedfn> 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 <methoddfn name="createSession">createSession(<var title="true">initDataType</var>, <var title="true">initData</var>, <var title="true">sessionType</var>)</methoddfn> method creates a new <coderef>MediaKeySession</coderef> object for the <var title="true">initData</var>. It must run the following steps:</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=26575">Bug 26575</a> - MediaKeySession creation may be separated from generating a license request.</p></div>
+    <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: 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">initDataType</var> is an empty string, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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><dom4ref name="exception-domexception">DOMException</dom4ref></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 <coderef>keySystem</coderef>, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <coderef>keySystem</coderef>, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <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 <methodref>create</methodref>.</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><dom4ref name="exception-domexception">DOMException</dom4ref></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><dom4ref name="exception-domexception">DOMException</dom4ref></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 "<coderef prefix="sessiontype">temporary</coderef>", the request is for a temporary non-persisted license.
+                If <var title="true">sessionType</var> is "<coderef prefix="sessiontype">persistent</coderef>", the request is for a persistable session, possibly with a persistable license.</p>
+                <p>If <var title="true">sessionType</var> is <em>not</em> "<coderef prefix="sessiontype">persistent</coderef>", 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 <videoanchor name="media-data">media data</videoanchor>, 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 <coderef>MediaKeySession</coderef> object, and initialize it as follows:</p>
+            <ol>
+              <li><p>Set the <coderef>sessionId</coderef> attribute to <var title="true">session ID</var>.</p></li>
+              <li><p>Let <coderef>expiration</coderef> be <code>NaN</code>.</p></li>
+              <li><p>Let <coderef>closed</coderef> 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><dom4ref name="exception-domexception">DOMException</dom4ref></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 <coderef>sessionId</coderef> 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 <methoddfn name="loadSession">loadSession(<var title="true">sessionId</var>)</methoddfn> method creates a new <coderef>MediaKeySession</coderef> object containing the data stored for the <var title="true">sessionId</var>. It must run the following steps:</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=26575">Bug 26575</a> - MediaKeySession creation may be separated from loading the session.</p></div>
+    <ol>
+      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to the <coderef>keySystem</coderef> attribute does not support loading previous sessions, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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><dom4ref name="exception-domexception">DOMException</dom4ref></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>Run the following steps asynchronously:</p>
+        <ol>
+          <li><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 <coderef>MediaKeys</coderef> object's <code><dom4ref name="document">Document</dom4ref></code>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <methodref>create</methodref>.</p></li>
+          <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
+            <ol>
+              <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><!-- "undefined" per https://github.com/w3ctag/promises-guide#rejections-should-be-used-for-exceptional-situations. -->
+              <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 is required:</p>
+                <ol>
+                  <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 <var title="true">session</var> be a new <coderef>MediaKeySession</coderef> object, and initialize it as follows:</p>
+            <ol>
+              <li><p>Set the <coderef>sessionId</coderef> attribute to <var title="true">sessionId</var>.</p></li>
+              <li><p>Let <coderef>expiration</coderef> be <code>NaN</code>.</p></li>
+              <li><p>Let <coderef>closed</coderef> be a new promise.</p></li>
+              <li><p>Let the session type be "<coderef prefix="sessiontype">persistent</coderef>".</p></li>
+            </ol>
+          </li>
+          <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <coderef>sessionId</coderef> 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 <var>promise</var>.</p></li>
+    </ol>
+
     <p>The <methoddfn name="update">update(<var title="true">response</var>)</methoddfn> 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>