[EME] Bug 25201 - Add ability to preemptively provide a server certificate
authorDavid Dorwin <ddorwin@google.com>
Mon, 28 Apr 2014 14:12:51 -0700
changeset 292 dcd1e4007d08
parent 291 971b075d5389
child 293 6a85b27906f5
[EME] Bug 25201 - Add ability to preemptively provide a server certificate
encrypted-media/encrypted-media.html
encrypted-media/encrypted-media.xml
--- a/encrypted-media/encrypted-media.html	Mon Apr 28 14:02:15 2014 -0700
+++ b/encrypted-media/encrypted-media.html	Mon Apr 28 14:12:51 2014 -0700
@@ -339,6 +339,7 @@
 
   Promise&lt;<a href="#dom-mediakeysession">MediaKeySession</a>&gt; <a href="#dom-createsession">createSession</a>(DOMString <a href="#initialization-data-type">initDataType</a>, Uint8Array 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;any&gt; <a href="#dom-setservercertificate">setServerCertificate</a>(Uint8Array serverCertificate);
 
   static Promise&lt;<a href="#dom-mediakeys">MediaKeys</a>&gt; <a href="#dom-create">create</a>(DOMString <a href="#key-system">keySystem</a>)
   static <a href="#dom-enumistypesupported">IsTypeSupported</a> <a href="#dom-istypesupported">isTypeSupported</a>(DOMstring <a href="#key-system">keySystem</a>, optional DOMString <a href="#initialization-data-type">initDataType</a>, optional DOMString contentType, optional DOMString capability);
@@ -453,7 +454,7 @@
     <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>
-    <p class="non-normative">Note: The contents of <var title="true">initData</var> are container-specific <a href="#initialization-data">Initialization Data</a>.
+    <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.
@@ -560,6 +561,26 @@
       <li><p>Return <var>promise</var>.</p></li>
     </ol>
 
+    <p>The <dfn id="dom-setservercertificate"><code>setServerCertificate(serverCertificate)</code></dfn> method provides a server certificate to be used to encrypt messages to the license server. It must run the following steps:</p>
+    <p class="non-normative">The contents of <var title="true">serverCertificate</var> are <a href="#key-system">Key System</a>-specific.</p>
+    <p class="non-normative">Key systems that use such certificates should also support requesting the certificate from the server via an  additional round trip. This simplifies interoperability for applications that are not designed to provide certificates to specific key systems.</p>
+
+    <ol>
+      <li><p>If <var title="true">serverCertificate</var> is an empty array, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code> and that has the message "The serverCertificate parameter is empty."</p></li>
+      <li><p>If the <code><a href="#dom-keysystem">keySystem</a></code> does not support server certificates, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-NotSupportedError">"NotSupportedError"</a></code> and that has the message "The operation is not supported by the key system."</p></li>
+      <li><p>Let <var>promise</var> be a new promise.</p></li>
+      <li>
+<p>Run the following steps asynchronously:</p>
+        <ol>
+          <li><p>Let <var title="true">cdm</var> be the <var title="true">cdm</var> loaded in <code><a href="#dom-create">create()</a></code>.</p></li>
+          <li><p>Use the <var title="true">cdm</var> to process <var title="true">serverCertificate</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="#mediakeyerror-names">error name</a> and that has an appropriate message.</p></li>
+          <li><p>Resolve <var>promise</var> with <code>undefined</code>.</p></li>
+        </ol>
+      </li>
+      <li><p>Return <var>promise</var>.</p></li>
+    </ol>
+
     <p>The <dfn id="dom-istypesupported"><code>isTypeSupported(keySystem, initDataType, contentType, capability)</code></dfn> method returns whether <var title="true">keySystem</var> is supported with the <var title="true"><a href="#initialization-data-type">initDataType</a></var>, container and codec(s) specified by <var title="true">contentType</var>, and <var title="true">capability</var>.</p>
     <div class="issue">
 <div class="issue-title"><span>Issue 2</span></div>
@@ -669,7 +690,7 @@
     This promise can only be fulfilled and is never rejected.</p>
 
     <p>The <dfn id="dom-update"><code>update(response)</code></dfn> method provides messages, including licenses, to the CDM. It must run the following steps:</p>
-    <p class="non-normative">Note: The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
+    <p class="non-normative">The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
 
     <ol>
       <li><p>If <var title="true">response</var> is an empty array, return a promise rejected with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code> and that has the message "The response parameter is empty."</p></li>
@@ -1385,6 +1406,7 @@
     <h3 id="example-selecting-key-system" class="exampleheader">8.2. Selecting a Supported Key System and Using Initialization Data from the "needkey" Event</h3>
     <p class="exampledescription">This example selects a supported <a href="#key-system">Key System</a> using the <code><a href="#dom-istypesupported">isTypeSupported()</a></code> method then uses
     the <a href="#initialization-data">Initialization Data</a> from the <a href="http://www.w3.org/TR/html5/embedded-content-0.html#media-data">media data</a> to generate the license request and send it to the appropriate license server.
+    One of the supported key systems uses a serverCertificate, which is provided proactively.
     </p>
 
     <div class="example">
@@ -1392,11 +1414,13 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
 
   function selectKeySystem() {
     if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.example.somesystem", "webm", "video/webm; codecs='vp8, vorbis'")) {
       licenseUrl = "https://license.example.com/getkey"; // OR "https://example.&lt;My Video Site domain&gt;"
       keySystem = "com.example.somesystem";
+      serverCertificate = new Uint8Array([ ... ]);
     } else if (<a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-istypesupported">isTypeSupported</a>("com.foobar", "webm", "video/webm; codecs='vp8, vorbis'")) {
       licenseUrl = "https://license.foobar.com/request";
       keySystem = "com.foobar";
@@ -1414,6 +1438,10 @@
       <a href="#dom-mediakeys">MediaKeys</a>.<a href="#dom-create">create</a>(keySystem).then(
         function(createdMediaKeys) {
           video.mediaKeysObject = createdMediaKeys;
+
+          if (serverCertificate)
+            createdMediaKeys.setServerCertificate(serverCertificate);
+
           for (var i = 0; i &lt; video.pendingSessionData.length; i++) {
             var data = video.pendingSessionData[i];
             createSession(video.mediaKeysObject, data.initDataType, data.initData);
@@ -1483,6 +1511,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See the previous example for implementations of these functions.
@@ -1500,6 +1529,8 @@
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
       video.src = "foo.webm";
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
     }
   ).catch(
@@ -1519,6 +1550,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See previous examples for implementations of these functions.
@@ -1576,6 +1608,8 @@
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
       video.src = "foo.webm";
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
     }
   ).catch(
@@ -1594,6 +1628,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See the previous examples for implementations of these functions.
@@ -1664,6 +1699,8 @@
     function(createdMediaKeys) {
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<a href="#dom-setmediakeys">setMediaKeys</a>(mediaKeys);
     }
   ).catch(
--- a/encrypted-media/encrypted-media.xml	Mon Apr 28 14:02:15 2014 -0700
+++ b/encrypted-media/encrypted-media.xml	Mon Apr 28 14:12:51 2014 -0700
@@ -336,6 +336,7 @@
 
   Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>createSession</premethodref>(DOMString <a href="#initialization-data-type">initDataType</a>, Uint8Array initData, optional <precoderef>SessionType</precoderef> sessionType = "<precoderef prefix="sessiontype">temporary</precoderef>");
   Promise&lt;<precoderef>MediaKeySession</precoderef>&gt; <premethodref>loadSession</premethodref>(DOMString sessionId);
+  Promise&lt;any&gt; <premethodref>setServerCertificate</premethodref>(Uint8Array serverCertificate);
 
   static Promise&lt;<precoderef>MediaKeys</precoderef>&gt; <premethodref>create</premethodref>(DOMString <a href="#key-system">keySystem</a>)
   static <precoderef prefix="enum">IsTypeSupported</precoderef> <premethodref>isTypeSupported</premethodref>(DOMstring <a href="#key-system">keySystem</a>, optional DOMString <a href="#initialization-data-type">initDataType</a>, optional DOMString contentType, optional DOMString capability);
@@ -440,7 +441,7 @@
     <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>
-    <p class="non-normative">Note: The contents of <var title="true">initData</var> are container-specific <a href="#initialization-data">Initialization Data</a>.
+    <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.
@@ -538,6 +539,25 @@
       <li><p>Return <var>promise</var>.</p></li>
     </ol>
 
+    <p>The <methoddfn name="setServerCertificate">setServerCertificate(<var title="true">serverCertificate</var>)</methoddfn> method provides a server certificate to be used to encrypt messages to the license server. It must run the following steps:</p>
+    <p class="non-normative">The contents of <var title="true">serverCertificate</var> are <a href="#key-system">Key System</a>-specific.</p>
+    <p class="non-normative">Key systems that use such certificates should also support requesting the certificate from the server via an  additional round trip. This simplifies interoperability for applications that are not designed to provide certificates to specific key systems.</p>
+
+    <ol>
+      <li><p>If <var title="true">serverCertificate</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> and that has the message "The serverCertificate parameter is empty."</p></li>
+      <li><p>If the <coderef>keySystem</coderef> does not support server certificates, 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> and that has the message "The operation is not supported by the key system."</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>Use the <var title="true">cdm</var> to process <var title="true">serverCertificate</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="#mediakeyerror-names">error name</a> and that has an appropriate message.</p></li>
+          <li><p>Resolve <var>promise</var> with <code>undefined</code>.</p></li>
+        </ol>
+      </li>
+      <li><p>Return <var>promise</var>.</p></li>
+    </ol>
+
     <p>The <methoddfn name="isTypeSupported">isTypeSupported(<var title="true">keySystem</var>, <var title="true">initDataType</var>, <var title="true">contentType</var>, <var title="true">capability</var>)</methoddfn> method returns whether <var title="true">keySystem</var> is supported with the <var title="true"><a href="#initialization-data-type">initDataType</a></var>, container and codec(s) specified by <var title="true">contentType</var>, and <var title="true">capability</var>.</p>
     <div class="issue"><div class="issue-title"><span>Issue 2</span></div><p class="">isTypeSupported() is still under discussion. See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=24873">Bug 24873</a>.</p></div>
     <div class="example">
@@ -633,7 +653,7 @@
     This promise can only be fulfilled and is never rejected.</p>
 
     <p>The <methoddfn name="update">update(<var title="true">response</var>)</methoddfn> method provides messages, including licenses, to the CDM. It must run the following steps:</p>
-    <p class="non-normative">Note: The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
+    <p class="non-normative">The contents of <var title="true">response</var> are <var title="true"><a href="#key-system">keySystem</a></var>-specific.</p>
 
     <ol>
       <li><p>If <var title="true">response</var> is an empty array, return a promise rejected with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code> and that has the message "The response parameter is empty."</p></li>
@@ -1317,6 +1337,7 @@
     <h3 id="example-selecting-key-system" class="exampleheader">8.2. Selecting a Supported Key System and Using Initialization Data from the "needkey" Event</h3>
     <p class="exampledescription">This example selects a supported <a href="#key-system">Key System</a> using the <methodref>isTypeSupported</methodref> method then uses
     the <a href="#initialization-data">Initialization Data</a> from the <videoanchor name="media-data">media data</videoanchor> to generate the license request and send it to the appropriate license server.
+    One of the supported key systems uses a serverCertificate, which is provided proactively.
     </p>
 
     <div class="example">
@@ -1324,11 +1345,13 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
 
   function selectKeySystem() {
     if (<precoderef>MediaKeys</precoderef>.<premethodref>isTypeSupported</premethodref>("com.example.somesystem", "webm", "video/webm; codecs='vp8, vorbis'")) {
       licenseUrl = "https://license.example.com/getkey"; // OR "https://example.&lt;My Video Site domain&gt;"
       keySystem = "com.example.somesystem";
+      serverCertificate = new Uint8Array([ ... ]);
     } else if (<precoderef>MediaKeys</precoderef>.<premethodref>isTypeSupported</premethodref>("com.foobar", "webm", "video/webm; codecs='vp8, vorbis'")) {
       licenseUrl = "https://license.foobar.com/request";
       keySystem = "com.foobar";
@@ -1346,6 +1369,10 @@
       <precoderef>MediaKeys</precoderef>.<premethodref>create</premethodref>(keySystem).then(
         function(createdMediaKeys) {
           video.mediaKeysObject = createdMediaKeys;
+
+          if (serverCertificate)
+            createdMediaKeys.setServerCertificate(serverCertificate);
+
           for (var i = 0; i &lt; video.pendingSessionData.length; i++) {
             var data = video.pendingSessionData[i];
             createSession(video.mediaKeysObject, data.initDataType, data.initData);
@@ -1415,6 +1442,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See the previous example for implementations of these functions.
@@ -1432,6 +1460,8 @@
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
       video.src = "foo.webm";
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<premethodref>setMediaKeys</premethodref>(mediaKeys);
     }
   ).catch(
@@ -1451,6 +1481,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See previous examples for implementations of these functions.
@@ -1508,6 +1539,8 @@
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
       video.src = "foo.webm";
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<premethodref>setMediaKeys</premethodref>(mediaKeys);
     }
   ).catch(
@@ -1526,6 +1559,7 @@
 &lt;script&gt;
   var keySystem;
   var licenseUrl;
+  var serverCertificate;
   var mediaKeys;
 
   // See the previous examples for implementations of these functions.
@@ -1596,6 +1630,8 @@
     function(createdMediaKeys) {
       mediaKeys = createdMediaKeys;
       var video = document.getElementById("v");
+      if (serverCertificate)
+        mediaKeys.setServerCertificate(serverCertificate);
       return video.<premethodref>setMediaKeys</premethodref>(mediaKeys);
     }
   ).catch(