<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[212109] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/212109">212109</a></dd>
<dt>Author</dt> <dd>zandobersek@gmail.com</dd>
<dt>Date</dt> <dd>2017-02-10 02:31:57 -0800 (Fri, 10 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[EME] Implement MediaKeySession::sessionClosed()
https://bugs.webkit.org/show_bug.cgi?id=168039

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Implement the 'session closed' algorithm for MediaKeySession by
following the specified steps. After this algorithm is run, the
session should be considered closed, which we track via the m_closed
member variable on the class. This is set to true before the promise
that's accessible through the 'closed' attribute is resolved.

Because the algorithm requires the CDM instance to store any record
of key usage when the session's type is 'persistent-usage-record', the
storeRecordOfKeyUsage() virtual method is added to the CDMInstance
interface. MockCDMInstance implementation is left unimplemented for now.

JSMediaKeySession::closed() accessor now has a custom implementation
that creates a deferred promise for that object if there's none yet, and
shares it with the wrapped class through the registerClosedPromise()
method, storing a reference to the promise in the m_closedPromise
member variable, or resolving the promise immediately if the session was
already closed.

Test cases added to media/encrypted-media/mock-MediaKeySession-close.html.

* Modules/encryptedmedia/CDMInstance.h:
* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::registerClosedPromise):
(WebCore::MediaKeySession::sessionClosed):
* Modules/encryptedmedia/MediaKeySession.h:
* bindings/js/JSMediaKeySessionCustom.cpp:
(WebCore::JSMediaKeySession::closed):
* testing/MockCDMFactory.cpp:
(WebCore::MockCDMInstance::storeRecordOfKeyUsage):
* testing/MockCDMFactory.h:

LayoutTests:

Enhance the mock-MediaKeySession-close.html test by adding test cases
covering the dispatch of the promise that's accessible through the
'closed' attribute and covering the session closure status, making
sure that various operations properly resolve or reject after the
session object was closed.

* media/encrypted-media/mock-MediaKeySession-close-expected.txt:
* media/encrypted-media/mock-MediaKeySession-close.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsmediaencryptedmediamockMediaKeySessioncloseexpectedtxt">trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediaencryptedmediamockMediaKeySessionclosehtml">trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaCDMInstanceh">trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySessioncpp">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesencryptedmediaMediaKeySessionh">trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSMediaKeySessionCustomcpp">trunk/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMFactorycpp">trunk/Source/WebCore/testing/MockCDMFactory.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingMockCDMFactoryh">trunk/Source/WebCore/testing/MockCDMFactory.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/LayoutTests/ChangeLog        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -1,5 +1,21 @@
</span><span class="cx"> 2017-02-10  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
</span><span class="cx"> 
</span><ins>+        [EME] Implement MediaKeySession::sessionClosed()
+        https://bugs.webkit.org/show_bug.cgi?id=168039
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Enhance the mock-MediaKeySession-close.html test by adding test cases
+        covering the dispatch of the promise that's accessible through the
+        'closed' attribute and covering the session closure status, making
+        sure that various operations properly resolve or reject after the
+        session object was closed.
+
+        * media/encrypted-media/mock-MediaKeySession-close-expected.txt:
+        * media/encrypted-media/mock-MediaKeySession-close.html:
+
+2017-02-10  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
+
</ins><span class="cx">         [EME] Implement MediaKeySession::updateKeyStatuses(), MediaKeyStatusMap
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=167888
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsmediaencryptedmediamockMediaKeySessioncloseexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close-expected.txt (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close-expected.txt        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close-expected.txt        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -31,6 +31,26 @@
</span><span class="cx"> RUN(promise = mediaKeySession.close())
</span><span class="cx"> Promise resolved OK
</span><span class="cx"> 
</span><ins>+Closing a valid MediaKeySession should resolve the &quot;closed&quot; promise.
+RUN(kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] }))
+RUN(mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;))
+RUN(promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids)))
+Promise resolved OK
+RUN(promise = mediaKeySession.close())
+Promise resolved OK
+Promise resolved OK
+&quot;closed&quot; promise correctly resolved.
+
+Already closed MediaKeySession should resolve the &quot;closed&quot; promise immediately.
+RUN(kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] }))
+RUN(mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;))
+RUN(promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids)))
+Promise resolved OK
+RUN(promise = mediaKeySession.close())
+Promise resolved OK
+Promise resolved OK
+&quot;closed&quot; promise correctly resolved.
+
</ins><span class="cx"> Closing a closed MediaKeySession should resolve.
</span><span class="cx"> RUN(kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] }))
</span><span class="cx"> RUN(mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;))
</span><span class="lines">@@ -40,5 +60,21 @@
</span><span class="cx"> Promise resolved OK
</span><span class="cx"> RUN(promise = mediaKeySession.close())
</span><span class="cx"> Promise resolved OK
</span><ins>+
+Operating on a closed MediaKeySession should resolve for close(), reject otherwise.
+RUN(kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] }))
+RUN(mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;))
+RUN(promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids)))
+Promise resolved OK
+RUN(promise = mediaKeySession.close())
+Promise resolved OK
+RUN(promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids)))
+Promise rejected correctly OK
+RUN(promise = mediaKeySession.update(encoder.encode(&quot;some-data&quot;)))
+Promise rejected correctly OK
+RUN(promise = mediaKeySession.close())
+Promise resolved OK
+RUN(promise = mediaKeySession.remove())
+Promise rejected correctly OK
</ins><span class="cx"> END OF TEST
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsmediaencryptedmediamockMediaKeySessionclosehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close.html (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close.html        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-close.html        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -87,6 +87,38 @@
</span><span class="cx">         },
</span><span class="cx"> 
</span><span class="cx">         function() {
</span><ins>+            consoleWrite('Closing a valid MediaKeySession should resolve the &quot;closed&quot; promise.')
+            run('kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] })');
+            run('mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;)');
+            run('promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids))');
+            shouldResolve(promise).then(function() {
+                shouldResolve(mediaKeySession.closed).then(function() {
+                    consoleWrite('&quot;closed&quot; promise correctly resolved.');
+                    next();
+                }, next);
+
+                run('promise = mediaKeySession.close()');
+                shouldResolve(promise);
+            }, next);
+        },
+
+        function() {
+            consoleWrite('Already closed MediaKeySession should resolve the &quot;closed&quot; promise immediately.');
+            run('kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] })');
+            run('mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;)');
+            run('promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids))');
+            shouldResolve(promise).then(function() {
+                run('promise = mediaKeySession.close()');
+                shouldResolve(promise).then(function() {
+                    shouldResolve(mediaKeySession.closed).then(function () {
+                        consoleWrite('&quot;closed&quot; promise correctly resolved.');
+                        next();
+                    }, next);
+                }, next);
+            }, next);
+        },
+
+        function() {
</ins><span class="cx">             consoleWrite('Closing a closed MediaKeySession should resolve.')
</span><span class="cx">             run('kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] })');
</span><span class="cx">             run('mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;)');
</span><span class="lines">@@ -99,6 +131,29 @@
</span><span class="cx">                 }, next);
</span><span class="cx">             }, next);
</span><span class="cx">         },
</span><ins>+
+        function() {
+            consoleWrite('Operating on a closed MediaKeySession should resolve for close(), reject otherwise.')
+            run('kids = JSON.stringify({ kids: [ &quot;MTIzNDU=&quot; ] })');
+            run('mediaKeySession = mediaKeys.createSession(&quot;temporary&quot;)');
+            run('promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids))');
+            shouldResolve(promise).then(function() {
+                run('promise = mediaKeySession.close()');
+                shouldResolve(promise).then(function() {
+                    run('promise = mediaKeySession.generateRequest(&quot;keyids&quot;, encoder.encode(kids))');
+                    shouldReject(promise).then(function() {
+                        run('promise = mediaKeySession.update(encoder.encode(&quot;some-data&quot;))');
+                        shouldReject(promise).then(function() {
+                            run('promise = mediaKeySession.close()');
+                            shouldResolve(promise).then(function() {
+                                run('promise = mediaKeySession.remove()');
+                                shouldReject(promise).then(next, next);
+                            }, next);
+                        }, next);
+                    }, next);
+                }, next);
+            }, next);
+        },
</ins><span class="cx">     ];
</span><span class="cx">     &lt;/script&gt;
</span><span class="cx"> &lt;/head&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/ChangeLog        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -1,5 +1,43 @@
</span><span class="cx"> 2017-02-10  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
</span><span class="cx"> 
</span><ins>+        [EME] Implement MediaKeySession::sessionClosed()
+        https://bugs.webkit.org/show_bug.cgi?id=168039
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Implement the 'session closed' algorithm for MediaKeySession by
+        following the specified steps. After this algorithm is run, the
+        session should be considered closed, which we track via the m_closed
+        member variable on the class. This is set to true before the promise
+        that's accessible through the 'closed' attribute is resolved.
+
+        Because the algorithm requires the CDM instance to store any record
+        of key usage when the session's type is 'persistent-usage-record', the
+        storeRecordOfKeyUsage() virtual method is added to the CDMInstance
+        interface. MockCDMInstance implementation is left unimplemented for now.
+
+        JSMediaKeySession::closed() accessor now has a custom implementation
+        that creates a deferred promise for that object if there's none yet, and
+        shares it with the wrapped class through the registerClosedPromise()
+        method, storing a reference to the promise in the m_closedPromise
+        member variable, or resolving the promise immediately if the session was
+        already closed.
+
+        Test cases added to media/encrypted-media/mock-MediaKeySession-close.html.
+
+        * Modules/encryptedmedia/CDMInstance.h:
+        * Modules/encryptedmedia/MediaKeySession.cpp:
+        (WebCore::MediaKeySession::registerClosedPromise):
+        (WebCore::MediaKeySession::sessionClosed):
+        * Modules/encryptedmedia/MediaKeySession.h:
+        * bindings/js/JSMediaKeySessionCustom.cpp:
+        (WebCore::JSMediaKeySession::closed):
+        * testing/MockCDMFactory.cpp:
+        (WebCore::MockCDMInstance::storeRecordOfKeyUsage):
+        * testing/MockCDMFactory.h:
+
+2017-02-10  Zan Dobersek  &lt;zdobersek@igalia.com&gt;
+
</ins><span class="cx">         [EME] Implement MediaKeySession::updateKeyStatuses(), MediaKeyStatusMap
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=167888
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaCDMInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -72,6 +72,8 @@
</span><span class="cx"> 
</span><span class="cx">     using RemoveSessionDataCallback = Function&lt;void(KeyStatusVector&amp;&amp;, std::optional&lt;Ref&lt;SharedBuffer&gt;&gt;&amp;&amp;, SuccessValue)&gt;;
</span><span class="cx">     virtual void removeSessionData(const String&amp; sessionId, LicenseType, RemoveSessionDataCallback) = 0;
</span><ins>+
+    virtual void storeRecordOfKeyUsage(const String&amp; sessionId) = 0;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -469,6 +469,16 @@
</span><span class="cx">     // 5. Return promise.
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaKeySession::registerClosedPromise(ClosedPromise&amp;&amp; promise)
+{
+    ASSERT(!m_closedPromise);
+    if (m_closed) {
+        promise.resolve();
+        return;
+    }
+    m_closedPromise = WTFMove(promise);
+}
+
</ins><span class="cx"> void MediaKeySession::enqueueMessage(MediaKeyMessageType messageType, const SharedBuffer&amp; message)
</span><span class="cx"> {
</span><span class="cx">     // 6.4.1 Queue a &quot;message&quot; Event
</span><span class="lines">@@ -536,7 +546,30 @@
</span><span class="cx"> 
</span><span class="cx"> void MediaKeySession::sessionClosed()
</span><span class="cx"> {
</span><del>-    notImplemented();
</del><ins>+    // https://w3c.github.io/encrypted-media/#session-closed
+    // W3C Editor's Draft 09 November 2016
+
+    // 1. Let session be the associated MediaKeySession object.
+    // 2. If session's session type is &quot;persistent-usage-record&quot;, execute the following steps in parallel:
+    if (m_sessionType == MediaKeySessionType::PersistentUsageRecord) {
+        // 2.1. Let cdm be the CDM instance represented by session's cdm instance value.
+        // 2.2. Use cdm to store session's record of key usage, if it exists.
+        m_instance-&gt;storeRecordOfKeyUsage(m_sessionId);
+    }
+
+    // 3. Run the Update Key Statuses algorithm on the session, providing an empty sequence.
+    updateKeyStatuses({ });
+
+    // 4. Run the Update Expiration algorithm on the session, providing NaN.
+    updateExpiration(std::numeric_limits&lt;double&gt;::quiet_NaN());
+
+    // Let's consider the session closed before any promise on the 'closed' attribute is resolved.
+    m_closed = true;
+
+    // 5. Let promise be the closed attribute of the session.
+    // 6. Resolve promise.
+    if (m_closedPromise)
+        m_closedPromise-&gt;resolve();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool MediaKeySession::hasPendingActivity() const
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesencryptedmediaMediaKeySessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -70,6 +70,9 @@
</span><span class="cx">     void close(Ref&lt;DeferredPromise&gt;&amp;&amp;);
</span><span class="cx">     void remove(Ref&lt;DeferredPromise&gt;&amp;&amp;);
</span><span class="cx"> 
</span><ins>+    using ClosedPromise = DOMPromise&lt;void&gt;;
+    void registerClosedPromise(ClosedPromise&amp;&amp;);
+
</ins><span class="cx">     const Vector&lt;std::pair&lt;Ref&lt;SharedBuffer&gt;, MediaKeyStatus&gt;&gt;&amp; statuses() const { return m_statuses; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -93,6 +96,7 @@
</span><span class="cx"> 
</span><span class="cx">     String m_sessionId;
</span><span class="cx">     double m_expiration;
</span><ins>+    std::optional&lt;ClosedPromise&gt; m_closedPromise;
</ins><span class="cx">     Ref&lt;MediaKeyStatusMap&gt; m_keyStatuses;
</span><span class="cx">     bool m_closed { false };
</span><span class="cx">     bool m_uninitialized { true };
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSMediaKeySessionCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -32,14 +32,16 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSMediaKeySession.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;NotImplemented.h&quot;
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-JSC::JSValue JSMediaKeySession::closed(JSC::ExecState&amp;) const
</del><ins>+JSC::JSValue JSMediaKeySession::closed(JSC::ExecState&amp; state) const
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return JSC::jsUndefined();
</del><ins>+    if (!m_closed) {
+        auto promise = createDeferredPromise(state, domWindow());
+        m_closed.set(state.vm(), this, promise-&gt;promise());
+        wrapped().registerClosedPromise(WTFMove(promise));
+    }
+    return m_closed.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMFactorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockCDMFactory.cpp (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDMFactory.cpp        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/testing/MockCDMFactory.cpp        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -349,6 +349,11 @@
</span><span class="cx">     callback(WTFMove(keyStatusVector), SharedBuffer::create(message.data(), message.length()), SuccessValue::Succeeded);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MockCDMInstance::storeRecordOfKeyUsage(const String&amp;)
+{
+    // FIXME: This should be implemented along with the support for persistent-usage-record sessions.
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoretestingMockCDMFactoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/MockCDMFactory.h (212108 => 212109)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/MockCDMFactory.h        2017-02-10 10:28:59 UTC (rev 212108)
+++ trunk/Source/WebCore/testing/MockCDMFactory.h        2017-02-10 10:31:57 UTC (rev 212109)
</span><span class="lines">@@ -134,6 +134,7 @@
</span><span class="cx">     void updateLicense(const String&amp;, LicenseType, const SharedBuffer&amp;, LicenseUpdateCallback) final;
</span><span class="cx">     void closeSession(const String&amp;, CloseSessionCallback) final;
</span><span class="cx">     void removeSessionData(const String&amp;, LicenseType, RemoveSessionDataCallback) final;
</span><ins>+    void storeRecordOfKeyUsage(const String&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     WeakPtr&lt;MockCDM&gt; m_cdm;
</span><span class="cx">     bool m_distinctiveIdentifiersAllowed { true };
</span></span></pre>
</div>
</div>

</body>
</html>