Title: [236317] trunk/Source/WebCore
Revision
236317
Author
jer.no...@apple.com
Date
2018-09-21 08:08:35 -0700 (Fri, 21 Sep 2018)

Log Message

[EME] Introduce the concept of CDMInstanceSession.
https://bugs.webkit.org/show_bug.cgi?id=189725

Reviewed by Eric Carlson.

Currently, the same CDMInstance owned by a MediaKeys object is passed to every MediaKeySession created by that
MediaKeys, and since the CDMInstance has only a single CDMInstanceClient, subsequent MediaKeySessions prevent
previous ones from getting updates.

Add a new virtual interface, CDMInstanceSession, to be passed to MediaKeySession upon creation. Refactor
CDMInstanceClearKey and CDMInstanceFairPlayStreamingAVFObjC to adopt this new interface.

Drive-by fixes: Made a number of virtual overrides in final classes final themselves.

* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::create):
(WebCore::MediaKeySession::MediaKeySession):
(WebCore::MediaKeySession::generateRequest):
(WebCore::MediaKeySession::load):
(WebCore::MediaKeySession::update):
(WebCore::MediaKeySession::remove):
(WebCore::MediaKeySession::updateKeyStatuses):
* Modules/encryptedmedia/MediaKeySession.h:
* Modules/encryptedmedia/MediaKeys.cpp:
(WebCore::MediaKeys::createSession):
* WebCore.xcodeproj/project.pbxproj:
* platform/encryptedmedia/CDMInstance.h:
(WebCore::CDMInstance::setHDCPStatus):
(WebCore::CDMInstance::setClient): Deleted.
(WebCore::CDMInstance::clearClient): Deleted.
* platform/encryptedmedia/CDMInstanceSession.h: Copied from Source/WebCore/platform/encryptedmedia/CDMInstance.h.
(WebCore::CDMInstanceSession::setClient):
(WebCore::CDMInstanceSession::clearClient):
* platform/encryptedmedia/clearkey/CDMClearKey.cpp:
(WebCore::parseLicenseFormat):
(WebCore::CDMInstanceClearKey::keySystem const):
(WebCore::CDMInstanceClearKey::createSession):
(WebCore::CDMInstanceSessionClearKey::requestLicense):
(WebCore::CDMInstanceSessionClearKey::keys const):
(WebCore::CDMInstanceSessionClearKey::updateLicense):
(WebCore::CDMInstanceSessionClearKey::loadSession):
(WebCore::CDMInstanceSessionClearKey::closeSession):
(WebCore::CDMInstanceSessionClearKey::removeSessionData):
(WebCore::CDMInstanceSessionClearKey::storeRecordOfKeyUsage):
(WebCore::CDMInstanceClearKey::requestLicense): Deleted.
(WebCore::CDMInstanceClearKey::keys const): Deleted.
(WebCore::CDMInstanceClearKey::updateLicense): Deleted.
(WebCore::CDMInstanceClearKey::loadSession): Deleted.
(WebCore::CDMInstanceClearKey::closeSession): Deleted.
(WebCore::CDMInstanceClearKey::removeSessionData): Deleted.
(WebCore::CDMInstanceClearKey::storeRecordOfKeyUsage): Deleted.
* platform/encryptedmedia/clearkey/CDMClearKey.h:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::createSession):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::processContentKeyRequestForSession):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::processNextContentKeyRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::keySystem const):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::storeRecordOfKeyUsage):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setClient):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::clearClient):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRequest):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRenewingRequest):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvidePersistableRequest):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didFailToProvideRequest):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::sessionIdentifierChanged):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported const):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::isLicenseTypeSupported const): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::keyIDs): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestLicense): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::updateLicense): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::loadSession): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::closeSession): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::removeSessionData): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::storeRecordOfKeyUsage): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::setClient): Deleted.
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::clearClient): Deleted.
* testing/MockCDMFactory.cpp:
(WebCore::MockCDMInstance::keySystem const):
(WebCore::MockCDMInstance::createSession):
(WebCore::MockCDMInstanceSession::MockCDMInstanceSession):
(WebCore::MockCDMInstanceSession::requestLicense):
(WebCore::MockCDMInstanceSession::updateLicense):
(WebCore::MockCDMInstanceSession::loadSession):
(WebCore::MockCDMInstanceSession::closeSession):
(WebCore::MockCDMInstanceSession::removeSessionData):
(WebCore::MockCDMInstanceSession::storeRecordOfKeyUsage):
(WebCore::MockCDMInstance::requestLicense): Deleted.
(WebCore::MockCDMInstance::updateLicense): Deleted.
(WebCore::MockCDMInstance::loadSession): Deleted.
(WebCore::MockCDMInstance::closeSession): Deleted.
(WebCore::MockCDMInstance::removeSessionData): Deleted.
(WebCore::MockCDMInstance::storeRecordOfKeyUsage): Deleted.
* testing/MockCDMFactory.h:
(WebCore::MockCDMInstance::factory const):
(WebCore::MockCDMInstance::distinctiveIdentifiersAllowed const):
(WebCore::MockCDMInstance::persistentStateAllowed const):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (236316 => 236317)


--- trunk/Source/WebCore/ChangeLog	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/ChangeLog	2018-09-21 15:08:35 UTC (rev 236317)
@@ -1,3 +1,121 @@
+2018-09-21  Jer Noble  <jer.no...@apple.com>
+
+        [EME] Introduce the concept of CDMInstanceSession.
+        https://bugs.webkit.org/show_bug.cgi?id=189725
+
+        Reviewed by Eric Carlson.
+
+        Currently, the same CDMInstance owned by a MediaKeys object is passed to every MediaKeySession created by that
+        MediaKeys, and since the CDMInstance has only a single CDMInstanceClient, subsequent MediaKeySessions prevent
+        previous ones from getting updates.
+
+        Add a new virtual interface, CDMInstanceSession, to be passed to MediaKeySession upon creation. Refactor
+        CDMInstanceClearKey and CDMInstanceFairPlayStreamingAVFObjC to adopt this new interface.
+
+        Drive-by fixes: Made a number of virtual overrides in final classes final themselves.
+
+        * Modules/encryptedmedia/MediaKeySession.cpp:
+        (WebCore::MediaKeySession::create):
+        (WebCore::MediaKeySession::MediaKeySession):
+        (WebCore::MediaKeySession::generateRequest):
+        (WebCore::MediaKeySession::load):
+        (WebCore::MediaKeySession::update):
+        (WebCore::MediaKeySession::remove):
+        (WebCore::MediaKeySession::updateKeyStatuses):
+        * Modules/encryptedmedia/MediaKeySession.h:
+        * Modules/encryptedmedia/MediaKeys.cpp:
+        (WebCore::MediaKeys::createSession):
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/encryptedmedia/CDMInstance.h:
+        (WebCore::CDMInstance::setHDCPStatus):
+        (WebCore::CDMInstance::setClient): Deleted.
+        (WebCore::CDMInstance::clearClient): Deleted.
+        * platform/encryptedmedia/CDMInstanceSession.h: Copied from Source/WebCore/platform/encryptedmedia/CDMInstance.h.
+        (WebCore::CDMInstanceSession::setClient):
+        (WebCore::CDMInstanceSession::clearClient):
+        * platform/encryptedmedia/clearkey/CDMClearKey.cpp:
+        (WebCore::parseLicenseFormat):
+        (WebCore::CDMInstanceClearKey::keySystem const):
+        (WebCore::CDMInstanceClearKey::createSession):
+        (WebCore::CDMInstanceSessionClearKey::requestLicense):
+        (WebCore::CDMInstanceSessionClearKey::keys const):
+        (WebCore::CDMInstanceSessionClearKey::updateLicense):
+        (WebCore::CDMInstanceSessionClearKey::loadSession):
+        (WebCore::CDMInstanceSessionClearKey::closeSession):
+        (WebCore::CDMInstanceSessionClearKey::removeSessionData):
+        (WebCore::CDMInstanceSessionClearKey::storeRecordOfKeyUsage):
+        (WebCore::CDMInstanceClearKey::requestLicense): Deleted.
+        (WebCore::CDMInstanceClearKey::keys const): Deleted.
+        (WebCore::CDMInstanceClearKey::updateLicense): Deleted.
+        (WebCore::CDMInstanceClearKey::loadSession): Deleted.
+        (WebCore::CDMInstanceClearKey::closeSession): Deleted.
+        (WebCore::CDMInstanceClearKey::removeSessionData): Deleted.
+        (WebCore::CDMInstanceClearKey::storeRecordOfKeyUsage): Deleted.
+        * platform/encryptedmedia/clearkey/CDMClearKey.h:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::createSession):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::processContentKeyRequestForSession):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::processNextContentKeyRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::keySystem const):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::storeRecordOfKeyUsage):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setClient):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::clearClient):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRequest):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRenewingRequest):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didProvidePersistableRequest):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::didFailToProvideRequest):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::sessionIdentifierChanged):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported const):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::isLicenseTypeSupported const): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::keyIDs): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestLicense): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::updateLicense): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::loadSession): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::closeSession): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::removeSessionData): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::storeRecordOfKeyUsage): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setClient): Deleted.
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::clearClient): Deleted.
+        * testing/MockCDMFactory.cpp:
+        (WebCore::MockCDMInstance::keySystem const):
+        (WebCore::MockCDMInstance::createSession):
+        (WebCore::MockCDMInstanceSession::MockCDMInstanceSession):
+        (WebCore::MockCDMInstanceSession::requestLicense):
+        (WebCore::MockCDMInstanceSession::updateLicense):
+        (WebCore::MockCDMInstanceSession::loadSession):
+        (WebCore::MockCDMInstanceSession::closeSession):
+        (WebCore::MockCDMInstanceSession::removeSessionData):
+        (WebCore::MockCDMInstanceSession::storeRecordOfKeyUsage):
+        (WebCore::MockCDMInstance::requestLicense): Deleted.
+        (WebCore::MockCDMInstance::updateLicense): Deleted.
+        (WebCore::MockCDMInstance::loadSession): Deleted.
+        (WebCore::MockCDMInstance::closeSession): Deleted.
+        (WebCore::MockCDMInstance::removeSessionData): Deleted.
+        (WebCore::MockCDMInstance::storeRecordOfKeyUsage): Deleted.
+        * testing/MockCDMFactory.h:
+        (WebCore::MockCDMInstance::factory const):
+        (WebCore::MockCDMInstance::distinctiveIdentifiersAllowed const):
+        (WebCore::MockCDMInstance::persistentStateAllowed const):
+
 2018-09-21  Alicia Boya GarcĂ­a  <ab...@igalia.com>
 
         [MSE] Fix comparsion with uninitialized greatestDecodeDuration

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp (236316 => 236317)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp	2018-09-21 15:08:35 UTC (rev 236317)
@@ -48,14 +48,14 @@
 
 namespace WebCore {
 
-Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstanceSession>&& instanceSession)
 {
-    auto session = adoptRef(*new MediaKeySession(context, WTFMove(keys), sessionType, useDistinctiveIdentifier, WTFMove(implementation), WTFMove(instance)));
+    auto session = adoptRef(*new MediaKeySession(context, WTFMove(keys), sessionType, useDistinctiveIdentifier, WTFMove(implementation), WTFMove(instanceSession)));
     session->suspendIfNeeded();
     return session;
 }
 
-MediaKeySession::MediaKeySession(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+MediaKeySession::MediaKeySession(ScriptExecutionContext& context, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstanceSession>&& instanceSession)
     : ActiveDOMObject(&context)
     , m_keys(WTFMove(keys))
     , m_expiration(std::numeric_limits<double>::quiet_NaN())
@@ -63,10 +63,10 @@
     , m_useDistinctiveIdentifier(useDistinctiveIdentifier)
     , m_sessionType(sessionType)
     , m_implementation(WTFMove(implementation))
-    , m_instance(WTFMove(instance))
+    , m_instanceSession(WTFMove(instanceSession))
     , m_eventQueue(*this)
 {
-    // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
+    // https://w3c.github.io/encrypted-media/#dom-mediakeys-createsession
     // W3C Editor's Draft 09 November 2016
     // createSession(), ctd.
 
@@ -88,13 +88,13 @@
     UNUSED_PARAM(m_closed);
     UNUSED_PARAM(m_uninitialized);
 
-    m_instance->setClient(*this);
+    m_instanceSession->setClient(m_cdmInstanceClientWeakPtrFactory.createWeakPtr(*this));
 }
 
 MediaKeySession::~MediaKeySession()
 {
     m_keyStatuses->detachSession();
-    m_instance->clearClient();
+    m_instanceSession->clearClient();
 }
 
 const String& MediaKeySession::sessionId() const
@@ -194,7 +194,7 @@
             m_latestDecryptTime = 0;
         }
 
-        m_instance->requestLicense(m_sessionType, initDataType, WTFMove(initData), [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstance::SuccessValue succeeded) mutable {
+        m_instanceSession->requestLicense(m_sessionType, initDataType, WTFMove(initData), [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstanceSession::SuccessValue succeeded) mutable {
             if (!weakThis)
                 return;
 
@@ -217,7 +217,7 @@
             // 10.10. Queue a task to run the following steps:
             m_taskQueue.enqueueTask([this, promise = WTFMove(promise), message = WTFMove(message), messageType, sessionId, succeeded] () mutable {
                 // 10.10.1. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
-                if (succeeded == CDMInstance::SuccessValue::Failed) {
+                if (succeeded == CDMInstanceSession::SuccessValue::Failed) {
                     promise->reject(NotSupportedError);
                     return;
                 }
@@ -287,7 +287,7 @@
         // 8.6. Let message type be null.
         // 8.7. Let cdm be the CDM instance represented by this object's cdm instance value.
         // 8.8. Use the cdm to execute the following steps:
-        m_instance->loadSession(m_sessionType, *sanitizedSessionId, origin, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise), sanitizedSessionId = *sanitizedSessionId] (std::optional<CDMInstance::KeyStatusVector>&& knownKeys, std::optional<double>&& expiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded, CDMInstance::SessionLoadFailure failure) mutable {
+        m_instanceSession->loadSession(m_sessionType, *sanitizedSessionId, origin, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise), sanitizedSessionId = *sanitizedSessionId] (std::optional<CDMInstanceSession::KeyStatusVector>&& knownKeys, std::optional<double>&& expiration, std::optional<CDMInstanceSession::Message>&& message, CDMInstanceSession::SuccessValue succeeded, CDMInstanceSession::SessionLoadFailure failure) mutable {
             // 8.8.1. If there is no data stored for the sanitized session ID in the origin, resolve promise with false and abort these steps.
             // 8.8.2. If the stored session's session type is not the same as the current MediaKeySession session type, reject promise with a newly created TypeError.
             // 8.8.3. Let session data be the data stored for the sanitized session ID in the origin. This must not include data from other origin(s) or that is not associated with an origin.
@@ -299,19 +299,19 @@
             //   8.8.7.2. Let message type be the appropriate MediaKeyMessageType for the message.
             // NOTE: Steps 8.8.1. through 8.8.7. should be implemented in CDMInstance.
 
-            if (succeeded == CDMInstance::SuccessValue::Failed) {
+            if (succeeded == CDMInstanceSession::SuccessValue::Failed) {
                 switch (failure) {
-                case CDMInstance::SessionLoadFailure::NoSessionData:
+                case CDMInstanceSession::SessionLoadFailure::NoSessionData:
                     promise->resolve<IDLBoolean>(false);
                     return;
-                case CDMInstance::SessionLoadFailure::MismatchedSessionType:
+                case CDMInstanceSession::SessionLoadFailure::MismatchedSessionType:
                     promise->reject(TypeError);
                     return;
-                case CDMInstance::SessionLoadFailure::QuotaExceeded:
+                case CDMInstanceSession::SessionLoadFailure::QuotaExceeded:
                     promise->reject(QuotaExceededError);
                     return;
-                case CDMInstance::SessionLoadFailure::None:
-                case CDMInstance::SessionLoadFailure::Other:
+                case CDMInstanceSession::SessionLoadFailure::None:
+                case CDMInstanceSession::SessionLoadFailure::Other:
                     // In any other case, the session load failure will cause a rejection in the following task.
                     break;
                 }
@@ -320,7 +320,7 @@
             // 8.9. Queue a task to run the following steps:
             m_taskQueue.enqueueTask([this, knownKeys = WTFMove(knownKeys), expiration = WTFMove(expiration), message = WTFMove(message), sanitizedSessionId, succeeded, promise = WTFMove(promise)] () mutable {
                 // 8.9.1. If any of the preceding steps failed, reject promise with a the appropriate error name.
-                if (succeeded == CDMInstance::SuccessValue::Failed) {
+                if (succeeded == CDMInstanceSession::SuccessValue::Failed) {
                     promise->reject(NotSupportedError);
                     return;
                 }
@@ -388,7 +388,7 @@
         // 6.5. Let session closed be false.
         // 6.6. Let cdm be the CDM instance represented by this object's cdm instance value.
         // 6.7. Use the cdm to execute the following steps:
-        m_instance->updateLicense(m_sessionId, m_sessionType, *sanitizedResponse, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (bool sessionWasClosed, std::optional<CDMInstance::KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<CDMInstance::Message>&& message, CDMInstance::SuccessValue succeeded) mutable {
+        m_instanceSession->updateLicense(m_sessionId, m_sessionType, *sanitizedResponse, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (bool sessionWasClosed, std::optional<CDMInstanceSession::KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<CDMInstanceSession::Message>&& message, CDMInstanceSession::SuccessValue succeeded) mutable {
             if (!weakThis)
                 return;
 
@@ -414,7 +414,7 @@
             //     Process sanitized response, not storing any session data.
             // NOTE: Steps 6.7.1. and 6.7.2. should be implemented in CDMInstance.
 
-            if (succeeded == CDMInstance::SuccessValue::Failed) {
+            if (succeeded == CDMInstanceSession::SuccessValue::Failed) {
                 promise->reject(TypeError);
                 return;
             }
@@ -450,16 +450,16 @@
                     if (message) {
                         MediaKeyMessageType messageType;
                         switch (message->first) {
-                        case CDMInstance::MessageType::LicenseRequest:
+                        case CDMInstanceSession::MessageType::LicenseRequest:
                             messageType = MediaKeyMessageType::LicenseRequest;
                             break;
-                        case CDMInstance::MessageType::LicenseRenewal:
+                        case CDMInstanceSession::MessageType::LicenseRenewal:
                             messageType = MediaKeyMessageType::LicenseRenewal;
                             break;
-                        case CDMInstance::MessageType::LicenseRelease:
+                        case CDMInstanceSession::MessageType::LicenseRelease:
                             messageType = MediaKeyMessageType::LicenseRelease;
                             break;
-                        case CDMInstance::MessageType::IndividualizationRequest:
+                        case CDMInstanceSession::MessageType::IndividualizationRequest:
                             messageType = MediaKeyMessageType::IndividualizationRequest;
                             break;
                         }
@@ -500,7 +500,7 @@
     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 = makeWeakPtr(*this), promise = WTFMove(promise)] () mutable {
+        m_instanceSession->closeSession(m_sessionId, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] () mutable {
             if (!weakThis)
                 return;
 
@@ -538,7 +538,7 @@
         // 4.3. Let message type be null.
 
         // 4.4. Use the cdm to execute the following steps:
-        m_instance->removeSessionData(m_sessionId, m_sessionType, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (CDMInstance::KeyStatusVector&& keys, std::optional<Ref<SharedBuffer>>&& message, CDMInstance::SuccessValue succeeded) mutable {
+        m_instanceSession->removeSessionData(m_sessionId, m_sessionType, [this, weakThis = makeWeakPtr(*this), promise = WTFMove(promise)] (CDMInstanceSession::KeyStatusVector&& keys, std::optional<Ref<SharedBuffer>>&& message, CDMInstanceSession::SuccessValue succeeded) mutable {
             if (!weakThis)
                 return;
 
@@ -565,7 +565,7 @@
                 updateExpiration(std::numeric_limits<double>::quiet_NaN());
 
                 // 4.5.3. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
-                if (succeeded == CDMInstance::SuccessValue::Failed) {
+                if (succeeded == CDMInstanceSession::SuccessValue::Failed) {
                     promise->reject(NotSupportedError);
                     return;
                 }
@@ -599,7 +599,7 @@
     m_eventQueue.enqueueEvent(WTFMove(messageEvent));
 }
 
-void MediaKeySession::updateKeyStatuses(CDMInstanceClient::KeyStatusVector&& inputStatuses)
+void MediaKeySession::updateKeyStatuses(CDMInstanceSession::KeyStatusVector&& inputStatuses)
 {
     // https://w3c.github.io/encrypted-media/#update-key-statuses
     // W3C Editor's Draft 09 November 2016
@@ -613,21 +613,21 @@
     //     4.2.1. Let pair be the pair.
     //     4.2.2. Insert an entry for pair's key ID into statuses with the value of pair's MediaKeyStatus value.
 
-    static auto toMediaKeyStatus = [] (CDMInstance::KeyStatus status) -> MediaKeyStatus {
+    static auto toMediaKeyStatus = [] (CDMInstanceSession::KeyStatus status) -> MediaKeyStatus {
         switch (status) {
-        case CDMInstance::KeyStatus::Usable:
+        case CDMInstanceSession::KeyStatus::Usable:
             return MediaKeyStatus::Usable;
-        case CDMInstance::KeyStatus::Expired:
+        case CDMInstanceSession::KeyStatus::Expired:
             return MediaKeyStatus::Expired;
-        case CDMInstance::KeyStatus::Released:
+        case CDMInstanceSession::KeyStatus::Released:
             return MediaKeyStatus::Released;
-        case CDMInstance::KeyStatus::OutputRestricted:
+        case CDMInstanceSession::KeyStatus::OutputRestricted:
             return MediaKeyStatus::OutputRestricted;
-        case CDMInstance::KeyStatus::OutputDownscaled:
+        case CDMInstanceSession::KeyStatus::OutputDownscaled:
             return MediaKeyStatus::OutputDownscaled;
-        case CDMInstance::KeyStatus::StatusPending:
+        case CDMInstanceSession::KeyStatus::StatusPending:
             return MediaKeyStatus::StatusPending;
-        case CDMInstance::KeyStatus::InternalError:
+        case CDMInstanceSession::KeyStatus::InternalError:
             return MediaKeyStatus::InternalError;
         };
 
@@ -666,7 +666,7 @@
     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->storeRecordOfKeyUsage(m_sessionId);
+        m_instanceSession->storeRecordOfKeyUsage(m_sessionId);
     }
 
     // 3. Run the Update Key Statuses algorithm on the session, providing an empty sequence.

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h (236316 => 236317)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -31,7 +31,7 @@
 #if ENABLE(ENCRYPTED_MEDIA)
 
 #include "ActiveDOMObject.h"
-#include "CDMInstance.h"
+#include "CDMInstanceSession.h"
 #include "DOMPromiseProxy.h"
 #include "EventTarget.h"
 #include "GenericEventQueue.h"
@@ -52,9 +52,9 @@
 class MediaKeys;
 class SharedBuffer;
 
-class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject, public CanMakeWeakPtr<MediaKeySession>, public CDMInstanceClient {
+class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject, public CanMakeWeakPtr<MediaKeySession>, public CDMInstanceSessionClient {
 public:
-    static Ref<MediaKeySession> create(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&);
+    static Ref<MediaKeySession> create(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstanceSession>&&);
     virtual ~MediaKeySession();
 
     using RefCounted<MediaKeySession>::ref;
@@ -78,14 +78,14 @@
     const Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>>& statuses() const { return m_statuses; }
 
 private:
-    MediaKeySession(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&);
+    MediaKeySession(ScriptExecutionContext&, WeakPtr<MediaKeys>&&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstanceSession>&&);
     void enqueueMessage(MediaKeyMessageType, const SharedBuffer&);
     void updateExpiration(double);
     void sessionClosed();
     String mediaKeysStorageDirectory() const;
 
-    // CDMInstanceClient
-    void updateKeyStatuses(CDMInstanceClient::KeyStatusVector&&) override;
+    // CDMInstanceSessionClient
+    void updateKeyStatuses(CDMInstanceSessionClient::KeyStatusVector&&) override;
 
     // EventTarget
     EventTargetInterface eventTargetInterface() const override { return MediaKeySessionEventTargetInterfaceType; }
@@ -110,7 +110,7 @@
     bool m_useDistinctiveIdentifier;
     MediaKeySessionType m_sessionType;
     Ref<CDM> m_implementation;
-    Ref<CDMInstance> m_instance;
+    Ref<CDMInstanceSession> m_instanceSession;
     GenericEventQueue m_eventQueue;
     GenericTaskQueue<Timer> m_taskQueue;
     Vector<Ref<SharedBuffer>> m_recordOfKeyUsage;
@@ -117,6 +117,7 @@
     double m_firstDecryptTime { 0 };
     double m_latestDecryptTime { 0 };
     Vector<std::pair<Ref<SharedBuffer>, MediaKeyStatus>> m_statuses;
+    WeakPtrFactory<CDMInstanceSessionClient> m_cdmInstanceClientWeakPtrFactory;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp (236316 => 236317)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2018-09-21 15:08:35 UTC (rev 236317)
@@ -64,10 +64,14 @@
     if (!m_implementation->supportsSessions())
         return Exception(InvalidStateError);
 
+    auto instanceSession = m_instance->createSession();
+    if (!instanceSession)
+        return Exception(InvalidStateError);
+
     // 3. Let session be a new MediaKeySession object, and initialize it as follows:
     // NOTE: Continued in MediaKeySession.
     // 4. Return session.
-    auto session = MediaKeySession::create(context, makeWeakPtr(*this), sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), m_instance.copyRef());
+    auto session = MediaKeySession::create(context, makeWeakPtr(*this), sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), instanceSession.releaseNonNull());
     m_sessions.append(session.copyRef());
     return WTFMove(session);
 }

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (236316 => 236317)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-09-21 15:08:35 UTC (rev 236317)
@@ -13324,6 +13324,7 @@
 		CD94A5D61F71CB6D00F525C5 /* CDMMessageType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMMessageType.h; sourceTree = "<group>"; };
 		CD94A5DA1F71CBB000F525C5 /* CDMClearKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMClearKey.h; sourceTree = "<group>"; };
 		CD94A5DB1F71CBB000F525C5 /* CDMClearKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CDMClearKey.cpp; sourceTree = "<group>"; };
+		CD9D375A215163E40049657B /* CDMInstanceSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDMInstanceSession.h; sourceTree = "<group>"; };
 		CD9D82731C7AE535006FF066 /* TextureCacheCV.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextureCacheCV.mm; sourceTree = "<group>"; };
 		CD9D82741C7AE535006FF066 /* TextureCacheCV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCacheCV.h; sourceTree = "<group>"; };
 		CD9D82771C7B8EE1006FF066 /* VideoTextureCopierCV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoTextureCopierCV.cpp; sourceTree = "<group>"; };
@@ -24777,6 +24778,7 @@
 				CD94A5D11F71CB6B00F525C5 /* CDMFactory.cpp */,
 				CD94A5D21F71CB6B00F525C5 /* CDMFactory.h */,
 				CD94A5CE1F71CB6A00F525C5 /* CDMInstance.h */,
+				CD9D375A215163E40049657B /* CDMInstanceSession.h */,
 				CD94A5D41F71CB6C00F525C5 /* CDMKeyStatus.h */,
 				CD94A5CD1F71CB6900F525C5 /* CDMKeySystemConfiguration.h */,
 				CD94A5D31F71CB6C00F525C5 /* CDMMediaCapability.h */,

Modified: trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h (236316 => 236317)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -41,17 +41,9 @@
 
 class SharedBuffer;
 
+class CDMInstanceSession;
 struct CDMKeySystemConfiguration;
 
-class CDMInstanceClient {
-public:
-    virtual ~CDMInstanceClient() = default;
-
-    using KeyStatus = CDMKeyStatus;
-    using KeyStatusVector = Vector<std::pair<Ref<SharedBuffer>, KeyStatus>>;
-    virtual void updateKeyStatuses(KeyStatusVector&&) = 0;
-};
-
 class CDMInstance : public RefCounted<CDMInstance> {
 public:
     virtual ~CDMInstance() = default;
@@ -61,7 +53,6 @@
         ClearKey,
         FairPlayStreaming,
     };
-
     virtual ImplementationType implementationType() const = 0;
 
     enum SuccessValue {
@@ -69,15 +60,13 @@
         Succeeded,
     };
 
-    using KeyStatus = CDMKeyStatus;
-    using LicenseType = CDMSessionType;
-    using MessageType = CDMMessageType;
-
     virtual SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) = 0;
     virtual SuccessValue setDistinctiveIdentifiersAllowed(bool) = 0;
     virtual SuccessValue setPersistentStateAllowed(bool) = 0;
     virtual SuccessValue setServerCertificate(Ref<SharedBuffer>&&) = 0;
     virtual SuccessValue setStorageDirectory(const String&) = 0;
+    virtual const String& keySystem() const = 0;
+    virtual RefPtr<CDMInstanceSession> createSession() = 0;
 
     enum class HDCPStatus {
         Unknown,
@@ -86,38 +75,6 @@
         OutputDownscaled,
     };
     virtual SuccessValue setHDCPStatus(HDCPStatus) { return Failed; }
-
-    virtual void setClient(CDMInstanceClient&) { }
-    virtual void clearClient() { }
-
-    using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>;
-    virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) = 0;
-
-    using KeyStatusVector = CDMInstanceClient::KeyStatusVector;
-    using Message = std::pair<MessageType, Ref<SharedBuffer>>;
-    using LicenseUpdateCallback = Function<void(bool sessionWasClosed, std::optional<KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<Message>&& message, SuccessValue succeeded)>;
-    virtual void updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback) = 0;
-
-    enum class SessionLoadFailure {
-        None,
-        NoSessionData,
-        MismatchedSessionType,
-        QuotaExceeded,
-        Other,
-    };
-
-    using LoadSessionCallback = Function<void(std::optional<KeyStatusVector>&&, std::optional<double>&&, std::optional<Message>&&, SuccessValue, SessionLoadFailure)>;
-    virtual void loadSession(LicenseType, const String& sessionId, const String& origin, LoadSessionCallback) = 0;
-
-    using CloseSessionCallback = Function<void()>;
-    virtual void closeSession(const String& sessionId, CloseSessionCallback) = 0;
-
-    using RemoveSessionDataCallback = Function<void(KeyStatusVector&&, std::optional<Ref<SharedBuffer>>&&, SuccessValue)>;
-    virtual void removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback) = 0;
-
-    virtual void storeRecordOfKeyUsage(const String& sessionId) = 0;
-
-    virtual const String& keySystem() const = 0;
 };
 
 } // namespace WebCore

Copied: trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h (from rev 236316, trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h) (0 => 236317)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "CDMKeyStatus.h"
+#include "CDMMessageType.h"
+#include "CDMSessionType.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+class CDMInstanceSessionClient {
+public:
+    virtual ~CDMInstanceSessionClient() = default;
+
+    using KeyStatus = CDMKeyStatus;
+    using KeyStatusVector = Vector<std::pair<Ref<SharedBuffer>, KeyStatus>>;
+    virtual void updateKeyStatuses(KeyStatusVector&&) = 0;
+};
+
+class CDMInstanceSession : public RefCounted<CDMInstanceSession> {
+public:
+    virtual ~CDMInstanceSession() = default;
+
+    using KeyStatus = CDMKeyStatus;
+    using LicenseType = CDMSessionType;
+    using MessageType = CDMMessageType;
+
+    virtual void setClient(WeakPtr<CDMInstanceSessionClient>&&) { }
+    virtual void clearClient() { }
+
+    enum SuccessValue {
+        Failed,
+        Succeeded,
+    };
+
+    using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>;
+    virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&&) = 0;
+
+    using KeyStatusVector = CDMInstanceSessionClient::KeyStatusVector;
+    using Message = std::pair<MessageType, Ref<SharedBuffer>>;
+    using LicenseUpdateCallback = Function<void(bool sessionWasClosed, std::optional<KeyStatusVector>&& changedKeys, std::optional<double>&& changedExpiration, std::optional<Message>&& message, SuccessValue succeeded)>;
+    virtual void updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback&&) = 0;
+
+    enum class SessionLoadFailure {
+        None,
+        NoSessionData,
+        MismatchedSessionType,
+        QuotaExceeded,
+        Other,
+    };
+
+    using LoadSessionCallback = Function<void(std::optional<KeyStatusVector>&&, std::optional<double>&&, std::optional<Message>&&, SuccessValue, SessionLoadFailure)>;
+    virtual void loadSession(LicenseType, const String& sessionId, const String& origin, LoadSessionCallback&&) = 0;
+
+    using CloseSessionCallback = Function<void()>;
+    virtual void closeSession(const String& sessionId, CloseSessionCallback&&) = 0;
+
+    using RemoveSessionDataCallback = Function<void(KeyStatusVector&&, std::optional<Ref<SharedBuffer>>&&, SuccessValue)>;
+    virtual void removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback&&) = 0;
+
+    virtual void storeRecordOfKeyUsage(const String& sessionId) = 0;
+};
+
+} // namespace WebCore
+
+#define SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(ToValueTypeName, ImplementationTypeName) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \
+static bool isType(const WebCore::CDMInstance& instance) { return instance.implementationType() == ImplementationTypeName; } \
+SPECIALIZE_TYPE_TRAITS_END()
+
+#endif

Modified: trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp (236316 => 236317)


--- trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.cpp	2018-09-21 15:08:35 UTC (rev 236317)
@@ -40,7 +40,6 @@
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/Base64.h>
 
-
 namespace WebCore {
 
 // ClearKey CENC SystemID.
@@ -120,7 +119,7 @@
             if (!WTF::base64URLDecode(keyID, { keyIDData }) || !WTF::base64URLDecode(keyValue, { keyValueData }))
                 return false;
 
-            decodedKeys.append({ CDMInstanceClearKey::KeyStatus::Usable, SharedBuffer::create(WTFMove(keyIDData)), SharedBuffer::create(WTFMove(keyValueData)) });
+            decodedKeys.append({ CDMInstanceSession::KeyStatus::Usable, SharedBuffer::create(WTFMove(keyIDData)), SharedBuffer::create(WTFMove(keyValueData)) });
             return true;
         });
     if (!validFormat)
@@ -493,8 +492,35 @@
     return storageDirectory.isEmpty() ? Succeeded : Failed;
 }
 
-void CDMInstanceClearKey::requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback)
+const String& CDMInstanceClearKey::keySystem() const
 {
+    static const NeverDestroyed<String> s_keySystem { MAKE_STATIC_STRING_IMPL("org.w3.clearkey") };
+
+    return s_keySystem;
+}
+
+RefPtr<CDMInstanceSession> CDMInstanceClearKey::createSession()
+{
+    return adoptRef(new CDMInstanceSessionClearKey());
+}
+
+const Vector<CDMInstanceClearKey::Key> CDMInstanceClearKey::keys() const
+{
+    // Return the keys of all sessions.
+    Vector<CDMInstanceClearKey::Key> allKeys { };
+    size_t initialCapacity = 0;
+    for (auto& key : ClearKeyState::singleton().keys().values())
+        initialCapacity += key.size();
+    allKeys.reserveInitialCapacity(initialCapacity);
+
+    for (auto& key : ClearKeyState::singleton().keys().values())
+        allKeys.appendVector(key);
+
+    return allKeys;
+}
+
+void CDMInstanceSessionClearKey::requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&& callback)
+{
     static uint32_t s_sessionIdValue = 0;
     ++s_sessionIdValue;
 
@@ -513,18 +539,8 @@
         });
 }
 
-const Vector<CDMInstanceClearKey::Key> CDMInstanceClearKey::keys() const
+void CDMInstanceSessionClearKey::updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback&& callback)
 {
-    // Return the keys of all sessions.
-    Vector<CDMInstanceClearKey::Key> allKeys { };
-    for (auto& key : ClearKeyState::singleton().keys().values())
-        allKeys.appendVector(key);
-
-    return allKeys;
-}
-
-void CDMInstanceClearKey::updateLicense(const String& sessionId, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback)
-{
     // Use a helper functor that schedules the callback dispatch, avoiding
     // duplicated callOnMainThread() calls.
     auto dispatchCallback =
@@ -548,7 +564,7 @@
     // Parse the response using 'license' formatting, if possible.
     if (auto decodedKeys = parseLicenseFormat(*root)) {
         // Retrieve the target Vector of Key objects for this session.
-        auto& keyVector = ClearKeyState::singleton().keys().ensure(sessionId, [] { return Vector<Key> { }; }).iterator->value;
+        auto& keyVector = ClearKeyState::singleton().keys().ensure(sessionId, [] { return Vector<CDMInstanceClearKey::Key> { }; }).iterator->value;
 
         // For each decoded key, find an existing item for the decoded key's ID. If none exist,
         // the key is decoded. Otherwise, the key is updated in case there's a mismatch between
@@ -556,7 +572,7 @@
         bool keysChanged = false;
         for (auto& key : *decodedKeys) {
             auto it = std::find_if(keyVector.begin(), keyVector.end(),
-                [&key] (const Key& containedKey) {
+                [&key] (const CDMInstanceClearKey::Key& containedKey) {
                     return containedKey.keyIDData->size() == key.keyIDData->size()
                         && !std::memcmp(containedKey.keyIDData->data(), key.keyIDData->data(), containedKey.keyIDData->size());
                 });
@@ -624,7 +640,7 @@
     dispatchCallback(false, std::nullopt, SuccessValue::Failed);
 }
 
-void CDMInstanceClearKey::loadSession(LicenseType, const String& sessionId, const String&, LoadSessionCallback callback)
+void CDMInstanceSessionClearKey::loadSession(LicenseType, const String& sessionId, const String&, LoadSessionCallback&& callback)
 {
     // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls.
     auto dispatchCallback =
@@ -657,7 +673,7 @@
     dispatchCallback(WTFMove(keyStatusVector), Succeeded, SessionLoadFailure::None);
 }
 
-void CDMInstanceClearKey::closeSession(const String&, CloseSessionCallback callback)
+void CDMInstanceSessionClearKey::closeSession(const String&, CloseSessionCallback&& callback)
 {
     callOnMainThread(
         [weakThis = makeWeakPtr(*this), callback = WTFMove(callback)] {
@@ -668,7 +684,7 @@
         });
 }
 
-void CDMInstanceClearKey::removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback callback)
+void CDMInstanceSessionClearKey::removeSessionData(const String& sessionId, LicenseType, RemoveSessionDataCallback&& callback)
 {
     // Use a helper functor that schedules the callback dispatch, avoiding duplicated callOnMainThread() calls.
     auto dispatchCallback =
@@ -726,17 +742,10 @@
     dispatchCallback(WTFMove(keyStatusVector), Ref<SharedBuffer>(*message), SuccessValue::Succeeded);
 }
 
-void CDMInstanceClearKey::storeRecordOfKeyUsage(const String&)
+void CDMInstanceSessionClearKey::storeRecordOfKeyUsage(const String&)
 {
 }
 
-const String& CDMInstanceClearKey::keySystem() const
-{
-    static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.w3.clearkey");
-
-    return s_keySystem;
-}
-
 } // namespace WebCore
 
 #endif // ENABLE(ENCRYPTED_MEDIA)

Modified: trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h (236316 => 236317)


--- trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/platform/encryptedmedia/clearkey/CDMClearKey.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -32,6 +32,7 @@
 
 #include "CDMFactory.h"
 #include "CDMInstance.h"
+#include "CDMInstanceSession.h"
 #include "CDMPrivate.h"
 #include "SharedBuffer.h"
 #include <wtf/WeakPtr.h>
@@ -44,8 +45,8 @@
 
     virtual ~CDMFactoryClearKey();
 
-    std::unique_ptr<CDMPrivate> createCDM(const String&) override;
-    bool supportsKeySystem(const String&) override;
+    std::unique_ptr<CDMPrivate> createCDM(const String&) final;
+    bool supportsKeySystem(const String&) final;
 
 private:
     friend class NeverDestroyed<CDMFactoryClearKey>;
@@ -57,21 +58,21 @@
     CDMPrivateClearKey();
     virtual ~CDMPrivateClearKey();
 
-    bool supportsInitDataType(const AtomicString&) const override;
-    bool supportsConfiguration(const CDMKeySystemConfiguration&) const override;
-    bool supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override;
-    bool supportsSessionTypeWithConfiguration(CDMSessionType&, const CDMKeySystemConfiguration&) const override;
-    bool supportsRobustness(const String&) const override;
-    CDMRequirement distinctiveIdentifiersRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override;
-    CDMRequirement persistentStateRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override;
-    bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const CDMKeySystemConfiguration&) const override;
-    RefPtr<CDMInstance> createInstance() override;
-    void loadAndInitialize() override;
-    bool supportsServerCertificates() const override;
-    bool supportsSessions() const override;
-    bool supportsInitData(const AtomicString&, const SharedBuffer&) const override;
-    RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const override;
-    std::optional<String> sanitizeSessionId(const String&) const override;
+    bool supportsInitDataType(const AtomicString&) const final;
+    bool supportsConfiguration(const CDMKeySystemConfiguration&) const final;
+    bool supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final;
+    bool supportsSessionTypeWithConfiguration(CDMSessionType&, const CDMKeySystemConfiguration&) const final;
+    bool supportsRobustness(const String&) const final;
+    CDMRequirement distinctiveIdentifiersRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final;
+    CDMRequirement persistentStateRequirement(const CDMKeySystemConfiguration&, const CDMRestrictions&) const final;
+    bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const CDMKeySystemConfiguration&) const final;
+    RefPtr<CDMInstance> createInstance() final;
+    void loadAndInitialize() final;
+    bool supportsServerCertificates() const final;
+    bool supportsSessions() const final;
+    bool supportsInitData(const AtomicString&, const SharedBuffer&) const final;
+    RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const final;
+    std::optional<String> sanitizeSessionId(const String&) const final;
 };
 
 class CDMInstanceClearKey final : public CDMInstance, public CanMakeWeakPtr<CDMInstanceClearKey> {
@@ -81,23 +82,16 @@
 
     ImplementationType implementationType() const final { return ImplementationType::ClearKey; }
 
-    SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) override;
-    SuccessValue setDistinctiveIdentifiersAllowed(bool) override;
-    SuccessValue setPersistentStateAllowed(bool) override;
-    SuccessValue setServerCertificate(Ref<SharedBuffer>&&) override;
-    SuccessValue setStorageDirectory(const String&) override;
-
-    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) override;
-    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) override;
-    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) override;
-    void closeSession(const String&, CloseSessionCallback) override;
-    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) override;
-    void storeRecordOfKeyUsage(const String&) override;
-
+    SuccessValue initializeWithConfiguration(const CDMKeySystemConfiguration&) final;
+    SuccessValue setDistinctiveIdentifiersAllowed(bool) final;
+    SuccessValue setPersistentStateAllowed(bool) final;
+    SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final;
+    SuccessValue setStorageDirectory(const String&) final;
     const String& keySystem() const final;
+    RefPtr<CDMInstanceSession> createSession() final;
 
     struct Key {
-        KeyStatus status;
+        CDMInstanceSession::KeyStatus status;
         RefPtr<SharedBuffer> keyIDData;
         RefPtr<SharedBuffer> keyValueData;
     };
@@ -105,6 +99,16 @@
     const Vector<Key> keys() const;
 };
 
+class CDMInstanceSessionClearKey final : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionClearKey> {
+public:
+    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&&) final;
+    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback&&) final;
+    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback&&) final;
+    void closeSession(const String&, CloseSessionCallback&&) final;
+    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback&&) final;
+    void storeRecordOfKeyUsage(const String&) final;
+};
+
 } // namespace WebCore
 
 SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(WebCore::CDMInstanceClearKey, WebCore::CDMInstance::ImplementationType::ClearKey);

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h (236316 => 236317)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -28,9 +28,10 @@
 #if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
 
 #include "CDMInstance.h"
+#include "CDMInstanceSession.h"
 #include <wtf/Function.h>
+#include <wtf/HashMap.h>
 #include <wtf/RetainPtr.h>
-#include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
 OBJC_CLASS AVContentKeyRequest;
@@ -42,6 +43,8 @@
 
 namespace WebCore {
 
+class CDMInstanceSessionFairPlayStreamingAVFObjC;
+
 class CDMInstanceFairPlayStreamingAVFObjC final : public CDMInstance, public CanMakeWeakPtr<CDMInstanceFairPlayStreamingAVFObjC> {
 public:
     CDMInstanceFairPlayStreamingAVFObjC();
@@ -58,15 +61,9 @@
     SuccessValue setPersistentStateAllowed(bool) final;
     SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final;
     SuccessValue setStorageDirectory(const String&) final;
+    RefPtr<CDMInstanceSession> createSession() final;
 
-    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final;
-    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final;
-    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final;
-    void closeSession(const String&, CloseSessionCallback) final;
-    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final;
-    void storeRecordOfKeyUsage(const String&) final;
-    void setClient(CDMInstanceClient&) final;
-    void clearClient() final;
+    void processContentKeyRequestForSession(CDMInstanceSessionFairPlayStreamingAVFObjC&, RetainPtr<NSString>&& identifier, RetainPtr<NSData>&& initData);
 
     const String& keySystem() const final;
 
@@ -79,21 +76,62 @@
     void sessionIdentifierChanged(NSData *);
     void outputObscuredDueToInsufficientExternalProtectionChanged(bool);
 
+    NSURL *storageDirectory() const { return m_storageDirectory.get(); }
     AVContentKeySession *contentKeySession() { return m_session.get(); }
+    bool persistentStateAllowed() const { return m_persistentStateAllowed; }
+    SharedBuffer* serverCertificate() const { return m_serverCertificate.get(); }
 
 private:
-    bool isLicenseTypeSupported(LicenseType) const;
+    void processNextContentKeyRequest();
 
-    Vector<Ref<SharedBuffer>> keyIDs();
+    struct ContentKeyRequest {
+        WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> sessionInstance;
+        RetainPtr<NSString> identifier;
+        RetainPtr<NSData> initData;
+    };
+    Vector<ContentKeyRequest> m_currentRequests;
 
+    HashMap<RetainPtr<AVContentKeyRequest>, WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC>> m_requestMap;
+
     RefPtr<SharedBuffer> m_serverCertificate;
     bool m_persistentStateAllowed { true };
     RetainPtr<NSURL> m_storageDirectory;
     RetainPtr<AVContentKeySession> m_session;
+    RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate;
+};
+
+class CDMInstanceSessionFairPlayStreamingAVFObjC final : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> {
+public:
+    CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&&);
+
+    // CDMInstanceSession
+    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&&) final;
+    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback&&) final;
+    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback&&) final;
+    void closeSession(const String&, CloseSessionCallback&&) final;
+    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback&&) final;
+    void storeRecordOfKeyUsage(const String&) final;
+    void setClient(WeakPtr<CDMInstanceSessionClient>&&) final;
+    void clearClient() final;
+
+    void didProvideRequest(AVContentKeyRequest*);
+    void didProvideRenewingRequest(AVContentKeyRequest*);
+    void didProvidePersistableRequest(AVContentKeyRequest*);
+    void didFailToProvideRequest(AVContentKeyRequest*, NSError*);
+    void requestDidSucceed(AVContentKeyRequest*);
+    bool shouldRetryRequestForReason(AVContentKeyRequest*, NSString*);
+    void sessionIdentifierChanged(NSData*);
+    void outputObscuredDueToInsufficientExternalProtectionChanged(bool);
+
+    Vector<Ref<SharedBuffer>> keyIDs();
+
+private:
+    bool isLicenseTypeSupported(LicenseType) const;
+
+    Ref<CDMInstanceFairPlayStreamingAVFObjC> m_instance;
     RetainPtr<AVContentKeyRequest> m_request;
-    RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate;
     Vector<RetainPtr<NSData>> m_expiredSessions;
-    CDMInstanceClient* m_client;
+    WeakPtr<CDMInstanceSessionClient> m_client;
     String m_sessionId;
 
     LicenseCallback m_requestLicenseCallback;
@@ -101,6 +139,7 @@
     CloseSessionCallback m_closeSessionCallback;
     RemoveSessionDataCallback m_removeSessionDataCallback;
 };
+
 }
 
 SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(WebCore::CDMInstanceFairPlayStreamingAVFObjC, WebCore::CDMInstance::ImplementationType::FairPlayStreaming)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm (236316 => 236317)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2018-09-21 15:08:35 UTC (rev 236317)
@@ -221,20 +221,123 @@
     return Succeeded;
 }
 
-bool CDMInstanceFairPlayStreamingAVFObjC::isLicenseTypeSupported(LicenseType licenseType) const
+RefPtr<CDMInstanceSession> CDMInstanceFairPlayStreamingAVFObjC::createSession()
 {
-    switch (licenseType) {
-    case CDMSessionType::PersistentLicense:
-        return m_persistentStateAllowed && supportsPersistentKeys();
-    case CDMSessionType::PersistentUsageRecord:
-        return m_persistentStateAllowed && supportsPersistableState();
-    case CDMSessionType::Temporary:
-        return true;
+    return adoptRef(new CDMInstanceSessionFairPlayStreamingAVFObjC(*this));
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::processContentKeyRequestForSession(CDMInstanceSessionFairPlayStreamingAVFObjC& session, RetainPtr<NSString>&& identifier, RetainPtr<NSData>&& initData)
+{
+    m_currentRequests.append({ makeWeakPtr(session), WTFMove(identifier), WTFMove(initData) });
+    if (m_currentRequests.size() == 1)
+        processNextContentKeyRequest();
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::processNextContentKeyRequest()
+{
+    if (m_currentRequests.isEmpty())
+        return;
+
+    auto& nextRequest = m_currentRequests.first();
+    [m_session processContentKeyRequestWithIdentifier:nextRequest.identifier.get() initializationData:nextRequest.initData.get() options:nil];
+}
+
+const String& CDMInstanceFairPlayStreamingAVFObjC::keySystem() const
+{
+    static NeverDestroyed<String> keySystem { "com.apple.fps"_s };
+    return keySystem;
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request)
+{
+    if (m_currentRequests.isEmpty())
+        return;
+
+    auto currentRequest = WTFMove(m_currentRequests.first());
+    m_currentRequests.remove(0);
+
+    if (!currentRequest.sessionInstance)
+        return;
+
+    m_requestMap.set(request, currentRequest.sessionInstance);
+    currentRequest.sessionInstance->didProvideRequest(request);
+    processNextContentKeyRequest();
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)
+{
+    if (m_currentRequests.isEmpty())
+        return;
+
+    auto currentRequest = WTFMove(m_currentRequests.first());
+    m_currentRequests.remove(0);
+
+    if (!currentRequest.sessionInstance)
+        return;
+
+    m_requestMap.set(request, currentRequest.sessionInstance);
+    currentRequest.sessionInstance->didProvideRenewingRequest(request);
+    processNextContentKeyRequest();
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request)
+{
+    if (m_currentRequests.isEmpty())
+        return;
+
+    auto currentRequest = WTFMove(m_currentRequests.first());
+    m_currentRequests.remove(0);
+
+    if (!currentRequest.sessionInstance)
+        return;
+
+    m_requestMap.set(request, currentRequest.sessionInstance);
+    currentRequest.sessionInstance->didProvidePersistableRequest(request);
+    processNextContentKeyRequest();
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error)
+{
+    if (auto sessionInterface = m_requestMap.get(request))
+        sessionInterface->didFailToProvideRequest(request, error);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
+{
+    if (auto sessionInterface = m_requestMap.get(request))
+        sessionInterface->requestDidSucceed(request);
+}
+
+bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
+{
+    if (auto sessionInterface = m_requestMap.get(request))
+        return sessionInterface->shouldRetryRequestForReason(request, reason);
+    return false;
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier)
+{
+    for (auto sessionInterface : m_requestMap.values()) {
+        if (sessionInterface)
+            sessionInterface->sessionIdentifierChanged(sessionIdentifier);
     }
 }
 
-Vector<Ref<SharedBuffer>> CDMInstanceFairPlayStreamingAVFObjC::keyIDs()
+void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
 {
+    for (auto sessionInterface : m_requestMap.values()) {
+        if (sessionInterface)
+            sessionInterface->outputObscuredDueToInsufficientExternalProtectionChanged(obscured);
+    }
+}
+
+CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&& instance)
+    : m_instance(WTFMove(instance))
+{
+}
+
+Vector<Ref<SharedBuffer>> CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs()
+{
     // FIXME(rdar://problem/35597141): use the future AVContentKeyRequest keyID property, rather than parsing it out of the init
     // data, to get the keyID.
     if ([m_request.get().identifier isKindOfClass:[NSString class]])
@@ -250,7 +353,7 @@
     return { };
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&& callback)
 {
     if (!isLicenseTypeSupported(licenseType)) {
         callback(SharedBuffer::create(), emptyString(), false, Failed);
@@ -257,7 +360,7 @@
         return;
     }
 
-    if (!m_serverCertificate) {
+    if (!m_instance->serverCertificate()) {
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
@@ -275,7 +378,7 @@
     }
 
     m_requestLicenseCallback = WTFMove(callback);
-    [m_session processContentKeyRequestWithIdentifier:identifier.get() initializationData:initializationData.get() options:nil];
+    m_instance->processContentKeyRequestForSession(*this, WTFMove(identifier), WTFMove(initializationData));
 }
 
 static bool isEqual(const SharedBuffer& data, const String& value)
@@ -296,14 +399,23 @@
     return stringOrException.returnValue() == value;
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer& responseData, LicenseUpdateCallback callback)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer& responseData, LicenseUpdateCallback&& callback)
 {
     if (!m_expiredSessions.isEmpty() && isEqual(responseData, "acknowledged"_s)) {
         auto expiredSessions = adoptNS([[NSMutableArray alloc] init]);
         for (auto& session : m_expiredSessions)
-            [expiredSessions addObject:session.get()]; 
-        RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData();
-        [getAVContentKeySessionClass() removePendingExpiredSessionReports:expiredSessions.get() withAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()];
+            [expiredSessions addObject:session.get()];
+
+        auto* certificate = m_instance->serverCertificate();
+        auto* storageDirectory = m_instance->storageDirectory();
+
+        if (!certificate || !storageDirectory) {
+            callback(false, std::nullopt, std::nullopt, std::nullopt, Failed);
+            return;
+        }
+
+        RetainPtr<NSData> appIdentifier = certificate->createNSData();
+        [getAVContentKeySessionClass() removePendingExpiredSessionReports:expiredSessions.get() withAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory];
         callback(false, { }, std::nullopt, std::nullopt, Succeeded);
         return;
     }
@@ -333,22 +445,24 @@
     m_updateLicenseCallback = WTFMove(callback);
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::loadSession(LicenseType licenseType, const String& sessionId, const String& origin, LoadSessionCallback callback)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession(LicenseType licenseType, const String& sessionId, const String& origin, LoadSessionCallback&& callback)
 {
     UNUSED_PARAM(origin);
     if (licenseType == LicenseType::PersistentUsageRecord) {
-        if (!m_persistentStateAllowed || !m_storageDirectory) {
+        auto* storageDirectory = m_instance->storageDirectory();
+        if (!m_instance->persistentStateAllowed() || storageDirectory) {
             callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::MismatchedSessionType);
             return;
         }
-        if (!m_serverCertificate) {
-            callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::Other);
+        auto* certificate = m_instance->serverCertificate();
+        if (!certificate) {
+            callback(std::nullopt, std::nullopt, std::nullopt, Failed, SessionLoadFailure::NoSessionData);
             return;
         }
 
-        RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData();
+        RetainPtr<NSData> appIdentifier = certificate->createNSData();
         KeyStatusVector changedKeys;
-        for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()]) {
+        for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory]) {
             NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
             NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
             if (![playbackSessionIdValue isKindOfClass:[NSString class]])
@@ -370,7 +484,7 @@
     }
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessionCallback callback)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessionCallback&& callback)
 {
     if (m_requestLicenseCallback) {
         m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
@@ -384,25 +498,28 @@
         m_removeSessionDataCallback({ }, std::nullopt, Failed);
         m_removeSessionDataCallback = nullptr;
     }
-    m_session = nullptr;
     m_request = nullptr;
     callback();
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::removeSessionData(const String& sessionId, LicenseType licenseType, RemoveSessionDataCallback callback)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData(const String& sessionId, LicenseType licenseType, RemoveSessionDataCallback&& callback)
 {
-    [m_session expire];
+    // FIXME: We should be able to expire individual AVContentKeyRequests rather than the entire AVContentKeySession.
+    [m_instance->contentKeySession() expire];
 
     if (licenseType == LicenseType::PersistentUsageRecord) {
-        if (!m_persistentStateAllowed || !m_storageDirectory || !m_serverCertificate) {
+        auto* storageDirectory = m_instance->storageDirectory();
+        auto* certificate = m_instance->serverCertificate();
+
+        if (!m_instance->persistentStateAllowed() || !storageDirectory || !certificate) {
             callback({ }, std::nullopt, Failed);
             return;
         }
 
-        RetainPtr<NSData> appIdentifier = m_serverCertificate->createNSData();
+        RetainPtr<NSData> appIdentifier = certificate->createNSData();
         RetainPtr<NSMutableArray> expiredSessionsArray = adoptNS([[NSMutableArray alloc] init]);
         KeyStatusVector changedKeys;
-        for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:m_storageDirectory.get()]) {
+        for (NSData* expiredSessionData in [getAVContentKeySessionClass() pendingExpiredSessionReportsWithAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageDirectory]) {
             NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
             NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
             if (![playbackSessionIdValue isKindOfClass:[NSString class]])
@@ -422,34 +539,30 @@
     }
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::storeRecordOfKeyUsage(const String&)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::storeRecordOfKeyUsage(const String&)
 {
     // no-op; key usage data is stored automatically.
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::setClient(CDMInstanceClient& client)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::setClient(WeakPtr<CDMInstanceSessionClient>&& client)
 {
-    m_client = &client;
+    m_client = WTFMove(client);
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::clearClient()
+void CDMInstanceSessionFairPlayStreamingAVFObjC::clearClient()
 {
     m_client = nullptr;
 }
 
-const String& CDMInstanceFairPlayStreamingAVFObjC::keySystem() const
+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request)
 {
-    static NeverDestroyed<String> s_keySystem { "com.apple.fps"_s };
-    return s_keySystem;
-}
-
-void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request)
-{
     m_request = request;
     if (!m_requestLicenseCallback)
         return;
 
-    RetainPtr<NSData> appIdentifier = m_serverCertificate ? m_serverCertificate->createNSData() : nullptr;
+    RetainPtr<NSData> appIdentifier;
+    if (auto* certificate = m_instance->serverCertificate())
+        appIdentifier = certificate->createNSData();
     Vector<Ref<SharedBuffer>> keyIDs = this->keyIDs();
 
     if (keyIDs.isEmpty()) {
@@ -473,17 +586,17 @@
     }];
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)
 {
     UNUSED_PARAM(request);
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request)
 {
     UNUSED_PARAM(request);
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error)
 {
     UNUSED_PARAM(request);
     UNUSED_PARAM(error);
@@ -491,7 +604,7 @@
         m_updateLicenseCallback(false, std::nullopt, std::nullopt, std::nullopt, Failed);
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
 {
     UNUSED_PARAM(request);
     if (!m_updateLicenseCallback)
@@ -504,7 +617,7 @@
     m_updateLicenseCallback(false, std::make_optional(WTFMove(keyStatuses)), std::nullopt, std::nullopt, Succeeded);
 }
 
-bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
+bool CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
 {
     UNUSED_PARAM(request);
     UNUSED_PARAM(reason);
@@ -512,7 +625,7 @@
     return false;
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier)
 {
     if (!sessionIdentifier) {
         m_sessionId = emptyString();
@@ -523,7 +636,7 @@
     m_sessionId = sessionIdentifierString.get();
 }
 
-void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
+void CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
 {
     if (!m_client || !m_request)
         return;
@@ -556,6 +669,18 @@
     m_client->updateKeyStatuses(WTFMove(keyStatuses));
 }
 
+bool CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported(LicenseType licenseType) const
+{
+    switch (licenseType) {
+    case CDMSessionType::PersistentLicense:
+        return m_instance->persistentStateAllowed() && m_instance->supportsPersistentKeys();
+    case CDMSessionType::PersistentUsageRecord:
+        return m_instance->persistentStateAllowed() && m_instance->supportsPersistableState();
+    case CDMSessionType::Temporary:
+        return true;
+    }
 }
 
+}
+
 #endif // ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)

Modified: trunk/Source/WebCore/testing/MockCDMFactory.cpp (236316 => 236317)


--- trunk/Source/WebCore/testing/MockCDMFactory.cpp	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/testing/MockCDMFactory.cpp	2018-09-21 15:08:35 UTC (rev 236317)
@@ -269,9 +269,26 @@
     return Succeeded;
 }
 
-void MockCDMInstance::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback)
+const String& MockCDMInstance::keySystem() const
 {
-    MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+    static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.webkit.mock");
+
+    return s_keySystem;
+}
+
+RefPtr<CDMInstanceSession> MockCDMInstance::createSession()
+{
+    return adoptRef(new MockCDMInstanceSession(makeWeakPtr(*this)));
+}
+
+MockCDMInstanceSession::MockCDMInstanceSession(WeakPtr<MockCDMInstance>&& instance)
+    : m_instance(WTFMove(instance))
+{
+}
+
+void MockCDMInstanceSession::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&& callback)
+{
+    MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr;
     if (!factory) {
         callback(SharedBuffer::create(), emptyAtom(), false, SuccessValue::Failed);
         return;
@@ -295,9 +312,9 @@
     callback(SharedBuffer::create(license.data(), license.length()), sessionID, false, SuccessValue::Succeeded);
 }
 
-void MockCDMInstance::updateLicense(const String& sessionID, LicenseType, const SharedBuffer& response, LicenseUpdateCallback callback)
+void MockCDMInstanceSession::updateLicense(const String& sessionID, LicenseType, const SharedBuffer& response, LicenseUpdateCallback&& callback)
 {
-    MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+    MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr;
     if (!factory) {
         callback(false, std::nullopt, std::nullopt, std::nullopt, SuccessValue::Failed);
         return;
@@ -329,9 +346,9 @@
     callback(false, WTFMove(changedKeys), std::nullopt, std::nullopt, SuccessValue::Succeeded);
 }
 
-void MockCDMInstance::loadSession(LicenseType, const String&, const String&, LoadSessionCallback callback)
+void MockCDMInstanceSession::loadSession(LicenseType, const String&, const String&, LoadSessionCallback&& callback)
 {
-    MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+    MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr;
     if (!factory) {
         callback(std::nullopt, std::nullopt, std::nullopt, SuccessValue::Failed, SessionLoadFailure::Other);
         return;
@@ -345,9 +362,9 @@
     callback(std::nullopt, std::nullopt, WTFMove(message), SuccessValue::Succeeded, SessionLoadFailure::None);
 }
 
-void MockCDMInstance::closeSession(const String& sessionID, CloseSessionCallback callback)
+void MockCDMInstanceSession::closeSession(const String& sessionID, CloseSessionCallback&& callback)
 {
-    MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+    MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr;
     if (!factory) {
         callback();
         return;
@@ -357,9 +374,9 @@
     callback();
 }
 
-void MockCDMInstance::removeSessionData(const String& id, LicenseType, RemoveSessionDataCallback callback)
+void MockCDMInstanceSession::removeSessionData(const String& id, LicenseType, RemoveSessionDataCallback&& callback)
 {
-    MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+    MockCDMFactory* factory = m_instance ? m_instance->factory() : nullptr;
     if (!factory) {
         callback({ }, std::nullopt, SuccessValue::Failed);
         return;
@@ -375,18 +392,11 @@
     callback(WTFMove(keyStatusVector), SharedBuffer::create(message.data(), message.length()), SuccessValue::Succeeded);
 }
 
-void MockCDMInstance::storeRecordOfKeyUsage(const String&)
+void MockCDMInstanceSession::storeRecordOfKeyUsage(const String&)
 {
     // FIXME: This should be implemented along with the support for persistent-usage-record sessions.
 }
 
-const String& MockCDMInstance::keySystem() const
-{
-    static const NeverDestroyed<String> s_keySystem = MAKE_STATIC_STRING_IMPL("org.webkit.mock");
-
-    return s_keySystem;
 }
 
-}
-
 #endif

Modified: trunk/Source/WebCore/testing/MockCDMFactory.h (236316 => 236317)


--- trunk/Source/WebCore/testing/MockCDMFactory.h	2018-09-21 14:37:48 UTC (rev 236316)
+++ trunk/Source/WebCore/testing/MockCDMFactory.h	2018-09-21 15:08:35 UTC (rev 236317)
@@ -30,6 +30,7 @@
 #include "CDM.h"
 #include "CDMFactory.h"
 #include "CDMInstance.h"
+#include "CDMInstanceSession.h"
 #include "CDMPrivate.h"
 #include "MediaKeysRequirement.h"
 #include <wtf/HashMap.h>
@@ -121,10 +122,14 @@
     WeakPtr<MockCDMFactory> m_factory;
 };
 
-class MockCDMInstance : public CDMInstance {
+class MockCDMInstance : public CDMInstance, public CanMakeWeakPtr<MockCDMInstance> {
 public:
     MockCDMInstance(WeakPtr<MockCDM>);
 
+    MockCDMFactory* factory() const { return m_cdm ? m_cdm->factory() : nullptr; }
+    bool distinctiveIdentifiersAllowed() const { return m_distinctiveIdentifiersAllowed; }
+    bool persistentStateAllowed() const { return m_persistentStateAllowed; }
+
 private:
     ImplementationType implementationType() const final { return ImplementationType::Mock; }
     SuccessValue initializeWithConfiguration(const MediaKeySystemConfiguration&) final;
@@ -132,14 +137,8 @@
     SuccessValue setPersistentStateAllowed(bool) final;
     SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final;
     SuccessValue setStorageDirectory(const String&) final;
-    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final;
-    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback) final;
-    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback) final;
-    void closeSession(const String&, CloseSessionCallback) final;
-    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback) final;
-    void storeRecordOfKeyUsage(const String&) final;
-
     const String& keySystem() const final;
+    RefPtr<CDMInstanceSession> createSession() final;
 
     WeakPtr<MockCDM> m_cdm;
     bool m_distinctiveIdentifiersAllowed { true };
@@ -146,6 +145,21 @@
     bool m_persistentStateAllowed { true };
 };
 
+class MockCDMInstanceSession : public CDMInstanceSession {
+public:
+    MockCDMInstanceSession(WeakPtr<MockCDMInstance>&&);
+
+private:
+    void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&&) final;
+    void updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback&&) final;
+    void loadSession(LicenseType, const String&, const String&, LoadSessionCallback&&) final;
+    void closeSession(const String&, CloseSessionCallback&&) final;
+    void removeSessionData(const String&, LicenseType, RemoveSessionDataCallback&&) final;
+    void storeRecordOfKeyUsage(const String&) final;
+
+    WeakPtr<MockCDMInstance> m_instance;
+};
+
 }
 
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to