Title: [253064] trunk/Source/WebCore
Revision
253064
Author
jer.no...@apple.com
Date
2019-12-03 15:03:58 -0800 (Tue, 03 Dec 2019)

Log Message

Adopt AVContentKeyReportGroup
https://bugs.webkit.org/show_bug.cgi?id=204765

Reviewed by Eric Carlson.

Source/WebCore:

Adopt a new class, AVContentKeyReportGroup, which allows muliple MediaKeySessions to share
an AVContentKeySession, while allowing independent expiration and persistent key usage
tokens. However, this has to be runtime detected, so that existing usage of
AVContentKeySession continues to work on platform versions without report group support.

* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
* platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
(-[WebCoreFPSContentKeySessionDelegate initWithParent:]):
(-[WebCoreFPSContentKeySessionDelegate contentKeySession:contentProtectionSessionIdentifierDidChangeForKeyGroup:]):
(-[WebCoreFPSContentKeySessionDelegate contentKeySession:contentProtectionSessionIdentifierDidChangeForReportGroup:]):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::CDMInstanceFairPlayStreamingAVFObjC):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::ensureSession):
(WebCore::groupForRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
(WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionForGroup const):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC):
(WebCore::initTypeForRequest):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSessionOrGroup):
(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSession): Deleted.

Source/WebCore/PAL:

* pal/cocoa/AVFoundationSoftLink.h:
* pal/cocoa/AVFoundationSoftLink.mm:
* pal/spi/mac/AVFoundationSPI.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (253063 => 253064)


--- trunk/Source/WebCore/ChangeLog	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/ChangeLog	2019-12-03 23:03:58 UTC (rev 253064)
@@ -1,3 +1,42 @@
+2019-12-03  Jer Noble  <jer.no...@apple.com>
+
+        Adopt AVContentKeyReportGroup
+        https://bugs.webkit.org/show_bug.cgi?id=204765
+
+        Reviewed by Eric Carlson.
+
+        Adopt a new class, AVContentKeyReportGroup, which allows muliple MediaKeySessions to share
+        an AVContentKeySession, while allowing independent expiration and persistent key usage
+        tokens. However, this has to be runtime detected, so that existing usage of
+        AVContentKeySession continues to work on platform versions without report group support.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
+        * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+        (-[WebCoreFPSContentKeySessionDelegate initWithParent:]):
+        (-[WebCoreFPSContentKeySessionDelegate contentKeySession:contentProtectionSessionIdentifierDidChangeForKeyGroup:]):
+        (-[WebCoreFPSContentKeySessionDelegate contentKeySession:contentProtectionSessionIdentifierDidChangeForReportGroup:]):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::CDMInstanceFairPlayStreamingAVFObjC):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::ensureSession):
+        (WebCore::groupForRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
+        (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionForGroup const):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC):
+        (WebCore::initTypeForRequest):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestLicense):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::groupSessionIdentifierChanged):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSessionOrGroup):
+        (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSession): Deleted.
+
 2019-12-03  Eric Carlson  <eric.carl...@apple.com>
 
         Add a runtime setting for media in the GPU process

Modified: trunk/Source/WebCore/PAL/ChangeLog (253063 => 253064)


--- trunk/Source/WebCore/PAL/ChangeLog	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/PAL/ChangeLog	2019-12-03 23:03:58 UTC (rev 253064)
@@ -1,3 +1,14 @@
+2019-12-03  Jer Noble  <jer.no...@apple.com>
+
+        Adopt AVContentKeyReportGroup
+        https://bugs.webkit.org/show_bug.cgi?id=204765
+
+        Reviewed by Eric Carlson.
+
+        * pal/cocoa/AVFoundationSoftLink.h:
+        * pal/cocoa/AVFoundationSoftLink.mm:
+        * pal/spi/mac/AVFoundationSPI.h:
+
 2019-11-28  Fujii Hironori  <hironori.fu...@sony.com>
 
         Remove ENABLE_KEYBOARD_CODE_ATTRIBUTE and ENABLE_KEYBOARD_KEY_ATTRIBUTE macros

Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h (253063 => 253064)


--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h	2019-12-03 23:03:58 UTC (rev 253064)
@@ -50,6 +50,7 @@
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVCaptureOutput)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVCaptureSession)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVCaptureVideoDataOutput)
+SOFT_LINK_CLASS_FOR_HEADER(PAL, AVContentKeyReportGroup)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVContentKeyResponse)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVContentKeySession)
 SOFT_LINK_CLASS_FOR_HEADER(PAL, AVFrameRateRange)

Modified: trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm (253063 => 253064)


--- trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm	2019-12-03 23:03:58 UTC (rev 253064)
@@ -61,6 +61,7 @@
 SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAsset, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVAssetReaderSampleReferenceOutput, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVAssetResourceLoadingRequest, PAL_EXPORT)
+SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVContentKeyReportGroup, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVContentKeyResponse, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVContentKeySession, PAL_EXPORT)
 SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVSampleBufferAudioRenderer, PAL_EXPORT)

Modified: trunk/Source/WebCore/PAL/pal/spi/mac/AVFoundationSPI.h (253063 => 253064)


--- trunk/Source/WebCore/PAL/pal/spi/mac/AVFoundationSPI.h	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/PAL/pal/spi/mac/AVFoundationSPI.h	2019-12-03 23:03:58 UTC (rev 253064)
@@ -28,6 +28,10 @@
 #import <objc/runtime.h>
 #import <wtf/SoftLinking.h>
 
+#if HAVE(AVCONTENTKEYSESSION)
+#import <AVFoundation/AVContentKeySession.h>
+#endif
+
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <AVFoundation/AVAssetCache_Private.h>
@@ -154,7 +158,6 @@
 NS_ASSUME_NONNULL_END
 
 #if HAVE(AVCONTENTKEYSESSION)
-#import <AVFoundation/AVContentKeySession.h>
 @interface AVStreamDataParser () <AVContentKeyRecipient>
 @end
 #endif
@@ -163,6 +166,18 @@
 
 #endif // USE(APPLE_INTERNAL_SDK)
 
+#if HAVE(AVCONTENTKEYSESSION)
+@interface AVContentKeyReportGroup : NSObject
+@property (readonly, nullable) NSData *contentProtectionSessionIdentifier;
+- (void)expire;
+- (void)processContentKeyRequestWithIdentifier:(nullable id)identifier initializationData:(nullable NSData *)initializationData options:(nullable NSDictionary<NSString *, id> *)options;
+@end
+
+@interface AVContentKeySession (AVContentKeyGroup_Support)
+- (nonnull AVContentKeyReportGroup *)makeContentKeyGroup;
+@end
+#endif // HAVE(AVCONTENTKEYSESSION)
+
 #if PLATFORM(MAC) && !USE(APPLE_INTERNAL_SDK)
 NS_ASSUME_NONNULL_BEGIN
 @interface AVStreamDataParser (AVStreamDataParserPrivate)

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (253063 => 253064)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-12-03 23:03:58 UTC (rev 253064)
@@ -22948,6 +22948,8 @@
 				A5C974CF11485FF10066F2AB /* KeyEventCocoa.h */,
 				A5C974D011485FF10066F2AB /* KeyEventCocoa.mm */,
 				1A4832B21A953BA6008B4DFE /* LocalizedStringsCocoa.mm */,
+				CD53555723748E5900A613BD /* MediaToolboxSoftLink.cpp */,
+				CD53555623748E5900A613BD /* MediaToolboxSoftLink.h */,
 				C53D39331C97892D007F3AE9 /* MIMETypeRegistryCocoa.mm */,
 				A19D93491AA11B1E00B46C24 /* NetworkExtensionContentFilter.h */,
 				A19D93481AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm */,

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h	2019-12-03 23:03:58 UTC (rev 253064)
@@ -34,6 +34,7 @@
 #include <wtf/RetainPtr.h>
 #include <wtf/text/WTFString.h>
 
+OBJC_CLASS AVContentKeyReportGroup;
 OBJC_CLASS AVContentKeyRequest;
 OBJC_CLASS AVContentKeySession;
 OBJC_CLASS NSData;
@@ -46,8 +47,24 @@
 class CDMInstanceSessionFairPlayStreamingAVFObjC;
 struct CDMMediaCapability;
 
-class CDMInstanceFairPlayStreamingAVFObjC final : public CDMInstance, public CanMakeWeakPtr<CDMInstanceFairPlayStreamingAVFObjC> {
+class AVContentKeySessionDelegateClient {
 public:
+    virtual ~AVContentKeySessionDelegateClient() = default;
+    virtual void didProvideRequest(AVContentKeyRequest*) = 0;
+    virtual void didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&&) = 0;
+    virtual void didProvideRenewingRequest(AVContentKeyRequest*) = 0;
+    virtual void didProvidePersistableRequest(AVContentKeyRequest*) = 0;
+    virtual void didFailToProvideRequest(AVContentKeyRequest*, NSError*) = 0;
+    virtual void requestDidSucceed(AVContentKeyRequest*) = 0;
+    virtual bool shouldRetryRequestForReason(AVContentKeyRequest*, NSString*) = 0;
+    virtual void sessionIdentifierChanged(NSData*) = 0;
+    virtual void groupSessionIdentifierChanged(AVContentKeyReportGroup*, NSData*) = 0;
+    virtual void outputObscuredDueToInsufficientExternalProtectionChanged(bool) = 0;
+};
+
+class CDMInstanceFairPlayStreamingAVFObjC final : public CDMInstance, public AVContentKeySessionDelegateClient, public CanMakeWeakPtr<CDMInstanceFairPlayStreamingAVFObjC> {
+public:
+    CDMInstanceFairPlayStreamingAVFObjC();
     virtual ~CDMInstanceFairPlayStreamingAVFObjC() = default;
 
     static bool supportsPersistableState();
@@ -70,13 +87,29 @@
     NSURL *storageURL() const { return m_storageURL.get(); }
     bool persistentStateAllowed() const { return m_persistentStateAllowed; }
     SharedBuffer* serverCertificate() const { return m_serverCertificate.get(); }
+    AVContentKeySession* contentKeySession() { return m_session.get(); }
 
-    void outputObscuredDueToInsufficientExternalProtectionChanged(bool);
+    // AVContentKeySessionDelegateClient
+    void didProvideRequest(AVContentKeyRequest*) final;
+    void didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&&) final;
+    void didProvideRenewingRequest(AVContentKeyRequest*) final;
+    void didProvidePersistableRequest(AVContentKeyRequest*) final;
+    void didFailToProvideRequest(AVContentKeyRequest*, NSError*) final;
+    void requestDidSucceed(AVContentKeyRequest*) final;
+    bool shouldRetryRequestForReason(AVContentKeyRequest*, NSString*) final;
+    void sessionIdentifierChanged(NSData*) final;
+    void groupSessionIdentifierChanged(AVContentKeyReportGroup*, NSData*) final;
+    void outputObscuredDueToInsufficientExternalProtectionChanged(bool) final;
 
     using Keys = Vector<Ref<SharedBuffer>>;
     CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForKeyIDs(const Keys&) const;
+    CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForGroup(AVContentKeyReportGroup*) const;
 
 private:
+    void ensureSession();
+
+    RetainPtr<AVContentKeySession> m_session;
+    RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate;
     RefPtr<SharedBuffer> m_serverCertificate;
     bool m_persistentStateAllowed { true };
     RetainPtr<NSURL> m_storageURL;
@@ -83,7 +116,7 @@
     Vector<WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC>> m_sessions;
 };
 
-class CDMInstanceSessionFairPlayStreamingAVFObjC final : public CDMInstanceSession, public CanMakeWeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> {
+class CDMInstanceSessionFairPlayStreamingAVFObjC final : public CDMInstanceSession, public AVContentKeySessionDelegateClient, public CanMakeWeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC> {
 public:
     CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&&);
     virtual ~CDMInstanceSessionFairPlayStreamingAVFObjC();
@@ -98,19 +131,22 @@
     void setClient(WeakPtr<CDMInstanceSessionClient>&&) final;
     void clearClient() final;
 
-    void didProvideRequest(AVContentKeyRequest*);
-    void didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&&);
-    void didProvideRenewingRequest(AVContentKeyRequest*);
-    void didProvidePersistableRequest(AVContentKeyRequest*);
-    void didFailToProvideRequest(AVContentKeyRequest*, NSError*);
-    void requestDidSucceed(AVContentKeyRequest*);
-    bool shouldRetryRequestForReason(AVContentKeyRequest*, NSString*);
-    void sessionIdentifierChanged(NSData*);
-    void outputObscuredDueToInsufficientExternalProtectionChanged(bool);
+    // AVContentKeySessionDelegateClient
+    void didProvideRequest(AVContentKeyRequest*) final;
+    void didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&&) final;
+    void didProvideRenewingRequest(AVContentKeyRequest*) final;
+    void didProvidePersistableRequest(AVContentKeyRequest*) final;
+    void didFailToProvideRequest(AVContentKeyRequest*, NSError*) final;
+    void requestDidSucceed(AVContentKeyRequest*) final;
+    bool shouldRetryRequestForReason(AVContentKeyRequest*, NSString*) final;
+    void sessionIdentifierChanged(NSData*) final;
+    void groupSessionIdentifierChanged(AVContentKeyReportGroup*, NSData*) final;
+    void outputObscuredDueToInsufficientExternalProtectionChanged(bool) final;
 
     using Keys = CDMInstanceFairPlayStreamingAVFObjC::Keys;
     Keys keyIDs();
-    AVContentKeySession* contentKeySession() { return m_session.get(); }
+    AVContentKeySession* contentKeySession() { return m_session ? m_session.get() : m_instance->contentKeySession(); }
+    AVContentKeyReportGroup* contentKeyReportGroup() { return m_group.get(); }
 
     struct Request {
         AtomString initType;
@@ -119,7 +155,7 @@
     };
 
 private:
-    AVContentKeySession* ensureSession();
+    bool ensureSessionOrGroup();
     bool isLicenseTypeSupported(LicenseType) const;
 
     KeyStatusVector keyStatuses() const;
@@ -127,6 +163,7 @@
     AVContentKeyRequest* lastKeyRequest() const;
 
     Ref<CDMInstanceFairPlayStreamingAVFObjC> m_instance;
+    RetainPtr<AVContentKeyReportGroup> m_group;
     RetainPtr<AVContentKeySession> m_session;
     Optional<Request> m_currentRequest;
     RetainPtr<WebCoreFPSContentKeySessionDelegate> m_delegate;

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2019-12-03 22:56:46 UTC (rev 253063)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm	2019-12-03 23:03:58 UTC (rev 253064)
@@ -48,14 +48,15 @@
 
 static const NSString *PlaybackSessionIdKey = @"PlaybackSessionID";
 static NSString * const InitializationDataTypeKey = @"InitializationDataType";
+static NSString * const ContentKeyReportGroupKey = @"ContentKeyReportGroup";
 
 @interface WebCoreFPSContentKeySessionDelegate : NSObject<AVContentKeySessionDelegate> {
-    WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC* _parent;
+    WebCore::AVContentKeySessionDelegateClient* _parent;
 }
 @end
 
 @implementation WebCoreFPSContentKeySessionDelegate
-- (id)initWithParent:(WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC *)parent
+- (id)initWithParent:(WebCore::AVContentKeySessionDelegateClient *)parent
 {
     if (!(self = [super init]))
         return nil;
@@ -141,11 +142,52 @@
     if (_parent)
         _parent->sessionIdentifierChanged(session.contentProtectionSessionIdentifier);
 }
+- (void)contentKeySession:(AVContentKeySession *)session contentProtectionSessionIdentifierDidChangeForKeyGroup:(nullable AVContentKeyReportGroup *)reportGroup
+{
+    // FIXME: Remove after rdar://57430747 is fixed
+    [self contentKeySession:session contentProtectionSessionIdentifierDidChangeForReportGroup:reportGroup];
+}
 
+- (void)contentKeySession:(AVContentKeySession *)session contentProtectionSessionIdentifierDidChangeForReportGroup:(nullable AVContentKeyReportGroup *)reportGroup
+{
+    UNUSED_PARAM(session);
+    if (_parent)
+        _parent->groupSessionIdentifierChanged(reportGroup, reportGroup.contentProtectionSessionIdentifier);
+}
+
 @end
 
 namespace WebCore {
 
+CDMInstanceFairPlayStreamingAVFObjC::CDMInstanceFairPlayStreamingAVFObjC()
+{
+    if (PAL::getAVContentKeyReportGroupClass())
+        ensureSession();
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::ensureSession()
+{
+    if (m_session)
+        return;
+
+    if (!PAL::canLoad_AVFoundation_AVContentKeySystemFairPlayStreaming())
+        return;
+
+    auto storageURL = this->storageURL();
+    if (!persistentStateAllowed() || !storageURL)
+        m_session = [PAL::getAVContentKeySessionClass() contentKeySessionWithKeySystem:AVContentKeySystemFairPlayStreaming];
+    else
+        m_session = [PAL::getAVContentKeySessionClass() contentKeySessionWithKeySystem:AVContentKeySystemFairPlayStreaming storageDirectoryAtURL:storageURL];
+
+    if (!m_session)
+        return;
+
+    if (!m_delegate)
+        m_delegate = adoptNS([[WebCoreFPSContentKeySessionDelegate alloc] initWithParent:this]);
+
+    [m_session setDelegate:m_delegate.get() queue:dispatch_get_main_queue()];
+}
+
 class CDMInstanceSessionFairPlayStreamingAVFObjC::UpdateResponseCollector {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -306,6 +348,71 @@
     return keySystem;
 }
 
+static AVContentKeyReportGroup* groupForRequest(AVContentKeyRequest* request)
+{
+    ASSERT([request respondsToSelector:@selector(options)]);
+    ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
+    auto group = (AVContentKeyReportGroup*)[request.options valueForKey:ContentKeyReportGroupKey];
+    ALLOW_NEW_API_WITHOUT_GUARDS_END
+    return group;
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest(AVContentKeyRequest *request)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        session->didProvideRequest(request);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRequests(Vector<RetainPtr<AVContentKeyRequest>>&& requests)
+{
+    if (auto* session = sessionForGroup(groupForRequest(requests.first().get())))
+        session->didProvideRequests(WTFMove(requests));
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        session->didProvideRenewingRequest(request);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didProvidePersistableRequest(AVContentKeyRequest *request)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        session->didProvidePersistableRequest(request);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest(AVContentKeyRequest *request, NSError *error)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        session->didFailToProvideRequest(request, error);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        session->requestDidSucceed(request);
+}
+
+bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
+{
+    if (auto* session = sessionForGroup(groupForRequest(request)))
+        return session->shouldRetryRequestForReason(request, reason);
+    return false;
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::sessionIdentifierChanged(NSData *sessionIdentifier)
+{
+    UNUSED_PARAM(sessionIdentifier);
+    // No-op. If we are getting this callback, there are outstanding AVContentKeyRequestGroups which are managing their own
+    // session identifiers.
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::groupSessionIdentifierChanged(AVContentKeyReportGroup* group, NSData *sessionIdentifier)
+{
+    if (auto* session = sessionForGroup(group))
+        session->groupSessionIdentifierChanged(group, sessionIdentifier);
+}
+
 void CDMInstanceFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
 {
     for (auto& sessionInterface : m_sessions) {
@@ -329,9 +436,20 @@
     return nullptr;
 }
 
+CDMInstanceSessionFairPlayStreamingAVFObjC* CDMInstanceFairPlayStreamingAVFObjC::sessionForGroup(AVContentKeyReportGroup* group) const
+{
+    auto index = m_sessions.findMatching([group] (auto session) {
+        return session && session->contentKeyReportGroup() == group;
+    });
+
+    if (index != notFound)
+        return m_sessions[index].get();
+    return nullptr;
+}
+
 CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&& instance)
     : m_instance(WTFMove(instance))
-    , m_delegate([[WebCoreFPSContentKeySessionDelegate alloc] initWithParent:this])
+    , m_delegate(adoptNS([[WebCoreFPSContentKeySessionDelegate alloc] initWithParent:this]))
 {
 }
 
@@ -374,8 +492,12 @@
 ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
     auto nsInitType = (NSString*)[request.options valueForKey:InitializationDataTypeKey];
 ALLOW_NEW_API_WITHOUT_GUARDS_END
-    if (![nsInitType isKindOfClass:NSString.class])
-        return emptyAtom();
+    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);
 }
@@ -405,7 +527,7 @@
         return;
     }
 
-    if (!ensureSession()) {
+    if (!ensureSessionOrGroup()) {
         callback(SharedBuffer::create(), emptyString(), false, Failed);
         return;
     }
@@ -429,7 +551,14 @@
     }
 
     m_requestLicenseCallback = WTFMove(callback);
-    [m_session processContentKeyRequestWithIdentifier:identifier.get() initializationData:initializationData.get() options:@{ InitializationDataTypeKey: (NSString*)initDataType }];
+
+    if (m_group) {
+        auto* options = @{ ContentKeyReportGroupKey: m_group.get(), InitializationDataTypeKey: (NSString*)initDataType };
+        [m_group processContentKeyRequestWithIdentifier:identifier.get() initializationData:initializationData.get() options:options];
+    } else {
+        auto* options = @{ InitializationDataTypeKey: (NSString*)initDataType };
+        [m_session processContentKeyRequestWithIdentifier:identifier.get() initializationData:initializationData.get() options:options];
+    }
 }
 
 static bool isEqual(const SharedBuffer& data, const String& value)
@@ -656,8 +785,10 @@
 
 void CDMInstanceSessionFairPlayStreamingAVFObjC::removeSessionData(const String& sessionId, LicenseType licenseType, RemoveSessionDataCallback&& callback)
 {
-    // FIXME: We should be able to expire individual AVContentKeyRequests rather than the entire AVContentKeySession.
-    [m_session expire];
+    if (m_group)
+        [m_group expire];
+    else
+        [m_session expire];
 
     if (licenseType == LicenseType::PersistentUsageRecord) {
         auto* storageURL = m_instance->storageURL();
@@ -988,6 +1119,12 @@
     m_client->sessionIdChanged(m_sessionId);
 }
 
+void CDMInstanceSessionFairPlayStreamingAVFObjC::groupSessionIdentifierChanged(AVContentKeyReportGroup* group, NSData *sessionIdentifier)
+{
+    UNUSED_PARAM(group);
+    sessionIdentifierChanged(sessionIdentifier);
+}
+
 static auto requestStatusToCDMStatus(AVContentKeyRequestStatus status)
 {
     switch (status) {
@@ -1034,11 +1171,16 @@
         m_client->updateKeyStatuses(keyStatuses());
 }
 
-AVContentKeySession* CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSession()
+bool CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSessionOrGroup()
 {
-    if (m_session)
-        return m_session.get();
+    if (m_session || m_group)
+        return true;
 
+    if (auto* session = m_instance->contentKeySession()) {
+        m_group = [session makeContentKeyGroup];
+        return true;
+    }
+
     auto storageURL = m_instance->storageURL();
     if (!m_instance->persistentStateAllowed() || !storageURL)
         m_session = [PAL::getAVContentKeySessionClass() contentKeySessionWithKeySystem:AVContentKeySystemFairPlayStreaming];
@@ -1046,10 +1188,10 @@
         m_session = [PAL::getAVContentKeySessionClass() contentKeySessionWithKeySystem:AVContentKeySystemFairPlayStreaming storageDirectoryAtURL:storageURL];
 
     if (!m_session)
-        return nullptr;
+        return false;
 
     [m_session setDelegate:m_delegate.get() queue:dispatch_get_main_queue()];
-    return m_session.get();
+    return true;
 }
 
 bool CDMInstanceSessionFairPlayStreamingAVFObjC::isLicenseTypeSupported(LicenseType licenseType) const
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to