Diff
Modified: trunk/LayoutTests/ChangeLog (225636 => 225637)
--- trunk/LayoutTests/ChangeLog 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/LayoutTests/ChangeLog 2017-12-07 19:46:53 UTC (rev 225637)
@@ -1,3 +1,16 @@
+2017-12-07 Jer Noble <jer.no...@apple.com>
+
+ [EME] Support generateRequest() in CDMFairPlayStreaming
+ https://bugs.webkit.org/show_bug.cgi?id=179752
+
+ Reviewed by Eric Carlson.
+
+ * platform/mac/TestExpectations:
+ * platform/mac/media/encrypted-media/fps-createSession-expected.txt: Added.
+ * platform/mac/media/encrypted-media/fps-createSession.html: Added.
+ * platform/mac/media/encrypted-media/fps-generateRequest-expected.txt: Added.
+ * platform/mac/media/encrypted-media/fps-generateRequest.html: Added.
+
2017-12-07 Ryan Haddad <ryanhad...@apple.com>
Unreviewed, rolling out r224931.
Modified: trunk/LayoutTests/platform/mac/TestExpectations (225636 => 225637)
--- trunk/LayoutTests/platform/mac/TestExpectations 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2017-12-07 19:46:53 UTC (rev 225637)
@@ -1748,6 +1748,8 @@
# AVContentKeySession not available pre-High Sierra
[ ElCapitan Sierra ] platform/mac/media/encrypted-media/fps-createMediaKeys.html [ Skip ]
[ ElCapitan Sierra ] platform/mac/media/encrypted-media/fps-requestMediaKeySystemAccess.html [ Skip ]
+[ ElCapitan Sierra ] platform/mac/media/encrypted-media/fps-createSession.html [ Skip ]
+[ ElCapitan Sierra ] platform/mac/media/encrypted-media/fps-generateRequest.html [ Skip ]
# rdar://problem/35395437
[ HighSierra+ ] imported/w3c/web-platform-tests/media-source/mediasource-play.html [ Failure ]
Added: trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession-expected.txt (0 => 225637)
--- trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession-expected.txt 2017-12-07 19:46:53 UTC (rev 225637)
@@ -0,0 +1,8 @@
+RUN(promise = navigator.requestMediaKeySystemAccess("com.apple.fps", capabilities))
+Promise resolved OK
+RUN(promise = access.createMediaKeys())
+Promise resolved OK
+RUN(session = keys.createSession())
+EXPECTED (session != 'null') OK
+END OF TEST
+
Added: trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession.html (0 => 225637)
--- trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession.html (rev 0)
+++ trunk/LayoutTests/platform/mac/media/encrypted-media/fps-createSession.html 2017-12-07 19:46:53 UTC (rev 225637)
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>fps-requestMediaKeySystemAccess</title>
+ <script src=""
+ <script>
+ var capabilities = [{
+ initDataTypes: ['sinf'],
+ videoCapabilities: [{ contentType: 'video/mp4', robustness: '' }],
+ distinctiveIdentifier: 'not-allowed',
+ persistentState: 'not-allowed',
+ sessionTypes: ['temporary'],
+ }];
+ var promise;
+ var access;
+ var keys;
+ var session;
+ var initData = null;
+
+ function startTest() {
+ run('promise = navigator.requestMediaKeySystemAccess("com.apple.fps", capabilities)');
+ shouldResolve(promise).then(gotAccess, endTest);
+ }
+
+ function gotAccess(access) {
+ window.access = access;
+ run('promise = access.createMediaKeys()');
+ shouldResolve(promise).then(createdKeys, endTest);
+ }
+
+ function createdKeys(keys) {
+ window.keys = keys;
+ run('session = keys.createSession()');
+ testExpected('session', 'null', '!=');
+ endTest();
+ }
+
+ window.addEventListener('load', startTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
Added: trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest-expected.txt (0 => 225637)
--- trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest-expected.txt 2017-12-07 19:46:53 UTC (rev 225637)
@@ -0,0 +1,11 @@
+RUN(promise = navigator.requestMediaKeySystemAccess("com.apple.fps", capabilities))
+Promise resolved OK
+RUN(promise = access.createMediaKeys())
+Promise resolved OK
+RUN(keys.setServerCertificate(serverCertificate))
+RUN(session = keys.createSession())
+EXPECTED (session != 'null') OK
+RUN(promise = session.generateRequest("sinf", initData))
+Promise resolved OK
+END OF TEST
+
Added: trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest.html (0 => 225637)
--- trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest.html (rev 0)
+++ trunk/LayoutTests/platform/mac/media/encrypted-media/fps-generateRequest.html 2017-12-07 19:46:53 UTC (rev 225637)
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>fps-requestMediaKeySystemAccess</title>
+ <script src=""
+ <script>
+ var capabilities = [{
+ initDataTypes: ['sinf'],
+ videoCapabilities: [{ contentType: 'video/mp4', robustness: '' }],
+ distinctiveIdentifier: 'not-allowed',
+ persistentState: 'not-allowed',
+ sessionTypes: ['temporary'],
+ }];
+ var promise;
+ var access;
+ var keys;
+ var session;
+ var initData = new TextEncoder().encode(JSON.stringify({
+ sinf: [
+ "AAAADGZybWFtcDRhAAAAFHNjaG0AAAAAY2JjcwABAAAAAAA5c2NoaQAAADF0ZW5jAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAENwoLj77jCjwCAAw3SqKao8=",
+ ]
+ }));
+ var serverCertificateURI = "data:application/x-x509-ca-cert;base64,MIIEyDCCA7CgAwIBAgIID0/07cCHH0YwDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYDVQQDDCpBcHBsZSBLZXkgU2VydmljZXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIxMjIwMDAzODQzWhcNMTQxMjIxMDAzODQzWjBIMQswCQYDVQQGEwJVUzESMBAGA1UECgwJQXBwbGUgSW5jMRIwEAYDVQQLDAlBcHBsZSBJbmMxETAPBgNVBAMMCGZwc3Rlc3Q0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuHevDlphOM0sD67r3olFkN/2vC0oPl+dJ2CrBkL0tUJov9YbXud6ymJp2TkKkGqnubRaX5mI94+V9Cc/0zSlp+NTCDTcZ7y44E8j85Av/5XqozUf/wUyY+UYPBRD6BHUnH5YD6uuSlLcqE0DaE8ptXiQyN3SRteCFQ4nI9f11uQIDAQABo4ICATCCAf0wHQYDVR0OBBYEFBaVf1g1bfyAW776Sfveqj9N03EMMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUY+RHVMuFcVlGLIOszEQxZGcDLL4wgeIGA1UdIASB2jCB1zCB1AYJKoZIhvdjZAUBMIHGMIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZ
SwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuYXBwbGUuY29tL2tleXNlcnZpY2VzLmNybDAOBgNVHQ8BAf8EBAMCBSAwNAYLKoZIhvdjZAYNAQMBAf8EIgHGeq0WCxH3oALqbKRDeCl4lqDaHVSQjsQZnyCME2TecUEwSwYLKoZIhvdjZAYNAQQBAf8EOQHlHhdsgB8QPJZFb9aAmvc8kYSTQYbjF6/U2mq46sXWRKWPKGpqLyC5ActNQUuHjynZn6Y0vs0D8jANBgkqhkiG9w0BAQUFAAOCAQEAg8GkEw0gDRn7raA8w+V36NOvKlUx3Wh3pcqI8cRATv9Twp4zfyJ4FwxdT90/zCtUUjTVtau6yESTwX+LUFu/Y0kvaV0htgBIBu7MWYCvfLlSwS4MqbBtNdloDNvU7CNyWXaMpKpYKN6i0SqEnTvF0mSTpBliCT+QxuNIxaWq9h2cCn79kbXJM5+IC37mIWO0jvzQjeSlOXJPZrNHZ6Bjt0AyiCIiZVkPmVm5lV3Ycd0gf4mfhAVJYE/p6/dTk+mqnxDdUUMVFDUfu1OqBim6ldWnAh8PlWaGh5rLYVgGvxEEPDNeueYhxTrDnENbhCZ5n/by0Rp0s67t1924Wk+QUQ==";
+ var serverCertificate;
+
+ function startTest() {
+ run('promise = navigator.requestMediaKeySystemAccess("com.apple.fps", capabilities)');
+ shouldResolve(promise).then(gotAccess, endTest);
+ }
+
+ function gotAccess(access) {
+ window.access = access;
+ run('promise = access.createMediaKeys()');
+ shouldResolve(promise).then(createdKeys, endTest);
+ }
+
+ async function createdKeys(keys) {
+ window.keys = keys;
+ var response = await fetch(serverCertificateURI);
+ serverCertificate = await response.arrayBuffer();
+ run('keys.setServerCertificate(serverCertificate)');
+ run('session = keys.createSession()');
+ testExpected('session', 'null', '!=');
+ run('promise = session.generateRequest("sinf", initData)');
+ shouldResolve(promise).then(endTest, endTest);
+ }
+
+ window.addEventListener('load', startTest);
+ </script>
+</head>
+<body>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (225636 => 225637)
--- trunk/Source/WebCore/ChangeLog 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/Source/WebCore/ChangeLog 2017-12-07 19:46:53 UTC (rev 225637)
@@ -1,5 +1,29 @@
2017-12-07 Jer Noble <jer.no...@apple.com>
+ [EME] Support generateRequest() in CDMFairPlayStreaming
+ https://bugs.webkit.org/show_bug.cgi?id=179752
+
+ Reviewed by Eric Carlson.
+
+ Tests: platform/mac/media/encrypted-media/fps-createSession.html
+ platform/mac/media/encrypted-media/fps-generateRequest.html
+
+ Add support for generating license requests from initialization data in
+ CDMFairPlayStreaming. To do so, add explicit checks for FairPlay Steraming requirements:
+ reqests will fail if no server certificate exists, and will fail if no content key id exists
+ in the initialization data.
+
+ * platform/graphics/avfoundation/CDMFairPlayStreaming.cpp:
+ (WebCore::CDMPrivateFairPlayStreaming::extractKeyIDsSinf):
+ (WebCore::CDMPrivateFairPlayStreaming::sanitizeSinf):
+ (WebCore::CDMFactory::platformRegisterFactories):
+ * platform/graphics/avfoundation/CDMFairPlayStreaming.h:
+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::requestLicense):
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::didProvideRequest):
+
+2017-12-07 Jer Noble <jer.no...@apple.com>
+
[EME] Possible deadlock when aborting a SourceBufferPrivateAVFObjC append operation
https://bugs.webkit.org/show_bug.cgi?id=180486
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp (225636 => 225637)
--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.cpp 2017-12-07 19:46:53 UTC (rev 225637)
@@ -50,6 +50,23 @@
namespace WebCore {
+static const Vector<FourCC>& validFairPlayStreamingSchemes()
+{
+ static NeverDestroyed<Vector<FourCC>> validSchemes = Vector<FourCC>({
+ "cbcs",
+ "cbc2",
+ "cbc1",
+ });
+
+ return validSchemes;
+}
+
+static const String& sinfName()
+{
+ static NeverDestroyed<String> sinf { MAKE_STATIC_STRING_IMPL("sinf") };
+ return sinf;
+}
+
static Vector<Ref<SharedBuffer>> extractSinfData(const SharedBuffer& buffer)
{
// JSON of the format: "{ sinf: [ <base64-encoded-string> ] }"
@@ -66,7 +83,7 @@
return { };
RefPtr<JSON::Array> sinfArray;
- if (!object->getArray("sinf", sinfArray))
+ if (!object->getArray(sinfName(), sinfArray))
return { };
Vector<Ref<SharedBuffer>> sinfs;
@@ -134,28 +151,21 @@
return result;
}
-static Vector<Ref<SharedBuffer>> extractKeyIDsSinf(const SharedBuffer& buffer)
+Vector<Ref<SharedBuffer>> CDMPrivateFairPlayStreaming::extractKeyIDsSinf(const SharedBuffer& buffer)
{
- auto sinfs = extractSinfData(buffer);
- if (sinfs.isEmpty())
- return { };
Vector<Ref<SharedBuffer>> keyIDs;
- for (auto& sinf : sinfs) {
- auto results = extractSchemeAndKeyIdFromSinf(sinf);
- if (!results.size())
- continue;
+ auto results = extractSchemeAndKeyIdFromSinf(buffer);
- for (auto& result : results) {
- if (result.first == 'cbcs')
- keyIDs.append(SharedBuffer::create(result.second.data(), result.second.size()));
- }
+ for (auto& result : results) {
+ if (validFairPlayStreamingSchemes().contains(result.first))
+ keyIDs.append(SharedBuffer::create(result.second.data(), result.second.size()));
}
return keyIDs;
}
-static RefPtr<SharedBuffer> sanitizeSinf(const SharedBuffer& buffer)
+RefPtr<SharedBuffer> CDMPrivateFairPlayStreaming::sanitizeSinf(const SharedBuffer& buffer)
{
// Common SINF Box Format
UNUSED_PARAM(buffer);
@@ -168,7 +178,7 @@
factories.append(&CDMFactoryClearKey::singleton());
factories.append(&CDMFactoryFairPlayStreaming::singleton());
- InitDataRegistry::shared().registerInitDataType("sinf", { sanitizeSinf, extractKeyIDsSinf });
+ InitDataRegistry::shared().registerInitDataType(sinfName(), { CDMPrivateFairPlayStreaming::sanitizeSinf, CDMPrivateFairPlayStreaming::extractKeyIDsSinf });
}
CDMFactoryFairPlayStreaming& CDMFactoryFairPlayStreaming::singleton()
@@ -200,12 +210,12 @@
bool CDMPrivateFairPlayStreaming::supportsInitDataType(const AtomicString& initDataType) const
{
- return initDataType == "sinf";
+ return initDataType == sinfName();
}
bool CDMPrivateFairPlayStreaming::supportsConfiguration(const CDMKeySystemConfiguration& configuration) const
{
- if (!configuration.initDataTypes.contains("sinf"))
+ if (!configuration.initDataTypes.contains(sinfName()))
return false;
#if HAVE(AVCONTENTKEYSESSION)
@@ -321,7 +331,7 @@
return false;
return WTF::anyOf(extractSchemeAndKeyIdFromSinf(initData), [](auto& result) {
- return result.first == 'cbcs' || result.first == 'cbc2' || result.first == 'cbc1';
+ return validFairPlayStreamingSchemes().contains(result.first);
});
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h (225636 => 225637)
--- trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/CDMFairPlayStreaming.h 2017-12-07 19:46:53 UTC (rev 225637)
@@ -64,6 +64,9 @@
bool supportsInitData(const AtomicString&, const SharedBuffer&) const override;
RefPtr<SharedBuffer> sanitizeResponse(const SharedBuffer&) const override;
std::optional<String> sanitizeSessionId(const String&) const override;
+
+ static Vector<Ref<SharedBuffer>> extractKeyIDsSinf(const SharedBuffer&);
+ static RefPtr<SharedBuffer> sanitizeSinf(const SharedBuffer&);
};
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm (225636 => 225637)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2017-12-07 19:41:35 UTC (rev 225636)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2017-12-07 19:46:53 UTC (rev 225637)
@@ -28,6 +28,7 @@
#if HAVE(AVCONTENTKEYSESSION)
+#import "CDMFairPlayStreaming.h"
#import "CDMKeySystemConfiguration.h"
#import "NotImplemented.h"
#import "SharedBuffer.h"
@@ -226,6 +227,12 @@
callback(SharedBuffer::create(), emptyString(), false, Failed);
return;
}
+
+ if (!m_serverCertificate) {
+ callback(SharedBuffer::create(), emptyString(), false, Failed);
+ return;
+ }
+
m_requestLicenseCallback = WTFMove(callback);
[m_session processContentKeyRequestWithIdentifier:nil initializationData:initData->createNSData().get() options:nil];
@@ -268,10 +275,15 @@
if (!m_requestLicenseCallback)
return;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnonnull"
RetainPtr<NSData> appIdentifier = m_serverCertificate ? m_serverCertificate->createNSData() : nullptr;
- [m_request makeStreamingContentKeyRequestDataForApp:appIdentifier.get() contentIdentifier:nil options:nil completionHandler:[this, weakThis = createWeakPtr()] (NSData *contentKeyRequestData, NSError *error) mutable {
+ Vector<Ref<SharedBuffer>> keyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(SharedBuffer::create(request.initializationData));
+ if (keyIDs.isEmpty()) {
+ m_requestLicenseCallback(SharedBuffer::create(), m_sessionId, false, Failed);
+ return;
+ }
+
+ RetainPtr<NSData> contentIdentifier = keyIDs.first()->createNSData();
+ [m_request makeStreamingContentKeyRequestDataForApp:appIdentifier.get() contentIdentifier:contentIdentifier.get() options:nil completionHandler:[this, weakThis = createWeakPtr()] (NSData *contentKeyRequestData, NSError *error) mutable {
callOnMainThread([this, weakThis = WTFMove(weakThis), error = retainPtr(error), contentKeyRequestData = retainPtr(contentKeyRequestData)] {
if (!weakThis || !m_requestLicenseCallback)
return;
@@ -282,7 +294,6 @@
m_requestLicenseCallback(SharedBuffer::create(contentKeyRequestData.get()), m_sessionId, false, Succeeded);
});
}];
-#pragma clang diagnostic pop
}
void CDMInstanceFairPlayStreamingAVFObjC::didProvideRenewingRequest(AVContentKeyRequest *request)