Title: [258295] trunk/Source
Revision
258295
Author
[email protected]
Date
2020-03-11 16:49:59 -0700 (Wed, 11 Mar 2020)

Log Message

[EME] Issue an "encrypted" event when a new encrypted initialization segment is encountered
https://bugs.webkit.org/show_bug.cgi?id=208923

Reviewed by Eric Carlson.

Source/WebCore:

When AVStreamDataParser encounters an initialization segment indicating encrypted content, it
will issue a -streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID: message
to its delegate. If the parser is already associated with an AVContentKeySession, it will instead
allow the session to handle the initialization segment and the delagete method will not be called.

When the latter situation occurs, we can detect that the -didProvideRequest callback did not
occur due to the client calling MediaKeySession.generateRequest() and therefore must have been
due to parsing an encrypted segment. In response, store the request in a list of "unexpected"
requests to be checked the next time a MediaKeySession tries to generateRequest(). Then, we will
pass the initalizationData and type to HTMLMediaElement through a new client interface, where it
will use that initializationData to issue an "encrypted" event. If the client passes that same
initializationData back into MediaKeySession, the "unexpected" request can be found, and re-used.

Drive-by fixes: Added a ton of debug logging messages to the CDMPrivate classes.

* Modules/encryptedmedia/CDM.cpp:
(WebCore::CDM::CDM):
* Modules/encryptedmedia/CDM.h:
* Modules/encryptedmedia/CDMClient.h:
* Modules/encryptedmedia/MediaKeySession.cpp:
(WebCore::MediaKeySession::create):
(WebCore::MediaKeySession::MediaKeySession):
* Modules/encryptedmedia/MediaKeySession.h:
* Modules/encryptedmedia/MediaKeySystemAccess.cpp:
(WebCore::MediaKeySystemAccess::createMediaKeys):
* Modules/encryptedmedia/MediaKeySystemAccess.h:
* Modules/encryptedmedia/MediaKeySystemAccess.idl:
* Modules/encryptedmedia/MediaKeys.cpp:
(WebCore::MediaKeys::MediaKeys):
(WebCore::MediaKeys::createSession):
(WebCore::MediaKeys::setServerCertificate):
(WebCore::MediaKeys::attachCDMClient):
(WebCore::MediaKeys::detachCDMClient):
(WebCore::MediaKeys::attemptToResumePlaybackOnClients):
(WebCore::MediaKeys::unrequestedInitializationDataReceived):
(WebCore::MediaKeys::nextChildIdentifier const):
* Modules/encryptedmedia/MediaKeys.h:
(WebCore::MediaKeys::create): Deleted.
(WebCore::MediaKeys::cdmInstance): Deleted.
(WebCore::MediaKeys::cdmInstance const): Deleted.
* Modules/encryptedmedia/MediaKeys.idl:
* WebCore.xcodeproj/project.pbxproj:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::cdmClientUnrequestedInitializationDataReceived):
* html/HTMLMediaElement.h:
* platform/encryptedmedia/CDMFactory.h:
* platform/encryptedmedia/CDMInstance.h:
(WebCore::CDMInstance::setClient):
(WebCore::CDMInstance::clearClient):
(WebCore::CDMInstance::setLogger):
* platform/encryptedmedia/CDMInstanceSession.h:
(WebCore::CDMInstanceSession::setLogger):
(WebCore::CDMInstanceSession::setClient):
* platform/encryptedmedia/CDMPrivate.h:
(WebCore::CDMPrivate::setLogger):
* platform/graphics/avfoundation/CDMFairPlayStreaming.cpp:
(WebCore::logChannel):
(WebCore::CDMPrivateFairPlayStreaming::setLogger):
(WebCore::CDMPrivateFairPlayStreaming::supportsConfiguration const):
* platform/graphics/avfoundation/CDMFairPlayStreaming.h:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
(WebCore::logChannel):
(WebCore::initTypeForRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::setLogger):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::takeUnexpectedKeyRequestForInitializationData):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::setServerCertificate):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::setStorageDirectory):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::setClient):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::clearClient):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionForRequest const):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setLogger):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setClient):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::hasRequest const):

Source/WebCore/PAL:

* pal/spi/cocoa/AVFoundationSPI.h:

Source/WTF:

* wtf/LoggerHelper.h:
(WTF::LoggerHelper::childLogIdentifier): Made static.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (258294 => 258295)


--- trunk/Source/WTF/ChangeLog	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WTF/ChangeLog	2020-03-11 23:49:59 UTC (rev 258295)
@@ -1,3 +1,13 @@
+2020-03-11  Jer Noble  <[email protected]>
+
+        [EME] Issue an "encrypted" event when a new encrypted initialization segment is encountered
+        https://bugs.webkit.org/show_bug.cgi?id=208923
+
+        Reviewed by Eric Carlson.
+
+        * wtf/LoggerHelper.h:
+        (WTF::LoggerHelper::childLogIdentifier): Made static.
+
 2020-03-11  Per Arne Vollan  <[email protected]>
 
         [macOS] Crash under WebKit::WebProcessPool::platformInitialize()

Modified: trunk/Source/WTF/wtf/LoggerHelper.h (258294 => 258295)


--- trunk/Source/WTF/wtf/LoggerHelper.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WTF/wtf/LoggerHelper.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -56,7 +56,14 @@
 #define INFO_LOG_IF(condition, ...)       if (condition) logger().info(logChannel(), __VA_ARGS__)
 #define DEBUG_LOG_IF(condition, ...)      if (condition) logger().debug(logChannel(), __VA_ARGS__)
 
-    const void* childLogIdentifier(const void* parentIdentifier, uint64_t childIdentifier) const
+#define ALWAYS_LOG_IF_POSSIBLE(...)     if (loggerPtr()) loggerPtr()->logAlways(logChannel(), __VA_ARGS__)
+#define ERROR_LOG_IF_POSSIBLE(...)      if (loggerPtr()) loggerPtr()->error(logChannel(), __VA_ARGS__)
+#define WARNING_LOG_IF_POSSIBLE(...)    if (loggerPtr()) loggerPtr()->warning(logChannel(), __VA_ARGS__)
+#define INFO_LOG_IF_POSSIBLE(...)       if (loggerPtr()) loggerPtr()->info(logChannel(), __VA_ARGS__)
+#define DEBUG_LOG_IF_POSSIBLE(...)      if (loggerPtr()) loggerPtr()->debug(logChannel(), __VA_ARGS__)
+#define WILL_LOG_IF_POSSIBLE(_level_)   if (loggerPtr()) loggerPtr()->willLog(logChannel(), _level_)
+
+    static const void* childLogIdentifier(const void* parentIdentifier, uint64_t childIdentifier)
     {
         static constexpr uint64_t parentMask = 0xffffffffffff0000ull;
         static constexpr uint64_t maskLowerWord = 0xffffull;
@@ -88,6 +95,13 @@
 #define INFO_LOG_IF(condition, ...)       ((void)0)
 #define DEBUG_LOG_IF(condition, ...)      ((void)0)
 
+#define ALWAYS_LOG_IF_POSSIBLE(...)     ((void)0)
+#define ERROR_LOG_IF_POSSIBLE(...)      ((void)0)
+#define WARNING_LOG_IF_POSSIBLE(...)    ((void)0)
+#define INFO_LOG_IF_POSSIBLE(...)       ((void)0)
+#define DEBUG_LOG_IF_POSSIBLE(...)      ((void)0)
+#define WILL_LOG_IF_POSSIBLE(_level_)   ((void)0)
+
 #endif // RELEASE_LOG_DISABLED
 
 };

Modified: trunk/Source/WebCore/ChangeLog (258294 => 258295)


--- trunk/Source/WebCore/ChangeLog	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/ChangeLog	2020-03-11 23:49:59 UTC (rev 258295)
@@ -1,3 +1,98 @@
+2020-03-11  Jer Noble  <[email protected]>
+
+        [EME] Issue an "encrypted" event when a new encrypted initialization segment is encountered
+        https://bugs.webkit.org/show_bug.cgi?id=208923
+
+        Reviewed by Eric Carlson.
+
+        When AVStreamDataParser encounters an initialization segment indicating encrypted content, it
+        will issue a -streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID: message
+        to its delegate. If the parser is already associated with an AVContentKeySession, it will instead
+        allow the session to handle the initialization segment and the delagete method will not be called.
+
+        When the latter situation occurs, we can detect that the -didProvideRequest callback did not
+        occur due to the client calling MediaKeySession.generateRequest() and therefore must have been
+        due to parsing an encrypted segment. In response, store the request in a list of "unexpected"
+        requests to be checked the next time a MediaKeySession tries to generateRequest(). Then, we will
+        pass the initalizationData and type to HTMLMediaElement through a new client interface, where it
+        will use that initializationData to issue an "encrypted" event. If the client passes that same
+        initializationData back into MediaKeySession, the "unexpected" request can be found, and re-used.
+
+        Drive-by fixes: Added a ton of debug logging messages to the CDMPrivate classes.
+
+        * Modules/encryptedmedia/CDM.cpp:
+        (WebCore::CDM::CDM):
+        * Modules/encryptedmedia/CDM.h:
+        * Modules/encryptedmedia/CDMClient.h:
+        * Modules/encryptedmedia/MediaKeySession.cpp:
+        (WebCore::MediaKeySession::create):
+        (WebCore::MediaKeySession::MediaKeySession):
+        * Modules/encryptedmedia/MediaKeySession.h:
+        * Modules/encryptedmedia/MediaKeySystemAccess.cpp:
+        (WebCore::MediaKeySystemAccess::createMediaKeys):
+        * Modules/encryptedmedia/MediaKeySystemAccess.h:
+        * Modules/encryptedmedia/MediaKeySystemAccess.idl:
+        * Modules/encryptedmedia/MediaKeys.cpp:
+        (WebCore::MediaKeys::MediaKeys):
+        (WebCore::MediaKeys::createSession):
+        (WebCore::MediaKeys::setServerCertificate):
+        (WebCore::MediaKeys::attachCDMClient):
+        (WebCore::MediaKeys::detachCDMClient):
+        (WebCore::MediaKeys::attemptToResumePlaybackOnClients):
+        (WebCore::MediaKeys::unrequestedInitializationDataReceived):
+        (WebCore::MediaKeys::nextChildIdentifier const):
+        * Modules/encryptedmedia/MediaKeys.h:
+        (WebCore::MediaKeys::create): Deleted.
+        (WebCore::MediaKeys::cdmInstance): Deleted.
+        (WebCore::MediaKeys::cdmInstance const): Deleted.
+        * Modules/encryptedmedia/MediaKeys.idl:
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::cdmClientUnrequestedInitializationDataReceived):
+        * html/HTMLMediaElement.h:
+        * platform/encryptedmedia/CDMFactory.h:
+        * platform/encryptedmedia/CDMInstance.h:
+        (WebCore::CDMInstance::setClient):
+        (WebCore::CDMInstance::clearClient):
+        (WebCore::CDMInstance::setLogger):
+        * platform/encryptedmedia/CDMInstanceSession.h:
+        (WebCore::CDMInstanceSession::setLogger):
+        (WebCore::CDMInstanceSession::setClient):
+        * platform/encryptedmedia/CDMPrivate.h:
+        (WebCore::CDMPrivate::setLogger):
+        * platform/graphics/avfoundation/CDMFairPlayStreaming.cpp:
+        (WebCore::logChannel):
+        (WebCore::CDMPrivateFairPlayStreaming::setLogger):
+        (WebCore::CDMPrivateFairPlayStreaming::supportsConfiguration const):
+        * platform/graphics/avfoundation/CDMFairPlayStreaming.h:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+        (WebCore::logChannel):
+        (WebCore::initTypeForRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setLogger):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::takeUnexpectedKeyRequestForInitializationData):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setServerCertificate):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setStorageDirectory):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::setClient):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::clearClient):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionForRequest const):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setLogger):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateLicense):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::loadSession):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::setClient):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::hasRequest const):
+
 2020-03-11  Jiewen Tan  <[email protected]>
 
         [WebAuthn] Formalize the Keychain schema

Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -42,6 +42,8 @@
 #include "SecurityOriginData.h"
 #include "Settings.h"
 #include <wtf/FileSystem.h>
+#include <wtf/Logger.h>
+#include <wtf/LoggerHelper.h>
 #include <wtf/NeverDestroyed.h>
 
 namespace WebCore {
@@ -62,6 +64,10 @@
 
 CDM::CDM(Document& document, const String& keySystem)
     : ContextDestructionObserver(&document)
+#if !RELEASE_LOG_DISABLED
+    , m_logger(document.logger())
+    , m_logIdentifier(LoggerHelper::uniqueLogIdentifier())
+#endif
     , m_keySystem(keySystem)
 {
     ASSERT(supportsKeySystem(keySystem));
@@ -68,6 +74,9 @@
     for (auto* factory : CDMFactory::registeredFactories()) {
         if (factory->supportsKeySystem(keySystem)) {
             m_private = factory->createCDM(keySystem);
+#if !RELEASE_LOG_DISABLED
+            m_private->setLogger(m_logger, m_logIdentifier);
+#endif
             break;
         }
     }

Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.h (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -40,6 +40,12 @@
 #include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 class CDMFactory;
@@ -80,6 +86,10 @@
 private:
     CDM(Document&, const String& keySystem);
 
+#if !RELEASE_LOG_DISABLED
+    Ref<WTF::Logger> m_logger;
+    const void* m_logIdentifier;
+#endif
     String m_keySystem;
     std::unique_ptr<CDMPrivate> m_private;
 };

Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMClient.h (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/CDMClient.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMClient.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -30,15 +30,20 @@
 
 #if ENABLE(ENCRYPTED_MEDIA)
 
+#include <wtf/Forward.h>
+#include <wtf/WeakPtr.h>
+
 namespace WebCore {
 
 class CDMInstance;
+class SharedBuffer;
 
-class CDMClient {
+class CDMClient : public CanMakeWeakPtr<CDMClient> {
 public:
     virtual ~CDMClient() = default;
 
     virtual void cdmClientAttemptToResumePlaybackIfNecessary() = 0;
+    virtual void cdmClientUnrequestedInitializationDataReceived(const String&, Ref<SharedBuffer>&&) = 0;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -64,7 +64,10 @@
 
 MediaKeySession::MediaKeySession(Document& document, WeakPtr<MediaKeys>&& keys, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstanceSession>&& instanceSession)
     : ActiveDOMObject(&document)
+#if !RELEASE_LOG_DISABLED
     , m_logger(document.logger())
+    , m_logIdentifier(keys ? keys->nextChildIdentifier() : nullptr)
+#endif
     , m_keys(WTFMove(keys))
     , m_expiration(std::numeric_limits<double>::quiet_NaN())
     , m_closedPromise(makeUniqueRef<ClosedPromise>())
@@ -98,6 +101,9 @@
     UNUSED_PARAM(m_closed);
     UNUSED_PARAM(m_uninitialized);
 
+#if !RELEASE_LOG_DISABLED
+    m_instanceSession->setLogger(m_logger, m_logIdentifier);
+#endif
     m_instanceSession->setClient(makeWeakPtr(*this));
 }
 

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -43,9 +43,11 @@
 #include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
+#if !RELEASE_LOG_DISABLED
 namespace WTF {
 class Logger;
 }
+#endif
 
 namespace WebCore {
 
@@ -113,10 +115,12 @@
     const WTF::Logger& logger() const { return m_logger; }
     const char* logClassName() const { return "MediaKeySession"; }
     WTFLogChannel& logChannel() const;
-    const void* logIdentifier() const { return this; }
+    const void* logIdentifier() const { return m_logIdentifier; }
+
+    Ref<WTF::Logger> m_logger;
+    const void* m_logIdentifier;
 #endif
 
-    Ref<WTF::Logger> m_logger;
     WeakPtr<MediaKeys> m_keys;
     String m_sessionId;
     double m_expiration;

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -33,6 +33,7 @@
 
 #include "CDM.h"
 #include "CDMInstance.h"
+#include "Document.h"
 #include "JSDOMPromiseDeferred.h"
 #include "JSMediaKeys.h"
 #include "MediaKeys.h"
@@ -54,7 +55,7 @@
 
 MediaKeySystemAccess::~MediaKeySystemAccess() = default;
 
-void MediaKeySystemAccess::createMediaKeys(Ref<DeferredPromise>&& promise)
+void MediaKeySystemAccess::createMediaKeys(Document& document, Ref<DeferredPromise>&& promise)
 {
     // https://w3c.github.io/encrypted-media/#dom-mediakeysystemaccess-createmediakeys
     // W3C Editor's Draft 09 November 2016
@@ -62,7 +63,7 @@
     // When this method is invoked, the user agent must run the following steps:
     // 1. Let promise be a new promise.
     // 2. Run the following steps in parallel:
-    m_taskQueue.enqueueTask([this, promise = WTFMove(promise)] () mutable {
+    m_taskQueue.enqueueTask([this, weakDocument = makeWeakPtr(document), promise = WTFMove(promise)] () mutable {
         // 2.1. Let configuration be the value of this object's configuration value.
         // 2.2. Let use distinctive identifier be true if the value of configuration's distinctiveIdentifier member is "required" and false otherwise.
         bool useDistinctiveIdentifier = m_configuration->distinctiveIdentifier == MediaKeysRequirement::Required;
@@ -86,8 +87,8 @@
         auto allowDistinctiveIdentifiers = useDistinctiveIdentifier ? CDMInstance::AllowDistinctiveIdentifiers::Yes : CDMInstance::AllowDistinctiveIdentifiers::No;
         auto allowPersistentState = persistentStateAllowed ? CDMInstance::AllowPersistentState::Yes : CDMInstance::AllowPersistentState::No;
 
-        instance->initializeWithConfiguration(*m_configuration, allowDistinctiveIdentifiers, allowPersistentState, [sessionTypes = m_configuration->sessionTypes, implementation = m_implementation.copyRef(), useDistinctiveIdentifier, persistentStateAllowed, instance = instance.releaseNonNull(), promise = WTFMove(promise)] (auto successValue) mutable {
-            if (successValue == CDMInstance::Failed) {
+        instance->initializeWithConfiguration(*m_configuration, allowDistinctiveIdentifiers, allowPersistentState, [weakDocument = WTFMove(weakDocument), sessionTypes = m_configuration->sessionTypes, implementation = m_implementation.copyRef(), useDistinctiveIdentifier, persistentStateAllowed, instance = instance.releaseNonNull(), promise = WTFMove(promise)] (auto successValue) mutable {
+            if (successValue == CDMInstance::Failed || !weakDocument) {
                 promise->reject(NotAllowedError);
                 return;
             }
@@ -99,7 +100,7 @@
             // 2.10.3. Let the supported session types value be be the value of configuration's sessionTypes member.
             // 2.10.4. Let the cdm implementation value be this object's cdm implementation value.
             // 2.10.5. Let the cdm instance value be instance.
-            auto mediaKeys = MediaKeys::create(useDistinctiveIdentifier, persistentStateAllowed, sessionTypes, WTFMove(implementation), WTFMove(instance));
+            auto mediaKeys = MediaKeys::create(*weakDocument, useDistinctiveIdentifier, persistentStateAllowed, sessionTypes, WTFMove(implementation), WTFMove(instance));
 
             // 2.11. Resolve promise with media keys.
             promise->resolveWithNewlyCreated<IDLInterface<MediaKeys>>(WTFMove(mediaKeys));

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -39,6 +39,7 @@
 
 class CDM;
 class DeferredPromise;
+class Document;
 class MediaKeys;
 
 class MediaKeySystemAccess : public RefCounted<MediaKeySystemAccess> {
@@ -48,7 +49,7 @@
 
     const String& keySystem() const { return m_keySystem; }
     const MediaKeySystemConfiguration& getConfiguration() const { return *m_configuration; }
-    void createMediaKeys(Ref<DeferredPromise>&&);
+    void createMediaKeys(Document&, Ref<DeferredPromise>&&);
 
 private:
     MediaKeySystemAccess(const String& keySystem, MediaKeySystemConfiguration&&, Ref<CDM>&&);

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.idl	2020-03-11 23:49:59 UTC (rev 258295)
@@ -34,5 +34,5 @@
 ] interface MediaKeySystemAccess {
     readonly attribute DOMString keySystem;
     MediaKeySystemConfiguration getConfiguration();
-    Promise<MediaKeys> createMediaKeys();
+    [CallWith=Document] Promise<MediaKeys> createMediaKeys();
 };

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -40,26 +40,31 @@
 #include "Logging.h"
 #include "MediaKeySession.h"
 #include "SharedBuffer.h"
+#include <wtf/Logger.h>
+#include <wtf/LoggerHelper.h>
 
 namespace WebCore {
 
-template<typename... Arguments>
-inline void infoLog(Logger& logger, const Arguments&... arguments)
-{
-#if !LOG_DISABLED || !RELEASE_LOG_DISABLED
-    logger.info(LogEME, arguments...);
-#else
-    UNUSED_PARAM(logger);
+#if !RELEASE_LOG_DISABLED
+static WTFLogChannel& logChannel() { return LogEME; }
+static const char* logClassName() { return "MediaKeys"; }
 #endif
-}
 
-MediaKeys::MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+MediaKeys::MediaKeys(Document& document, bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
     : m_useDistinctiveIdentifier(useDistinctiveIdentifier)
     , m_persistentStateAllowed(persistentStateAllowed)
     , m_supportedSessionTypes(supportedSessionTypes)
     , m_implementation(WTFMove(implementation))
     , m_instance(WTFMove(instance))
+#if !RELEASE_LOG_DISABLED
+    , m_logger(document.logger())
+    , m_logIdentifier(LoggerHelper::uniqueLogIdentifier())
+#endif
 {
+#if !RELEASE_LOG_DISABLED
+    m_instance->setLogger(document.logger(), m_logIdentifier);
+#endif
+    m_instance->setClient(makeWeakPtr(this));
 }
 
 MediaKeys::~MediaKeys() = default;
@@ -68,26 +73,25 @@
 {
     // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
     // W3C Editor's Draft 09 November 2016
-    LOG(EME, "EME - check if a new session can be created");
-    auto identifier = WTF::Logger::LogSiteIdentifier("MediaKeys", __func__, this);
-    Ref<Logger> logger = document.logger();
+    auto identifier = LOGIDENTIFIER;
+    INFO_LOG(identifier, "EME - check if a new session can be created");
 
     // When this method is invoked, the user agent must run the following steps:
     // 1. If this object's supported session types value does not contain sessionType, throw [WebIDL] a NotSupportedError.
     if (!m_supportedSessionTypes.contains(sessionType)) {
-        infoLog(logger, identifier, "Exception: unsupported sessionType: ", sessionType);
+        INFO_LOG(identifier, "Exception: unsupported sessionType: ", sessionType);
         return Exception(NotSupportedError);
     }
 
     // 2. If the implementation does not support MediaKeySession operations in the current state, throw [WebIDL] an InvalidStateError.
     if (!m_implementation->supportsSessions()) {
-        infoLog(logger, identifier, "Exception: implementation does not support sessions");
+        INFO_LOG(identifier, "Exception: implementation does not support sessions");
         return Exception(InvalidStateError);
     }
 
     auto instanceSession = m_instance->createSession();
     if (!instanceSession) {
-        infoLog(logger, identifier, "Exception: could not create session");
+        INFO_LOG(identifier, "Exception: could not create session");
         return Exception(InvalidStateError);
     }
 
@@ -95,23 +99,22 @@
     // NOTE: Continued in MediaKeySession.
     // 4. Return session.
     auto session = MediaKeySession::create(document, makeWeakPtr(*this), sessionType, m_useDistinctiveIdentifier, m_implementation.copyRef(), instanceSession.releaseNonNull());
-    infoLog(logger, identifier, " Created session");
+    INFO_LOG(identifier, "Created session");
     m_sessions.append(session.copyRef());
     return session;
 }
 
-void MediaKeys::setServerCertificate(Document& document, const BufferSource& serverCertificate, Ref<DeferredPromise>&& promise)
+void MediaKeys::setServerCertificate(const BufferSource& serverCertificate, Ref<DeferredPromise>&& promise)
 {
     // https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
     // W3C Editor's Draft 09 November 2016
-    auto identifier = WTF::Logger::LogSiteIdentifier("MediaKeys", __func__, this);
-    Ref<Logger> logger = document.logger();
+    auto identifier = LOGIDENTIFIER;
 
     // When this method is invoked, the user agent must run the following steps:
     // 1. If the Key System implementation represented by this object's cdm implementation value does not support
     //    server certificates, return a promise resolved with false.
     if (!m_implementation->supportsServerCertificates()) {
-        infoLog(logger, identifier, "Rejected: !supportsServerCertificates()");
+        INFO_LOG(identifier, "Rejected: !supportsServerCertificates()");
         promise->resolve<IDLBoolean>(false);
         return;
     }
@@ -118,7 +121,7 @@
 
     // 2. If serverCertificate is an empty array, return a promise rejected with a new a newly created TypeError.
     if (!serverCertificate.length()) {
-        infoLog(logger, identifier, "Rejected: empty serverCertificate");
+        INFO_LOG(identifier, "Rejected: empty serverCertificate");
         promise->reject(TypeError);
         return;
     }
@@ -130,16 +133,16 @@
     // 5. Run the following steps in parallel:
 
     // 5.1. Use this object's cdm instance to process certificate.
-    m_instance->setServerCertificate(WTFMove(certificate), [promise = WTFMove(promise), logger = WTFMove(logger), identifier = WTFMove(identifier)] (auto success) {
+    m_instance->setServerCertificate(WTFMove(certificate), [this, protectedThis = makeRef(*this), promise = WTFMove(promise), identifier = WTFMove(identifier)] (auto success) {
         // 5.2. If the preceding step failed, resolve promise with a new DOMException whose name is the appropriate error name.
         // 5.1. [Else,] Resolve promise with true.
         if (success == CDMInstance::Failed) {
-            infoLog(logger, identifier, "Rejected, setServerCertificate() failed");
+            INFO_LOG(identifier, "::task() - Rejected, setServerCertificate() failed");
             promise->reject(InvalidStateError);
             return;
         }
 
-        infoLog(logger, identifier, "Resolved");
+        INFO_LOG(identifier, "::task() - Resolved");
         promise->resolve<IDLBoolean>(true);
     });
 
@@ -148,20 +151,20 @@
 
 void MediaKeys::attachCDMClient(CDMClient& client)
 {
-    ASSERT(!m_cdmClients.contains(&client));
-    m_cdmClients.append(&client);
+    ASSERT(!m_cdmClients.contains(client));
+    m_cdmClients.add(client);
 }
 
 void MediaKeys::detachCDMClient(CDMClient& client)
 {
-    ASSERT(m_cdmClients.contains(&client));
-    m_cdmClients.removeFirst(&client);
+    ASSERT(m_cdmClients.contains(client));
+    m_cdmClients.remove(client);
 }
 
 void MediaKeys::attemptToResumePlaybackOnClients()
 {
-    for (auto* cdmClient : m_cdmClients)
-        cdmClient->cdmClientAttemptToResumePlaybackIfNecessary();
+    for (auto& cdmClient : m_cdmClients)
+        cdmClient.cdmClientAttemptToResumePlaybackIfNecessary();
 }
 
 bool MediaKeys::hasOpenSessions() const
@@ -172,6 +175,19 @@
         });
 }
 
+void MediaKeys::unrequestedInitializationDataReceived(const String& initDataType, Ref<SharedBuffer>&& initData)
+{
+    for (auto& cdmClient : m_cdmClients)
+        cdmClient.cdmClientUnrequestedInitializationDataReceived(initDataType, initData.copyRef());
+}
+
+#if !RELEASE_LOG_DISABLED
+const void* MediaKeys::nextChildIdentifier() const
+{
+    return LoggerHelper::childLogIdentifier(m_logIdentifier, ++m_childIdentifierSeed);
+}
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(ENCRYPTED_MEDIA)

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -30,12 +30,18 @@
 
 #if ENABLE(ENCRYPTED_MEDIA)
 
+#include "CDMInstance.h"
 #include "ExceptionOr.h"
 #include "MediaKeySessionType.h"
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
+#include <wtf/WeakHashSet.h>
 #include <wtf/WeakPtr.h>
 
+namespace WTF {
+class Logger;
+}
+
 namespace WebCore {
 
 class CDM;
@@ -46,19 +52,21 @@
 class Document;
 class MediaKeySession;
 
-class MediaKeys : public RefCounted<MediaKeys>, public CanMakeWeakPtr<MediaKeys> {
+class MediaKeys final
+    : public RefCounted<MediaKeys>
+    , public CDMInstanceClient {
 public:
     using KeySessionType = MediaKeySessionType;
 
-    static Ref<MediaKeys> create(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
+    static Ref<MediaKeys> create(Document& document, bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>& supportedSessionTypes, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
     {
-        return adoptRef(*new MediaKeys(useDistinctiveIdentifier, persistentStateAllowed, supportedSessionTypes, WTFMove(implementation), WTFMove(instance)));
+        return adoptRef(*new MediaKeys(document, useDistinctiveIdentifier, persistentStateAllowed, supportedSessionTypes, WTFMove(implementation), WTFMove(instance)));
     }
 
     ~MediaKeys();
 
     ExceptionOr<Ref<MediaKeySession>> createSession(Document&, MediaKeySessionType);
-    void setServerCertificate(Document&, const BufferSource&, Ref<DeferredPromise>&&);
+    void setServerCertificate(const BufferSource&, Ref<DeferredPromise>&&);
 
     void attachCDMClient(CDMClient&);
     void detachCDMClient(CDMClient&);
@@ -68,9 +76,21 @@
     CDMInstance& cdmInstance() { return m_instance; }
     const CDMInstance& cdmInstance() const { return m_instance; }
 
+#if !RELEASE_LOG_DISABLED
+    const void* nextChildIdentifier() const;
+#endif
+
 protected:
-    MediaKeys(bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>&, Ref<CDM>&&, Ref<CDMInstance>&&);
+    MediaKeys(Document&, bool useDistinctiveIdentifier, bool persistentStateAllowed, const Vector<MediaKeySessionType>&, Ref<CDM>&&, Ref<CDMInstance>&&);
 
+    // CDMInstanceClient
+    void unrequestedInitializationDataReceived(const String&, Ref<SharedBuffer>&&) final;
+
+#if !RELEASE_LOG_DISABLED
+    const WTF::Logger& logger() const { return m_logger; }
+    const void* logIdentifier() const { return m_logIdentifier; }
+#endif
+
     bool m_useDistinctiveIdentifier;
     bool m_persistentStateAllowed;
     Vector<MediaKeySessionType> m_supportedSessionTypes;
@@ -78,7 +98,13 @@
     Ref<CDMInstance> m_instance;
 
     Vector<Ref<MediaKeySession>> m_sessions;
-    Vector<CDMClient*> m_cdmClients;
+    WeakHashSet<CDMClient> m_cdmClients;
+
+#if !RELEASE_LOG_DISABLED
+    Ref<WTF::Logger> m_logger;
+    const void* m_logIdentifier;
+    mutable uint64_t m_childIdentifierSeed { 0 };
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl (258294 => 258295)


--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.idl	2020-03-11 23:49:59 UTC (rev 258295)
@@ -30,8 +30,7 @@
     Conditional=ENCRYPTED_MEDIA,
     EnabledAtRuntime=EncryptedMediaAPI,
     DisabledByQuirk=hasBrokenEncryptedMediaAPISupport,
-    ImplementationLacksVTable,
 ] interface MediaKeys {
     [CallWith=Document, MayThrowException] MediaKeySession createSession(optional MediaKeySessionType sessionType = "temporary");
-    [CallWith=Document] Promise<bool> setServerCertificate(BufferSource serverCertificate);
+    Promise<bool> setServerCertificate(BufferSource serverCertificate);
 };

Modified: trunk/Source/WebCore/PAL/ChangeLog (258294 => 258295)


--- trunk/Source/WebCore/PAL/ChangeLog	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/PAL/ChangeLog	2020-03-11 23:49:59 UTC (rev 258295)
@@ -1,3 +1,12 @@
+2020-03-11  Jer Noble  <[email protected]>
+
+        [EME] Issue an "encrypted" event when a new encrypted initialization segment is encountered
+        https://bugs.webkit.org/show_bug.cgi?id=208923
+
+        Reviewed by Eric Carlson.
+
+        * pal/spi/cocoa/AVFoundationSPI.h:
+
 2020-03-09  Don Olmstead  <[email protected]>
 
         Remove obsolete feature flags

Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h (258294 => 258295)


--- trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -174,6 +174,7 @@
 @property (readonly, nullable) NSData *contentProtectionSessionIdentifier;
 - (void)expire;
 - (void)processContentKeyRequestWithIdentifier:(nullable id)identifier initializationData:(nullable NSData *)initializationData options:(nullable NSDictionary<NSString *, id> *)options;
+- (void)associateContentKeyRequest:(nonnull AVContentKeyRequest *)contentKeyRequest;
 @end
 
 @interface AVContentKeySession (AVContentKeyGroup_Support)

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (258294 => 258295)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -2876,6 +2876,11 @@
     attemptToResumePlaybackIfNecessary();
 }
 
+void HTMLMediaElement::cdmClientUnrequestedInitializationDataReceived(const String& initDataType, Ref<SharedBuffer>&& initData)
+{
+    mediaPlayerInitializationDataEncountered(initDataType, initData->tryCreateArrayBuffer());
+}
+
 #endif // ENABLE(ENCRYPTED_MEDIA)
 
 void HTMLMediaElement::progressEventTimerFired()

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (258294 => 258295)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -701,6 +701,7 @@
 
     // CDMClient
     void cdmClientAttemptToResumePlaybackIfNecessary() final;
+    void cdmClientUnrequestedInitializationDataReceived(const String&, Ref<SharedBuffer>&&) final;
 #endif
 
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA) && ENABLE(ENCRYPTED_MEDIA)

Modified: trunk/Source/WebCore/platform/encryptedmedia/CDMFactory.h (258294 => 258295)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMFactory.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMFactory.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -32,6 +32,12 @@
 #include <memory>
 #include <wtf/Forward.h>
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 class CDMPrivate;

Modified: trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h (258294 => 258295)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMInstance.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -36,7 +36,14 @@
 #include <wtf/RefCounted.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/TypeCasts.h>
+#include <wtf/WeakPtr.h>
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 class SharedBuffer;
@@ -43,6 +50,13 @@
 class CDMInstanceSession;
 struct CDMKeySystemConfiguration;
 
+class CDMInstanceClient : public CanMakeWeakPtr<CDMInstanceClient> {
+public:
+    virtual ~CDMInstanceClient() = default;
+
+    virtual void unrequestedInitializationDataReceived(const String&, Ref<SharedBuffer>&&) = 0;
+};
+
 // _javascript_'s handle to a CDMInstance, must be used from the
 // main-thread only!
 class CDMInstance : public RefCounted<CDMInstance> {
@@ -49,6 +63,13 @@
 public:
     virtual ~CDMInstance() = default;
 
+    virtual void setClient(WeakPtr<CDMInstanceClient>&&) { }
+    virtual void clearClient() { }
+
+#if !RELEASE_LOG_DISABLED
+    virtual void setLogger(WTF::Logger&, const void*) { }
+#endif
+
     enum class ImplementationType {
         Mock,
         ClearKey,

Modified: trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h (258294 => 258295)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMInstanceSession.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -35,6 +35,12 @@
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 class SharedBuffer;
@@ -58,6 +64,10 @@
     using LicenseType = CDMSessionType;
     using MessageType = CDMMessageType;
 
+#if !RELEASE_LOG_DISABLED
+    virtual void setLogger(WTF::Logger&, const void*) { }
+#endif
+
     virtual void setClient(WeakPtr<CDMInstanceSessionClient>&&) { }
     virtual void clearClient() { }
 

Modified: trunk/Source/WebCore/platform/encryptedmedia/CDMPrivate.h (258294 => 258295)


--- trunk/Source/WebCore/platform/encryptedmedia/CDMPrivate.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/encryptedmedia/CDMPrivate.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -33,6 +33,12 @@
 #include <wtf/Forward.h>
 #include <wtf/WeakPtr.h>
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 struct CDMKeySystemConfiguration;
@@ -43,6 +49,10 @@
 public:
     WEBCORE_EXPORT virtual ~CDMPrivate();
 
+#if !RELEASE_LOG_DISABLED
+    virtual void setLogger(WTF::Logger&, const void*) { };
+#endif
+
     enum class LocalStorageAccess : bool {
         NotAllowed,
         Allowed,

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp (258294 => 258295)


--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp	2020-03-11 23:49:59 UTC (rev 258295)
@@ -37,11 +37,13 @@
 #include "ISOSchemeTypeBox.h"
 #include "ISOTrackEncryptionBox.h"
 #include "InitDataRegistry.h"
+#include "Logging.h"
 #include "NotImplemented.h"
 #include <_javascript_Core/ArrayBuffer.h>
 #include <_javascript_Core/DataView.h>
 #include <wtf/Algorithms.h>
 #include <wtf/JSONValues.h>
+#include <wtf/LoggerHelper.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/Base64.h>
 
@@ -55,6 +57,10 @@
 
 namespace WebCore {
 
+#if !RELEASE_LOG_DISABLED
+static WTFLogChannel& logChannel() { return LogEME; }
+#endif
+
 const Vector<FourCC>& CDMPrivateFairPlayStreaming::validFairPlayStreamingSchemes()
 {
     static NeverDestroyed<Vector<FourCC>> validSchemes = Vector<FourCC>({
@@ -250,6 +256,14 @@
 CDMPrivateFairPlayStreaming::CDMPrivateFairPlayStreaming() = default;
 CDMPrivateFairPlayStreaming::~CDMPrivateFairPlayStreaming() = default;
 
+#if !RELEASE_LOG_DISABLED
+void CDMPrivateFairPlayStreaming::setLogger(Logger& logger, const void* logIdentifier)
+{
+    m_logger = makeRefPtr(logger);
+    m_logIdentifier = logIdentifier;
+}
+#endif
+
 Vector<AtomString> CDMPrivateFairPlayStreaming::supportedInitDataTypes() const
 {
     return copyToVector(validInitDataTypes());
@@ -257,33 +271,47 @@
 
 bool CDMPrivateFairPlayStreaming::supportsConfiguration(const CDMKeySystemConfiguration& configuration) const
 {
-    if (!WTF::anyOf(configuration.initDataTypes, [] (auto& initDataType) { return validInitDataTypes().contains(initDataType); }))
+    if (!WTF::anyOf(configuration.initDataTypes, [] (auto& initDataType) { return validInitDataTypes().contains(initDataType); })) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " false, no initDataType supported");
         return false;
+    }
 
 #if HAVE(AVCONTENTKEYSESSION)
     // FIXME: verify that FairPlayStreaming does not (and cannot) expose a distinctive identifier to the client
-    if (configuration.distinctiveIdentifier == CDMRequirement::Required)
+    if (configuration.distinctiveIdentifier == CDMRequirement::Required) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "false, requried distinctiveIdentifier not supported");
         return false;
-    if (configuration.persistentState == CDMRequirement::Required && !CDMInstanceFairPlayStreamingAVFObjC::supportsPersistableState())
+    }
+
+    if (configuration.persistentState == CDMRequirement::Required && !CDMInstanceFairPlayStreamingAVFObjC::supportsPersistableState()) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "false, required persistentState not supported");
         return false;
+    }
 
     if (configuration.sessionTypes.contains(CDMSessionType::PersistentLicense)
         && !configuration.sessionTypes.contains(CDMSessionType::Temporary)
-        && !CDMInstanceFairPlayStreamingAVFObjC::supportsPersistentKeys())
+        && !CDMInstanceFairPlayStreamingAVFObjC::supportsPersistentKeys()) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "false, sessionType PersistentLicense not supported");
         return false;
+    }
 
     if (!configuration.audioCapabilities.isEmpty()
         && !WTF::anyOf(configuration.audioCapabilities, [](auto& capability) {
             return CDMInstanceFairPlayStreamingAVFObjC::supportsMediaCapability(capability);
-        }))
+        })) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "false, no audio configuration supported");
         return false;
+    }
 
     if (!configuration.videoCapabilities.isEmpty()
         && !WTF::anyOf(configuration.videoCapabilities, [](auto& capability) {
             return CDMInstanceFairPlayStreamingAVFObjC::supportsMediaCapability(capability);
-        }))
+        })) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "false, no video configuration supported");
         return false;
+    }
 
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "true, supported");
     return true;
 #else
     return false;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h (258294 => 258295)


--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -55,6 +55,10 @@
     CDMPrivateFairPlayStreaming();
     virtual ~CDMPrivateFairPlayStreaming();
 
+#if !RELEASE_LOG_DISABLED
+    void setLogger(WTF::Logger&, const void* logIdentifier) final;
+#endif
+
     Vector<AtomString> supportedInitDataTypes() const override;
     bool supportsConfiguration(const CDMKeySystemConfiguration&) const override;
     bool supportsConfigurationWithRestrictions(const CDMKeySystemConfiguration&, const CDMRestrictions&) const override;
@@ -80,6 +84,16 @@
     static RefPtr<SharedBuffer> sanitizeSkd(const SharedBuffer&);
 
     static const Vector<FourCC>& validFairPlayStreamingSchemes();
+
+private:
+#if !RELEASE_LOG_DISABLED
+    WTF::Logger* loggerPtr() const { return m_logger.get(); };
+    const void* logIdentifier() const { return m_logIdentifier; }
+    const char* logClassName() const { return "CDMPrivateFairPlayStreaming"; }
+
+    RefPtr<WTF::Logger> m_logger;
+    const void* m_logIdentifier;
+#endif
 };
 
 }

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2020-03-11 23:49:59 UTC (rev 258295)
@@ -42,6 +42,12 @@
 OBJC_CLASS NSURL;
 OBJC_CLASS WebCoreFPSContentKeySessionDelegate;
 
+#if !RELEASE_LOG_DISABLED
+namespace WTF {
+class Logger;
+}
+#endif
+
 namespace WebCore {
 
 class CDMInstanceSessionFairPlayStreamingAVFObjC;
@@ -67,6 +73,10 @@
     CDMInstanceFairPlayStreamingAVFObjC();
     virtual ~CDMInstanceFairPlayStreamingAVFObjC() = default;
 
+#if !RELEASE_LOG_DISABLED
+    void setLogger(WTF::Logger&, const void* logIdentifier);
+#endif
+
     static bool supportsPersistableState();
     static bool supportsPersistentKeys();
     static bool supportsMediaCapability(const CDMMediaCapability&);
@@ -78,6 +88,8 @@
     void setServerCertificate(Ref<SharedBuffer>&&, SuccessCallback&&) final;
     void setStorageDirectory(const String&) final;
     RefPtr<CDMInstanceSession> createSession() final;
+    void setClient(WeakPtr<CDMInstanceClient>&&) final;
+    void clearClient() final;
 
     const String& keySystem() const final;
 
@@ -86,6 +98,8 @@
     SharedBuffer* serverCertificate() const { return m_serverCertificate.get(); }
     AVContentKeySession* contentKeySession();
 
+    RetainPtr<AVContentKeyRequest> takeUnexpectedKeyRequestForInitializationData(const AtomString& initDataType, SharedBuffer& initData);
+
     // AVContentKeySessionDelegateClient
     void didProvideRequest(AVContentKeyRequest*) final;
     void didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&&) final;
@@ -101,8 +115,16 @@
     using Keys = Vector<Ref<SharedBuffer>>;
     CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForKeyIDs(const Keys&) const;
     CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForGroup(AVContentKeyReportGroup*) const;
+    CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForRequest(AVContentKeyRequest*) const;
 
 private:
+#if !RELEASE_LOG_DISABLED
+    WTF::Logger* loggerPtr() const { return m_logger.get(); };
+    const void* logIdentifier() const { return m_logIdentifier; }
+    const char* logClassName() const { return "CDMInstanceFairPlayStreamingAVFObjC"; }
+#endif
+
+    WeakPtr<CDMInstanceClient> m_client;
     RetainPtr<AVContentKeySession> m_session;
     RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate;
     RefPtr<SharedBuffer> m_serverCertificate;
@@ -109,6 +131,11 @@
     bool m_persistentStateAllowed { true };
     RetainPtr<NSURL> m_storageURL;
     Vector<WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC>> m_sessions;
+    HashSet<RetainPtr<AVContentKeyRequest>> m_unexpectedKeyRequests;
+#if !RELEASE_LOG_DISABLED
+    RefPtr<WTF::Logger> m_logger;
+    const void* m_logIdentifier { nullptr };
+#endif
 };
 
 class CDMInstanceSessionFairPlayStreamingAVFObjC final : public CDMInstanceSession, public AVContentKeySessionDelegateClient, public CanMakeWeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> {
@@ -116,6 +143,10 @@
     CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&&);
     virtual ~CDMInstanceSessionFairPlayStreamingAVFObjC();
 
+#if !RELEASE_LOG_DISABLED
+    void setLogger(WTF::Logger&, const void* logIdentifier);
+#endif
+
     // CDMInstanceSession
     void requestLicense(LicenseType, const AtomString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&&) final;
     void updateLicense(const String&, LicenseType, Ref<SharedBuffer>&&, LicenseUpdateCallback&&) final;
@@ -149,6 +180,8 @@
         bool operator==(const Request& other) const { return initType == other.initType && requests == other.requests; }
     };
 
+    bool hasRequest(AVContentKeyRequest*) const;
+
 private:
     bool ensureSessionOrGroup();
     bool isLicenseTypeSupported(LicenseType) const;
@@ -157,6 +190,12 @@
     void nextRequest();
     AVContentKeyRequest* lastKeyRequest() const;
 
+#if !RELEASE_LOG_DISABLED
+    WTF::Logger* loggerPtr() const { return m_logger.get(); };
+    const void* logIdentifier() const { return m_logIdentifier; }
+    const char* logClassName() const { return "CDMInstanceSessionFairPlayStreamingAVFObjC"; }
+#endif
+
     Ref<CDMInstanceFairPlayStreamingAVFObjC> m_instance;
     RetainPtr<AVContentKeyReportGroup> m_group;
     RetainPtr<AVContentKeySession> m_session;
@@ -177,6 +216,11 @@
     LicenseUpdateCallback m_updateLicenseCallback;
     CloseSessionCallback m_closeSessionCallback;
     RemoveSessionDataCallback m_removeSessionDataCallback;
+
+#if !RELEASE_LOG_DISABLED
+    RefPtr<WTF::Logger> m_logger;
+    const void* m_logIdentifier { nullptr };
+#endif
 };
 
 }

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2020-03-11 23:27:19 UTC (rev 258294)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2020-03-11 23:49:59 UTC (rev 258295)
@@ -42,6 +42,7 @@
 #import <wtf/Algorithms.h>
 #import <wtf/FileSystem.h>
 #import <wtf/JSONValues.h>
+#import <wtf/LoggerHelper.h>
 #import <wtf/text/Base64.h>
 #import <wtf/text/StringHash.h>
 
@@ -160,8 +161,41 @@
 
 namespace WebCore {
 
+#if !RELEASE_LOG_DISABLED
+static WTFLogChannel& logChannel() { return LogEME; }
+#endif
+
+static AtomString initTypeForRequest(AVContentKeyRequest* request)
+{
+    if (![request respondsToSelector:@selector(options)]) {
+        // AVContentKeyRequest.options was added in 10.14.4; if we are running on a previous version
+        // we don't have support for 'cenc' anyway, so just assume 'sinf'.
+        return CDMPrivateFairPlayStreaming::sinfName();
+    }
+
+ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
+    auto nsInitType = (NSString*)[request.options valueForKey:InitializationDataTypeKey];
+ALLOW_NEW_API_WITHOUT_GUARDS_END
+    if (![nsInitType isKindOfClass:NSString.class]) {
+        // The only way for an initialization data to end up here without an appropriate key in
+        // the options dictionary is for that data to have been generated by the AVStreamDataParser
+        // and currently, the only initialization data supported by the parser is the 'sinf' kind.
+        return CDMPrivateFairPlayStreaming::sinfName();
+    }
+
+    return AtomString(nsInitType);
+}
+
 CDMInstanceFairPlayStreamingAVFObjC::CDMInstanceFairPlayStreamingAVFObjC() = default;
 
+#if !RELEASE_LOG_DISABLED
+void CDMInstanceFairPlayStreamingAVFObjC::setLogger(Logger& logger, const void* logIdentifier)
+{
+    m_logger = makeRefPtr(logger);
+    m_logIdentifier = logIdentifier;
+}
+#endif
+
 AVContentKeySession* CDMInstanceFairPlayStreamingAVFObjC::contentKeySession()
 {
     if (m_session)
@@ -189,6 +223,20 @@
     return m_session.get();
 }
 
+RetainPtr<AVContentKeyRequest> CDMInstanceFairPlayStreamingAVFObjC::takeUnexpectedKeyRequestForInitializationData(const AtomString& initDataType, SharedBuffer& initData)
+{
+    for (auto requestIter = m_unexpectedKeyRequests.begin(); requestIter != m_unexpectedKeyRequests.end(); ++requestIter) {
+        auto& request = *requestIter;
+        auto requestType = initTypeForRequest(request.get());
+        auto* requestInitData  = request.get().initializationData;
+        if (initDataType != requestType || initData != SharedBuffer::create(requestInitData))
+            continue;
+
+        return m_unexpectedKeyRequests.take(requestIter);
+    }
+    return nullptr;
+}
+
 class CDMInstanceSessionFairPlayStreamingAVFObjC::UpdateResponseCollector {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -295,6 +343,7 @@
 
 void CDMInstanceFairPlayStreamingAVFObjC::setServerCertificate(Ref<SharedBuffer>&& serverCertificate, SuccessCallback&& callback)
 {
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER);
     m_serverCertificate = WTFMove(serverCertificate);
     callback(Succeeded);
 }
@@ -301,6 +350,7 @@
 
 void CDMInstanceFairPlayStreamingAVFObjC::setStorageDirectory(const String& storageDirectory)
 {
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER);
     if (storageDirectory.isEmpty()) {
         m_storageURL = nil;
         return;
@@ -334,6 +384,16 @@
     return session;
 }
 
+void CDMInstanceFairPlayStreamingAVFObjC::setClient(WeakPtr<CDMInstanceClient>&& client)
+{
+    m_client = WTFMove(client);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::clearClient()
+{
+    m_client = nullptr;
+}
+
 const String& CDMInstanceFairPlayStreamingAVFObjC::keySystem() const
 {
     static NeverDestroyed<String> keySystem { "com.apple.fps"_s };
@@ -351,44 +411,81 @@
 
 void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request)) {
         session->didProvideRequest(request);
+        return;
+    }
+
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- Unexpected request");
+
+    m_unexpectedKeyRequests.add(request);
+
+    if (m_client)
+        m_client->unrequestedInitializationDataReceived(initTypeForRequest(request), SharedBuffer::create(request.initializationData));
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&& requests)
 {
-    if (auto* session = sessionForGroup(groupForRequest(requests.first().get())))
+    if (auto* session = sessionForRequest(requests.first().get())) {
         session->didProvideRequests(WTFMove(requests));
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request)) {
         session->didProvideRenewingRequest(request);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request)) {
         session->didProvidePersistableRequest(request);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request)) {
         session->didFailToProvideRequest(request, error);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request)) {
         session->requestDidSucceed(request);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
 {
-    if (auto* session = sessionForGroup(groupForRequest(request)))
+    if (auto* session = sessionForRequest(request))
         return session->shouldRetryRequestForReason(request, reason);
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
     return false;
 }
 
@@ -401,8 +498,13 @@
 
 void CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged(AVContentKeyReportGroup* group, NSData *sessionIdentifier)
 {
-    if (auto* session = sessionForGroup(group))
+    if (auto* session = sessionForGroup(group)) {
         session->groupSessionIdentifierChanged(group, sessionIdentifier);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+    ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "- no responsible session; dropping");
 }
 
 void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
@@ -428,6 +530,18 @@
     return nullptr;
 }
 
+CDMInstanceSessionFairPlayStreamingAVFObjC* CDMInstanceFairPlayStreamingAVFObjC::sessionForRequest(AVContentKeyRequest* request) const
+{
+    auto index = m_sessions.findMatching([&] (auto session) {
+        return session && session->hasRequest(request);
+    });
+
+    if (index != notFound)
+        return m_sessions[index].get();
+
+    return sessionForGroup(groupForRequest(request));
+}
+
 CDMInstanceSessionFairPlayStreamingAVFObjC* CDMInstanceFairPlayStreamingAVFObjC::sessionForGroup(AVContentKeyReportGroup* group) const
 {
     auto index = m_sessions.findMatching([group] (auto session) {
@@ -450,6 +564,14 @@
     [m_delegate invalidate];
 }
 
+#if !RELEASE_LOG_DISABLED
+void CDMInstanceSessionFairPlayStreamingAVFObjC::setLogger(Logger& logger, const void* logIdentifier)
+{
+    m_logger = makeRefPtr(logger);
+    m_logIdentifier = logIdentifier;
+}
+#endif
+
 using Keys = CDMInstanceSessionFairPlayStreamingAVFObjC::Keys;
 static Keys keyIDsForRequest(AVContentKeyRequest* request)
 {
@@ -473,27 +595,6 @@
     return keyIDs;
 }
 
-static AtomString initTypeForRequest(AVContentKeyRequest* request)
-{
-    if (![request respondsToSelector:@selector(options)]) {
-        // AVContentKeyRequest.options was added in 10.14.4; if we are running on a previous version
-        // we don't have support for 'cenc' anyway, so just assume 'sinf'.
-        return CDMPrivateFairPlayStreaming::sinfName();
-    }
-
-ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
-    auto nsInitType = (NSString*)[request.options valueForKey:InitializationDataTypeKey];
-ALLOW_NEW_API_WITHOUT_GUARDS_END
-    if (![nsInitType isKindOfClass:NSString.class]) {
-        // The only way for an initialization data to end up here without an appropriate key in
-        // the options dictionary is for that data to have been generated by the AVStreamDataParser
-        // and currently, the only initialization data supported by the parser is the 'sinf' kind.
-        return CDMPrivateFairPlayStreaming::sinfName();
-    }
-
-    return AtomString(nsInitType);
-}
-
 Keys CDMInstanceSessionFairPlayStreamingAVFObjC::keyIDs()
 {
     // FIXME(rdar://problem/35597141): use the future AVContentKeyRequest keyID property, rather than parsing it out of the init
@@ -510,20 +611,35 @@
 void CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense(LicenseType licenseType, const AtomString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback&& callback)
 {
     if (!isLicenseTypeSupported(licenseType)) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " false, licenseType \"", licenseType, "\" not supported");
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
 
     if (!m_instance->serverCertificate()) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " false, no serverCertificate");
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
 
     if (!ensureSessionOrGroup()) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " false, could not create session or group object");
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
 
+    if (auto unexpectedRequest = m_instance->takeUnexpectedKeyRequestForInitializationData(initDataType, initData)) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " found unexpectedRequest matching initData");
+        if (m_group) {
+            ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
+            [m_group associateContentKeyRequest:unexpectedRequest.get()];
+            ALLOW_NEW_API_WITHOUT_GUARDS_END
+        }
+        m_requestLicenseCallback = WTFMove(callback);
+        didProvideRequest(unexpectedRequest.get());
+        return;
+    }
+
     RetainPtr<NSString> identifier;
     RetainPtr<NSData> initializationData;
 
@@ -538,10 +654,12 @@
     }
 #endif
     else {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " false, initDataType not suppported");
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
 
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " processing request");
     m_requestLicenseCallback = WTFMove(callback);
 
     if (m_group) {
@@ -582,10 +700,12 @@
         auto* storageURL = m_instance->storageURL();
 
         if (!certificate || !storageURL) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "\"acknowledged\", Failed, no certificate and storageURL");
             callback(false, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
             return;
         }
 
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "\"acknowledged\", Succeeded, removing expired session report");
         RetainPtr<NSData> appIdentifier = certificate->createNSData();
         [PAL::getAVContentKeySessionClass() removePendingExpiredSessionReports:expiredSessions.get() withAppIdentifier:appIdentifier.get() storageDirectoryAtURL:storageURL];
         callback(false, { }, WTF::nullopt, WTF::nullopt, Succeeded);
@@ -595,9 +715,11 @@
     if (!m_requests.isEmpty() && isEqual(responseData, "renew"_s)) {
         auto request = lastKeyRequest();
         if (!request) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "\"renew\", Failed, no outstanding keys");
             callback(false, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
             return;
         }
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "\"renew\", processing renewal");
         auto session = m_session ? m_session.get() : m_instance->contentKeySession();
         [session renewExpiringResponseDataForContentKeyRequest:request];
         m_updateLicenseCallback = WTFMove(callback);
@@ -605,11 +727,13 @@
     }
 
     if (!m_currentRequest) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, no currentRequest");
         callback(false, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
         return;
     }
     Keys keyIDs = keyIDsForRequest(m_currentRequest.value());
     if (keyIDs.isEmpty()) {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, no keyIDs in currentRequest");
         callback(false, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
         return;
     }
@@ -628,10 +752,12 @@
                 return;
 
             if (!responses || responses.value().isEmpty()) {
+                DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "'cenc' initData, Failed, no responses");
                 m_updateLicenseCallback(true, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
                 return;
             }
 
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "'cenc' initData, Succeeded, no keyIDs in currentRequest");
             m_updateLicenseCallback(false, keyStatuses(), WTF::nullopt, WTF::nullopt, Succeeded);
             m_updateResponseCollector = nullptr;
             m_currentRequest = WTF::nullopt;
@@ -697,12 +823,15 @@
         };
         for (auto value : *array) {
             if (!parseResponse(value)) {
+                DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "'cenc' initData, Failed, could not parse response");
                 callback(false, WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed);
                 return;
             }
         }
-    } else
+    } else {
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, "'sinf' initData, processing response");
         [m_currentRequest.value().requests.first() processContentKeyResponse:[PAL::getAVContentKeyResponseClass() contentKeyResponseWithFairPlayStreamingKeyResponseData:responseData->createNSData().get()]];
+    }
 
     // FIXME(rdar://problem/35592277): stash the callback and call it once AVContentKeyResponse supports a success callback.
     struct objc_method_description method = protocol_getMethodDescription(@protocol(AVContentKeySessionDelegate), @selector(contentKeySession:contentKeyRequestDidSucceed:), NO, YES);
@@ -723,11 +852,13 @@
     if (licenseType == LicenseType::PersistentUsageRecord) {
         auto* storageURL = m_instance->storageURL();
         if (!m_instance->persistentStateAllowed() || !storageURL) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, mismatched session type");
             callback(WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed, SessionLoadFailure::MismatchedSessionType);
             return;
         }
         auto* certificate = m_instance->serverCertificate();
         if (!certificate) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, no sessionCertificate");
             callback(WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed, SessionLoadFailure::NoSessionData);
             return;
         }
@@ -748,10 +879,12 @@
         }
 
         if (changedKeys.isEmpty()) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, no session data found");
             callback(WTF::nullopt, WTF::nullopt, WTF::nullopt, Failed, SessionLoadFailure::NoSessionData);
             return;
         }
 
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Succeeded, mismatched session type");
         callback(WTFMove(changedKeys), WTF::nullopt, WTF::nullopt, Succeeded, SessionLoadFailure::None);
     }
 }
@@ -758,6 +891,7 @@
 
 void CDMInstanceSessionFairPlayStreamingAVFObjC::closeSession(const String&, CloseSessionCallback&& callback)
 {
+    DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER);
     if (m_requestLicenseCallback) {
         m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
         ASSERT(!m_requestLicenseCallback);
@@ -788,6 +922,7 @@
         auto* certificate = m_instance->serverCertificate();
 
         if (!m_instance->persistentStateAllowed() || !storageURL || !certificate) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, persistentState not allowed or no storageURL or no certificate");
             callback({ }, WTF::nullopt, Failed);
             return;
         }
@@ -810,6 +945,7 @@
         }
 
         if (!expiredSessionsArray.get().count) {
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Succeeded, no expired sessions");
             callback(WTFMove(changedKeys), WTF::nullopt, Succeeded);
             return;
         }
@@ -819,6 +955,7 @@
             // It should not be possible to have a persistent-usage-record session that does not generate
             // a persistent-usage-record message on close. Signal this by failing and assert.
             ASSERT_NOT_REACHED();
+            DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Failed, no expired session data");
             callback(WTFMove(changedKeys), WTF::nullopt, Failed);
             return;
         }
@@ -828,8 +965,9 @@
         RetainPtr<NSData> expiredSessionsData = [NSPropertyListSerialization dataWithPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 options:kCFPropertyListImmutable error:nullptr];
 
         if (expiredSessionsCount > 1)
-            RELEASE_LOG(EME, "Multiple(%lu) expired session reports found with same sessionID(%s)!", expiredSessionsCount, sessionId.utf8().data());
+            ERROR_LOG_IF_POSSIBLE(LOGIDENTIFIER, "Multiple(", expiredSessionsCount, ") expired session reports found with same sessionID(", sessionId, ")!");
 
+        DEBUG_LOG_IF_POSSIBLE(LOGIDENTIFIER, " Succeeded");
         callback(WTFMove(changedKeys), SharedBuffer::create(expiredSessionsData.get()), Succeeded);
     }
 }
@@ -1113,6 +1251,15 @@
     return lastRequest.requests.last().get();
 }
 
+bool CDMInstanceSessionFairPlayStreamingAVFObjC::hasRequest(AVContentKeyRequest* keyRequest) const
+{
+    for (auto& request : m_requests) {
+        if (request.requests.contains(keyRequest))
+            return true;
+    }
+    return false;
+}
+
 bool CDMInstanceSessionFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
 {
     UNUSED_PARAM(request);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to