Diff
Modified: trunk/LayoutTests/ChangeLog (210554 => 210555)
--- trunk/LayoutTests/ChangeLog 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/ChangeLog 2017-01-10 20:09:21 UTC (rev 210555)
@@ -1,5 +1,26 @@
2017-01-10 Jer Noble <jer.no...@apple.com>
+ Add support for MediaKeys.generateRequest().
+ https://bugs.webkit.org/show_bug.cgi?id=166880
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ Add shouldResolve() and shouldReject() to video-test.js and update existing
+ tests to use these new functions.
+
+ * media/encrypted-media/mock-MediaKeys-createSession-expected.txt: Added.
+ * media/encrypted-media/mock-MediaKeys-createSession.html: Added.
+ * media/encrypted-media/mock-MediaKeys-setServerCertificate.html:
+ * media/encrypted-media/mock-MediaKeySession-generateRequest.html:
+ * media/encrypted-media/mock-MediaKeySystemAccess.html:
+ * media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html:
+ * media/video-test.js:
+ (shouldResolve):
+ (shouldReject):
+ * platform/mac/TestExpectations:
+
+2017-01-10 Jer Noble <jer.no...@apple.com>
+
Add support for MediaKeys.createSession().
https://bugs.webkit.org/show_bug.cgi?id=166796
Added: trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest-expected.txt (0 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest-expected.txt (rev 0)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest-expected.txt 2017-01-10 20:09:21 UTC (rev 210555)
@@ -0,0 +1,41 @@
+RUN(internals.initializeMockMediaSource())
+RUN(mock = internals.registerMockCDM())
+RUN(mock.supportedDataTypes = ["keyids"])
+RUN(capabilities.initDataTypes = ["keyids"])
+RUN(capabilities.videoCapabilities = [{ contentType: 'video/mock; codecs="mock"' }] )
+RUN(promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities]))
+Promise resolved OK
+
+RUN(promise = mediaKeySystemAccess.createMediaKeys())
+Promise resolved OK
+
+Using an invalid initDataType string should reject.
+RUN(mediaKeySession = mediaKeys.createSession("temporary"))
+EXPECTED (typeof mediaKeySession == 'object') OK
+RUN(promise = mediaKeySession.generateRequest("invalid", stringToUInt8Array("invalid")))
+Promise rejected correctly OK
+
+Re-using a failed mediaKeySession should reject.
+RUN(kids = JSON.stringify({ kids: [ "MTIzNDU=" ] }))
+RUN(promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids)))
+Promise rejected correctly OK
+
+Using a new mediaKeySession should resolve.
+RUN(kids = JSON.stringify({ kids: [ "MTIzNDU=" ] }))
+RUN(mediaKeySession = mediaKeys.createSession("temporary"))
+RUN(promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids)))
+Promise resolved OK
+
+Using invalid initData should reject.
+RUN(kids = JSON.stringify({ invalid: "invalid" }))
+RUN(mediaKeySession = mediaKeys.createSession("temporary"))
+RUN(promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids)))
+Promise rejected correctly OK
+
+Using initData with extraneous information should resolve.
+RUN(kids = JSON.stringify({ kids: [ "MTIzNDU="], invalid: "invalid" }))
+RUN(mediaKeySession = mediaKeys.createSession("temporary"))
+RUN(promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids)))
+Promise resolved OK
+END OF TEST
+
Added: trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest.html (0 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest.html (rev 0)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeySession-generateRequest.html 2017-01-10 20:09:21 UTC (rev 210555)
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src=""
+ <script type="text/_javascript_">
+ var mock;
+ var promise;
+ var mediaKeySystemAccess;
+ var mediaKeys;
+ var mediaKeySession;
+ var capabilities = {};
+ var kids;
+
+ function doTest()
+ {
+ if (!window.internals) {
+ failTest("Internals is required for this test.")
+ return;
+ }
+
+ run('internals.initializeMockMediaSource()');
+ run('mock = internals.registerMockCDM()');
+ run('mock.supportedDataTypes = ["keyids"]');
+ run('capabilities.initDataTypes = ["keyids"]');
+ run(`capabilities.videoCapabilities = [{ contentType: 'video/mock; codecs="mock"' }] `);
+ run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
+ }
+
+ function next() {
+ if (!tests.length) {
+ mock.unregister();
+ endTest()
+ return;
+ }
+
+ var nextTest = tests.shift();
+ consoleWrite('');
+ nextTest();
+ }
+
+ function gotMediaKeySystemAccess(result) {
+ mediaKeySystemAccess = result;
+ next();
+ }
+
+ function gotMediaKeys(result) {
+ mediaKeys = result;
+ next();
+ }
+
+ function stringToUInt8Array(str)
+ {
+ var array = new Uint8Array(str.length);
+ for (var i=0; i<str.length; i++)
+ array[i] = str.charCodeAt(i);
+ return array;
+ }
+
+ tests = [
+ function() {
+ run('promise = mediaKeySystemAccess.createMediaKeys()');
+ shouldResolve(promise).then(gotMediaKeys, failTest);
+ },
+
+ function() {
+ consoleWrite('Using an invalid initDataType string should reject.')
+ run('mediaKeySession = mediaKeys.createSession("temporary")');
+ testExpected('typeof mediaKeySession', 'object')
+ run('promise = mediaKeySession.generateRequest("invalid", stringToUInt8Array("invalid"))');
+ shouldReject(promise).then(next, next);
+ },
+
+ function() {
+ consoleWrite('Re-using a failed mediaKeySession should reject.')
+ run('kids = JSON.stringify({ kids: [ "MTIzNDU=" ] })');
+ run('promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids))');
+ shouldReject(promise).then(next, next);
+ },
+
+ function() {
+ consoleWrite('Using a new mediaKeySession should resolve.')
+ run('kids = JSON.stringify({ kids: [ "MTIzNDU=" ] })');
+ run('mediaKeySession = mediaKeys.createSession("temporary")');
+ run('promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids))');
+ shouldResolve(promise).then(next, next);
+ },
+
+ function() {
+ consoleWrite('Using invalid initData should reject.')
+ run('kids = JSON.stringify({ invalid: "invalid" })');
+ run('mediaKeySession = mediaKeys.createSession("temporary")');
+ run('promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids))');
+ shouldReject(promise).then(next, next);
+ },
+
+ function() {
+ consoleWrite('Using initData with extraneous information should resolve.')
+ run('kids = JSON.stringify({ kids: [ "MTIzNDU="], invalid: "invalid" })');
+ run('mediaKeySession = mediaKeys.createSession("temporary")');
+ run('promise = mediaKeySession.generateRequest("keyids", stringToUInt8Array(kids))');
+ shouldResolve(promise).then(next, next);
+ },
+ ];
+ </script>
+</head>
+<body _onload_="doTest()">
+</body>
+</html>
Modified: trunk/LayoutTests/media/encrypted-media/mock-MediaKeySystemAccess.html (210554 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeySystemAccess.html 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeySystemAccess.html 2017-01-10 20:09:21 UTC (rev 210555)
@@ -34,28 +34,7 @@
nextTest();
}
- function shouldResolve(promise) {
- promise.then(mediaKeySystemAccess => {
- logResult(Success, 'Promise resolved');
- next();
- }, () => {
- logResult(Failed, 'Promise rejected');
- next();
- });
- }
-
- function shouldReject(promise) {
- promise.then(() => {
- logResult(Failed, 'Promise resolved incorrectly');
- next();
- }, exceptionCode => {
- logResult(Success, 'Promise rejected correctly');
- next();
- });
- }
-
function gotMediaKeySystemAccess(result) {
- logResult(Success, 'Promise resolved');
mediaKeySystemAccess = result;
next();
}
@@ -65,18 +44,18 @@
run('capabilities.initDataTypes = ["mock"]');
run(`capabilities.videoCapabilities = [{ contentType: 'video/mock; codecs="mock"' }] `);
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
- promise.then(gotMediaKeySystemAccess).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
},
function() {
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldResolve(promise);
+ shouldResolve(promise).then(next, next);
},
function() {
run('mock.canCreateInstances = false');
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
function() {
@@ -83,18 +62,18 @@
run('mock.canCreateInstances = true');
run('capabilities.distinctiveIdentifier = "not-allowed"');
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
- promise.then(gotMediaKeySystemAccess).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
},
function() {
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldResolve(promise);
+ shouldResolve(promise).then(next, next);
},
function() {
run('mock.distinctiveIdentifiersRequirement = "required"');
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
function() {
@@ -101,18 +80,18 @@
run('mock.distinctiveIdentifiersRequirement = "optional"');
run('capabilities.persistentState = "not-allowed"');
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
- promise.then(gotMediaKeySystemAccess).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
},
function() {
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldResolve(promise);
+ shouldResolve(promise).then(next, next);
},
function() {
run('mock.persistentStateRequirement = "required"');
run('promise = mediaKeySystemAccess.createMediaKeys()');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
];
</script>
Modified: trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-createSession.html (210554 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-createSession.html 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-createSession.html 2017-01-10 20:09:21 UTC (rev 210555)
@@ -23,7 +23,7 @@
run('capabilities.initDataTypes = ["mock"]');
run(`capabilities.videoCapabilities = [{ contentType: 'video/mock; codecs="mock"' }] `);
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
- promise.then(gotMediaKeySystemAccess).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
}
function next() {
@@ -38,34 +38,12 @@
nextTest();
}
- function shouldResolve(promise) {
- promise.then(mediaKeySystemAccess => {
- logResult(Success, 'Promise resolved');
- next();
- }, () => {
- logResult(Failed, 'Promise rejected');
- next();
- });
- }
-
- function shouldReject(promise) {
- promise.then(() => {
- logResult(Failed, 'Promise resolved incorrectly');
- next();
- }, exceptionCode => {
- logResult(Success, 'Promise rejected correctly');
- next();
- });
- }
-
function gotMediaKeySystemAccess(result) {
- logResult(Success, 'Promise resolved');
mediaKeySystemAccess = result;
next();
}
function gotMediaKeys(result) {
- logResult(Success, 'Promise resolved');
mediaKeys = result;
next();
}
@@ -81,7 +59,7 @@
tests = [
function() {
run('promise = mediaKeySystemAccess.createMediaKeys()');
- promise.then(gotMediaKeys).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeys, failTest);
},
function() {
Modified: trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-setServerCertificate.html (210554 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-setServerCertificate.html 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/media/encrypted-media/mock-MediaKeys-setServerCertificate.html 2017-01-10 20:09:21 UTC (rev 210555)
@@ -22,7 +22,7 @@
run('capabilities.initDataTypes = ["mock"]');
run(`capabilities.videoCapabilities = [{ contentType: 'video/mock; codecs="mock"' }] `);
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", [capabilities])');
- promise.then(gotMediaKeySystemAccess).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeySystemAccess, failTest);
}
function next() {
@@ -37,34 +37,12 @@
nextTest();
}
- function shouldResolve(promise) {
- promise.then(mediaKeySystemAccess => {
- logResult(Success, 'Promise resolved');
- next();
- }, () => {
- logResult(Failed, 'Promise rejected');
- next();
- });
- }
-
- function shouldReject(promise) {
- promise.then(() => {
- logResult(Failed, 'Promise resolved incorrectly');
- next();
- }, exceptionCode => {
- logResult(Success, 'Promise rejected correctly');
- next();
- });
- }
-
function gotMediaKeySystemAccess(result) {
- logResult(Success, 'Promise resolved');
mediaKeySystemAccess = result;
next();
}
function gotMediaKeys(result) {
- logResult(Success, 'Promise resolved');
mediaKeys = result;
next();
}
@@ -80,28 +58,28 @@
tests = [
function() {
run('promise = mediaKeySystemAccess.createMediaKeys()');
- promise.then(gotMediaKeys).catch(failTest);
+ shouldResolve(promise).then(gotMediaKeys, failTest);
},
function() {
run('promise = mediaKeys.setServerCertificate(new ArrayBuffer())');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
function() {
run('promise = mediaKeys.setServerCertificate(stringToUInt8Array("invalid"))');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
function() {
run('promise = mediaKeys.setServerCertificate(stringToUInt8Array("valid"))');
- shouldResolve(promise);
+ shouldResolve(promise).then(next, next);
},
function() {
run('mock.supportsServerCertificates = false');
run('promise = mediaKeys.setServerCertificate(stringToUInt8Array("valid"))');
- shouldReject(promise);
+ shouldReject(promise).then(next, next);
},
];
</script>
Modified: trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html (210554 => 210555)
--- trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/media/encrypted-media/mock-navigator-requestMediaKeySystemAccess.html 2017-01-10 20:09:21 UTC (rev 210555)
@@ -34,27 +34,11 @@
}
function passingTestWithCapabilities(capabilities, success) {
- testWithCapabilities(capabilities);
- promise.then(mediaKeySystemAccess => {
- logResult(Success, 'Promise resolved');
- success(mediaKeySystemAccess);
- next();
- }, () => {
- logResult(Failed, 'Promise rejected');
- next();
- });
+ shouldResolve(testWithCapabilities(capabilities)).then(success).then(next, next);
}
function failingTestWithCapabilities(capabilities, failure) {
- testWithCapabilities(capabilities);
- promise.then(() => {
- logResult(Failed, 'Promise resolved incorrectly');
- next();
- }, exceptionCode => {
- logResult(Success, 'Promise rejected correctly');
- failure(exceptionCode)
- next();
- });
+ shouldReject(testWithCapabilities(capabilities)).then(failure).then(next, next);
}
function testWithCapabilities(capabilities) {
@@ -61,6 +45,7 @@
window.capabilities = capabilities;
consoleWrite(`SET capabilities = '${ JSON.stringify(capabilities, null, 1) }'`);
run('promise = navigator.requestMediaKeySystemAccess("org.webkit.mock", capabilities)');
+ return promise;
}
tests = [
Modified: trunk/LayoutTests/media/video-test.js (210554 => 210555)
--- trunk/LayoutTests/media/video-test.js 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/media/video-test.js 2017-01-10 20:09:21 UTC (rev 210555)
@@ -416,3 +416,28 @@
eventSender.mouseDown();
}
}
+
+function shouldResolve(promise) {
+ return new Promise((resolve, reject) => {
+ promise.then(result => {
+ logResult(Success, 'Promise resolved');
+ resolve(result);
+ }).catch((error) => {
+ logResult(Failed, 'Promise rejected');
+ reject(error);
+ });
+ });
+}
+
+function shouldReject(promise) {
+ return new Promise((resolve, reject) => {
+ promise.then(result => {
+ logResult(Failed, 'Promise resolved incorrectly');
+ reject(result);
+ }).catch((error) => {
+ logResult(Success, 'Promise rejected correctly');
+ resolve(error);
+ });
+ });
+
+}
Modified: trunk/LayoutTests/platform/mac/TestExpectations (210554 => 210555)
--- trunk/LayoutTests/platform/mac/TestExpectations 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2017-01-10 20:09:21 UTC (rev 210555)
@@ -1469,6 +1469,7 @@
media/encrypted-media/mock-MediaKeySystemAccess.html [ Skip ]
media/encrypted-media/mock-MediaKeys-setServerCertificate.html [ Skip ]
media/encrypted-media/mock-MediaKeys-createSession.html [ Skip ]
+media/encrypted-media/mock-MediaKeySession-generateRequest.html [ Skip ]
webkit.org/b/166025 http/tests/fetch/fetching-same-resource-with-diffferent-options.html [ Pass Failure ]
Modified: trunk/Source/WebCore/CMakeLists.txt (210554 => 210555)
--- trunk/Source/WebCore/CMakeLists.txt 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/CMakeLists.txt 2017-01-10 20:09:21 UTC (rev 210555)
@@ -2982,6 +2982,7 @@
if (ENABLE_ENCRYPTED_MEDIA)
list(APPEND WebCore_SOURCES
Modules/encryptedmedia/CDM.cpp
+ Modules/encryptedmedia/InitDataRegistry.cpp
Modules/encryptedmedia/MediaKeyMessageEvent.cpp
Modules/encryptedmedia/MediaKeySession.cpp
Modules/encryptedmedia/MediaKeyStatusMap.cpp
Modified: trunk/Source/WebCore/ChangeLog (210554 => 210555)
--- trunk/Source/WebCore/ChangeLog 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/ChangeLog 2017-01-10 20:09:21 UTC (rev 210555)
@@ -1,5 +1,74 @@
2017-01-10 Jer Noble <jer.no...@apple.com>
+ Add support for MediaKeys.generateRequest().
+ https://bugs.webkit.org/show_bug.cgi?id=166880
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ Test: media/encrypted-media/mock-MediaKeySession-generateRequest.html
+
+ Implement MediaKeySession::generateRequest(). This requires some additions
+ to CDM, CDMPrivate, and CDMInstance to support platform adoption and to
+ implement mock support for testing. Additionally, add an InitDataRegistry
+ object which can sanitize and extract key data from various initData types.
+ (At the moment, only the "keyids" initData type is implemented.)
+
+ Drive-by fixes: Change all instances of initDataType from String -> AtomicString.
+ Add "const" flags to all CDMPrivate methods that might be called from a const
+ reference.
+
+ * CMakeLists.txt:
+ * Modules/encryptedmedia/CDM.cpp:
+ (WebCore::CDM::supportsInitDataType):
+ (WebCore::CDM::sanitizeInitData):
+ (WebCore::CDM::supportsInitData):
+ * Modules/encryptedmedia/CDM.h:
+ * Modules/encryptedmedia/CDMInstance.h:
+ * Modules/encryptedmedia/CDMPrivate.h:
+ * Modules/encryptedmedia/InitDataRegistry.cpp: Added.
+ (WebCore::extractKeyIDsKeyids):
+ (WebCore::sanitizeKeyids):
+ (WebCore::sanitizeCenc):
+ (WebCore::extractKeyIDsCenc):
+ (WebCore::sanitizeWebM):
+ (WebCore::extractKeyIDsWebM):
+ (WebCore::InitDataRegistry::shared):
+ (WebCore::InitDataRegistry::InitDataRegistry):
+ (WebCore::InitDataRegistry::sanitizeInitData):
+ (WebCore::InitDataRegistry::extractKeyIDs):
+ (WebCore::InitDataRegistry::registerInitDataType):
+ * Modules/encryptedmedia/InitDataRegistry.h:
+ * Modules/encryptedmedia/MediaKeySession.cpp:
+ (WebCore::messageEventName):
+ (WebCore::MediaKeySession::MediaKeySession):
+ (WebCore::MediaKeySession::generateRequest):
+ (WebCore::MediaKeySession::enqueueMessage):
+ * Modules/encryptedmedia/MediaKeySession.h:
+ * Modules/encryptedmedia/MediaKeys.cpp:
+ (WebCore::MediaKeys::setServerCertificate):
+ * WebCore.xcodeproj/project.pbxproj:
+ * testing/MockCDMFactory.cpp:
+ (WebCore::MockCDMFactory::addKeysToSessionWithID):
+ (WebCore::MockCDMFactory::setSupportedDataTypes):
+ (WebCore::MockCDM::supportsInitDataType):
+ (WebCore::MockCDM::supportsConfiguration):
+ (WebCore::MockCDM::supportsConfigurationWithRestrictions):
+ (WebCore::MockCDM::supportsSessionTypeWithConfiguration):
+ (WebCore::MockCDM::supportsRobustness):
+ (WebCore::MockCDM::distinctiveIdentifiersRequirement):
+ (WebCore::MockCDM::persistentStateRequirement):
+ (WebCore::MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable):
+ (WebCore::MockCDM::supportsInitData):
+ (WebCore::MockCDMInstance::setServerCertificate):
+ (WebCore::MockCDMInstance::requestLicense):
+ * testing/MockCDMFactory.h:
+ (WebCore::MockCDMFactory::supportedDataTypes):
+ (WebCore::MockCDMFactory::hasSessionWithID):
+ (WebCore::MockCDMFactory::removeSessionWithID):
+ (WebCore::MockCDMFactory::setSupportedDataTypes): Deleted.
+
+2017-01-10 Jer Noble <jer.no...@apple.com>
+
Add support for MediaKeys.createSession().
https://bugs.webkit.org/show_bug.cgi?id=166796
Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.cpp 2017-01-10 20:09:21 UTC (rev 210555)
@@ -30,6 +30,7 @@
#include "CDMPrivate.h"
#include "Document.h"
+#include "InitDataRegistry.h"
#include "MediaKeysRestrictions.h"
#include "MediaPlayer.h"
#include "NotImplemented.h"
@@ -634,6 +635,21 @@
return m_private && m_private->supportsSessions();
}
+bool CDM::supportsInitDataType(const AtomicString& initDataType) const
+{
+ return m_private && m_private->supportsInitDataType(initDataType);
}
+RefPtr<SharedBuffer> CDM::sanitizeInitData(const AtomicString& initDataType, const SharedBuffer& initData)
+{
+ return InitDataRegistry::shared().sanitizeInitData(initDataType, initData);
+}
+
+bool CDM::supportsInitData(const AtomicString& initDataType, const SharedBuffer& initData)
+{
+ return m_private && m_private->supportsInitData(initDataType, initData);
+}
+
+}
+
#endif
Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDM.h (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/CDM.h 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDM.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -29,6 +29,7 @@
#include "ContextDestructionObserver.h"
#include "MediaKeySystemConfiguration.h"
+#include "SharedBuffer.h"
#include <functional>
#include <wtf/HashSet.h>
#include <wtf/Ref.h>
@@ -43,6 +44,7 @@
class CDMPrivate;
class Document;
class ScriptExecutionContext;
+class SharedBuffer;
struct MediaKeysRestrictions;
@@ -73,7 +75,11 @@
RefPtr<CDMInstance> createInstance();
bool supportsServerCertificates() const;
bool supportsSessions() const;
+ bool supportsInitDataType(const AtomicString&) const;
+ RefPtr<SharedBuffer> sanitizeInitData(const AtomicString& initDataType, const SharedBuffer&);
+ bool supportsInitData(const AtomicString& initDataType, const SharedBuffer&);
+
private:
CDM(Document&, const String& keySystem);
Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -30,13 +30,10 @@
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
-namespace JSC {
-class ArrayBuffer;
-}
-
namespace WebCore {
struct MediaKeySystemConfiguration;
+class SharedBuffer;
class CDMInstance : public RefCounted<CDMInstance> {
public:
@@ -50,7 +47,16 @@
virtual SuccessValue initializeWithConfiguration(const MediaKeySystemConfiguration&) = 0;
virtual SuccessValue setDistinctiveIdentifiersAllowed(bool) = 0;
virtual SuccessValue setPersistentStateAllowed(bool) = 0;
- virtual SuccessValue setServerCertificate(JSC::ArrayBuffer&) = 0;
+ virtual SuccessValue setServerCertificate(Ref<SharedBuffer>&&) = 0;
+
+ enum class LicenseType {
+ Temporary,
+ Persistable,
+ UsageRecord,
+ };
+
+ using LicenseCallback = Function<void(Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, SuccessValue succeeded)>;
+ virtual void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) = 0;
};
}
Modified: trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/CDMPrivate.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -41,18 +41,19 @@
public:
virtual ~CDMPrivate() { }
- virtual bool supportsInitDataType(const String&) = 0;
- virtual bool supportsConfiguration(const MediaKeySystemConfiguration&) = 0;
- virtual bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) = 0;
- virtual bool supportsSessionTypeWithConfiguration(MediaKeySessionType&, const MediaKeySystemConfiguration&) = 0;
- virtual bool supportsRobustness(const String&) = 0;
- virtual MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) = 0;
- virtual MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) = 0;
- virtual bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) = 0;
+ virtual bool supportsInitDataType(const AtomicString&) const = 0;
+ virtual bool supportsConfiguration(const MediaKeySystemConfiguration&) const = 0;
+ virtual bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual bool supportsSessionTypeWithConfiguration(MediaKeySessionType&, const MediaKeySystemConfiguration&) const = 0;
+ virtual bool supportsRobustness(const String&) const = 0;
+ virtual MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const = 0;
+ virtual bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) const = 0;
virtual RefPtr<CDMInstance> createInstance() = 0;
virtual void loadAndInitialize() = 0;
virtual bool supportsServerCertificates() const = 0;
virtual bool supportsSessions() const = 0;
+ virtual bool supportsInitData(const AtomicString&, const SharedBuffer&) const = 0;
};
}
Added: trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp (0 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.cpp 2017-01-10 20:09:21 UTC (rev 210555)
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InitDataRegistry.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "NotImplemented.h"
+#include "SharedBuffer.h"
+#include "inspector/InspectorValues.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/Base64.h>
+
+using namespace Inspector;
+
+namespace WebCore {
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsKeyids(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
+ String json { buffer.data(), buffer.size() };
+
+ RefPtr<InspectorValue> value;
+ if (!InspectorValue::parseJSON(json, value))
+ return { };
+
+ RefPtr<InspectorObject> object;
+ if (!value->asObject(object))
+ return { };
+
+ RefPtr<InspectorArray> kidsArray;
+ if (!object->getArray("kids", kidsArray))
+ return { };
+
+ Vector<Ref<SharedBuffer>> keyIDs;
+ for (auto& value : *kidsArray) {
+ String keyID;
+ if (!value->asString(keyID))
+ continue;
+
+ Vector<char> keyIDData;
+ if (!WTF::base64Decode(keyID, { keyIDData }))
+ continue;
+
+ Ref<SharedBuffer> keyIDBuffer = SharedBuffer::adoptVector(keyIDData);
+ keyIDs.append(WTFMove(keyIDBuffer));
+ }
+
+ return keyIDs;
+}
+
+static RefPtr<SharedBuffer> sanitizeKeyids(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/keyids.html#format
+ Vector<Ref<SharedBuffer>> keyIDBuffer = extractKeyIDsKeyids(buffer);
+ if (keyIDBuffer.isEmpty())
+ return nullptr;
+
+ auto object = InspectorObject::create();
+ auto kidsArray = InspectorArray::create();
+ for (auto& buffer : keyIDBuffer)
+ kidsArray->pushString(base64Encode(buffer->data(), buffer->size()));
+ object->setArray("kids", WTFMove(kidsArray));
+
+ CString jsonData = object->toJSONString().utf8();
+ return SharedBuffer::create(jsonData.data(), jsonData.length());
+}
+
+static RefPtr<SharedBuffer> sanitizeCenc(const SharedBuffer& buffer)
+{
+ // 4. Common SystemID and PSSH Box Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system
+ notImplemented();
+ return buffer.copy();
+}
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsCenc(const SharedBuffer&)
+{
+ // 4. Common SystemID and PSSH Box Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html#common-system
+ notImplemented();
+ return { };
+}
+
+static RefPtr<SharedBuffer> sanitizeWebM(const SharedBuffer& buffer)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format
+ notImplemented();
+ return buffer.copy();
+}
+
+static Vector<Ref<SharedBuffer>> extractKeyIDsWebM(const SharedBuffer&)
+{
+ // 1. Format
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/webm.html#format
+ notImplemented();
+ return { };
+}
+
+InitDataRegistry& InitDataRegistry::shared()
+{
+ static NeverDestroyed<InitDataRegistry> registry;
+ return registry.get();
+}
+
+InitDataRegistry::InitDataRegistry()
+{
+ registerInitDataType("keyids", { &sanitizeKeyids, &extractKeyIDsKeyids });
+ registerInitDataType("cenc", { &sanitizeCenc, &extractKeyIDsCenc });
+ registerInitDataType("webm", { &sanitizeWebM, &extractKeyIDsWebM });
+}
+
+InitDataRegistry::~InitDataRegistry() = default;
+
+RefPtr<SharedBuffer> InitDataRegistry::sanitizeInitData(const AtomicString& initDataType, const SharedBuffer& buffer)
+{
+ auto iter = m_types.find(initDataType);
+ if (iter == m_types.end() || !iter->value.sanitizeInitData)
+ return nullptr;
+ return iter->value.sanitizeInitData(buffer);
+}
+
+Vector<Ref<SharedBuffer>> InitDataRegistry::extractKeyIDs(const AtomicString& initDataType, const SharedBuffer& buffer)
+{
+ auto iter = m_types.find(initDataType);
+ if (iter == m_types.end() || !iter->value.sanitizeInitData)
+ return { };
+ return iter->value.extractKeyIDs(buffer);
+}
+
+void InitDataRegistry::registerInitDataType(const AtomicString& initDataType, InitDataTypeCallbacks&& callbacks)
+{
+ ASSERT(!m_types.contains(initDataType));
+ m_types.set(initDataType, WTFMove(callbacks));
+}
+
+}
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
Copied: trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h (from rev 210554, trunk/Source/WebCore/Modules/encryptedmedia/CDMInstance.h) (0 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h (rev 0)
+++ trunk/Source/WebCore/Modules/encryptedmedia/InitDataRegistry.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include <wtf/Function.h>
+#include <wtf/HashMap.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+class InitDataRegistry {
+public:
+ WEBCORE_EXPORT static InitDataRegistry& shared();
+ friend class NeverDestroyed<InitDataRegistry>;
+
+ RefPtr<SharedBuffer> sanitizeInitData(const AtomicString& initDataType, const SharedBuffer&);
+ WEBCORE_EXPORT Vector<Ref<SharedBuffer>> extractKeyIDs(const AtomicString& initDataType, const SharedBuffer&);
+
+ struct InitDataTypeCallbacks {
+ using SanitizeInitDataCallback = Function<RefPtr<SharedBuffer>(const SharedBuffer&)>;
+ using ExtractKeyIDsCallback = Function<Vector<Ref<SharedBuffer>>(const SharedBuffer&)>;
+
+ SanitizeInitDataCallback sanitizeInitData;
+ ExtractKeyIDsCallback extractKeyIDs;
+ };
+ void registerInitDataType(const AtomicString& initDataType, InitDataTypeCallbacks&&);
+
+private:
+ InitDataRegistry();
+ ~InitDataRegistry();
+
+ HashMap<AtomicString, InitDataTypeCallbacks> m_types;
+};
+
+}
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.cpp 2017-01-10 20:09:21 UTC (rev 210555)
@@ -33,11 +33,21 @@
#include "CDM.h"
#include "CDMInstance.h"
+#include "MediaKeyMessageEvent.h"
+#include "MediaKeyMessageType.h"
#include "MediaKeyStatusMap.h"
#include "NotImplemented.h"
+#include "SharedBuffer.h"
+#include <wtf/NeverDestroyed.h>
namespace WebCore {
+static AtomicString& messageEventName()
+{
+ NeverDestroyed<AtomicString> message { "message" };
+ return message.get();
+}
+
Ref<MediaKeySession> MediaKeySession::create(ScriptExecutionContext& context, MediaKeySessionType sessionType, bool useDistinctiveIdentifier, Ref<CDM>&& implementation, Ref<CDMInstance>&& instance)
{
auto session = adoptRef(*new MediaKeySession(context, sessionType, useDistinctiveIdentifier, WTFMove(implementation), WTFMove(instance)));
@@ -53,6 +63,8 @@
, m_sessionType(sessionType)
, m_implementation(WTFMove(implementation))
, m_instance(WTFMove(instance))
+ , m_eventQueue(*this)
+ , m_weakPtrFactory(this)
{
// https://w3c.github.io/encrypted-media/#dom-mediakeys-setservercertificate
// W3C Editor's Draft 09 November 2016
@@ -94,9 +106,143 @@
return m_keyStatuses.copyRef();
}
-void MediaKeySession::generateRequest(const String&, const BufferSource&, Ref<DeferredPromise>&&)
+void MediaKeySession::generateRequest(const AtomicString& initDataType, const BufferSource& initData, Ref<DeferredPromise>&& promise)
{
- notImplemented();
+ // https://w3c.github.io/encrypted-media/#dom-mediakeysession-generaterequest
+ // W3C Editor's Draft 09 November 2016
+
+ // When this method is invoked, the user agent must run the following steps:
+ // 1. If this object is closed, return a promise rejected with an InvalidStateError.
+ // 2. If this object's uninitialized value is false, return a promise rejected with an InvalidStateError.
+ if (m_closed || !m_uninitialized) {
+ promise->reject(INVALID_STATE_ERR);
+ return;
+ }
+
+ // 3. Let this object's uninitialized value be false.
+ m_uninitialized = false;
+
+ // 4. If initDataType is the empty string, return a promise rejected with a newly created TypeError.
+ // 5. If initData is an empty array, return a promise rejected with a newly created TypeError.
+ if (initDataType.isEmpty() || !initData.length()) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 6. If the Key System implementation represented by this object's cdm implementation value does not support
+ // initDataType as an Initialization Data Type, return a promise rejected with a NotSupportedError. String
+ // comparison is case-sensitive.
+ if (!m_implementation->supportsInitDataType(initDataType)) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 7. Let init data be a copy of the contents of the initData parameter.
+ // 8. Let session type be this object's session type.
+ // 9. Let promise be a new promise.
+ // 10. Run the following steps in parallel:
+ m_taskQueue.enqueueTask([this, initData = SharedBuffer::create(initData.data(), initData.length()), initDataType, promise = WTFMove(promise)] () mutable {
+ // 10.1. If the init data is not valid for initDataType, reject promise with a newly created TypeError.
+ // 10.2. Let sanitized init data be a validated and sanitized version of init data.
+ RefPtr<SharedBuffer> sanitizedInitData = m_implementation->sanitizeInitData(initDataType, initData);
+
+ // 10.3. If the preceding step failed, reject promise with a newly created TypeError.
+ if (!sanitizedInitData) {
+ promise->reject(TypeError);
+ return;
+ }
+
+ // 10.4. If sanitized init data is empty, reject promise with a NotSupportedError.
+ if (sanitizedInitData->isEmpty()) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 10.5. Let session id be the empty string.
+ // 10.6. Let message be null.
+ // 10.7. Let message type be null.
+ // 10.8. Let cdm be the CDM instance represented by this object's cdm instance value.
+ // 10.9. Use the cdm to execute the following steps:
+ // 10.9.1. If the sanitized init data is not supported by the cdm, reject promise with a NotSupportedError.
+ if (!m_implementation->supportsInitData(initDataType, *sanitizedInitData)) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ // 10.9.2 Follow the steps for the value of session type from the following list:
+ CDMInstance::LicenseType requestedLicenseType;
+ switch (m_sessionType) {
+ case MediaKeySessionType::Temporary:
+ // ↳ "temporary"
+ // Let requested license type be a temporary non-persistable license.
+ requestedLicenseType = CDMInstance::LicenseType::Temporary;
+ break;
+ case MediaKeySessionType::PersistentLicense:
+ // ↳ "persistent-license"
+ // Let requested license type be a persistable license.
+ requestedLicenseType = CDMInstance::LicenseType::Persistable;
+ break;
+ case MediaKeySessionType::PersistentUsageRecord:
+ // ↳ "persistent-usage-record"
+ // 1. Initialize this object's record of key usage as follows.
+ // Set the list of key IDs known to the session to an empty list.
+ m_recordOfKeyUsage.clear();
+
+ // Set the first decrypt time to null.
+ m_firstDecryptTime = 0;
+
+ // Set the latest decrypt time to null.
+ m_latestDecryptTime = 0;
+
+ // 2. Let requested license type be a non-persistable license that will
+ // persist a record of key usage.
+ requestedLicenseType = CDMInstance::LicenseType::UsageRecord;
+ break;
+ }
+
+ m_instance->requestLicense(requestedLicenseType, initDataType, WTFMove(initData), [this, weakThis = m_weakPtrFactory.createWeakPtr(), promise = WTFMove(promise)] (Ref<SharedBuffer>&& message, const String& sessionId, bool needsIndividualization, CDMInstance::SuccessValue succeeded) mutable {
+ if (!weakThis)
+ return;
+
+ // 10.9.3. Let session id be a unique Session ID string.
+
+ MediaKeyMessageType messageType;
+ if (!needsIndividualization) {
+ // 10.9.4. If a license request for the requested license type can be generated based on the sanitized init data:
+ // 10.9.4.1. Let message be a license request for the requested license type generated based on the sanitized init data interpreted per initDataType.
+ // 10.9.4.2. Let message type be "license-request".
+ messageType = MediaKeyMessageType::LicenseRequest;
+ } else {
+ // 10.9.5. Otherwise:
+ // 10.9.5.1. Let message be the request that needs to be processed before a license request request for the requested license
+ // type can be generated based on the sanitized init data.
+ // 10.9.5.2. Let message type reflect the type of message, either "license-request" or "individualization-request".
+ messageType = MediaKeyMessageType::IndividualizationRequest;
+ }
+
+ // 10.10. Queue a task to run the following steps:
+ m_taskQueue.enqueueTask([this, promise = WTFMove(promise), message = WTFMove(message), messageType, sessionId, succeeded] () mutable {
+ // 10.10.1. If any of the preceding steps failed, reject promise with a new DOMException whose name is the appropriate error name.
+ if (succeeded == CDMInstance::SuccessValue::Failed) {
+ promise->reject(NOT_SUPPORTED_ERR);
+ return;
+ }
+ // 10.10.2. Set the sessionId attribute to session id.
+ m_sessionId = sessionId;
+
+ // 10.9.3. Let this object's callable value be true.
+ m_callable = true;
+
+ // 10.9.3. Run the Queue a "message" Event algorithm on the session, providing message type and message.
+ enqueueMessage(messageType, message);
+
+ // 10.9.3. Resolve promise.
+ promise->resolve();
+ });
+ });
+ });
+
+ // 11. Return promise.
}
void MediaKeySession::load(const String&, Ref<DeferredPromise>&&)
@@ -119,6 +265,21 @@
notImplemented();
}
+void MediaKeySession::enqueueMessage(MediaKeyMessageType messageType, const SharedBuffer& message)
+{
+ // 6.4.1 Queue a "message" Event
+ // https://w3c.github.io/encrypted-media/#queue-message
+ // W3C Editor's Draft 09 November 2016
+
+ // The following steps are run:
+ // 1. Let the session be the specified MediaKeySession object.
+ // 2. Queue a task to create an event named message that does not bubble and is not cancellable using the MediaKeyMessageEvent
+ // interface with its type attribute set to message and its isTrusted attribute initialized to true, and dispatch it at the
+ // session.
+ auto messageEvent = MediaKeyMessageEvent::create(messageEventName(), {messageType, message.createArrayBuffer()}, Event::IsTrusted::Yes);
+ m_eventQueue.enqueueEvent(WTFMove(messageEvent));
+}
+
bool MediaKeySession::hasPendingActivity() const
{
notImplemented();
Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeySession.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -33,9 +33,13 @@
#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "GenericEventQueue.h"
+#include "GenericTaskQueue.h"
#include "JSDOMPromise.h"
+#include "MediaKeyMessageType.h"
#include "MediaKeySessionType.h"
#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -45,6 +49,7 @@
class CDMInstance;
class MediaKeyStatusMap;
class MediaKeys;
+class SharedBuffer;
class MediaKeySession final : public RefCounted<MediaKeySession>, public EventTargetWithInlineData, public ActiveDOMObject {
public:
@@ -58,7 +63,7 @@
double expiration() const;
Ref<MediaKeyStatusMap> keyStatuses() const;
- void generateRequest(const String&, const BufferSource&, Ref<DeferredPromise>&&);
+ void generateRequest(const AtomicString&, const BufferSource&, Ref<DeferredPromise>&&);
void load(const String&, Ref<DeferredPromise>&&);
void update(const BufferSource&, Ref<DeferredPromise>&&);
void close(Ref<DeferredPromise>&&);
@@ -66,6 +71,7 @@
private:
MediaKeySession(ScriptExecutionContext&, MediaKeySessionType, bool useDistinctiveIdentifier, Ref<CDM>&&, Ref<CDMInstance>&&);
+ void enqueueMessage(MediaKeyMessageType, const SharedBuffer&);
// EventTarget
EventTargetInterface eventTargetInterface() const override { return MediaKeySessionEventTargetInterfaceType; }
@@ -89,6 +95,12 @@
MediaKeySessionType m_sessionType;
Ref<CDM> m_implementation;
Ref<CDMInstance> m_instance;
+ GenericEventQueue m_eventQueue;
+ GenericTaskQueue<Timer> m_taskQueue;
+ Vector<Ref<SharedBuffer>> m_recordOfKeyUsage;
+ double m_firstDecryptTime { 0 };
+ double m_latestDecryptTime { 0 };
+ WeakPtrFactory<MediaKeySession> m_weakPtrFactory;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp (210554 => 210555)
--- trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/Modules/encryptedmedia/MediaKeys.cpp 2017-01-10 20:09:21 UTC (rev 210555)
@@ -35,7 +35,7 @@
#include "CDMInstance.h"
#include "MediaKeySession.h"
#include "NotImplemented.h"
-#include <runtime/ArrayBuffer.h>
+#include "SharedBuffer.h"
namespace WebCore {
@@ -90,7 +90,7 @@
}
// 3. Let certificate be a copy of the contents of the serverCertificate parameter.
- auto certificate = ArrayBuffer::create(serverCertificate.data(), serverCertificate.length());
+ auto certificate = SharedBuffer::create(serverCertificate.data(), serverCertificate.length());
// 4. Let promise be a new promise.
// 5. Run the following steps in parallel:
@@ -97,7 +97,7 @@
m_taskQueue.enqueueTask([this, certificate = WTFMove(certificate), promise = WTFMove(promise)] () mutable {
// 5.1. Use this object's cdm instance to process certificate.
- if (m_instance->setServerCertificate(certificate) == CDMInstance::Failed) {
+ if (m_instance->setServerCertificate(WTFMove(certificate)) == CDMInstance::Failed) {
// 5.2. If the preceding step failed, resolve promise with a new DOMException whose name is the appropriate error name.
promise->reject(INVALID_STATE_ERR);
return;
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (210554 => 210555)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-01-10 20:09:21 UTC (rev 210555)
@@ -5717,6 +5717,8 @@
CCC2B51415F613060048CDD6 /* DeviceClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CCC2B51015F613060048CDD6 /* DeviceClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
CCC2B51515F613060048CDD6 /* DeviceController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CCC2B51115F613060048CDD6 /* DeviceController.cpp */; };
CCC2B51615F613060048CDD6 /* DeviceController.h in Headers */ = {isa = PBXBuildFile; fileRef = CCC2B51215F613060048CDD6 /* DeviceController.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ CD063F821E23FA8900812BE3 /* InitDataRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD063F801E23FA8900812BE3 /* InitDataRegistry.cpp */; };
+ CD063F831E23FA8900812BE3 /* InitDataRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = CD063F811E23FA8900812BE3 /* InitDataRegistry.h */; };
CD0EEE0E14743F39003EAFA2 /* AudioDestinationIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD0EEE0B14743E35003EAFA2 /* AudioDestinationIOS.cpp */; };
CD127DED14F3097D00E84779 /* WebCoreFullScreenWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD127DEB14F3097900E84779 /* WebCoreFullScreenWindow.mm */; };
CD127DEE14F3098400E84779 /* WebCoreFullScreenWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CD127DEA14F3097900E84779 /* WebCoreFullScreenWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -13643,6 +13645,8 @@
CCC2B51015F613060048CDD6 /* DeviceClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceClient.h; sourceTree = "<group>"; };
CCC2B51115F613060048CDD6 /* DeviceController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeviceController.cpp; sourceTree = "<group>"; };
CCC2B51215F613060048CDD6 /* DeviceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceController.h; sourceTree = "<group>"; };
+ CD063F801E23FA8900812BE3 /* InitDataRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitDataRegistry.cpp; sourceTree = "<group>"; };
+ CD063F811E23FA8900812BE3 /* InitDataRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitDataRegistry.h; sourceTree = "<group>"; };
CD0EEE0A14743E34003EAFA2 /* AudioDestinationIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDestinationIOS.h; sourceTree = "<group>"; };
CD0EEE0B14743E35003EAFA2 /* AudioDestinationIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDestinationIOS.cpp; sourceTree = "<group>"; };
CD127DEA14F3097900E84779 /* WebCoreFullScreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreFullScreenWindow.h; sourceTree = "<group>"; };
@@ -22773,6 +22777,8 @@
CDF4B7141E00B7E500E235A2 /* CDM.h */,
CD9D05421E1EFA12003B4C4F /* CDMInstance.h */,
CDF4B7251E03C15B00E235A2 /* CDMPrivate.h */,
+ CD063F801E23FA8900812BE3 /* InitDataRegistry.cpp */,
+ CD063F811E23FA8900812BE3 /* InitDataRegistry.h */,
2D9BF72F1DBFDC0F007A7D99 /* MediaKeyMessageEvent.cpp */,
2D9BF7301DBFDC0F007A7D99 /* MediaKeyMessageEvent.h */,
2D9BF6F51DBFB71F007A7D99 /* MediaKeyMessageEvent.idl */,
@@ -27867,6 +27873,7 @@
7CE58D501DD69A1E00128552 /* SVGNumber.h in Headers */,
B2227A510D00BF220071B782 /* SVGNumberList.h in Headers */,
B2227A570D00BF220071B782 /* SVGParserUtilities.h in Headers */,
+ CD063F831E23FA8900812BE3 /* InitDataRegistry.h in Headers */,
2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */,
84C6784D1214814700A92902 /* SVGPathBlender.h in Headers */,
8476C9EB11DF6A2900555B02 /* SVGPathBuilder.h in Headers */,
@@ -30820,6 +30827,7 @@
B27535630B053814002CE64F /* PathCG.cpp in Sources */,
A88DD4890B4629B000C02990 /* PathTraversalState.cpp in Sources */,
2D5002FB1B56D7990020AAF7 /* PathUtilities.cpp in Sources */,
+ CD063F821E23FA8900812BE3 /* InitDataRegistry.cpp in Sources */,
A8FA6E5E0E4CFDED00D5CF49 /* Pattern.cpp in Sources */,
A80A38FE0E50CC8200A25EBC /* PatternCG.cpp in Sources */,
1A8A646C1D19FF8700D0E00F /* PaymentCocoa.mm in Sources */,
Modified: trunk/Source/WebCore/testing/MockCDMFactory.cpp (210554 => 210555)
--- trunk/Source/WebCore/testing/MockCDMFactory.cpp 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/testing/MockCDMFactory.cpp 2017-01-10 20:09:21 UTC (rev 210555)
@@ -28,7 +28,10 @@
#if ENABLE(ENCRYPTED_MEDIA)
+#include "InitDataRegistry.h"
+#include "UUID.h"
#include <runtime/ArrayBuffer.h>
+#include <wtf/text/StringHash.h>
#include <wtf/text/StringView.h>
namespace WebCore {
@@ -58,6 +61,24 @@
return equalIgnoringASCIICase(keySystem, "org.webkit.mock");
}
+void MockCDMFactory::addKeysToSessionWithID(const String& id, Vector<Ref<SharedBuffer>>&& keys)
+{
+ auto addResult = m_sessions.add(id, WTFMove(keys));
+ if (addResult.isNewEntry)
+ return;
+
+ auto& value = addResult.iterator->value;
+ for (auto& key : keys)
+ value.append(WTFMove(key));
+}
+
+void MockCDMFactory::setSupportedDataTypes(Vector<String>&& types)
+{
+ m_supportedDataTypes.clear();
+ for (auto& type : types)
+ m_supportedDataTypes.append(type);
+}
+
std::unique_ptr<CDMPrivate> MockCDMFactory::createCDM(CDM&)
{
return std::make_unique<MockCDM>(m_weakPtrFactory.createWeakPtr());
@@ -69,7 +90,7 @@
{
}
-bool MockCDM::supportsInitDataType(const String& initDataType)
+bool MockCDM::supportsInitDataType(const AtomicString& initDataType) const
{
if (m_factory)
return m_factory->supportedDataTypes().contains(initDataType);
@@ -76,7 +97,7 @@
return false;
}
-bool MockCDM::supportsConfiguration(const MediaKeySystemConfiguration&)
+bool MockCDM::supportsConfiguration(const MediaKeySystemConfiguration&) const
{
// NOTE: Implement;
return true;
@@ -83,13 +104,13 @@
}
-bool MockCDM::supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&)
+bool MockCDM::supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const
{
// NOTE: Implement;
return true;
}
-bool MockCDM::supportsSessionTypeWithConfiguration(MediaKeySessionType& sessionType, const MediaKeySystemConfiguration&)
+bool MockCDM::supportsSessionTypeWithConfiguration(MediaKeySessionType& sessionType, const MediaKeySystemConfiguration&) const
{
if (!m_factory || !m_factory->supportedSessionTypes().contains(sessionType))
return false;
@@ -98,7 +119,7 @@
return true;
}
-bool MockCDM::supportsRobustness(const String& robustness)
+bool MockCDM::supportsRobustness(const String& robustness) const
{
if (m_factory)
return m_factory->supportedRobustness().contains(robustness);
@@ -105,7 +126,7 @@
return false;
}
-MediaKeysRequirement MockCDM::distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&)
+MediaKeysRequirement MockCDM::distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const
{
if (m_factory)
return m_factory->distinctiveIdentifiersRequirement();
@@ -112,7 +133,7 @@
return MediaKeysRequirement::Optional;
}
-MediaKeysRequirement MockCDM::persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&)
+MediaKeysRequirement MockCDM::persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const
{
if (m_factory)
return m_factory->persistentStateRequirement();
@@ -119,7 +140,7 @@
return MediaKeysRequirement::Optional;
}
-bool MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&)
+bool MockCDM::distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) const
{
// NOTE: Implement;
return true;
@@ -147,6 +168,15 @@
return m_factory && m_factory->supportsSessions();
}
+bool MockCDM::supportsInitData(const AtomicString& initDataType, const SharedBuffer& initData) const
+{
+ if (!supportsInitDataType(initDataType))
+ return false;
+
+ UNUSED_PARAM(initData);
+ return true;
+}
+
MockCDMInstance::MockCDMInstance(WeakPtr<MockCDM> cdm)
: m_cdm(cdm)
{
@@ -188,9 +218,9 @@
return Succeeded;
}
-CDMInstance::SuccessValue MockCDMInstance::setServerCertificate(ArrayBuffer& certificate)
+CDMInstance::SuccessValue MockCDMInstance::setServerCertificate(Ref<SharedBuffer>&& certificate)
{
- StringView certificateStringView(static_cast<const LChar*>(certificate.data()), certificate.byteLength());
+ StringView certificateStringView(reinterpret_cast<const LChar*>(certificate->data()), certificate->size());
if (equalIgnoringASCIICase(certificateStringView, "valid"))
return Succeeded;
@@ -197,6 +227,35 @@
return Failed;
}
+void MockCDMInstance::requestLicense(LicenseType licenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback callback)
+{
+ MockCDMFactory* factory = m_cdm ? m_cdm->factory() : nullptr;
+ if (!factory) {
+ callback(SharedBuffer::create(), emptyAtom, false, SuccessValue::Failed);
+ return;
+ }
+
+ if ((licenseType == LicenseType::Temporary && !factory->supportedSessionTypes().contains(MediaKeySessionType::Temporary))
+ || (licenseType == LicenseType::Persistable && !factory->supportedSessionTypes().contains(MediaKeySessionType::PersistentLicense))
+ || (licenseType == LicenseType::UsageRecord && !factory->supportedSessionTypes().contains(MediaKeySessionType::PersistentUsageRecord))
+ || !factory->supportedDataTypes().contains(initDataType)) {
+ callback(SharedBuffer::create(), emptyString(), false, SuccessValue::Failed);
+ return;
+ }
+
+ auto keyIDs = InitDataRegistry::shared().extractKeyIDs(initDataType, initData);
+ if (keyIDs.isEmpty()) {
+ callback(SharedBuffer::create(), emptyString(), false, SuccessValue::Failed);
+ return;
+ }
+
+ String sessionID = createCanonicalUUIDString();
+ factory->addKeysToSessionWithID(sessionID, WTFMove(keyIDs));
+
+ CString license { "license" };
+ callback(SharedBuffer::create(license.data(), license.length()), sessionID, false, SuccessValue::Succeeded);
}
+}
+
#endif
Modified: trunk/Source/WebCore/testing/MockCDMFactory.h (210554 => 210555)
--- trunk/Source/WebCore/testing/MockCDMFactory.h 2017-01-10 19:13:06 UTC (rev 210554)
+++ trunk/Source/WebCore/testing/MockCDMFactory.h 2017-01-10 20:09:21 UTC (rev 210555)
@@ -31,6 +31,7 @@
#include "CDMInstance.h"
#include "CDMPrivate.h"
#include "MediaKeysRequirement.h"
+#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
#include <wtf/WeakPtr.h>
@@ -42,8 +43,8 @@
static Ref<MockCDMFactory> create() { return adoptRef(*new MockCDMFactory); }
~MockCDMFactory();
- const Vector<String>& supportedDataTypes() const { return m_supportedDataTypes; }
- void setSupportedDataTypes(Vector<String>&& types) { m_supportedDataTypes = WTFMove(types); }
+ const Vector<AtomicString>& supportedDataTypes() const { return m_supportedDataTypes; }
+ void setSupportedDataTypes(Vector<String>&&);
const Vector<MediaKeySessionType>& supportedSessionTypes() const { return m_supportedSessionTypes; }
void setSupportedSessionTypes(Vector<MediaKeySessionType>&& types) { m_supportedSessionTypes = WTFMove(types); }
@@ -68,6 +69,10 @@
void unregister();
+ bool hasSessionWithID(const String& id) { return m_sessions.contains(id); }
+ void removeSessionWithID(const String& id) { m_sessions.remove(id); }
+ void addKeysToSessionWithID(const String& id, Vector<Ref<SharedBuffer>>&&);
+
private:
MockCDMFactory();
std::unique_ptr<CDMPrivate> createCDM(CDM&) final;
@@ -75,7 +80,7 @@
MediaKeysRequirement m_distinctiveIdentifiersRequirement { MediaKeysRequirement::Optional };
MediaKeysRequirement m_persistentStateRequirement { MediaKeysRequirement::Optional };
- Vector<String> m_supportedDataTypes;
+ Vector<AtomicString> m_supportedDataTypes;
Vector<MediaKeySessionType> m_supportedSessionTypes;
Vector<String> m_supportedRobustness;
bool m_registered { true };
@@ -83,6 +88,7 @@
bool m_supportsServerCertificates { true };
bool m_supportsSessions { true };
WeakPtrFactory<MockCDMFactory> m_weakPtrFactory;
+ HashMap<String, Vector<Ref<SharedBuffer>>> m_sessions;
};
class MockCDM : public CDMPrivate {
@@ -94,18 +100,19 @@
private:
friend class MockCDMInstance;
- bool supportsInitDataType(const String&) final;
- bool supportsConfiguration(const MediaKeySystemConfiguration&) final;
- bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) final;
- bool supportsSessionTypeWithConfiguration(MediaKeySessionType&, const MediaKeySystemConfiguration&) final;
- bool supportsRobustness(const String&) final;
- MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) final;
- MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) final;
- bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) final;
+ bool supportsInitDataType(const AtomicString&) const final;
+ bool supportsConfiguration(const MediaKeySystemConfiguration&) const final;
+ bool supportsConfigurationWithRestrictions(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const final;
+ bool supportsSessionTypeWithConfiguration(MediaKeySessionType&, const MediaKeySystemConfiguration&) const final;
+ bool supportsRobustness(const String&) const final;
+ MediaKeysRequirement distinctiveIdentifiersRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const final;
+ MediaKeysRequirement persistentStateRequirement(const MediaKeySystemConfiguration&, const MediaKeysRestrictions&) const final;
+ bool distinctiveIdentifiersAreUniquePerOriginAndClearable(const MediaKeySystemConfiguration&) const final;
RefPtr<CDMInstance> createInstance() final;
void loadAndInitialize() final;
bool supportsServerCertificates() const final;
bool supportsSessions() const final;
+ bool supportsInitData(const AtomicString&, const SharedBuffer&) const final;
WeakPtr<MockCDMFactory> m_factory;
WeakPtrFactory<MockCDM> m_weakPtrFactory;
@@ -119,7 +126,8 @@
SuccessValue initializeWithConfiguration(const MediaKeySystemConfiguration&) final;
SuccessValue setDistinctiveIdentifiersAllowed(bool) final;
SuccessValue setPersistentStateAllowed(bool) final;
- SuccessValue setServerCertificate(JSC::ArrayBuffer&) final;
+ SuccessValue setServerCertificate(Ref<SharedBuffer>&&) final;
+ void requestLicense(LicenseType, const AtomicString& initDataType, Ref<SharedBuffer>&& initData, LicenseCallback) final;
WeakPtr<MockCDM> m_cdm;
bool m_distinctiveIdentifiersAllowed { true };