[EME] Implement MediaKeySession::close()
https://bugs.webkit.org/show_bug.cgi?id=167869

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Implement MediaKeySession::close() as outlined in the specification.

The CDMInstance::closeSession() virtual method, when called, should
close the session that's represented by the passed-in session ID on
the CDMInstance implementor object. That's the same session ID that
the CDMInstance object passes to the MediaKeySession class through
the callback that's provided to the updateLicense call.

The CloseSessionCallback, passed to CDMInstance::closeSession(),
should be invoked by the CDMInstance implementor once the session
is closed. When that is invoked, another task is queued for the
MediaKeySession object that runs the `session closed` algorithm
and resolves the promise.

MockCDMInstance::closeSession() is defined to remove the session
from the MockCDMFactory object and invoke the CloseSessionCallback.

Test: media/encrypted-media/mock-MediaKeySession-close.html

* Modules/encryptedmedia/CDMInstance.h:
* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::close):
* testing/MockCDMFactory.cpp:
(WebCore::MockCDMInstance::closeSession):
* testing/MockCDMFactory.h:

LayoutTests:

Add the mock-MediaKeySession-close.html test case which checks proper
behavior of MediaKeySession::close(), specifically that under specific
conditions the promise returned by that method is properly resolved or
rejected. The test is skipped on all platforms for now.

* media/encrypted-media/mock-MediaKeySession-close-expected.txt: Added.
* media/encrypted-media/mock-MediaKeySession-close.html: Added.
* platform/efl/TestExpectations:
* platform/mac/TestExpectations:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@211856 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp
index 7bac30e..f14bc5c 100644
--- a/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp
+++ b/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp
@@ -359,9 +359,45 @@
     // 7. Return promise.
 }
 
-void MediaKeySession::close(Ref<DeferredPromise>&&)
+void MediaKeySession::close(Ref<DeferredPromise>&& promise)
 {
-    notImplemented();
+    // https://w3c.github.io/encrypted-media/#dom-mediakeysession-close
+    // W3C Editor's Draft 09 November 2016
+
+    // 1. Let session be the associated MediaKeySession object.
+    // 2. If session is closed, return a resolved promise.
+    if (m_closed) {
+        promise->resolve();
+        return;
+    }
+
+    // 3. If session's callable value is false, return a promise rejected with an InvalidStateError.
+    if (!m_callable) {
+        promise->reject(INVALID_STATE_ERR);
+        return;
+    }
+
+    // 4. Let promise be a new promise.
+    // 5. Run the following steps in parallel:
+    m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+        // 5.1. Let cdm be the CDM instance represented by session's cdm instance value.
+        // 5.2. Use cdm to close the key session associated with session.
+        m_instance->closeSession(m_sessionId, [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] () mutable {
+            if (!weakThis)
+                return;
+
+            // 5.3. Queue a task to run the following steps:
+            m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+                // 5.3.1. Run the Session Closed algorithm on the session.
+                sessionClosed();
+
+                // 5.3.2. Resolve promise.
+                promise->resolve();
+            });
+        });
+    });
+
+    // 6. Return promise.
 }
 
 void MediaKeySession::remove(Ref<DeferredPromise>&&)