Diff
Modified: trunk/Source/WebCore/ChangeLog (225765 => 225766)
--- trunk/Source/WebCore/ChangeLog 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/ChangeLog 2017-12-12 01:17:21 UTC (rev 225766)
@@ -1,3 +1,37 @@
+2017-12-11 Jer Noble <jer.no...@apple.com>
+
+ [EME] support update() for FairPlayStreaming in Modern EME API
+ https://bugs.webkit.org/show_bug.cgi?id=180542
+
+ Reviewed by Eric Carlson.
+
+ Support the updateLicense() method in CDMInstanceFairPlayStreaming. Also, support adding a
+ AVStreamDataParser to the AVContentKeySession.
+
+ Drive-by fixes:
+
+ - Sometimes, AVFoundation will give us a base64 encoded string with spaces url-disallowed
+ characters, so use base64Decode() rather than base64URLDecode().
+
+ * platform/graphics/avfoundation/CDMFairPlayStreaming.cpp:
+ (WebCore::validFairPlayStreamingSchemes):
+ (WebCore::extractSinfData):
+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::updateLicense):
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didFailToProvideRequest):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::cdmInstance const):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceAttached):
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceDetached):
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::attemptToDecryptWithInstance):
+ * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+ * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+ (WebCore::SourceBufferPrivateAVFObjC::destroyParser):
+ (WebCore::SourceBufferPrivateAVFObjC::setCDMInstance):
+
2017-12-11 Eric Carlson <eric.carl...@apple.com>
Web Inspector: Optionally log WebKit log parameters as JSON
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp 2017-12-12 01:17:21 UTC (rev 225766)
@@ -56,6 +56,7 @@
"cbcs",
"cbc2",
"cbc1",
+ "cenc",
});
return validSchemes;
@@ -95,7 +96,7 @@
continue;
Vector<char> sinfData;
- if (!WTF::base64URLDecode(keyID, { sinfData }))
+ if (!WTF::base64Decode(keyID, { sinfData }, WTF::Base64IgnoreSpacesAndNewLines))
continue;
sinfs.uncheckedAppend(SharedBuffer::create(WTFMove(sinfData)));
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h 2017-12-12 01:17:21 UTC (rev 225766)
@@ -75,6 +75,8 @@
bool shouldRetryRequestForReason(AVContentKeyRequest *, NSString *);
void sessionIdentifierChanged(NSData *);
+ AVContentKeySession *contentKeySession() { return m_session.get(); }
+
private:
WeakPtr<CDMInstanceFairPlayStreamingAVFObjC> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); }
bool isLicenseTypeSupported(LicenseType) const;
@@ -95,4 +97,6 @@
};
}
+SPECIALIZE_TYPE_TRAITS_CDM_INSTANCE(WebCore::CDMInstanceFairPlayStreamingAVFObjC, WebCore::CDMInstance::ImplementationType::FairPlayStreaming)
+
#endif // HAVE(AVCONTENTKEYSESSION)
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2017-12-12 01:17:21 UTC (rev 225766)
@@ -39,6 +39,7 @@
SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVContentKeySession);
+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVContentKeyResponse);
SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVURLAsset);
SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVContentKeySystemFairPlayStreaming, NSString*)
@@ -238,9 +239,27 @@
[m_session processContentKeyRequestWithIdentifier:nil initializationData:initData->createNSData().get() options:nil];
}
-void CDMInstanceFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer&, LicenseUpdateCallback)
+void CDMInstanceFairPlayStreamingAVFObjC::updateLicense(const String&, LicenseType, const SharedBuffer& responseData, LicenseUpdateCallback callback)
{
- notImplemented();
+ if (!m_request) {
+ callback(false, std::nullopt, std::nullopt, std::nullopt, Failed);
+ return;
+ }
+ // FIXME(rdar://problem/35597141): use the future AVContentKeyRequest keyID property, rather than parsing it out of the init
+ // data, to get the keyID.
+ Vector<Ref<SharedBuffer>> keyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(SharedBuffer::create(m_request.get().initializationData));
+ if (keyIDs.isEmpty()) {
+ callback(false, std::nullopt, std::nullopt, std::nullopt, Failed);
+ return;
+ }
+
+ [m_request processContentKeyResponse:[getAVContentKeyResponseClass() contentKeyResponseWithFairPlayStreamingKeyResponseData:responseData.createNSData().get()]];
+
+ // FIXME(rdar://problem/35592277): stash the callback and call it once AVContentKeyResponse supports a success callback.
+ KeyStatusVector keyStatuses;
+ keyStatuses.reserveInitialCapacity(1);
+ keyStatuses.uncheckedAppend(std::make_pair(WTFMove(keyIDs.first()), KeyStatus::Usable));
+ callback(false, std::make_optional(WTFMove(keyStatuses)), std::nullopt, std::nullopt, Succeeded);
}
void CDMInstanceFairPlayStreamingAVFObjC::loadSession(LicenseType, const String&, const String&, LoadSessionCallback)
@@ -279,6 +298,7 @@
Vector<Ref<SharedBuffer>> keyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(SharedBuffer::create(request.initializationData));
if (keyIDs.isEmpty()) {
m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
+ m_requestLicenseCallback = nullptr;
return;
}
@@ -292,6 +312,7 @@
m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
else
m_requestLicenseCallback(SharedBuffer::create(contentKeyRequestData.get()), m_sessionId, false, Succeeded);
+ m_requestLicenseCallback = nullptr;
});
}];
}
@@ -310,7 +331,8 @@
{
UNUSED_PARAM(request);
UNUSED_PARAM(error);
- m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
+ if (m_requestLicenseCallback)
+ m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
}
bool CDMInstanceFairPlayStreamingAVFObjC::shouldRetryRequestForReason(AVContentKeyRequest *request, NSString *reason)
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2017-12-12 01:17:21 UTC (rev 225766)
@@ -124,6 +124,16 @@
AVStreamSession *streamSession();
void setCDMSession(LegacyCDMSession*) override;
CDMSessionMediaSourceAVFObjC* cdmSession() const { return m_session; }
+#endif
+
+#if ENABLE(ENCRYPTED_MEDIA)
+ void cdmInstanceAttached(CDMInstance&) final;
+ void cdmInstanceDetached(CDMInstance&) final;
+ void attemptToDecryptWithInstance(CDMInstance&) final;
+ CDMInstance* cdmInstance() const { return m_cdmInstance.get(); }
+#endif
+
+#if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
void keyNeeded(Uint8Array*);
#endif
#if ENABLE(ENCRYPTED_MEDIA)
@@ -305,6 +315,9 @@
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
std::unique_ptr<VideoFullscreenLayerManager> m_videoFullscreenLayerManager;
#endif
+#if ENABLE(ENCRYPTED_MEDIA)
+ RefPtr<CDMInstance> m_cdmInstance;
+#endif
};
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2017-12-12 01:17:21 UTC (rev 225766)
@@ -30,6 +30,7 @@
#import "AVAssetTrackUtilities.h"
#import "AVFoundationMIMETypeCache.h"
+#import "CDMInstance.h"
#import "CDMSessionAVStreamSession.h"
#import "CDMSessionMediaSourceAVFObjC.h"
#import "FileSystem.h"
@@ -958,6 +959,27 @@
#endif
#if ENABLE(ENCRYPTED_MEDIA)
+void MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceAttached(CDMInstance& instance)
+{
+ ASSERT(!m_cdmInstance);
+ m_cdmInstance = &instance;
+ for (auto& sourceBuffer : m_mediaSourcePrivate->sourceBuffers())
+ sourceBuffer->setCDMInstance(&instance);
+}
+
+void MediaPlayerPrivateMediaSourceAVFObjC::cdmInstanceDetached(CDMInstance& instance)
+{
+ ASSERT_UNUSED(instance, m_cdmInstance && m_cdmInstance == &instance);
+ for (auto& sourceBuffer : m_mediaSourcePrivate->sourceBuffers())
+ sourceBuffer->setCDMInstance(nullptr);
+
+ m_cdmInstance = nullptr;
+}
+
+void MediaPlayerPrivateMediaSourceAVFObjC::attemptToDecryptWithInstance(CDMInstance&)
+{
+}
+
void MediaPlayerPrivateMediaSourceAVFObjC::initializationDataEncountered(const String& initDataType, RefPtr<ArrayBuffer>&& initData)
{
m_player->initializationDataEncountered(initDataType, WTFMove(initData));
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h 2017-12-12 01:17:21 UTC (rev 225766)
@@ -55,6 +55,8 @@
namespace WebCore {
+class CDMInstance;
+class CDMInstanceFairPlayStreamingAVFObjC;
class CDMSessionMediaSourceAVFObjC;
class MediaSourcePrivateAVFObjC;
class TimeRanges;
@@ -107,6 +109,7 @@
int protectedTrackID() const { return m_protectedTrackID; }
AVStreamDataParser* parser() const { return m_parser.get(); }
void setCDMSession(CDMSessionMediaSourceAVFObjC*);
+ void setCDMInstance(CDMInstance*);
void flush();
@@ -182,6 +185,9 @@
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
CDMSessionMediaSourceAVFObjC* m_session { nullptr };
#endif
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ RefPtr<CDMInstanceFairPlayStreamingAVFObjC> m_cdmInstance;
+#endif
std::optional<FloatSize> m_cachedSize;
FloatSize m_currentSize;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (225765 => 225766)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm 2017-12-12 00:53:30 UTC (rev 225765)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm 2017-12-12 01:17:21 UTC (rev 225766)
@@ -30,6 +30,7 @@
#import "AVAssetTrackUtilities.h"
#import "AudioTrackPrivateMediaSourceAVFObjC.h"
+#import "CDMInstanceFairPlayStreamingAVFObjC.h"
#import "CDMSessionAVContentKeySession.h"
#import "CDMSessionMediaSourceAVFObjC.h"
#import "InbandTextTrackPrivateAVFObjC.h"
@@ -675,7 +676,7 @@
}
#endif
-#if ENABLE(ENCRYPTED_MEDIA)
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
if (m_mediaSource) {
auto initDataBuffer = SharedBuffer::create(initData);
m_mediaSource->player()->initializationDataEncountered("sinf", initDataBuffer->tryCreateArrayBuffer());
@@ -682,11 +683,9 @@
}
#endif
-#if !ENABLE(ENCRYPTED_MEDIA) && !ENABLE(LEGACY_ENCRYPTED_MEDIA)
UNUSED_PARAM(initData);
UNUSED_PARAM(trackID);
UNUSED_PARAM(hasSessionSemaphore);
-#endif
}
void SourceBufferPrivateAVFObjC::setClient(SourceBufferPrivateClient* client)
@@ -766,6 +765,10 @@
if (m_mediaSource && m_mediaSource->player()->hasStreamSession())
[m_mediaSource->player()->streamSession() removeStreamDataParser:m_parser.get()];
#endif
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ if (m_cdmInstance)
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:m_parser.get()];
+#endif
[m_delegate invalidate];
m_delegate = nullptr;
@@ -918,6 +921,30 @@
#endif
}
+void SourceBufferPrivateAVFObjC::setCDMInstance(CDMInstance* instance)
+{
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ auto* fpsInstance = downcast<CDMInstanceFairPlayStreamingAVFObjC>(instance);
+ if (!fpsInstance || fpsInstance == m_cdmInstance)
+ return;
+
+ if (m_cdmInstance)
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:m_parser.get()];
+
+ m_cdmInstance = fpsInstance;
+
+ if (m_cdmInstance) {
+ [m_cdmInstance->contentKeySession() addContentKeyRecipient:m_parser.get()];
+ if (m_hasSessionSemaphore) {
+ dispatch_semaphore_signal(m_hasSessionSemaphore.get());
+ m_hasSessionSemaphore = nullptr;
+ }
+ }
+#else
+ UNUSED_PARAM(instance);
+#endif
+}
+
void SourceBufferPrivateAVFObjC::flush()
{
flushVideo();