Bug 26575 - Separate creation of the MediaKeySession from "message" event generation
authorDavid Dorwin <ddorwin@google.com>
Mon, 25 Aug 2014 11:42:27 -0700
changeset 402 19ef12173afb
parent 401 ec33087ef0db
child 403 4e31f7807448
Bug 26575 - Separate creation of the MediaKeySession from "message" event generation
encrypted-media/encrypted-media.html
encrypted-media/encrypted-media.xml
--- a/encrypted-media/encrypted-media.html	Mon Aug 25 11:40:20 2014 -0700
+++ b/encrypted-media/encrypted-media.html	Mon Aug 25 11:42:27 2014 -0700
@@ -258,7 +258,7 @@
     <h4 id="key-session">1.1.3. Key Session</h4>
     <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.
+    Each Key session is associated with a single instance of <a href="#initialization-data">Initialization Data</a> provided in the <code><a href="#dom-generaterequest">generateRequest()</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).
@@ -280,7 +280,7 @@
     <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.)
+    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-load">load()</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>
@@ -349,7 +349,7 @@
 interface <dfn id="dom-mediakeys">MediaKeys</dfn> {
   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-createsession">createSession</a>(optional <a href="#dom-sessiontype">SessionType</a> sessionType = "<a href="#dom-sessiontypetemporary">temporary</a>");
   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,8 +364,8 @@
   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);
+  Promise&lt;void&gt; <a href="#dom-generaterequest">generateRequest</a>(DOMString <a href="#initialization-data-type">initDataType</a>, (ArrayBuffer or ArrayBufferView) initData);
+  Promise&lt;bool&gt; <a href="#dom-load">load</a>(DOMString sessionId);
 
   // session operations
   Promise&lt;void&gt; <a href="#dom-update">update</a>((ArrayBuffer or ArrayBufferView) response);
@@ -428,7 +428,8 @@
     
     <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 using <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 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-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>
 
@@ -463,58 +464,31 @@
 
     <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(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>
+<p class=""><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=26575">Bug 26575</a> - This method may be changed to return the MediaKeySession object synchronously.</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>
+    <p>The <dfn id="dom-createsession"><code>createSession(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>
 
     <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>
+              <li><p>Let the <code><a href="#dom-sessionid">sessionId</a></code> attribute be the empty string.</p></li>
+              <li><p>Let the <code><a href="#dom-expiration">expiration</a></code> attribute be <code>NaN</code>.</p></li>
+              <li><p>Let the <code><a href="#dom-closed">closed</a></code> attribute be a new promise.</p></li>
+              <li><p>Let the <var title="true">session type</var> be <var title="true">sessionType</var>.</p></li>
+              <li><p>Let <var title="true">uninitialized</var> be true.</p></li>
+              <li><p>Let <var title="true">callable</var> be false.</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>
@@ -533,7 +507,7 @@
       <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>Let <var title="true">cdm</var> be the <var title="true">cdm</var> during the <a href="#dom-create">initialization</a> of this object.</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>
@@ -648,95 +622,84 @@
     <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>The <dfn id="dom-generaterequest"><code>generateRequest(initDataType, initData)</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: 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>.
+    <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>
 
     <ol>
+      <li><p>If this object's <var title="true">callable</var> value is false, 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 this object's <var title="true">uninitialized</var> be false.</p></li>
       <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 title="true">media keys</var> be the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that created this object.</p></li>
+      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to <var title="true">media keys</var>'s <code><a href="#dom-keysystem">keySystem</a></code> attribute does not support <var title="true">initDataType</var> as an <a href="#initialization-data-type">initialization data type</a>, 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>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 title="true">session type</var> be this object's <var title="true">session type</var>.</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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of <var title="true">media keys</var>.</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>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">session type</var>.</p>
+                <p>If <var title="true">session type</var> is "<code><a href="#dom-sessiontypetemporary">temporary</a></code>", the request is for a temporary non-persisted license.
+                If <var title="true">session type</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">session type</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>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to 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 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>Add an entry for the value of the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">media keys</var>'s <var title="true">list of active session IDs</var>.</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>
+          <li><p>Let this object's <var title="true">callable</var> be true.</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-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>
+    <p>The <dfn id="dom-load"><code>load(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 this object's <var title="true">uninitialized</var> value is false, 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 this object's <var title="true">uninitialized</var> be false.</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>If this object's <var title="true">session type</var> 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>Let <var title="true">media keys</var> be the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that created this object.</p></li>
+      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to <var title="true">media keys</var>'s <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>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>If <var title="true">media keys</var>'s <var title="true">list of active session IDs</var> includes an entry for <var title="true">sessionId</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-QuotaExceededError">"QuotaExceededError"</a></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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of <var title="true">media keys</var>.</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>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>false</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>
+<p>If the CDM needs to send a message:</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>
@@ -744,24 +707,17 @@
               </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>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>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>Add an entry for the value of the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">media keys</var>'s <var title="true">list of active session IDs</var>.</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>
+          <li><p>Let this object's <var title="true">callable</var> be true.</p></li>
+          <li><p>Resolve <var>promise</var> with <code>true</code>.</p></li>
         </ol>
       </li>
       <li><p>Return <var>promise</var>.</p></li>
@@ -771,13 +727,14 @@
     <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 this object's <var title="true">callable</var> value is false, 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>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>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">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object.</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>
@@ -828,12 +785,13 @@
     It must run the following steps:</p>
 
     <ol>
+      <li><p>If this object's <var title="true">callable</var> value is false, 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>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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object.</p></li>
           <li>
 <p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
@@ -854,13 +812,14 @@
     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 this object's <var title="true">callable</var> value is false, 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>If this object's <var title="true">session type</var> 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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object.</p></li>
           <li>
 <p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
@@ -868,7 +827,7 @@
                 <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>
+                  <span class="non-normative">(A subsequent call to <code><a href="#dom-load">load()</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>
@@ -889,11 +848,12 @@
     <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 this object's <var title="true">callable</var> value is false, 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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object.</p></li>
           <li>
 <p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
@@ -938,6 +898,8 @@
         <tr>
           <td><dfn id="dfn-InvalidStateError"><code>InvalidStateError</code></dfn></td>
           <td>The existing MediaKeys object cannot be removed at this time.<br>
+            The session has already been used.<br>
+            The session is not yet initialized.<br>
             The session is closed.
           </td>
         </tr>
@@ -953,7 +915,9 @@
         </tr>
         <tr>
           <td><dfn id="dfn-QuotaExceededError"><code>QuotaExceededError</code></dfn></td>
-          <td>The MediaKeys object cannot be used with additional HTMLMediaElements.</td>
+          <td>The MediaKeys object cannot be used with additional HTMLMediaElements.<br>
+            A non-closed session already exists for this sessionId.
+          </td>
         </tr>
       </tbody>
     </table>
@@ -1078,7 +1042,7 @@
           <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 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>
+            <span class="non-normative">For example, a license request has been generated as the result of a <code><a href="#dom-generaterequest">generateRequest()</a></code> call or another message must be sent in response to an <code><a href="#dom-update">update()</a></code> call.</span>
           </td>
         </tr>
       </tbody>
@@ -1122,7 +1086,7 @@
 <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-create">initialization</a> of the <var title="true">media keys</var>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-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>
@@ -1273,7 +1237,8 @@
     <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 title="true">media keys</var> be the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that created this 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 <var title="true">media keys</var>'s <var title="true">list of active session IDs</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>
@@ -1336,14 +1301,14 @@
       <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>
+      <li><p>The "<code><a href="#dom-sessiontypepersistent">persistent</a></code>" <code><a href="#dom-sessiontype">SessionType</a></code>: 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>
+<p>In the <code><a href="#dom-generaterequest">generateRequest()</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>
@@ -1454,7 +1419,7 @@
     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>.
+    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-generaterequest">generateRequest()</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.
@@ -1628,14 +1593,15 @@
       promise.then(
         function(createdMediaKeys) {
           var initData = new Uint8Array([ ... ]);
-          return createdMediaKeys.<a href="#dom-createsession">createSession</a>("webm", initData);
+          return createdMediaKeys.<a href="#dom-createsession">createSession</a>();
         }
       ).then(
         function(keySession) {
           keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
+          return keySession.<a href="#dom-generaterequest">generateRequest</a>("webm", initData);
         }
       ).catch(
-        console.error.bind(console, "Unable to create key session")
+        console.error.bind(console, "Unable to create or initialize key session")
       );
     }
   }
@@ -1695,7 +1661,7 @@
 
           for (var i = 0; i &lt; video.pendingSessionData.length; i++) {
             var data = video.pendingSessionData[i];
-            createSession(video.mediaKeysObject, data.initDataType, data.initData);
+            makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData);
           }
           video.pendingSessionData = [];
 
@@ -1710,16 +1676,17 @@
 
   function addSession(video, initDataType, initData) {
     if (video.mediaKeysObject) {
-      createSession(video.mediaKeysObject, initDataType, initData);
+      makeNewRequest(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 makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<a href="#dom-createsession">createSession</a>().then(
       function(keySession) {
         keySession.addEventListener("<a href="#dom-eventmessage">message</a>", licenseRequestReady, false);
+        return keySession.<a href="#dom-generaterequest">generateRequest</a>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize key session")
@@ -1762,11 +1729,11 @@
 
   // See the previous example for implementations of these functions.
   function selectKeySystem() { ... }
-  function createSession(mediaKeys, initDataType, initData) { ... }
+  function makeNewRequest(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>);
+    makeNewRequest(mediaKeys, event.<a href="#dom-initdatatype">initDataType</a>, event.<a href="#dom-initdata">initData</a>);
   }
 
   selectKeySystem();
@@ -1803,14 +1770,15 @@
   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 makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<a href="#dom-createsession">createSession</a>().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")
         );
+        return keySession.<a href="#dom-generaterequest">generateRequest</a>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize key session")
@@ -1890,8 +1858,8 @@
   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 makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<a href="#dom-createsession">createSession</a>("persistent").then(
       function(keySession) {
         keySession.addEventListener("<a href="#dom-eventmessage">message</a>", handleMessage, false);
         keySession.<a href="#dom-closed">closed</a>.then(
@@ -1900,6 +1868,7 @@
           }.bind(keySession)        
         );
         // Store keySession.<a href="#dom-sessionid">sessionId</a> in the application.
+        return keySession.<a href="#dom-generaterequest">generateRequest</a>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize a persistable key session")
@@ -1908,7 +1877,7 @@
 
   // 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(
+    mediaKeys.<a href="#dom-createsession">createSession</a>("persistent").then(
       function(keySession) {
         if (!keySession) {
           console.error("No stored session with the ID " + sessionId + " was found.");
@@ -1919,6 +1888,7 @@
         keySession.<a href="#dom-closed">closed</a>.then(
           console.log.bind(console, "Session closed")
         );
+        return keySession.<a href="#dom-load">load</a>(sessionId);
       }
     ).catch(
       console.error.bind(console, "Unable to load or initialize the stored session with the ID " + sessionId)
--- a/encrypted-media/encrypted-media.xml	Mon Aug 25 11:40:20 2014 -0700
+++ b/encrypted-media/encrypted-media.xml	Mon Aug 25 11:42:27 2014 -0700
@@ -255,7 +255,7 @@
     <h4 id="key-session">1.1.3. Key Session</h4>
     <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 <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.
+    Each Key session is associated with a single instance of <a href="#initialization-data">Initialization Data</a> provided in the <methodref>generateRequest</methodref> call.
     </p>
     <p>Each Key Session is associated with a single <coderef>MediaKeys</coderef> object, and only <a href="#media-element">media elements</a> associated with that object may access key(s) associated with the session.
     Other <coderef>MediaKeys</coderef> objects, <a href="#cdm">CDM</a> instances, and media elements may <em>not</em> access the key session or use its key(s).
@@ -277,7 +277,7 @@
     <p>Unless otherwise stated, key refers to a decryption key that can be used to decrypt blocks within <videoanchor name="media-data">media data</videoanchor>.
     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 <methodref>update</methodref> call. (They may later be loaded by <methodref>loadSession</methodref> as part of the stored session data.)
+    Such keys may only be provided to the <a href="#cdm">CDM</a> via an <methodref>update</methodref> call. (They may later be loaded by <methodref>load</methodref> 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>
@@ -346,7 +346,7 @@
 interface <precodedfn>MediaKeys</precodedfn> {
   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>createSession</premethodref>(optional <precoderef>SessionType</precoderef> sessionType = "<precoderef prefix="sessiontype">temporary</precoderef>");
   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,8 +361,8 @@
   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);
+  Promise&lt;void&gt; <premethodref>generateRequest</premethodref>(DOMString <a href="#initialization-data-type">initDataType</a>, (ArrayBuffer or ArrayBufferView) initData);
+  Promise&lt;bool&gt; <premethodref>load</premethodref>(DOMString sessionId);
 
   // session operations
   Promise&lt;void&gt; <premethodref>update</premethodref>((ArrayBuffer or ArrayBufferView) response);
@@ -419,7 +419,8 @@
     
     <p class="non-normative">Note: Support for clearing or replacing the associated <coderef>MediaKeys</coderef> 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 <methodref>setMediaKeys</methodref> before providing <videoanchor name="media-data">media data</videoanchor> (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, <coderef>MediaKeySession</coderef> objects created by <methodref>createSession</methodref> may not fire any events until the <coderef>MediaKeys</coderef> object is associated with a media element using <methodref>setMediaKeys</methodref>.</p>
+    <!-- TODO: Move to the MediaKeySession section when refactoring. -->
+    <p class="non-normative">Note: In some implementations, <coderef>MediaKeySession</coderef> objects may not fire any events until the <coderef>MediaKeys</coderef> object is associated with a media element using <methodref>setMediaKeys</methodref>.</p>
 
     <p>The <codedfn>onencrypted</codedfn> event handler for the <coderef>encrypted</coderef> event must be supported by all HTMLMediaElements as both a content attribute and an IDL attribute.</p>
 
@@ -453,51 +454,26 @@
 
     <p>The <codedfn>keySystem</codedfn> attribute identifies the <a href="#key-system">Key System</a> being used.</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>
+    <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> - This method may be changed to return the MediaKeySession object synchronously.</p></div>
+    <p>The <methoddfn name="createSession">createSession(<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>
 
     <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>
+              <li><p>Let the <coderef>sessionId</coderef> attribute be the empty string.</p></li>
+              <li><p>Let the <coderef>expiration</coderef> attribute be <code>NaN</code>.</p></li>
+              <li><p>Let the <coderef>closed</coderef> attribute be a new promise.</p></li>
+              <li><p>Let the <var title="true">session type</var> be <var title="true">sessionType</var>.</p></li>
+              <li><p>Let <var title="true">uninitialized</var> be true.</p></li>
+              <li><p>Let <var title="true">callable</var> be false.</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>
@@ -515,7 +491,7 @@
       <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 <methodref>create</methodref>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> during the <a href="#dom-create">initialization</a> of this object.</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><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>Resolve <var>promise</var>.</p></li>
@@ -616,81 +592,77 @@
     <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>The <methoddfn name="generateRequest">generateRequest(<var title="true">initDataType</var>, <var title="true">initData</var>)</methoddfn> method creates a new <coderef>MediaKeySession</coderef> 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: 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>.
+    <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>
 
     <ol>
+      <li><p>If this object's <var title="true">callable</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
+      <li><p>Let this object's <var title="true">uninitialized</var> be false.</p></li><!-- For simplicity and consistency, this object cannot be reused after any failure. -->
       <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 title="true">media keys</var> be the <coderef>MediaKeys</coderef> object that created this object.</p></li>
+      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to <var title="true">media keys</var>'s <coderef>keySystem</coderef> attribute does not support <var title="true">initDataType</var> as an <a href="#initialization-data-type">initialization data type</a>, 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>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 title="true">session type</var> be this object's <var title="true">session type</var>.</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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of <var title="true">media keys</var>.</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>
+              <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">session type</var>.</p>
+                <p>If <var title="true">session type</var> is "<coderef prefix="sessiontype">temporary</coderef>", the request is for a temporary non-persisted license.
+                If <var title="true">session type</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">session type</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>Set the <coderef>sessionId</coderef> attribute to 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 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>Add an entry for the value of the <coderef>sessionId</coderef> attribute to <var title="true">media keys</var>'s <var title="true">list of active session IDs</var>.</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>
+          <li><p>Let this object's <var title="true">callable</var> be true.</p></li>
+          <li><p>Resolve <var>promise</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>
+    <p>The <methoddfn name="load">load(<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>
+
     <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 this object's <var title="true">uninitialized</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
+      <li><p>Let this object's <var title="true">uninitialized</var> be false.</p></li><!-- For simplicity and consistency, this object cannot be reused after any failure. -->
       <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>If this object's <var title="true">session type</var> is not "<coderef prefix="sessiontype">persistent</coderef>", 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 title="true">media keys</var> be the <coderef>MediaKeys</coderef> object that created this object.</p></li>
+      <li><p>If the <a href="#cdm">content decryption module</a> corresponding to <var title="true">media keys</var>'s <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>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>
+          <li><p>If <var title="true">media keys</var>'s <var title="true">list of active session IDs</var> includes an entry for <var title="true">sessionId</var>, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-QuotaExceededError">"QuotaExceededError"</a></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>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of <var title="true">media keys</var>.</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>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>false</code>.</p></li><!-- 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>
+              <li><p>If the CDM needs to send a message:</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>
@@ -698,22 +670,16 @@
               </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>Set the <coderef>sessionId</coderef> 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><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>Add an entry for the value of the <coderef>sessionId</coderef> attribute to <var title="true">media keys</var>'s <var title="true">list of active session IDs</var>.</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>
+          <li><p>Let this object's <var title="true">callable</var> be true.</p></li>
+          <li><p>Resolve <var>promise</var> with <code>true</code>.</p></li>
         </ol>
       </li>
       <li><p>Return <var>promise</var>.</p></li>
@@ -723,12 +689,13 @@
     <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 this object's <var title="true">callable</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
       <li><p>If <var title="true">response</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>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>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <methodref>create</methodref>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <coderef>MediaKeys</coderef> object.</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>Use the <var title="true">cdm</var> to execute the following steps:</p>
@@ -775,11 +742,12 @@
     It must run the following steps:</p>
 
     <ol>
+      <li><p>If this object's <var title="true">callable</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</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 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 <methodref>create</methodref>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <coderef>MediaKeys</coderef> object.</p></li>
           <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
               <li>
@@ -799,19 +767,20 @@
     It must run the following steps:</p>
 
     <ol>
-      <li><p>If the session type is not "<coderef prefix="sessiontype">persistent</coderef>", 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 this object's <var title="true">callable</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidStateError">"InvalidStateError"</a></code>.</p></li>
+      <li><p>If this object's <var title="true">session type</var> is not "<coderef prefix="sessiontype">persistent</coderef>", 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 the <a href="#algorithms-session-close">Session Close</a> algorithm has been run on this object, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <methodref>create</methodref>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <coderef>MediaKeys</coderef> object.</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 <coderef>sessionId</coderef>, before proceeding to the next step.
-                  <span class="non-normative">(A subsequent call to <methodref>loadSession</methodref> with <coderef>sessionId</coderef> would fail because there is no data stored for the <var title="true">sessionId</var>.)</span>
+                  <span class="non-normative">(A subsequent call to <methodref>load</methodref> with <coderef>sessionId</coderef> would fail because there is no data stored for the <var title="true">sessionId</var>.)</span>
                 </p>
               </li>
             </ol>
@@ -831,10 +800,11 @@
     <p>The <methoddfn name="getUsableKeyIds">getUsableKeyIds()</methoddfn> 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 <videoanchor name="media-data">media data</videoanchor>. It must run the following steps:</p>
     
     <ol>
+      <li><p>If this object's <var title="true">callable</var> value is false, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></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 <methodref>create</methodref>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <coderef>MediaKeys</coderef> object.</p></li>
           <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
               <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 <videoanchor name="media-data">media data</videoanchor>. <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>
@@ -878,6 +848,8 @@
         <tr>
           <td><dfn id="dfn-InvalidStateError"><code>InvalidStateError</code></dfn></td>
           <td>The existing MediaKeys object cannot be removed at this time.<br/>
+            The session has already been used.<br/>
+            The session is not yet initialized.<br/>
             The session is closed.
           </td>
         </tr>
@@ -893,7 +865,9 @@
         </tr>
         <tr>
           <td><dfn id="dfn-QuotaExceededError"><code>QuotaExceededError</code></dfn></td>
-          <td>The MediaKeys object cannot be used with additional HTMLMediaElements.</td>
+          <td>The MediaKeys object cannot be used with additional HTMLMediaElements.<br/>
+            A non-closed session already exists for this sessionId.
+          </td>
         </tr>
       </tbody>
     </table>
@@ -1009,7 +983,7 @@
           <td><coderef>MediaKeyMessageEvent</coderef></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 license request has been generated as the result of a <methodref>createSession</methodref> call or another message must be sent in response to an <methodref>update</methodref> call.</span>
+            <span class="non-normative">For example, a license request has been generated as the result of a <methodref>generateRequest</methodref> call or another message must be sent in response to an <methodref>update</methodref> call.</span>
           </td>
         </tr>
       </tbody>
@@ -1052,7 +1026,7 @@
       <li><p>If the media element's <coderef prefix="attr">mediaKeys</coderef> attribute is not null, run the following steps:</p>
         <ol>
           <li><p>Let <var title="true">media keys</var> be the <coderef>MediaKeys</coderef> 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-create">initialization</a> of the <var title="true">media keys</var>.</p></li>
+          <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <var title="true">media keys</var>.</p></li>
           <li><p>If there is at least one <coderef>MediaKeySession</coderef> 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>
@@ -1193,7 +1167,8 @@
     <p>The following steps are run:</p>
     <ol>
       <li><p>Let the <var title="true">session</var> be the associated <coderef>MediaKeySession</coderef> object.</p></li>
-      <li><p>Remove the entry for the value of the <var title="true">session</var>'s <coderef>sessionId</coderef> 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 title="true">media keys</var> be the <coderef>MediaKeys</coderef> object that created this object.</p></li>
+      <li><p>Remove the entry for the value of the <var title="true">session</var>'s <coderef>sessionId</coderef> attribute from <var title="true">media keys</var>'s <var title="true">list of active session IDs</var>.</p></li>
       <li><p>Let <var>promise</var> be the <coderef>closed</coderef> attribute of the <var title="true">session</var>.</p></li>
       <li><p>Resolve <var>promise</var>.</p></li>
     </ol>
@@ -1254,13 +1229,13 @@
       <li><p>The <methodref>setMediaKeys</methodref> method: Implementations may support associating the <coderef>MediaKeys</coderef> object with more than one <coderef>HTMLMediaElement</coderef>.</p></li>
       <li><p>The <methodref>setServerCertificate</methodref> method: Not supported.</p></li>
       <li><p>The <methodref>isTypeSupported</methodref> method: There are no supported <var title="true">capability</var> values.</p></li>
-      <li><p>The "<coderef prefix="sessiontype">persistent</coderef>" <coderef>SessionType</coderef>, including the <methodref>loadSession</methodref> and <methodref>remove</methodref> methods: Implementations may support these.</p></li>
+      <li><p>The "<coderef prefix="sessiontype">persistent</coderef>" <coderef>SessionType</coderef>: 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 <methodref>createSession</methodref> algorithm:</p>
+      <li><p>In the <methodref>generateRequest</methodref> 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>
@@ -1369,7 +1344,7 @@
     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 <methodref>createSession</methodref>.
+    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 <methodref>generateRequest</methodref>.
     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.
@@ -1543,14 +1518,15 @@
       promise.then(
         function(createdMediaKeys) {
           var initData = new Uint8Array([ ... ]);
-          return createdMediaKeys.<premethodref>createSession</premethodref>("webm", initData);
+          return createdMediaKeys.<premethodref>createSession</premethodref>();
         }
       ).then(
         function(keySession) {
           keySession.addEventListener("<precoderef prefix="event">message</precoderef>", handleMessage, false);
+          return keySession.<premethodref>generateRequest</premethodref>("webm", initData);
         }
       ).catch(
-        console.error.bind(console, "Unable to create key session")
+        console.error.bind(console, "Unable to create or initialize key session")
       );
     }
   }
@@ -1610,7 +1586,7 @@
 
           for (var i = 0; i &lt; video.pendingSessionData.length; i++) {
             var data = video.pendingSessionData[i];
-            createSession(video.mediaKeysObject, data.initDataType, data.initData);
+            makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData);
           }
           video.pendingSessionData = [];
 
@@ -1625,16 +1601,17 @@
 
   function addSession(video, initDataType, initData) {
     if (video.mediaKeysObject) {
-      createSession(video.mediaKeysObject, initDataType, initData);
+      makeNewRequest(video.mediaKeysObject, initDataType, initData);
     } else {
       video.pendingSessionData.push({initDataType: initDataType, initData: initData});
     }
   }
 
-  function createSession(mediaKeys, initDataType, initData) {
-    mediaKeys.<premethodref>createSession</premethodref>(initDataType, initData).then(
+  function makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<premethodref>createSession</premethodref>().then(
       function(keySession) {
         keySession.addEventListener("<precoderef prefix="event">message</precoderef>", licenseRequestReady, false);
+        return keySession.<premethodref>generateRequest</premethodref>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize key session")
@@ -1677,11 +1654,11 @@
 
   // See the previous example for implementations of these functions.
   function selectKeySystem() { ... }
-  function createSession(mediaKeys, initDataType, initData) { ... }
+  function makeNewRequest(mediaKeys, initDataType, initData) { ... }
   function licenseRequestReady(event) { ... }
 
   function handleInitData(event) {
-    createSession(mediaKeys, event.<precoderef>initDataType</precoderef>, event.<precoderef>initData</precoderef>);
+    makeNewRequest(mediaKeys, event.<precoderef>initDataType</precoderef>, event.<precoderef>initData</precoderef>);
   }
 
   selectKeySystem();
@@ -1718,14 +1695,15 @@
   function handleInitData(event) { ... }
 
   // This replaces the implementation in the previous example.
-  function createSession(mediaKeys, initDataType, initData) {
-    mediaKeys.<premethodref>createSession</premethodref>(initDataType, initData).then(
+  function makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<premethodref>createSession</premethodref>().then(
       function(keySession) {
         keySession.addEventListener("<precoderef prefix="event">message</precoderef>", handleMessage, false);
         keySession.addEventListener("<precoderef prefix="event">keyschange</precoderef>", handleKeysChange, false);
         keySession.<precoderef>closed</precoderef>.then(
           console.log.bind(console, "Session closed")
         );
+        return keySession.<premethodref>generateRequest</premethodref>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize key session")
@@ -1807,8 +1785,8 @@
   function handleError(event) { ... }
 
   // Called if the application does not have a stored sessionId for the media resource.
-  function createSession(mediaKeys, initDataType, initData) {
-    mediaKeys.<premethodref>createSession</premethodref>(initDataType, initData, "persistent").then(
+  function makeNewRequest(mediaKeys, initDataType, initData) {
+    mediaKeys.<premethodref>createSession</premethodref>("persistent").then(
       function(keySession) {
         keySession.addEventListener("<precoderef prefix="event">message</precoderef>", handleMessage, false);
         keySession.<precoderef>closed</precoderef>.then(
@@ -1817,6 +1795,7 @@
           }.bind(keySession)        
         );
         // Store keySession.<precoderef>sessionId</precoderef> in the application.
+        return keySession.<premethodref>generateRequest</premethodref>(initDataType, initData);
       }
     ).catch(
       console.error.bind(console, "Unable to create or initialize a persistable key session")
@@ -1825,7 +1804,7 @@
 
   // Called if the application has a stored sessionId for the media resource.
   function loadStoredSession(mediaKeys, sessionId) {
-    mediaKeys.<premethodref>loadSession</premethodref>(sessionId).then(
+    mediaKeys.<premethodref>createSession</premethodref>("persistent").then(
       function(keySession) {
         if (!keySession) {
           console.error("No stored session with the ID " + sessionId + " was found.");
@@ -1836,6 +1815,7 @@
         keySession.<precoderef>closed</precoderef>.then(
           console.log.bind(console, "Session closed")
         );
+        return keySession.<premethodref>load</premethodref>(sessionId);
       }
     ).catch(
       console.error.bind(console, "Unable to load or initialize the stored session with the ID " + sessionId)