Bug 21854 - Define MediaKeySession life cycle states and/or events
authorAdrian Bateman <adrianba@microsoft.com>
Mon, 16 Sep 2013 22:09:35 -0700
changeset 155 83629aec22e1
parent 154 6fad6f186ce4
child 156 e9e9690472e0
Bug 21854 - Define MediaKeySession life cycle states and/or events
encrypted-media/encrypted-media.html
encrypted-media/encrypted-media.xml
encrypted-media/session_state.svg
encrypted-media/spec-html.xsl
--- a/encrypted-media/encrypted-media.html	Tue Aug 27 08:57:20 2013 -0700
+++ b/encrypted-media/encrypted-media.html	Mon Sep 16 22:09:35 2013 -0700
@@ -57,7 +57,7 @@
     <div class="head">
       <p><a href="http://www.w3.org/"><img src="https://www.w3.org/Icons/w3c_home" alt="W3C" width="72" height="48"></a></p>
       <h1>Encrypted Media Extensions</h1>
-      <h2 id="draft-date">W3C Editor's Draft 27 August 2013</h2>
+      <h2 id="draft-date">W3C Editor's Draft 16 September 2013</h2>
       <dl>
         <dt>This Version:</dt>
         <dd><a href="http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html">http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html</a></dd>
@@ -138,7 +138,8 @@
       <li><a href="#extensions">2. Media Element Extensions</a></li>
         <li><ul style="list-style-type:none">
           <li><a href="#error-codes">2.1. Error Codes</a></li>
-          <li><a href="#media-element-restictions">2.2. Media Element Restrictions</a></li>
+          <li><a href="#session-state">2.2. MediaKeySession States</a></li>
+          <li><a href="#media-element-restictions">2.3. Media Element Restrictions</a></li>
         </ul></li>
       <li><a href="#events">3. Events</a></li>
         <li><ul style="list-style-type:none">
@@ -308,7 +309,7 @@
     
     <ol>
       <li>
-<p>If loading has not started, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code> exception and abort these steps.</p>
+<p>If loading has not started, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p>
       <p class="non-normative">In general, applications should wait for an event named <code><a href="#dom-needkey">needkey</a></code> or <code><a href="http://www.w3.org/TR/html5/embedded-content-0.html#event-media-loadstart">loadstart</a></code> (per the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#concept-media-load-resource">resource fetch algorithm</a>) before calling this method.</p>
       </li>
       <li><p>If the <code><a href="#dom-mediakeys">MediaKeys</a></code> object is already in use and the user agent is unable to re-use it with this element, throw a <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-quota_exceeded_err">QUOTA_EXCEEDED_ERR</a></code> exception and abort these steps.</p></li>
@@ -322,7 +323,7 @@
     <p>The <dfn id="dom-media-keys-constructor"><code>MediaKeys(<var title="true">keySystem</var>)</code></dfn> constructor must run the following steps:</p>
 
     <ol>
-      <li><p>If <var title="true">keySystem</var> is null or an empty string, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code> exception and abort these steps.</p></li>
+      <li><p>If <var title="true">keySystem</var> is null or an empty string, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code> exception and abort these steps.</p></li>
 
       <li><p>If <var title="true">keySystem</var> is not one of the user agent's supported <a href="#key-system">Key Systems</a>, throw a <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-not_supported_err">NOT_SUPPORTED_ERR</a></code> and abort these steps. Key system string comparison is case-sensitive.</p></li>
 
@@ -376,6 +377,7 @@
         <ol>
           <li><p>Let the <code><a href="#dom-keysystem">keySystem</a></code> attribute be <var title="true">keySystem</var>.</p></li>
           <li><p>Let the <code><a href="#dom-sessionid">sessionId</a></code> attribute be a unique <a href="#session-id">Session ID</a> string. <span class="non-normative">It may be generated by <var title="true">cdm</var>.</span></p></li>
+          <li><p>Let the state of the session be <code><a href="#dom-created">CREATED</a></code>.</p></li>
         </ol>
       </li>
       
@@ -394,7 +396,7 @@
               <dd>
               <ol>
                 <li>
-<p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided.</p>
+<p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided. The <var title="true">key request</var> may be empty if the <a href="#cdm">CDM</a> does not need a message exchange.</p>
                   <p>Note: <var title="true">cdm</var> must not use any stream-specific data, including <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a>, not provided via <var title="true">initData</var>.</p>
                   <p class="non-normative"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
                 </li>
@@ -411,19 +413,38 @@
                   </li></ul>
                 </li>
                 <li><p>Set the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object's <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
+                <li><p>Let the state of the session be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
                 <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keyerror">keyerror</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
                 <li><p>Abort the task.</p></li>
               </ol></dd>
             </dl>
           </li>
           <li>
-<p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keymessage">keymessage</a></code> at the new object</p>
-            <p>The event is of type <code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code> and has:</p>
-            <ul style="list-style-type:none"><li>
-              <code><a href="#dom-message">message</a></code> = <var title="true">key request</var><br>
-              <code><a href="#dom-destinationurl">destinationURL</a></code> = <var title="true">defaultURL</var>
-            </li></ul>
-            <p class="non-normative">Note: <code><a href="#dom-message">message</a></code> may be a request for multiple keys, depending on the <var title="true"><a href="#key-system">keySystem</a></var> and/or <var title="true">initData</var>. This is transparent to the application.</p>
+<p>Follow the steps for the first matching condition from the following list:</p>
+            <dl class="switch">
+              <dt>If the <var title="true">key request</var> is not empty</dt>
+              <dd>
+                <ol>
+                  <li><p>Let the state of the session be <code><a href="#dom-pending">PENDING</a></code>.</p></li>
+                  <li>
+                    <p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keymessage">keymessage</a></code> at the new object.</p>
+                    <p>The event is of type <code><a href="#dom-mediakeymessageevent">MediaKeyMessageEvent</a></code> and has:</p>
+                    <ul style="list-style-type:none"><li>
+                      <code><a href="#dom-message">message</a></code> = <var title="true">key request</var><br>
+                      <code><a href="#dom-destinationurl">destinationURL</a></code> = <var title="true">defaultURL</var>
+                    </li></ul>
+                    <p class="non-normative">Note: <code><a href="#dom-message">message</a></code> may be a request for multiple keys, depending on the <var title="true"><a href="#key-system">keySystem</a></var> and/or <var title="true">initData</var>. This is transparent to the application.</p>                
+                  </li>
+                </ol>
+              </dd>
+              <dt>If the <var title="true">key request</var> is empty</dt>
+              <dd>
+                <ol>
+                  <li><p>Let the state of the session be <code><a href="#dom-ready">READY</a></code>.</p></li>
+                  <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keyready">keyready</a></code> at the new object.</p></li>
+                </ol>
+              </dd>
+            </dl>
           </li>
         </ol>
       </li>
@@ -463,7 +484,8 @@
     The contents may also vary depending on the container, key length, etc.</p>
 
     <ol>
-      <li><p>If the argument is null or an empty array, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code>.</p></li>
+      <li><p>If the argument is null or an empty array, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_state_err">INVALID_STATE_ERR</a></code>.</p></li>
+      <li><p>If the session is not in the <code><a href="#dom-pending">PENDING</a></code> state, throw an <code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_access_err">INVALID_ACCESS_ERR</a></code>.</p></li>
 
       <li>
 <p>Schedule a task to handle the call, providing <var title="true">key</var>.</p>
@@ -509,6 +531,7 @@
                <code><a href="#dom-destinationurl">destinationURL</a></code> = null
              </li></ul>
           </li>
+          <li><p>If <var title="true">next message</var> is null, let the state of the session be <code><a href="#dom-ready">READY</a></code> and <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keyready">keyready</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
           <li><p>If <var title="true">did store key</var> is true, <a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keyadded">keyadded</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
           <li>
 <p><i>Error</i>: If any of the preceding steps in the task failed</p>
@@ -521,6 +544,7 @@
                   </li></ul>
                 </li>
                 <li><p>Set the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object's <code><a href="#dom-error">error</a></code> attribute to the error object created in the previous step.</p></li>
+                <li><p>Let the state of the session be <code><a href="#dom-stateerror">ERROR</a></code>.</p></li>
                 <li><p><a href="http://www.w3.org/TR/html5/webappapis.html#queue-a-task">queue a task</a> to <a href="http://www.w3.org/TR/html5/webappapis.html#fire-a-simple-event">fire a simple event</a> named <code><a href="#dom-keyerror">keyerror</a></code> at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object.</p></li>
                 <li><p>Abort the task.</p></li>
               </ol>
@@ -628,8 +652,46 @@
     It should be 0 if there is no associated status code or such status codes are not supported by the Key System.
     </p>
     </div>
+
+    <h3 id="session-state">2.3 MediaKeySession States</h3>
+    <p><i>This section is non-normative.</i></p>
+    <p>Each <code><a href="#dom-mediakeysession">MediaKeySession</a></code> maintains an internal state that determines what events may be fired.</p>
+    <h4 id="session-state-list">2.3.1 MediaKeySession State Definitions</h4>
+    <p>The following table describes the possible states:</p>
     
-    <h3 id="media-element-restictions">2.2 Media Element Restrictions</h3>
+    <table>
+      <thead>
+        <tr>
+          <th>State name</th>
+          <th>Description</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td><dfn id="dom-created"><code>CREATED</code></dfn></td>
+          <td>The <code><a href="#dom-mediakeysession">MediaKeySession</a></code> has been created with a <code><a href="#dom-createsession">createSession()</a></code> call.</td>
+        </tr>
+        <tr>
+          <td><dfn id="dom-pending"><code>PENDING</code></dfn></td>
+          <td>A <code><a href="#dom-keymessage">keymessage</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. A call to <code><a href="#dom-update__">update()()</a></code> is expected next. The <a href="#media-element">media element</a> may block waiting for a key if encrypted data is encountered.</td>
+        </tr>
+        <tr>
+          <td><dfn id="dom-ready"><code>READY</code></dfn></td>
+          <td>A <code><a href="#dom-keyready">keyready</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. The <a href="#media-element">media element</a> should not need to block waiting for a key if encrypted data associated with this session is encountered.</td>
+        </tr>
+        <tr>
+          <td><dfn id="dom-stateerror"><code>ERROR</code></dfn></td>
+          <td>A <code><a href="#dom-keyerror">keyerror</a></code> event has been fired at the <code><a href="#dom-mediakeysession">MediaKeySession</a></code>. The <code><a href="#dom-error">error</a></code> attribute of the session holds information about the most recent error.</td>
+        </tr>
+      </tbody>
+    </table>
+    
+    
+    <h4 id="session-state-transitions">2.3.2 MediaKeySession State Transitions</h4>
+    <p>The following diagram shows the possible state transitions and the events fired when changing state:</p>
+    <p><img src="session_state.svg" width="528" height="408" alt="State transition diagram"></p>
+    
+    <h3 id="media-element-restictions">2.3 Media Element Restrictions</h3>
     <p><i>This section is non-normative.</i></p>
     <p>Media data processed by a CDM may not be available through Javascript APIs in the usual way (for example using the CanvasRenderingContext2D drawImage() method and the AudioContext MediaElementAudioSourceNode).
     This specification does not define conditions for such non-availability of media data, however, if media data is not available to Javascript APIs then these APIs may behave as if no media data was present at all.</p>
@@ -724,7 +786,7 @@
         <tr>
           <td><dfn id="dom-keyerror"><code>keyerror</code></dfn></td>
           <td><code><a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#event">Event</a></code></td>
-          <td>An error occurs in the session.</td>
+          <td>An error occurs in the session. The session moves to the <code><a href="#dom-stateerror">ERROR</a></code> state.</td>
           <td></td>
         </tr>
         <tr>
@@ -733,6 +795,15 @@
           <td>
             A message has been generated <span class="non-normative">(and likely needs to be sent to a server)</span>.
             <span class="non-normative">For example, a key request has been generated as the result of a <code><a href="#dom-createsession">createSession()</a></code> call or another message must be sent in response to an <code><a href="#dom-update">update()</a></code> call.</span>
+            The session moves to the <code><a href="#dom-pending">PENDING</a></code> state.
+          </td>
+          <td></td>
+        </tr>
+        <tr>
+          <td><dfn id="dom-keyready"><code>keyready</code></dfn></td>
+          <td><code><a href="#dom-event">Event</a></code></td>
+          <td>
+            The media element should not be blocked if encrypted data is encountered associated with the initData used to create the session. The session moves to the <code><a href="#dom-ready">READY</a></code> state.
           </td>
           <td></td>
         </tr>
@@ -1301,7 +1372,7 @@
     sendMessage(message, keySession);
   }
 
-  function handleKeyComplete(event) {
+  function handleKeyReady(event) {
     // Do some bookkeeping with event.target.<a href="#dom-sessionid">sessionId</a> if necessary.
   }
 
@@ -1326,7 +1397,7 @@
       throw "Could not create key session";
 
     keySession.addEventListener("<a href="#dom-keymessage">keymessage</a>",handleKeyMessage,false);
-    keySession.addEventListener("<a href="#dom-keyadded">keyadded</a>",handleKeyComplete,false);
+    keySession.addEventListener("<a href="#dom-keyready">keyready</a>",handleKeyReady,false);
     keySession.addEventListener("<a href="#dom-keyerror">keyerror</a>",handleKeyError,false);
   }
 &lt;/script&gt;
--- a/encrypted-media/encrypted-media.xml	Tue Aug 27 08:57:20 2013 -0700
+++ b/encrypted-media/encrypted-media.xml	Mon Sep 16 22:09:35 2013 -0700
@@ -56,7 +56,7 @@
     <div class="head">
       <p><a href="http://www.w3.org/"><img src="https://www.w3.org/Icons/w3c_home" alt="W3C" width="72" height="48" /></a></p>
       <h1>Encrypted Media Extensions</h1>
-      <h2 id="draft-date">W3C Editor's Draft 27 August 2013</h2>
+      <h2 id="draft-date">W3C Editor's Draft 16 September 2013</h2>
       <dl>
         <dt>This Version:</dt>
         <dd><a href="http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html">http://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html</a></dd>
@@ -135,7 +135,8 @@
       <li><a href="#extensions">2. Media Element Extensions</a></li>
         <li><ul style="list-style-type:none">
           <li><a href="#error-codes">2.1. Error Codes</a></li>
-          <li><a href="#media-element-restictions">2.2. Media Element Restrictions</a></li>
+          <li><a href="#session-state">2.2. MediaKeySession States</a></li>
+          <li><a href="#media-element-restictions">2.3. Media Element Restrictions</a></li>
         </ul></li>
       <li><a href="#events">3. Events</a></li>
         <li><ul style="list-style-type:none">
@@ -366,6 +367,7 @@
         <ol>
           <li><p>Let the <coderef>keySystem</coderef> attribute be <var title="true">keySystem</var>.</p></li>
           <li><p>Let the <coderef>sessionId</coderef> attribute be a unique <a href="#session-id">Session ID</a> string. <span class="non-normative">It may be generated by <var title="true">cdm</var>.</span></p></li>
+          <li><p>Let the state of the session be <coderef>CREATED</coderef>.</p></li>
         </ol>
       </li>
       
@@ -380,7 +382,7 @@
               <dt>If a request is successfully generated and the <videoanchor name="media-data">media data</videoanchor> is <cors-same-origin/></dt>
               <dd>
               <ol>
-                <li><p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided.</p>
+                <li><p>Let <var title="true">key request</var> be a key request generated by the <a href="#cdm">CDM</a> using <var title="true">initData</var>, if provided. The <var title="true">key request</var> may be empty if the <a href="#cdm">CDM</a> does not need a message exchange.</p>
                   <p>Note: <var title="true">cdm</var> must not use any stream-specific data, including <videoanchor name="media-data">media data</videoanchor>, not provided via <var title="true">initData</var>.</p>
                   <p class="non-normative"><var title="true">type</var> may be used to determine how to interpret <var title="true">initData</var>.</p>
                 </li>
@@ -396,18 +398,37 @@
                   </li></ul>
                 </li>
                 <li><p>Set the <coderef>MediaKeySession</coderef> object's <coderef>error</coderef> attribute to the error object created in the previous step.</p></li>
+                <li><p>Let the state of the session be <coderef prefix="state">ERROR</coderef>.</p></li>
                 <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keyerror</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
                 <li><p>Abort the task.</p></li>
               </ol></dd>
             </dl>
           </li>
-          <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keymessage</coderef> at the new object</p>
-            <p>The event is of type <coderef>MediaKeyMessageEvent</coderef> and has:</p>
-            <ul style="list-style-type:none"><li>
-              <coderef>message</coderef> = <var title="true">key request</var><br></br>
-              <coderef>destinationURL</coderef> = <var title="true">defaultURL</var>
-            </li></ul>
-            <p class="non-normative">Note: <coderef>message</coderef> may be a request for multiple keys, depending on the <var title="true"><a href="#key-system">keySystem</a></var> and/or <var title="true">initData</var>. This is transparent to the application.</p>
+          <li><p>Follow the steps for the first matching condition from the following list:</p>
+            <dl class="switch">
+              <dt>If the <var title="true">key request</var> is not empty</dt>
+              <dd>
+                <ol>
+                  <li><p>Let the state of the session be <coderef>PENDING</coderef>.</p></li>
+                  <li>
+                    <p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keymessage</coderef> at the new object.</p>
+                    <p>The event is of type <coderef>MediaKeyMessageEvent</coderef> and has:</p>
+                    <ul style="list-style-type:none"><li>
+                      <coderef>message</coderef> = <var title="true">key request</var><br></br>
+                      <coderef>destinationURL</coderef> = <var title="true">defaultURL</var>
+                    </li></ul>
+                    <p class="non-normative">Note: <coderef>message</coderef> may be a request for multiple keys, depending on the <var title="true"><a href="#key-system">keySystem</a></var> and/or <var title="true">initData</var>. This is transparent to the application.</p>                
+                  </li>
+                </ol>
+              </dd>
+              <dt>If the <var title="true">key request</var> is empty</dt>
+              <dd>
+                <ol>
+                  <li><p>Let the state of the session be <coderef>READY</coderef>.</p></li>
+                  <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keyready</coderef> at the new object.</p></li>
+                </ol>
+              </dd>
+            </dl>
           </li>
         </ol>
       </li>
@@ -448,6 +469,7 @@
 
     <ol>
       <li><p>If the argument is null or an empty array, throw an <invalid-access-err/>.</p></li>
+      <li><p>If the session is not in the <coderef>PENDING</coderef> state, throw an <invalid-state-err/>.</p></li>
 
       <li><p>Schedule a task to handle the call, providing <var title="true">key</var>.</p>
         <p>The user agent will asynchronously execute the following steps in the task:</p>
@@ -488,6 +510,7 @@
                <coderef>destinationURL</coderef> = null
              </li></ul>
           </li>
+          <li><p>If <var title="true">next message</var> is null, let the state of the session be <coderef>READY</coderef> and <queue-a-task/> to <fire-a-simple-event/> named <coderef>keyready</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
           <li><p>If <var title="true">did store key</var> is true, <queue-a-task/> to <fire-a-simple-event/> named <coderef>keyadded</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
           <li><p><i>Error</i>: If any of the preceding steps in the task failed</p>
               <ol>
@@ -498,6 +521,7 @@
                   </li></ul>
                 </li>
                 <li><p>Set the <coderef>MediaKeySession</coderef> object's <coderef>error</coderef> attribute to the error object created in the previous step.</p></li>
+                <li><p>Let the state of the session be <coderef prefix="state">ERROR</coderef>.</p></li>
                 <li><p><queue-a-task/> to <fire-a-simple-event/> named <coderef>keyerror</coderef> at the <coderef>MediaKeySession</coderef> object.</p></li>
                 <li><p>Abort the task.</p></li>
               </ol>
@@ -590,8 +614,46 @@
     It should be 0 if there is no associated status code or such status codes are not supported by the Key System.
     </p>
     </div>
+
+    <h3 id="session-state">2.3 MediaKeySession States</h3>
+    <non-normative-section/>
+    <p>Each <coderef>MediaKeySession</coderef> maintains an internal state that determines what events may be fired.</p>
+    <h4 id="session-state-list">2.3.1 MediaKeySession State Definitions</h4>
+    <p>The following table describes the possible states:</p>
     
-    <h3 id="media-element-restictions">2.2 Media Element Restrictions</h3>
+    <table>
+      <thead>
+        <tr>
+          <th>State name</th>
+          <th>Description</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td><codedfn>CREATED</codedfn></td>
+          <td>The <coderef>MediaKeySession</coderef> has been created with a <methodref>createSession</methodref> call.</td>
+        </tr>
+        <tr>
+          <td><codedfn>PENDING</codedfn></td>
+          <td>A <coderef>keymessage</coderef> event has been fired at the <coderef>MediaKeySession</coderef>. A call to <methodref>update()</methodref> is expected next. The <a href="#media-element">media element</a> may block waiting for a key if encrypted data is encountered.</td>
+        </tr>
+        <tr>
+          <td><codedfn>READY</codedfn></td>
+          <td>A <coderef>keyready</coderef> event has been fired at the <coderef>MediaKeySession</coderef>. The <a href="#media-element">media element</a> should not need to block waiting for a key if encrypted data associated with this session is encountered.</td>
+        </tr>
+        <tr>
+          <td><codedfn prefix="state">ERROR</codedfn></td>
+          <td>A <coderef>keyerror</coderef> event has been fired at the <coderef>MediaKeySession</coderef>. The <coderef>error</coderef> attribute of the session holds information about the most recent error.</td>
+        </tr>
+      </tbody>
+    </table>
+    
+    
+    <h4 id="session-state-transitions">2.3.2 MediaKeySession State Transitions</h4>
+    <p>The following diagram shows the possible state transitions and the events fired when changing state:</p>
+    <p><img src="session_state.svg" width="528" height="408" alt="State transition diagram"/></p>
+    
+    <h3 id="media-element-restictions">2.3 Media Element Restrictions</h3>
     <non-normative-section/>
     <p>Media data processed by a CDM may not be available through Javascript APIs in the usual way (for example using the CanvasRenderingContext2D drawImage() method and the AudioContext MediaElementAudioSourceNode).
     This specification does not define conditions for such non-availability of media data, however, if media data is not available to Javascript APIs then these APIs may behave as if no media data was present at all.</p>
@@ -678,7 +740,7 @@
         <tr>
           <td><codedfn>keyerror</codedfn></td>
           <td><code><dom4ref name="event">Event</dom4ref></code></td>
-          <td>An error occurs in the session.</td>
+          <td>An error occurs in the session. The session moves to the <coderef prefix="state">ERROR</coderef> state.</td>
           <td><!-- No Preconditions. --></td>
         </tr>
         <tr>
@@ -687,6 +749,15 @@
           <td>
             A message has been generated <span class="non-normative">(and likely needs to be sent to a server)</span>.
             <span class="non-normative">For example, a key request has been generated as the result of a <methodref>createSession</methodref> call or another message must be sent in response to an <methodref>update</methodref> call.</span>
+            The session moves to the <coderef>PENDING</coderef> state.
+          </td>
+          <td><!-- No Preconditions. --></td>
+        </tr>
+        <tr>
+          <td><codedfn>keyready</codedfn></td>
+          <td><coderef>Event</coderef></td>
+          <td>
+            The media element should not be blocked if encrypted data is encountered associated with the initData used to create the session. The session moves to the <coderef>READY</coderef> state.
           </td>
           <td><!-- No Preconditions. --></td>
         </tr>
@@ -1238,7 +1309,7 @@
     sendMessage(message, keySession);
   }
 
-  function handleKeyComplete(event) {
+  function handleKeyReady(event) {
     // Do some bookkeeping with event.target.<precoderef>sessionId</precoderef> if necessary.
   }
 
@@ -1263,7 +1334,7 @@
       throw "Could not create key session";
 
     keySession.addEventListener("<precoderef>keymessage</precoderef>",handleKeyMessage,false);
-    keySession.addEventListener("<precoderef>keyadded</precoderef>",handleKeyComplete,false);
+    keySession.addEventListener("<precoderef>keyready</precoderef>",handleKeyReady,false);
     keySession.addEventListener("<precoderef>keyerror</precoderef>",handleKeyError,false);
   }
 &lt;/script&gt;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/encrypted-media/session_state.svg	Mon Sep 16 22:09:35 2013 -0700
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by Microsoft Visio, SVG Export SessionState.svg Page-1 -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+		width="11in" height="8.5in" viewBox="0 0 792 612" xml:space="preserve" color-interpolation-filters="sRGB" class="st11">
+	<style type="text/css">
+	<![CDATA[
+		.st1 {visibility:visible}
+		.st2 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
+		.st3 {fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25}
+		.st4 {fill:#feffff;font-family:Calibri;font-size:1.5em}
+		.st5 {marker-end:url(#mrkr4-24);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.5}
+		.st6 {fill:#5b9bd5;fill-opacity:1;stroke:#5b9bd5;stroke-opacity:1;stroke-width:0.64102564102564}
+		.st7 {fill:#ffffff;stroke:none;stroke-linecap:butt;stroke-width:7.2}
+		.st8 {fill:#4f87bb;font-family:Calibri;font-size:1.5em}
+		.st9 {marker-start:url(#mrkr4-66);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.5}
+		.st10 {fill:#4f88bb;font-family:Calibri;font-size:1.5em}
+		.st11 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+	]]>
+	</style>
+
+	<defs id="Markers">
+		<g id="lend4">
+			<path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/>
+		</g>
+		<marker id="mrkr4-24" class="st6" refX="-3.12" orient="auto" markerUnits="strokeWidth" overflow="visible">
+			<use xlink:href="#lend4" transform="scale(-1.56,-1.56) "/>
+		</marker>
+		<marker id="mrkr4-66" class="st6" refX="3.04" orient="auto" markerUnits="strokeWidth" overflow="visible">
+			<use xlink:href="#lend4" transform="scale(1.56) "/>
+		</marker>
+	</defs>
+	<defs id="Filters">
+		<filter id="filter_2">
+			<feGaussianBlur stdDeviation="2"/>
+		</filter>
+	</defs>
+	<g>
+		<title>Page-1</title>
+		<g id="shape21-1" transform="translate(324,-463.5)">
+			<title>Square</title>
+			<desc>CREATED</desc>
+			<g id="shadow21-2" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+				<rect x="0" y="504" width="108" height="108" class="st2"/>
+			</g>
+			<rect x="0" y="504" width="108" height="108" class="st3"/>
+			<text x="20.4" y="563.4" class="st4">CREATED</text>		</g>
+		<g id="shape22-7" transform="translate(324,-261)">
+			<title>Square.22</title>
+			<desc>PENDING</desc>
+			<g id="shadow22-8" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+				<rect x="0" y="504" width="108" height="108" class="st2"/>
+			</g>
+			<rect x="0" y="504" width="108" height="108" class="st3"/>
+			<text x="19.85" y="563.4" class="st4">PENDING</text>		</g>
+		<g id="shape24-13" transform="translate(324,-54)">
+			<title>Square.24</title>
+			<desc>READY</desc>
+			<g id="shadow24-14" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+				<rect x="0" y="504" width="108" height="108" class="st2"/>
+			</g>
+			<rect x="0" y="504" width="108" height="108" class="st3"/>
+			<text x="29.59" y="563.4" class="st4">READY</text>		</g>
+		<g id="shape8-19" transform="translate(423,-517.5)">
+			<title>Dynamic connector</title>
+			<desc>KEYREADY</desc>
+			<path d="M9 612 L180 612 L180 1021.5 L23.04 1021.5" class="st5"/>
+			<rect x="142.132" y="805.95" width="75.7354" height="21.5999" class="st7"/>
+			<text x="142.13" y="822.15" class="st8">KEYREADY</text>		</g>
+		<g id="shape10-27" transform="translate(369,-463.5)">
+			<title>Dynamic connector.10</title>
+			<desc>KEYMESSAGE</desc>
+			<path d="M9 612 L9 692.46" class="st5"/>
+			<rect x="-40.0957" y="648.45" width="98.1914" height="21.5999" class="st7"/>
+			<text x="-40.1" y="664.65" class="st8">KEYMESSAGE</text>		</g>
+		<g id="shape23-34" transform="translate(72,-261)">
+			<title>Square.23</title>
+			<desc>ERROR</desc>
+			<g id="shadow23-35" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+				<rect x="0" y="504" width="108" height="108" class="st2"/>
+			</g>
+			<rect x="0" y="504" width="108" height="108" class="st3"/>
+			<text x="28.99" y="563.4" class="st4">ERROR</text>		</g>
+		<g id="shape13-40" transform="translate(324,-517.5)">
+			<title>Dynamic connector.13</title>
+			<desc>KEYERROR</desc>
+			<path d="M0 612 L-198 612 L-198 746.46" class="st5"/>
+			<rect x="-211.72" y="601.2" width="76.9395" height="21.5999" class="st7"/>
+			<text x="-211.72" y="617.4" class="st8">KEYERROR</text>		</g>
+		<g id="shape14-47" transform="translate(324,-306)">
+			<title>Dynamic connector.14</title>
+			<desc>KEYERROR</desc>
+			<path d="M0 603 L-129.96 603" class="st5"/>
+			<rect x="-110.47" y="592.2" width="76.9395" height="21.5999" class="st7"/>
+			<text x="-110.47" y="608.4" class="st8">KEYERROR</text>		</g>
+		<g id="shape28-54" transform="translate(1017,351) rotate(90)">
+			<title>Sheet.28</title>
+			<desc>KEYREADY</desc>
+			<path d="M0 612 L84.96 612" class="st5"/>
+			<rect x="-636.368" y="47.7002" width="75.7354" height="21.5999" transform="rotate(-90)" class="st7"/>
+			<text x="-636.37" y="63.9" transform="rotate(-90)" class="st8">KEYREADY</text>		</g>
+		<g id="shape29-61" transform="translate(963,351) rotate(90)">
+			<title>Sheet.29</title>
+			<desc>KEYMESSAGE</desc>
+			<path d="M13.68 612 L14.04 612 L99 612" class="st9"/>
+			<rect x="-676.846" y="25.2002" width="98.1914" height="21.5999" transform="rotate(-90)" class="st7"/>
+			<text x="-676.85" y="41.4" transform="rotate(-90)" class="st8">KEYMESSAGE</text>		</g>
+		<g id="shape30-69" transform="translate(423,-351)">
+			<title>Dynamic connector.30</title>
+			<desc>KEYMESSAGE</desc>
+			<path d="M9 612 L69.48 612 L69.48 684 L23.04 684" class="st5"/>
+			<rect x="20.3843" y="637.2" width="98.1914" height="21.5999" class="st7"/>
+			<text x="20.38" y="653.4" class="st10">KEYMESSAGE</text>		</g>
+	</g>
+</svg>
--- a/encrypted-media/spec-html.xsl	Tue Aug 27 08:57:20 2013 -0700
+++ b/encrypted-media/spec-html.xsl	Mon Sep 16 22:09:35 2013 -0700
@@ -89,6 +89,10 @@
   </xsl:template>
 
   <xsl:template match="//invalid-access-err">
+    <code><a><xsl:attribute name="href">http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_state_err</xsl:attribute>INVALID_STATE_ERR</a></code>
+  </xsl:template>
+
+  <xsl:template match="//invalid-state-err">
     <code><a><xsl:attribute name="href">http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-domexception-invalid_access_err</xsl:attribute>INVALID_ACCESS_ERR</a></code>
   </xsl:template>