diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/encrypted-media | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/encrypted-media')
218 files changed, 16958 insertions, 0 deletions
diff --git a/testing/web-platform/tests/encrypted-media/EncryptedMediaExtensions.idl b/testing/web-platform/tests/encrypted-media/EncryptedMediaExtensions.idl new file mode 100644 index 000000000..fbe898b20 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/EncryptedMediaExtensions.idl @@ -0,0 +1,119 @@ +// Encrypted Media Extensions WebIDL +// +// NOTE: Please update the link below to the specification version from +// which this IDL was extracted. +// +// https://www.w3.org/TR/2016/WD-encrypted-media-20160610/ +// + commit 5499821932391ae2c2e53756ae7ab9fae89d5863 +// + +partial interface Navigator { + Promise<MediaKeySystemAccess> requestMediaKeySystemAccess (DOMString keySystem, sequence<MediaKeySystemConfiguration> supportedConfigurations); +}; + +enum MediaKeysRequirement { + "required", + "optional", + "not-allowed" +}; + +dictionary MediaKeySystemConfiguration { + DOMString label = ""; + sequence<DOMString> initDataTypes = []; + sequence<MediaKeySystemMediaCapability> audioCapabilities = []; + sequence<MediaKeySystemMediaCapability> videoCapabilities = []; + MediaKeysRequirement distinctiveIdentifier = "optional"; + MediaKeysRequirement persistentState = "optional"; + sequence<DOMString> sessionTypes; +}; + +dictionary MediaKeySystemMediaCapability { + DOMString contentType = ""; + DOMString robustness = ""; +}; + +interface MediaKeySystemAccess { + readonly attribute DOMString keySystem; + MediaKeySystemConfiguration getConfiguration (); + Promise<MediaKeys> createMediaKeys (); +}; + +enum MediaKeySessionType { + "temporary", + "persistent-usage-record", + "persistent-license" +}; + +interface MediaKeys { + MediaKeySession createSession (optional MediaKeySessionType sessionType = "temporary"); + Promise<boolean> setServerCertificate (BufferSource serverCertificate); +}; + +interface MediaKeySession : EventTarget { + readonly attribute DOMString sessionId; + readonly attribute unrestricted double expiration; + readonly attribute Promise<void> closed; + readonly attribute MediaKeyStatusMap keyStatuses; + attribute EventHandler onkeystatuseschange; + attribute EventHandler onmessage; + Promise<void> generateRequest (DOMString initDataType, BufferSource initData); + Promise<boolean> load (DOMString sessionId); + Promise<void> update (BufferSource response); + Promise<void> close (); + Promise<void> remove (); +}; + +interface MediaKeyStatusMap { + iterable<BufferSource,MediaKeyStatus>; + readonly attribute unsigned long size; + boolean has (BufferSource keyId); + any get (BufferSource keyId); +}; + +enum MediaKeyStatus { + "usable", + "expired", + "released", + "output-restricted", + "output-downscaled", + "status-pending", + "internal-error" +}; + +enum MediaKeyMessageType { + "license-request", + "license-renewal", + "license-release", + "individualization-request" +}; + +[Constructor(DOMString type, MediaKeyMessageEventInit eventInitDict)] +interface MediaKeyMessageEvent : Event { + readonly attribute MediaKeyMessageType messageType; + readonly attribute ArrayBuffer message; +}; + +dictionary MediaKeyMessageEventInit : EventInit { + required MediaKeyMessageType messageType; + required ArrayBuffer message; +}; + +// partial interface HTMLMediaElement : EventTarget { +partial interface HTMLMediaElement { + readonly attribute MediaKeys? mediaKeys; + attribute EventHandler onencrypted; + attribute EventHandler onwaitingforkey; + Promise<void> setMediaKeys (MediaKeys? mediaKeys); +}; + +[Constructor(DOMString type, optional MediaEncryptedEventInit eventInitDict)] +interface MediaEncryptedEvent : Event { + readonly attribute DOMString initDataType; + readonly attribute ArrayBuffer? initData; +}; + +dictionary MediaEncryptedEventInit : EventInit { + DOMString initDataType = ""; + ArrayBuffer? initData = null; +}; + diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-creation-with-gc.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-creation-with-gc.html new file mode 100644 index 000000000..4dd705f9f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-creation-with-gc.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test asynchronous creation of MediaKeys and MediaKeySession while running garbage collection</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + // Run garbage collection often. + setInterval(asyncGC, 0); + + var initDataType; + var initData; + var mediaKeySession; + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + return mediaKeySession.close(); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Test asynchronous creation of MediaKeys and MediaKeySession while running garbage collection.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-setcert-with-gc.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-setcert-with-gc.html new file mode 100644 index 000000000..4da562894 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-async-setcert-with-gc.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test asynchronous setServerCertificate while running garbage collection</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Run garbage collection continuously. + setInterval(asyncGC, 0); + + promise_test(function(test) + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var cert = new Uint8Array(200); + return mediaKeys.setServerCertificate(cert); + }).then(function(result) { + assert_false(result); + }); + }, 'Test asynchronous setServerCertificate while running garbage collection.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys-with-session.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys-with-session.html new file mode 100644 index 000000000..a892b969c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys-with-session.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeys lifetime when adding a session</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // MediaKeySessions remain as long as: + // JavaScript has a reference to it + // OR (MediaKeys is around + // AND the session has not received a close() event) + // In the tests below, we do not close any session nor keep a + // Javascript reference to any session, so MediaKeySessions remain + // as long as the associated MediaKeys object is around. + + // For this test, create a MediaKeySession and verify lifetime. + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeys; + var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); + + function numActiveDOMObjectsCreated() + { + return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; + } + + // Create a MediaKeys object with a session. + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + + // Verify MediaKeys is an ActiveDOMObject. + // In non-Oilpan, numActiveDOMObjectsCreate() == 1. + // In Oilpan, numActiveDOMObjectsCreate() <= 4. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), + // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType()))) + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4, 'MediaKeys.create()'); + + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + // Should be 1 MediaKeys + 1 MediaKeySession. + // In non-Oilpan, numActiveDOMObjectsCreate() == 2. + // In Oilpan, numActiveDOMObjectsCreate() <= 6. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializer, + // 1 ContentDecryptionModuleResultPromise and + // 1 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 6, 'MediaKeys.createSession()'); + + // Run gc(), should not affect MediaKeys object nor the + // session since we still have a reference to it. + + // When enabling oilpan GC, the in-active + // ScriptPromiseResolvers will be destroyed. + return createGCPromise(); + }).then(function(result) { + assert_equals(typeof mediaKeys.createSession, 'function'); + + // MediaKeys + MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 3, 'After gc()'); + + // Drop reference to the MediaKeys object and run gc() + // again. Object should be collected this time. Since + // MediaKeySessions remain alive as long as MediaKeys is + // around, it is possible that gc() checks the + // MediaKeySession object first, and doesn't collect it + // since MediaKeys hasn't been collected yet. Thus run gc() + // twice, to ensure that the unreferenced MediaKeySession + // object get collected. + mediaKeys = null; + return createGCPromise(); + }).then(function(result) { + return createGCPromise(); + }).then(function(result) { + // No MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 0, 1, 'After final gc()'); + + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'MediaKeys lifetime with session'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys.html new file mode 100644 index 000000000..b8e79ac8b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeys.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeys lifetime</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + // Create a MediaKeys object and free immediately. + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + // Do nothing with the created object + }).then(function(result) { + // No way to verify that MediaKeys object is actually + // collected, but make sure it doesn't crash. + return createGCPromise(); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Creating and destroying MediaKeys does not crash'); + + async_test(function(test) + { + var mediaKeys; + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + return createGCPromise(); + }).then(function(result) { + // Check that the object still exists. + assert_equals(typeof mediaKeys.createSession, 'function'); + mediaKeys = null; + + // Now that the reference is dropped, it should be + // collected. No way to verify that it is actually + // collected, but make sure it doesn't crash. + return createGCPromise(); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'MediaKeys is not collected as long as we have a reference'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-reference.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-reference.html new file mode 100644 index 000000000..4b8ad1b46 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-reference.html @@ -0,0 +1,157 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeySession lifetime without release()</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Since MediaKeySession (and MediaKeys) are ActiveDOMObjects, + // we can determine when they are garbage collected. + // MediaKeySessions remain as long as: + // JavaScript has a reference to it + // OR (MediaKeys is around + // AND the session has not received a close() event) + + async_test(function(test) + { + var mediaKeys; + var mediaKeySession1; + var mediaKeySession2; + var mediaKeySession3; + var initDataType; + var initData; + var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); + + function numActiveDOMObjectsCreated() + { + return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + assert_equals(typeof mediaKeys.createSession, 'function'); + + // Verify MediaKeys is an ActiveDOMObject. + // In non-Oilpan, numActiveDOMObjectsCreate() == 1. + // In Oilpan, numActiveDOMObjectsCreate() <= 4. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), + // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType()))) + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4, 'MediaKeys.create()'); + + // Create 3 sessions. + mediaKeySession1 = mediaKeys.createSession(); + return mediaKeySession1.generateRequest(initDataType, initData); + }).then(function() { + assert_true(mediaKeySession1.sessionId && mediaKeySession1.sessionId.length > 0); + + // Should be 1 MediaKeys + 1 MediaKeySession. + // In non-Oilpan, numActiveDOMObjectsCreate() == 2. + // In Oilpan, numActiveDOMObjectsCreate() <= 6. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializer, + // 1 ContentDecryptionModuleResultPromise and + // 1 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 6, 'MediaKeys.createSession(1)'); + + mediaKeySession2 = mediaKeys.createSession(); + return mediaKeySession2.generateRequest(initDataType, initData); + }).then(function() { + assert_true(mediaKeySession2.sessionId && mediaKeySession2.sessionId.length > 0); + + // Should be 1 MediaKeys + 2 MediaKeySessions. + // In non-Oilpan, numActiveDOMObjectsCreate() == 3. + // In Oilpan, numActiveDOMObjectsCreate() <= 8. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializers, + // 2 ContentDecryptionModuleResultPromise and + // 2 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 8, 'mediaKeys.createSession(2)'); + + mediaKeySession3 = mediaKeys.createSession(); + return mediaKeySession3.generateRequest(initDataType, initData); + }).then(function() { + assert_true(mediaKeySession3.sessionId && mediaKeySession3.sessionId.length > 0); + + // Should be 1 MediaKeys + 3 MediaKeySessions. + // In non-Oilpan, numActiveDOMObjectsCreate() == 4. + // In Oilpan, numActiveDOMObjectsCreate() <= 10. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializers, + // 3 ContentDecryptionModuleResultPromise and + // 3 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 10, 'mediaKeys.createSession(3)'); + + // Run gc(). All sessions should remain as we have a + // reference to each one. However, running gc() + // asynchronously should free up the last PromiseResolver. + return createGCPromise(); + }).then(function(result) { + // Only MediaKeys + 3 MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 5, 'After gc()'); + + // Now drop references to 2 of the sessions. Even though we + // don't have a reference, MediaKeys is still around (and + // the sessions aren't closed), so the objects won't be + // collected. + mediaKeySession1 = null; + mediaKeySession2 = null; + return createGCPromise(); + }).then(function(result) { + return createGCPromise(); + }).then(function(result) { + // MediaKeys + 3 MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 5, 'After second gc()'); + + // Now drop the reference to MediaKeys. It and the 2 + // unreferenced sessions should be collected. Since + // MediaKeySessions remain alive as long as MediaKeys is + // around, it is possible that gc() checks one or both + // MediaKeySession objects first, and doesn't collect them + // since MediaKeys hasn't been collected yet. Thus run gc() + // twice, to ensure that the unreferenced MediaKeySession + // objects get collected. + mediaKeys = null; + return createGCPromise(); + }).then(function(result) { + return createGCPromise(); + }).then(function(result) { + // Only 1 MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 2, 'After mediaKeys = null'); + + // Drop the reference to the last session. It should get + // collected now since MediaKeys is gone. + mediaKeySession3 = null; + return createGCPromise(); + }).then(function(result) { + // No MediaKeySessions should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 0, 1, 'After final gc()'); + + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'MediaKeySession lifetime without release()'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release-noreference.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release-noreference.html new file mode 100644 index 000000000..a962844a3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release-noreference.html @@ -0,0 +1,131 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeySession lifetime after release() without references</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Since MediaKeySession (and MediaKeys) are ActiveDOMObjects, + // we can determine when they are garbage collected. + // MediaKeySessions remain as long as: + // JavaScript has a reference to it + // OR (MediaKeys is around + // AND the session has not received a close() event) + async_test(function(test) + { + var initDataType; + var initData; + var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); + + function numActiveDOMObjectsCreated() + { + return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; + } + + // Create 2 sessions. + var mediaKeys; + var mediaKeySession1; + var mediaKeySession2; + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + + // Verify MediaKeys is an ActiveDOMObject. + // In non-Oilpan, numActiveDOMObjectsCreate() == 1. + // In Oilpan, numActiveDOMObjectsCreate() <= 4. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), + // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType()))) + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4, 'MediaKeys.create()'); + + mediaKeySession1 = mediaKeys.createSession(); + return mediaKeySession1.generateRequest(initDataType, initData); + }).then(function() { + assert_true(mediaKeySession1.sessionId && mediaKeySession1.sessionId.length > 0); + + // Should be 1 MediaKeys + 1 MediaKeySession. + // In non-Oilpan, numActiveDOMObjectsCreate() == 2. + // In Oilpan, numActiveDOMObjectsCreate() <= 6. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializer, + // 1 ContentDecryptionModuleResultPromise and + // 1 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 6, 'MediaKeys.createSession(1)'); + + mediaKeySession2 = mediaKeys.createSession(); + return mediaKeySession2.generateRequest(initDataType, initData); + }).then(function() { + assert_true(mediaKeySession2.sessionId && mediaKeySession2.sessionId.length > 0); + + // Should be 1 MediaKeys + 2 MediaKeySessions. + // In non-Oilpan, numActiveDOMObjectsCreate() == 3. + // In Oilpan, numActiveDOMObjectsCreate() <= 8. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 2 MediaKeySystemAccessInitializers, + // 2 ContentDecryptionModuleResultPromise and + // 2 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 8, 'mediaKeys.createSession(2)'); + }).then(function(result) { + // Run gc(). All sessions should remain as we have a + // reference to each one. + return createGCPromise(); + }).then(function(result) { + // Should be just 1 MediaKeys + 2 MediaKeySessions. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 4, 'After gc()'); + + // Close the sessions. Once the close() event is received, + // they should get garbage collected as there are no JS + // references to them. + var promise = mediaKeySession1.close(); + mediaKeySession1 = null; + return promise; + }).then(function(result) { + // Give time so that the close event can be processed by + // MediaKeySession. + return delayToAllowEventProcessingPromise(); + }).then(function(result) { + return createGCPromise(); + }).then(function(result) { + // Only MediaKeys + mediaKeySession2 should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 3, 'mediaKeySession1 not collected'); + + var promise = mediaKeySession2.close(); + mediaKeySession2 = null; + return promise; + }).then(function(result) { + // Provide time for the mediaKeySession2 close event to be + // handled. + return delayToAllowEventProcessingPromise(); + }).then(function(result) { + return createGCPromise(); + }).then(function(result) { + // Only MediaKeys should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 2, 'mediaKeySession2 not collected'); + + assert_not_equals(mediaKeys, null); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'MediaKeySession lifetime after release() without references'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release.html new file mode 100644 index 000000000..626526761 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-mediakeysession-release.html @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>MediaKeySession lifetime after release()</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Since MediaKeySession (and MediaKeys) are ActiveDOMObjects, + // we can determine when they are garbage collected. + // MediaKeySessions remain as long as: + // JavaScript has a reference to it + // OR (MediaKeys is around + // AND the session has not received a close() event) + async_test(function(test) + { + var mediaKeys; + var mediaKeySession1; + var mediaKeySession2; + var initDataType; + var initData; + var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); + + function numActiveDOMObjectsCreated() + { + return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; + } + + // Create 2 sessions. + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + + // Verify MediaKeys is an ActiveDOMObject. + // In non-Oilpan, numActiveDOMObjectsCreate() == 1. + // In Oilpan, numActiveDOMObjectsCreate() <= 4. + // (1 MediaKeys, + // 1 MediaKeysInitializer and + // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), + // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType()))) + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4, 'MediaKeys.create()'); + + mediaKeySession1 = mediaKeys.createSession(); + return mediaKeySession1.generateRequest(initDataType, initData); + }).then(function() { + // Should be 1 MediaKeys + 1 MediaKeySession. + // In non-Oilpan, numActiveDOMObjectsCreate() == 2. + // In Oilpan, numActiveDOMObjectsCreate() <= 6. + // (1 MediaKeys, + // 1 MediaKeysInitializer, + // 2 MediaKeySystemAccessInitializers, + // 1 ContentDecryptionModuleResultPromise and + // 1 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 6, 'MediaKeys.createSession(1)'); + + mediaKeySession2 = mediaKeys.createSession(); + return mediaKeySession2.generateRequest(initDataType, initData); + }).then(function() { + // Should be 1 MediaKeys + 2 MediaKeySessions. + // In non-Oilpan, numActiveDOMObjectsCreate() == 3. + // In Oilpan, numActiveDOMObjectsCreate() <= 8. + // (1 MediaKeys, + // 1 MediaKeysInitializer, + // 2 MediaKeySystemAccessInitializers, + // 2 ContentDecryptionModuleResultPromise and + // 2 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 8, 'mediaKeys.createSession(2)'); + + // Close the sessions. Once completed, only the JS + // reference to them keeps them around. + return mediaKeySession1.close(); + }).then(function(result) { + return mediaKeySession2.close(); + }).then(function(result) { + // Since both sessions have been closed, dropping the + // reference to them from JS will result in the session + // being garbage-collected. + // Should be 1 MediaKeys + 2 MediaKeySessions. + // In non-Oilpan, numActiveDOMObjectsCreate() == 3. + // In Oilpan, numActiveDOMObjectsCreate() <= 10. + // (1 MediaKeys, + // 1 MediaKeysInitializer, + // 2 MediaKeySystemAccessInitializers, + // 4 ContentDecryptionModuleResultPromise and + // 2 MediaKeySession). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 10, 'after close'); + + mediaKeySession1 = null; + return createGCPromise(); + }).then(function() { + // Only MediaKeys + mediaKeySession2 should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 3, 'mediaKeySession1 not collected'); + + mediaKeySession2 = null; + return createGCPromise(); + }).then(function() { + // Only MediaKeys should remain. + // In non-Oilpan, there is also something from createGCPromise(). + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 2, 'mediaKeySession2 not collected'); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'MediaKeySession lifetime after release()'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-multiple-mediakeys.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-multiple-mediakeys.html new file mode 100644 index 000000000..42638a069 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-multiple-mediakeys.html @@ -0,0 +1,131 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test multiple MediaKeys lifetimes</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // For this test, create several MediaKeys and verify lifetime. + async_test(function(test) + { + var mediaKeys; + var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); + + function numActiveDOMObjectsCreated() + { + return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; + } + + // Create a MediaKeys object. Returns a promise that resolves + // with the new MediaKeys object. + function createMediaKeys() + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + return mediaKeys; + }); + } + + // Create a few MediaKeys objects. Only keep a reference to the + // last one created. + createMediaKeys().then(function(result) { + // Should be 1 MediaKeys. + // In non-Oilpan, numActiveDOMObjectsCreate() == 1. + // In Oilpan, numActiveDOMObjectsCreated() <= 4. + // (1 MediaKeysInitializer, + // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), + // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType())) and + // 1 ContentDecryptionModuleResultPromise). + assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4); + + return createMediaKeys(); + }).then(function(result) { + // Should be 2 MediaKeys. + // In non-Oilpan, numActiveDOMObjectsCreate() == 2. + // In Oilpan, numActiveDOMObjectsCreate() <= 8. + // (2 MediaKeysInitializer, + // 4 MediaKeySystemAccessInitializer and + // 2 ContentDecryptionModuleResultPromise). + assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 8); + + return createMediaKeys(); + }).then(function(result) { + // Should be 3 MediaKeys. + // In non-Oilpan, numActiveDOMObjectsCreate() == 3. + // In Oilpan, numActiveDOMObjectsCreate() <= 12. + // (3 MediaKeysInitializer, + // 6 MediaKeySystemAccessInitializer and + // 3 ContentDecryptionModuleResultPromise). + assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 12); + + return createMediaKeys(); + }).then(function(result) { + // Should be 4 MediaKeys. + // In non-Oilpan, numActiveDOMObjectsCreate() == 4. + // In Oilpan, numActiveDOMObjectsCreate() <= 16. + // (4 MediaKeysInitializer, + // 8 MediaKeySystemAccessInitializer and + // 4 ContentDecryptionModuleResultPromise). + assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 16); + + return createMediaKeys(); + }).then(function(result) { + // Should be 5 MediaKeys. + // In non-Oilpan, numActiveDOMObjectsCreate() == 5. + // In Oilpan, numActiveDOMObjectsCreate() <= 20. + // (5 MediaKeysInitializer, + // 10 MediaKeySystemAccessInitializer and + // 5 ContentDecryptionModuleResultPromise). + assert_between_inclusive(numActiveDOMObjectsCreated(), 5, 20); + + // |mediaKeys| refers to the most recently created MediaKeys + // object. + mediaKeys = result; + + // In order for the MediaKey objects to be garbage + // collected, it needs time to process any pending events. + return delayToAllowEventProcessingPromise(); + }).then(function(result) { + // In non-Oilpan, numActiveDOMObjectsCreated() == 5 + // (5 MediaKeySession objects). + // In Oilpan, numActiveDOMObjectsCreated() <= 23 + // (5 MediaKeysInitializer, + // 12 MediaKeySystemAccessInitializer, + // 5 ContentDecryptionModuleResultPromise and + // 1 DOMTimer (in delayToAllowEventProcessingPromise)) + assert_between_inclusive(numActiveDOMObjectsCreated(), 5, 23); + + // As we only have a reference (|mediaKeys|) to the last + // created MediaKeys object, the other 4 MediaKeys objects + // are available to be garbage collected. + return createGCPromise(); + }).then(function(result) { + // Should be 1 MediaKeys and DOMTimer. + assert_less_than_equal(numActiveDOMObjectsCreated(), 2); + assert_equals(typeof mediaKeys.createSession, 'function'); + + // Release the last MediaKeys object created. + mediaKeys = null; + + // Run gc() again to reclaim the remaining MediaKeys object. + return createGCPromise(); + }).then(function(result) { + // Should be just a DOMTimer. + assert_less_than_equal(numActiveDOMObjectsCreated(), 1); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Multiple MediaKeys lifetime'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-reload.html b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-reload.html new file mode 100644 index 000000000..b2f8ffb1f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/chromium_specific_disabled/encrypted-media-lifetime-reload.html @@ -0,0 +1,103 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Reloading during encrypted media playback</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test requires Chromium specific content and is being disabled. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted.webm'; + var mediaKeySession = null; + var hasSessionUpdateSucceeded = false; + var encryptedEventCount = 0; + + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + function onEncrypted(event) + { + assert_equals(event.target, video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // The same decryption key is used by both the audio and + // the video streams so only create a session once. To + // avoid issues when comparing the expected.txt file + // (which logs the events in the order they occur), create + // the session on the second event. This also ensures we + // see both events. + if (++encryptedEventCount != 2) + return; + + mediaKeySession = video.mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + mediaKeySession.generateRequest(event.initDataType, event.initData).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'message'); + assert_equals(event.messageType, 'license-request'); + + var keyId = extractSingleKeyIdFromMessage(event.message); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + mediaKeySession.update(jwkSet).then(function(result) { + hasSessionUpdateSucceeded = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onPlaying(event) + { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) + { + if (event.target.currentTime < 0.2 || !hasSessionUpdateSucceeded) + return; + + // Reload the page to catch any possible teardown issues. + if (location.hash == '#x') { + test.done(); + return; + } + + location.hash += 'x'; + location.reload(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + waitForEventAndRunStep('playing', video, onPlaying, test); + video.src = content; + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.play(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Reloading during encrypted media playback.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-check-init-data-type.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-check-init-data-type.html new file mode 100644 index 000000000..f71cf48a8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-check-init-data-type.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test support of different initDataTypes.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + function checkInitDataType(initDataType) + { + return isInitDataTypeSupported(initDataType).then(function(result) { + // If |initDataType| is not supported, simply succeed. + if (!result) + return Promise.resolve('Not supported'); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfigurationForInitDataType(initDataType)) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + var initData = getInitData(initDataType); + return mediaKeySession.generateRequest(initDataType, initData); + }); + }); + } + + promise_test(function() + { + return checkInitDataType('webm'); + }, 'Clear key support for "webm".'); + + promise_test(function() + { + return checkInitDataType('cenc'); + }, 'Clear key support for "cenc".'); + + promise_test(function() + { + return checkInitDataType('keyids'); + }, 'Clear key support for "keyids".'); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clear-key-invalid-license.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clear-key-invalid-license.html new file mode 100644 index 000000000..f145dfad7 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clear-key-invalid-license.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Invalid Clear Key License.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + var initDataType; + var initData; + var invalidLicense = new Uint8Array( + [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77]); + + function handleMessage(event) { + event.target.update(invalidLicense).then(function(event) { + assert_unreached('Error: update() succeeded unexpectedly.'); + test.done(); + }).catch(function(error) { + assert_equals(error.name, 'InvalidAccessError'); + test.done(); + }); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var keySession = mediaKeys.createSession(); + keySession.addEventListener('message', handleMessage, false); + keySession.generateRequest(initDataType, initData); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Invalid Clear Key License.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clearkey-update-non-ascii-input.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clearkey-update-non-ascii-input.html new file mode 100644 index 000000000..cf237a7da --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-clearkey-update-non-ascii-input.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test Clear Key handling of non-ASCII responses for update().</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // This test passes |response| to update() as a JSON Web Key Set. + // CDMs other than Clear Key won't expect |response| in this format. + + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + + function processMessage(event) + { + // |jwkSet| includes some non-ASCII characters. + var jwkSet = '{"keys":[{' + + '"kty":"oct\uDC00\uD800",' + + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",' + + '"kid":"MDEyMzQ1Njc4OTAxMjM0NQ"' + + '\xff\xfe}]'; + mediaKeySession.update(stringToUint8Array(jwkSet)).then(function() { + forceTestFailureFromPromise(test, 'Error: update() succeeded'); + }, function(error) { + assert_equals(error.name, 'InvalidAccessError'); + test.done(); + }); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, processMessage, test); + return mediaKeySession.generateRequest(initDataType, initData); + }); + }, 'Clear Key update() with non-ASCII response.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-events.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-events.html new file mode 100644 index 000000000..a2a70f169 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-events.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Verify v2 events</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Currently Clear Key only generates aynchronous "message" and + // "keychange" events. + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + function processMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'message'); + assert_equals(event.messageType, 'license-request'); + + var keyId = extractSingleKeyIdFromMessage(event.message); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + + waitForEventAndRunStep('keystatuseschange', mediaKeySession, test.step_func(processKeyStatusesChange), test); + + mediaKeySession.update(jwkSet).catch(test.step_func(function(error) { + forceTestFailureFromPromise(test, error); + })); + } + + function processKeyStatusesChange(event) + { + assert_true(event instanceof Event); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'keystatuseschange'); + test.done(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(test.step_func(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, test.step_func(processMessage), test); + return mediaKeySession.generateRequest(initDataType, initData); + })).catch(test.step_func(function(error) { + forceTestFailureFromPromise(test, error); + })); + }, 'Verify v2 events.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-generate-request-disallowed-input.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-generate-request-disallowed-input.html new file mode 100644 index 000000000..53e5c95b7 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-generate-request-disallowed-input.html @@ -0,0 +1,107 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test handling of invalid initData for generateRequest().</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // Create a session and call generateRequest() with |initDataType| + // and |initData|. generateRequest() should fail with an + // InvalidAccessError. Returns a promise that resolves successfully + // if the error happened, rejects otherwise. + function test_session(initDataType, initData) + { + return isInitDataTypeSupported(initDataType).then(function(result) { + // If |initDataType| is not supported, simply succeed. + if (!result) + return Promise.resolve('Not supported'); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfigurationForInitDataType(initDataType)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + assert_unreached('generateRequest() succeeded'); + }, function(error) { + assert_equals(error.name, 'InvalidAccessError'); + return Promise.resolve('success'); + }); + }) + } + + promise_test(function() + { + var initData = new Uint8Array(70000); + return test_session('webm', initData); + }, 'generateRequest() with webm initData longer than 64Kb characters.'); + + promise_test(function() + { + var initData = new Uint8Array(70000); + return test_session('cenc', initData); + }, 'generateRequest() with cenc initData longer than 64Kb characters.'); + + promise_test(function() + { + var initData = new Uint8Array(70000); + return test_session('keyids', initData); + }, 'generateRequest() with keyids initData longer than 64Kb characters.'); + + promise_test(function() + { + // Invalid 'pssh' box as the size specified is larger than what + // is provided. + var initData = new Uint8Array([ + 0x00, 0x00, 0xff, 0xff, // size = huge + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x00, // version = 0 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + return test_session('cenc', initData); + }, 'generateRequest() with invalid pssh box size.'); + + promise_test(function() + { + // Invalid data as type = 'psss'. + var initData = new Uint8Array([ + 0x00, 0x00, 0x00, 0x20, // size = 32 + 0x70, 0x73, 0x73, 0x73, // 'psss' + 0x00, // version = 0 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + return test_session('cenc', initData); + }, 'generateRequest() with non pssh data.'); + + promise_test(function() + { + // Valid key ID size must be at least 1 character for keyids. + var keyId = new Uint8Array(0); + var initData = stringToUint8Array(createKeyIDs(keyId)); + return test_session('keyids', initData); + }, 'generateRequest() with too short key ID.'); + + promise_test(function() + { + // Valid key ID size must be less than 512 characters for keyids. + var keyId = new Uint8Array(600); + var initData = stringToUint8Array(createKeyIDs(keyId)); + return test_session('keyids', initData); + }, 'generateRequest() with too long key ID.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-sessions.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-sessions.html new file mode 100644 index 000000000..3ee4e8c54 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-sessions.html @@ -0,0 +1,121 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Verify MediaKeySession.keyStatuses with multiple sessions</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + var mediaKeySession1; + var mediaKeySession2; + var initDataType; + var initData; + + // Even though key ids are uint8, using printable values so that + // they can be verified easily. + var key1 = stringToUint8Array('123'); + var key2 = stringToUint8Array('4567890'); + var rawKey1 = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var rawKey2 = new Uint8Array([0x3c, 0xae, 0xe4, 0xfc, 0x2a, 0x12, 0xef, 0x68, + 0x7b, 0xd2, 0x14, 0x68, 0xf1, 0x62, 0xdd, 0xeb]); + + function processMessage1(event) + { + // This should only be called for session1. + assert_equals(event.target, mediaKeySession1); + + // No keys added yet. + verifyKeyStatuses(mediaKeySession1.keyStatuses, { expected: [], unexpected: [key1, key2] }); + + // Add key1 to session1. + var jwkSet = stringToUint8Array(createJWKSet(createJWK(key1, rawKey1))); + mediaKeySession1.update(jwkSet).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function processKeyStatusesChange1(event) + { + // This should only be called for session1. + assert_equals(event.target, mediaKeySession1); + + // Check that keyStatuses contains the expected key1 only. + dumpKeyStatuses(mediaKeySession1.keyStatuses); + verifyKeyStatuses(mediaKeySession1.keyStatuses, { expected: [key1], unexpected: [key2] }); + + // Now trigger a message event on session2. + mediaKeySession2.generateRequest(initDataType, initData).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function processMessage2(event) + { + // This should only be called for session2. + assert_equals(event.target, mediaKeySession2); + + // session2 has no keys added yet. + verifyKeyStatuses(mediaKeySession2.keyStatuses, { expected: [], unexpected: [key1, key2] }); + + // session1 should still have 1 key. + verifyKeyStatuses(mediaKeySession1.keyStatuses, { expected: [key1], unexpected: [key2] }); + + // Add key2 to session2. + var jwkSet = stringToUint8Array(createJWKSet(createJWK(key2, rawKey2))); + mediaKeySession2.update(jwkSet).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function processKeyStatusesChange2(event) + { + // This should only be called for session2. + assert_equals(event.target, mediaKeySession2); + + // Check that keyStatuses contains the expected key2 only. + dumpKeyStatuses(mediaKeySession2.keyStatuses); + verifyKeyStatuses(mediaKeySession2.keyStatuses, { expected: [key2], unexpected: [key1] }); + + // session1 should still have 1 key. + verifyKeyStatuses(mediaKeySession1.keyStatuses, { expected: [key1], unexpected: [key2] }); + + test.done(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession1 = mediaKeys.createSession(); + mediaKeySession2 = mediaKeys.createSession(); + + // There should be no keys defined on either session. + verifyKeyStatuses(mediaKeySession1.keyStatuses, { expected: [], unexpected: [key1, key2] }); + verifyKeyStatuses(mediaKeySession2.keyStatuses, { expected: [], unexpected: [key1, key2] }); + + // Bind all the event handlers now. + waitForEventAndRunStep('message', mediaKeySession1, processMessage1, test); + waitForEventAndRunStep('message', mediaKeySession2, processMessage2, test); + waitForEventAndRunStep('keystatuseschange', mediaKeySession1, processKeyStatusesChange1, test); + waitForEventAndRunStep('keystatuseschange', mediaKeySession2, processKeyStatusesChange2, test); + + // Generate a request on session1. + return mediaKeySession1.generateRequest(initDataType, initData); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Verify MediaKeySession.keyStatuses with multiple sessions.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-updates.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-updates.html new file mode 100644 index 000000000..809045d99 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses-multiple-updates.html @@ -0,0 +1,87 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Verify MediaKeySession.keyStatuses with multiple updates</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + var firstEvent; + + // Even though key ids are uint8, using printable values so that + // they can be verified easily. + var key1 = stringToUint8Array('123'); + var key2 = stringToUint8Array('4567890'); + var rawKey1 = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var rawKey2 = new Uint8Array([0x3c, 0xae, 0xe4, 0xfc, 0x2a, 0x12, 0xef, 0x68, + 0x7b, 0xd2, 0x14, 0x68, 0xf1, 0x62, 0xdd, 0xeb]); + + function processMessage(event) + { + // No keys added yet. + verifyKeyStatuses(mediaKeySession.keyStatuses, { expected: [], unexpected: [key1, key2] }); + + // Add key1 to the session. + firstEvent = true; + var jwkSet = stringToUint8Array(createJWKSet(createJWK(key1, rawKey1))); + mediaKeySession.update(jwkSet).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function processKeyStatusesChange(event) + { + if (firstEvent) { + // Verify that the session only contains key1. + dumpKeyStatuses(mediaKeySession.keyStatuses); + verifyKeyStatuses(mediaKeySession.keyStatuses, { expected: [key1], unexpected: [key2] }); + + // Now add key2 to the session. + firstEvent = false; + var jwkSet = stringToUint8Array(createJWKSet(createJWK(key2, rawKey2))); + mediaKeySession.update(jwkSet).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } else { + // Verify that the session now contains key1 and key2. + dumpKeyStatuses(mediaKeySession.keyStatuses); + verifyKeyStatuses(mediaKeySession.keyStatuses, { expected: [key1, key2] }); + + test.done(); + } + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + + // There should be no keys defined yet. + assert_equals(mediaKeySession.keyStatuses.size, 0); + + waitForEventAndRunStep('message', mediaKeySession, processMessage, test); + waitForEventAndRunStep('keystatuseschange', mediaKeySession, processKeyStatusesChange, test); + + return mediaKeySession.generateRequest(initDataType, initData); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Verify MediaKeySession.keyStatuses with multiple updates.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses.html new file mode 100644 index 000000000..043bc1322 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-keystatuses.html @@ -0,0 +1,174 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Verify MediaKeySession.keyStatuses</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + var mediaKeySession; + var initDataType; + var initData; + var closed = false; + + // Even though key ids are uint8, using printable values so that + // they can be verified easily. + var key1String = '123'; + var key2String = '4567890'; + var key1 = stringToUint8Array(key1String); + var key2 = stringToUint8Array(key2String); + var rawKey1 = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var rawKey2 = new Uint8Array([0x3c, 0xae, 0xe4, 0xfc, 0x2a, 0x12, 0xef, 0x68, + 0x7b, 0xd2, 0x14, 0x68, 0xf1, 0x62, 0xdd, 0xeb]); + + function processMessage(event) + { + // No keys added yet. + assert_equals(mediaKeySession.keyStatuses.size, 0); + + waitForEventAndRunStep('keystatuseschange', mediaKeySession, processKeyStatusesChange, test); + + var jwkSet = stringToUint8Array(createJWKSet(createJWK(key1, rawKey1), createJWK(key2, rawKey2))); + mediaKeySession.update(jwkSet).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function checkKeyStatusFor2Keys() + { + // Two keys added, so both should show up in |keyStatuses|. + assert_equals(mediaKeySession.keyStatuses.size, 2); + dumpKeyStatuses(mediaKeySession.keyStatuses); + + // Check |keyStatuses| for 2 entries. + var result = []; + for (let [keyId, status] of mediaKeySession.keyStatuses) { + result.push({ key: arrayBufferAsString(keyId), value: status }); + } + assert_object_equals(result, + [{ key: key1String, value: 'usable'}, { key: key2String, value: 'usable'}], + 'keyStatuses fails'); + + // |keyStatuses| must contain both keys. + result = []; + for (var key of mediaKeySession.keyStatuses.keys()) { + result.push(arrayBufferAsString(key)); + } + assert_array_equals(result, + [key1String, key2String], + 'keyStatuses.keys() fails'); + + // Both values in |mediaKeySession| should be 'usable'. + result = []; + for (var value of mediaKeySession.keyStatuses.values()) { + result.push(value); + } + assert_array_equals(result, + ['usable', 'usable'], + 'keyStatuses.values() fails'); + + // Check |keyStatuses.entries()|. + result = []; + for (var entry of mediaKeySession.keyStatuses.entries()) { + result.push({ key: arrayBufferAsString(entry[0]), value: entry[1] }); + } + assert_object_equals(result, + [{ key: key1String, value: 'usable'}, { key: key2String, value: 'usable'}], + 'keyStatuses.entries() fails'); + + // forEach() should return both entries. + result = []; + mediaKeySession.keyStatuses.forEach(function(status, keyId) { + result.push({ key: arrayBufferAsString(keyId), value: status }); + }); + assert_object_equals(result, + [{ key: key1String, value: 'usable'}, { key: key2String, value: 'usable'}], + 'keyStatuses.forEach() fails'); + + // has() and get() should return the expected values. + assert_true(mediaKeySession.keyStatuses.has(key1)); + assert_true(mediaKeySession.keyStatuses.has(key2)); + assert_equals(mediaKeySession.keyStatuses.get(key1), 'usable'); + assert_equals(mediaKeySession.keyStatuses.get(key2), 'usable'); + + // Try some invalid keyIds. + var invalid1 = key1.subarray(0, key1.length - 1); + assert_false(mediaKeySession.keyStatuses.has(invalid1)); + assert_equals(mediaKeySession.keyStatuses.get(invalid1), undefined); + + var invalid2 = key1.subarray(1); + assert_false(mediaKeySession.keyStatuses.has(invalid2)); + assert_equals(mediaKeySession.keyStatuses.get(invalid2), undefined); + + var invalid3 = new Uint8Array(key1); + invalid3[0] += 1; + assert_false(mediaKeySession.keyStatuses.has(invalid3)); + assert_equals(mediaKeySession.keyStatuses.get(invalid3), undefined); + + var invalid4 = new Uint8Array(key1); + invalid4[invalid4.length - 1] -= 1; + assert_false(mediaKeySession.keyStatuses.has(invalid4)); + assert_equals(mediaKeySession.keyStatuses.get(invalid4), undefined); + + var invalid5 = new Uint8Array(key1.length + 1); + invalid5.set(key1, 1); // First element will be 0. + assert_false(mediaKeySession.keyStatuses.has(invalid5)); + assert_equals(mediaKeySession.keyStatuses.get(invalid5), undefined); + + var invalid6 = new Uint8Array(key1.length + 1); + invalid6.set(key1, 0); // Last element will be 0. + assert_false(mediaKeySession.keyStatuses.has(invalid6)); + assert_equals(mediaKeySession.keyStatuses.get(invalid6), undefined); + } + + function processKeyStatusesChange(event) + { + if ( !closed ) + { + // The first keystatuseschange (caused by update()) + // should include both keys. + checkKeyStatusFor2Keys(); + + mediaKeySession.close().catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + closed = true; + } + else + { + // The second keystatuseschange (caused by close()) + // should not have any keys. + assert_equals(mediaKeySession.keyStatuses.size, 0); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + + // There should be no keys defined yet. + assert_equals(mediaKeySession.keyStatuses.size, 0); + + waitForEventAndRunStep('message', mediaKeySession, processMessage, test); + return mediaKeySession.generateRequest(initDataType, initData); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Verify MediaKeySession.keyStatuses.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-not-callable-after-createsession.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-not-callable-after-createsession.html new file mode 100644 index 000000000..9b92c6905 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-not-callable-after-createsession.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeySession not callable immediately after CreateSession().</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // After creation, the MediaKeySession object is not + // callable, and we should get a InvalidStateError. + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + var arbitraryResponse = new Uint8Array([0x00, 0x11]); + return mediaKeySession.update(arbitraryResponse).then(function(result) { + assert_unreached('update() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, 'Update() immediately after CreateSession().'); + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + return mediaKeySession.close().then(function(result) { + assert_unreached('close() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, 'Close() immediately after CreateSession().'); + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + return mediaKeySession.remove().then(function(result) { + assert_unreached('remove() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, 'Remove() immediately after CreateSession().'); + </script> + </body> +</html> + diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-onencrypted.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-onencrypted.html new file mode 100644 index 000000000..ad408f0f3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-onencrypted.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>onencrypted</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo" controls></video> + <div id="log"></div> + <script> + var expectedInitData = stringToUint8Array('0123456789012345'); + + // Will get 2 identical events, one for audio, one for video. + var expectedEvents = 2; + + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted.webm'; + + var onEncrypted = function(event) + { + assert_equals(event.target, video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + assert_equals(event.initDataType, 'webm'); + assert_array_equals(new Uint8Array(event.initData), expectedInitData); + + if (--expectedEvents == 0) + test.done(); + }; + + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + video.src = content; + }, 'encrypted fired on encrypted media file.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-encrypted-and-clear-sources.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-encrypted-and-clear-sources.html new file mode 100644 index 000000000..495ba4188 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-encrypted-and-clear-sources.html @@ -0,0 +1,130 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Multiple playbacks alternating between encrypted and clear sources.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var isUpdatePromiseResolved = false; + var encryptedEventCount = 0; + var playbackCount = 0; + + // Content to be played. These files must be the same format. + var encryptedContent = 'webm/test-encrypted.webm'; + var unencryptedContent = 'webm/test.webm'; + + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + function onEncrypted(event) + { + assert_equals(event.target, video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // The same decryption key is used by both the audio and + // the video streams so only create a session once. To + // avoid issues when comparing the expected.txt file + // (which logs the events in the order they occur), create + // the session on the second event. This also ensures we + // see both events. + if (++encryptedEventCount != 2) + return; + + assert_false(video.mediaKeys === null, "video.mediaKeys is null."); + var mediaKeySession = video.mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + mediaKeySession.generateRequest(event.initDataType, event.initData).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + assert_equals(event.messageType, 'license-request'); + + var keyId = extractSingleKeyIdFromMessage(event.message); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + event.target.update(jwkSet).then(function(result) { + isUpdatePromiseResolved = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onPlaying(event) + { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) + { + if (event.target.currentTime < 0.2 || !isUpdatePromiseResolved) + return; + + video.removeEventListener('timeupdate', onTimeUpdate, true); + + if (playbackCount > 2) { + test.done(); + return; + } + + playbackCount++; + + resetSrc().then(function(){ + startPlayback(); + }); + } + + function resetSrc() { + encryptedEventCount = 0; + video.removeAttribute('src'); + video.load(); + return video.setMediaKeys(null); + } + + function startPlayback() { + // Alternate between encrypted and unencrypted files. + if (playbackCount % 2) { + // Unencrypted files don't require MediaKeys. + video.src = unencryptedContent; + video.play(); + return; + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(encryptedContent)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.src = encryptedContent; + assert_false(video.mediaKeys === null, "video.mediaKeys is null."); + video.play(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + waitForEventAndRunStep('playing', video, onPlaying, test); + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + startPlayback(); + }, 'Multiple playbacks alternating between encrypted and clear sources.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-multiple-sessions.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-multiple-sessions.html new file mode 100644 index 000000000..8bf94e13c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-multiple-sessions.html @@ -0,0 +1,143 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Clear Key Playback with Multiple Sessions</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted-different-av-keys.webm'; + var audioMediaKeySession = null; + var videoMediaKeySession = null; + var audioInitDataType = null; + var videoInitDataType = null; + var audioInitData = null; + var videoInitData = null; + var audioKeyProvided = false; + var videoKeyProvided = false; + + // The 2 streams use different key ids and different keys. + var audioKeyId = '1234567890123456'; + var audioKey = new Uint8Array([0x30, 0x30, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B, + 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A]); + var videoKeyId = '0123456789012345'; + var videoKey = new Uint8Array([0x7A, 0x7A, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B, + 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A]); + + function onEncrypted(event) + { + var keyId = String.fromCharCode.apply(null, new Uint8Array(event.initData)); + + // To avoid issues when comparing the expected.txt file + // (which logs the events in the order they occur), save + // the initData and make the calls to generateRequest() + // only after both "onencrypted" events are received. + // This prevents a "message" event from occurring before + // both "onencrypted" events are received. + var mediaKeySession = video.mediaKeys.createSession(); + if (keyId == videoKeyId) { + assert_equals(videoMediaKeySession, null); + videoMediaKeySession = mediaKeySession; + videoInitDataType = event.initDataType; + videoInitData = event.initData; + // Return if audio "onencrypted" event not yet received. + if (audioMediaKeySession == null) + return; + } else { + assert_equals(keyId, audioKeyId); + assert_equals(audioMediaKeySession, null); + audioMediaKeySession = mediaKeySession; + audioInitDataType = event.initDataType; + audioInitData = event.initData; + // Return if video "onencrypted" event not yet received. + if (videoMediaKeySession == null) + return; + } + + // Both sessions have been created. + assert_not_equals(videoMediaKeySession, null); + assert_not_equals(audioMediaKeySession, null); + + var promises = []; + waitForEventAndRunStep('message', videoMediaKeySession, onMessage, test); + promises.push(videoMediaKeySession.generateRequest(videoInitDataType, videoInitData)); + + waitForEventAndRunStep('message', audioMediaKeySession, onMessage, test); + promises.push(audioMediaKeySession.generateRequest(audioInitDataType, audioInitData)); + + Promise.all(promises).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onMessage(event) + { + assert_equals(event.messageType, 'license-request'); + var keyId = extractSingleKeyIdFromMessage(event.message); + if (event.target == videoMediaKeySession) { + assert_equals(String.fromCharCode.apply(null, keyId), videoKeyId); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, videoKey))); + videoMediaKeySession.update(jwkSet).then(function(result) { + videoKeyProvided = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } else { + assert_equals(event.target, audioMediaKeySession); + assert_equals(String.fromCharCode.apply(null, keyId), audioKeyId); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, audioKey))); + audioMediaKeySession.update(jwkSet).then(function(result) { + audioKeyProvided = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + } + + function onPlaying(event) + { + // Video should not start playing until both keys have been + // provided. + assert_true(videoKeyProvided); + assert_true(audioKeyProvided); + + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) + { + if (event.target.currentTime < 0.2) + return; + + test.done(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + waitForEventAndRunStep('playing', video, onPlaying, test); + video.src = content; + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.play(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Playback using Clear Key key system with multiple sessions.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-after-src.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-after-src.html new file mode 100644 index 000000000..2a8cac486 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-after-src.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Clear Key Playback</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted.webm'; + var isUpdatePromiseResolved = false; + var encryptedEventCount = 0; + + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + function onEncrypted(event) + { + assert_equals(event.target, video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // The same decryption key is used by both the audio and + // the video streams so only create a session once. To + // avoid issues when comparing the expected.txt file + // (which logs the events in the order they occur), create + // the session on the second event. This also ensures we + // see both events. + if (++encryptedEventCount != 2) + return; + + var mediaKeySession = video.mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + mediaKeySession.generateRequest(event.initDataType, event.initData).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + assert_equals(event.messageType, 'license-request'); + + var keyId = extractSingleKeyIdFromMessage(event.message); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + event.target.update(jwkSet).then(function(result) { + isUpdatePromiseResolved = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onPlaying(event) + { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) + { + if (event.target.currentTime < 0.2 || !isUpdatePromiseResolved) + return; + + test.done(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + waitForEventAndRunStep('playing', video, onPlaying, test); + + video.src = content; + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.play(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Playback using Clear Key key system, calling setMediaKeys() after setting src attribute.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-before-src.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-before-src.html new file mode 100644 index 000000000..84100570c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-setmediakeys-before-src.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Clear Key Playback</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted.webm'; + var isUpdatePromiseResolved = false; + var encryptedEventCount = 0; + + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + function onEncrypted(event) + { + assert_equals(event.target, video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // The same decryption key is used by both the audio and + // the video streams so only create a session once. To + // avoid issues when comparing the expected.txt file + // (which logs the events in the order they occur), create + // the session on the second event. This also ensures we + // see both events. + if (++encryptedEventCount != 2) + return; + + var mediaKeySession = video.mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + mediaKeySession.generateRequest(event.initDataType, event.initData).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + assert_equals(event.messageType, 'license-request'); + + var keyId = extractSingleKeyIdFromMessage(event.message); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + event.target.update(jwkSet).then(function(result) { + isUpdatePromiseResolved = true; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + } + + function onPlaying(event) + { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) + { + if (event.target.currentTime < 0.2 || !isUpdatePromiseResolved) + return; + + test.done(); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + waitForEventAndRunStep('playing', video, onPlaying, test); + + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.src = content; + video.play(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Playback using Clear Key key system, calling setMediaKeys() before setting src attribute.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-two-videos.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-two-videos.html new file mode 100644 index 000000000..0bdc7757b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-playback-two-videos.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Clear Key Play Two Videos At Same Time</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <video id="secondVideo"></video> + <div id="log"></div> + <script> + // As this code doesn't wait for the 'message' event to simplify + // the code, specify the key ID and key used by the encrypted + // content. + var keyId = stringToUint8Array('0123456789012345'); + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var content = 'webm/test-encrypted.webm'; + + promise_test(function(test) + { + var promises = [ + play_video_as_promise(document.getElementById('testVideo'), content), + play_video_as_promise(document.getElementById('secondVideo'), content) + ]; + return Promise.all(promises); + }, 'Play two videos at the same time.'); + + function play_video_as_promise(video, content) + { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + video.src = content; + video.play(); + return wait_for_encrypted_message(video); + }).then(function(result) { + return wait_for_timeupdate_message(video); + }); + }; + + function wait_for_encrypted_message(video) + { + var encryptedEventCount = 0; + return new Promise(function(resolve) { + video.addEventListener('encrypted', function listener(e) { + // The same decryption key is used by both the audio + // and the video streams so only create a session once. + // Create the session on the second event. This also + // ensures we see both events. + if (++encryptedEventCount != 2) + return; + video.removeEventListener('encrypted', listener); + + var mediaKeySession = video.mediaKeys.createSession(); + mediaKeySession.generateRequest(e.initDataType, e.initData).then(function(result) { + // Don't bother waiting for the 'message' event. + // Just call update() since we know the keyId + // needed. + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + return mediaKeySession.update(jwkSet); + }).then(function(result) { + resolve(result); + }); + }); + }); + }; + + function wait_for_timeupdate_message(video) + { + return new Promise(function(resolve) { + video.addEventListener('timeupdate', function listener(e) { + if (e.target.currentTime < 0.2) + return; + video.removeEventListener('timeupdate', listener); + resolve(e); + }); + }); + }; + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-requestmediakeysystemaccess.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-requestmediakeysystemaccess.html new file mode 100644 index 000000000..456f37f57 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-requestmediakeysystemaccess.html @@ -0,0 +1,322 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test navigator.requestMediaKeySystemAccess()</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + function expect_error(keySystem, configurations, expectedError, testName) { + promise_test(function(test) { + return navigator.requestMediaKeySystemAccess(keySystem, configurations).then(function(a) { + assert_unreached('Unexpected requestMediaKeySystemAccess() success.'); + }, function(e) { + assert_equals(e.name, expectedError); + }); + }, testName); + } + + function assert_subset(actual, expected, path) { + if (typeof expected == 'string') { + assert_equals(actual, expected, path); + } else { + if (expected.hasOwnProperty('length')) + assert_equals(actual.length, expected.length, path + '.length'); + for (property in expected) + assert_subset(actual[property], expected[property], path + '.' + property); + } + } + + function expect_config(keySystem, configurations, expectedConfiguration, testName) { + promise_test(function(test) { + return navigator.requestMediaKeySystemAccess(keySystem, configurations).then(function(a) { + assert_subset(a.getConfiguration(), expectedConfiguration, 'getConfiguration()'); + }); + }, testName); + } + + // Tests for keySystem. + expect_error('', [{}], 'InvalidAccessError', 'Empty keySystem'); + expect_error('com.example.unsupported', [{}], 'NotSupportedError', 'Unsupported keySystem'); + expect_error('org.w3.clearkey.', [{}], 'NotSupportedError', 'keySystem ends with "."'); + expect_error('org.w3.ClearKey', [{}], 'NotSupportedError', 'Capitalized keySystem'); + expect_error('org.w3.clearke\u028F', [{}], 'NotSupportedError', 'Non-ASCII keySystem'); + + // Parent of Clear Key not supported. + expect_error('org', [{}], 'NotSupportedError', 'Parent of Clear Key (org)'); + expect_error('org.', [{}], 'NotSupportedError', 'Parent of Clear Key (org.)'); + expect_error('org.w3', [{}], 'NotSupportedError', 'Parent of Clear Key (org.w3)'); + expect_error('org.w3.', [{}], 'NotSupportedError', 'Parent of Clear Key (org.w3.)'); + + // Child of Clear Key not supported. + expect_error('org.w3.clearkey.foo', [{}], 'NotSupportedError', 'Child of Clear Key'); + + // Prefixed Clear Key not supported. + expect_error('webkit-org.w3.clearkey', [{}], 'NotSupportedError', 'Prefixed Clear Key'); + + // Incomplete names. + expect_error('org.w3.learkey', [{}], 'NotSupportedError', 'Incomplete name org.w3.learkey'); + expect_error('org.w3.clearke', [{}], 'NotSupportedError', 'Incomplete name org.w3.clearke'); + expect_error('or.w3.clearkey', [{}], 'NotSupportedError', 'Incomplete name or.w3.clearkey'); + + // Spaces in key system name not supported. + expect_error(' org.w3.clearkey', [{}], 'NotSupportedError', 'Leading space in key system name'); + expect_error('org.w3. clearkey', [{}], 'NotSupportedError', 'Extra space in key system name'); + expect_error('org.w3.clearkey ', [{}], 'NotSupportedError', 'Trailing space in key system name'); + + // Extra dots in key systems names not supported. + expect_error('.org.w3.clearkey', [{}], 'NotSupportedError', 'Leading dot in key systems name'); + expect_error('org.w3.clearkey.', [{}], 'NotSupportedError', 'Trailing dot in key systems name'); + expect_error('org.w3..clearkey', [{}], 'NotSupportedError', 'Double dot in key systems name'); + expect_error('org.w3.clear.key', [{}], 'NotSupportedError', 'Extra dot in key systems name'); + + // Key system name is case sensitive. + expect_error('org.w3.Clearkey', [{}], 'NotSupportedError', 'Key system name is case sensitive'); + expect_error('Org.w3.clearkey', [{}], 'NotSupportedError', 'Key system name is case sensitive'); + + // Tests for trivial configurations. + expect_error('org.w3.clearkey', [], 'InvalidAccessError', 'Empty supportedConfigurations'); + expect_config('org.w3.clearkey', [{}], {}, 'Empty configuration'); + + // Various combinations of supportedConfigurations. + // TODO(jrummell): Specifying contentType without codecs is + // deprecated, so this test should fail. http://crbug.com/605661. + expect_config('org.w3.clearkey', [{ + initDataTypes: ['webm'], + audioCapabilities: [{contentType: 'audio/webm'}], + videoCapabilities: [{contentType: 'video/webm'}], + }], { + initDataTypes: ['webm'], + audioCapabilities: [{contentType: 'audio/webm'}], + videoCapabilities: [{contentType: 'video/webm'}], + }, 'Basic supported configuration'); + + // TODO(jrummell): Specifying contentType without codecs is + // deprecated, so this test should fail. http://crbug.com/605661. + expect_config('org.w3.clearkey', [{ + initDataTypes: ['fakeidt', 'webm'], + audioCapabilities: [{contentType: 'audio/fake'}, {contentType: 'audio/webm'}], + videoCapabilities: [{contentType: 'video/fake'}, {contentType: 'video/webm'}], + }], { + initDataTypes: ['webm'], + audioCapabilities: [{contentType: 'audio/webm'}], + videoCapabilities: [{contentType: 'video/webm'}], + }, 'Partially supported configuration'); + + expect_config('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'audio/webm; codecs=vorbis'}], + }], { + audioCapabilities: [{contentType: 'audio/webm; codecs=vorbis'}], + }, 'Supported audio codec'); + + expect_config('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'audio/webm; codecs="vorbis"'}], + }], { + audioCapabilities: [{contentType: 'audio/webm; codecs="vorbis"'}], + }, 'ContentType formatting must be preserved'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'audio/webm; codecs=fake'}], + }], 'NotSupportedError', 'Unsupported audio codec'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs=mp4a'}, + {contentType: 'audio/webm; codecs=mp4a.40.2'} + ], + }], 'NotSupportedError', 'Mismatched audio container/codec'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs=vp8'}], + }], { + videoCapabilities: [{contentType: 'video/webm; codecs=vp8'}], + }, 'Supported video codec'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'video/webm; codecs=vp8'}], + }], 'NotSupportedError', 'Video codec specified in audio field'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'audio/webm; codecs=vorbis'}], + }], 'NotSupportedError', 'Audio codec specified in video field'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'video/webm; codecs=fake'}], + }], 'NotSupportedError', 'Unsupported video codec'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs=avc1'}, + {contentType: 'audio/webm; codecs=avc1.42e01e'} + ], + }], 'NotSupportedError', 'Mismatched video container/codec'); + + expect_config('org.w3.clearkey', [ + {initDataTypes: ['fakeidt']}, + {initDataTypes: ['webm']} + ], {initDataTypes: ['webm']}, 'Two configurations, one supported'); + + expect_config('org.w3.clearkey', [ + {initDataTypes: ['webm']}, + {} + ], {initDataTypes: ['webm']}, 'Two configurations, both supported'); + + // Audio MIME type does not support video codecs. + expect_error('org.w3.clearkey', [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs="vp8,vorbis"'}, + {contentType: 'audio/webm; codecs="vorbis, vp8"'}, + {contentType: 'audio/webm; codecs="vp8"'} + ], + }], 'NotSupportedError', 'Audio MIME type does not support video codecs.'); + + // Video MIME type does not support audio codecs. + expect_error('org.w3.clearkey', [{ + videoCapabilities: [ + {contentType: 'video/webm; codecs="vp8,vorbis"'}, + {contentType: 'video/webm; codecs="vorbis, vp8"'}, + {contentType: 'video/webm; codecs="vorbis"'} + ], + }], 'NotSupportedError', 'Video MIME type does not support audio codecs.'); + + // WebM does not support AVC1/AAC. + expect_error('org.w3.clearkey', [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs="aac"'}, + {contentType: 'audio/webm; codecs="avc1"'}, + {contentType: 'audio/webm; codecs="vp8,aac"'} + ], + }], 'NotSupportedError', 'WebM audio does not support AVC1/AAC.'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [ + {contentType: 'video/webm; codecs="aac"'}, + {contentType: 'video/webm; codecs="avc1"'}, + {contentType: 'video/webm; codecs="vp8,aac"'} + ], + }], 'NotSupportedError', 'WebM video does not support AVC1/AAC.'); + + // Extra space is allowed in contentType. + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: ' video/webm; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: ' video/webm; codecs="vp8"'}], + }, 'Leading space in contentType'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm ; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/webm ; codecs="vp8"'}], + }, 'Space before ; in contentType'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/webm; codecs="vp8"'}], + }, 'Extra spaces after ; in contentType'); + + // TODO(jrummell): contentType should allow white space at the + // end of the string. http://crbug.com/487392 +// expect_config('org.w3.clearkey', [{ +// videoCapabilities: [{contentType: 'video/webm; codecs="vp8" '}], +// }], { +// videoCapabilities: [{contentType: 'video/webm; codecs="vp8" '}], +// }, 'Trailing space in contentType'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs=" vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/webm; codecs=" vp8"'}], + }, 'Space at start of codecs parameter'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs="vp8 "'}], + }], { + videoCapabilities: [{contentType: 'video/webm; codecs="vp8 "'}], + }, 'Space at end of codecs parameter'); + + // contentType is not case sensitive (except the codec names). + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'Video/webm; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'Video/webm; codecs="vp8"'}], + }, 'Video/webm'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/Webm; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/Webm; codecs="vp8"'}], + }, 'video/Webm'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; Codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/webm; Codecs="vp8"'}], + }, 'Codecs='); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'VIDEO/WEBM; codecs="vp8"'}], + }], { + videoCapabilities: [{contentType: 'VIDEO/WEBM; codecs="vp8"'}], + }, 'VIDEO/WEBM'); + + expect_config('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; CODECS="vp8"'}], + }], { + videoCapabilities: [{contentType: 'video/webm; CODECS="vp8"'}], + }, 'CODECS='); + + // Unrecognized attributes are not allowed. + // TODO(jrummell): Unrecognized attributes are ignored currently. + // http://crbug.com/449690 +// expect_error('org.w3.clearkey', [{ +// videoCapabilities: [{contentType: 'video/webm; foo="bar"'}], +// }], 'NotSupportedError', 'Unrecognized foo'); +// expect_error('org.w3.clearkey', [{ +// videoCapabilities: [{contentType: 'video/webm; foo="bar"; codecs="vp8"'}], +// }], 'NotSupportedError', 'Unrecognized foo with codecs'); + + // Invalid contentTypes. + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'fake'}], + }], 'NotSupportedError', 'contentType fake'); + + expect_error('org.w3.clearkey', [{ + audioCapabilities: [{contentType: 'audio/fake'}], + }], 'NotSupportedError', 'contentType audio/fake'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/fake'}], + }], 'NotSupportedError', 'contentType video/fake'); + + // The actual codec names are case sensitive. + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs="Vp8"'}], + }], 'NotSupportedError', 'codecs Vp8'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs="VP8"'}], + }], 'NotSupportedError', 'codecs VP8'); + + // Extra comma is not allowed in codecs. + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs=",vp8"'}], + }], 'NotSupportedError', 'Leading , in codecs'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs="vp8,"'}], + }], 'NotSupportedError', 'Trailing , in codecs'); + + expect_error('org.w3.clearkey', [{ + videoCapabilities: [{contentType: 'video/webm; codecs=",vp8,"'}], + }], 'NotSupportedError', 'Leading and trailing , in codecs'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-reset-src-after-setmediakeys.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-reset-src-after-setmediakeys.html new file mode 100644 index 000000000..15c91a001 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-reset-src-after-setmediakeys.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Reset src after setMediaKeys()</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var mediaKeys; + var encryptedEventIndex = 0; + var video = document.getElementById('testVideo'); + assert_not_equals(video, null); + + // Content to be played. These files must be the same format. + var content = 'webm/test-encrypted.webm'; + var alternateContent = 'webm/test-encrypted-different-av-keys.webm'; + + var onEncrypted = function(event) + { + ++encryptedEventIndex; + assert_not_equals(video.mediaKeys, null); + assert_true(video.mediaKeys === mediaKeys); + + // This event is fired once for the audio stream and once + // for the video stream each time .src is set. + if (encryptedEventIndex == 2) { + // Finished first video; set src to a different video. + video.src = alternateContent; + } else if (encryptedEventIndex == 4) { + // Finished second video. + test.done(); + } + }; + + // Create a MediaKeys object and assign it to video. + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)) + .then(function(access) { + assert_equals(access.keySystem, 'org.w3.clearkey'); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + assert_not_equals(mediaKeys, null); + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + assert_not_equals(video.mediaKeys, null, 'not set initially'); + assert_true(video.mediaKeys === mediaKeys); + + // Set src to a video. + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + video.src = content; + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Reset src after setMediaKeys().'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-session-closed-event.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-session-closed-event.html new file mode 100644 index 000000000..577047a25 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-session-closed-event.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test MediaKeySession closed event</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + // Wait for the session to be closed. + mediaKeySession.closed.then(function(result) { + assert_equals(result, undefined); + // Now that the session is closed, verify that the + // closed attribute immediately returns a fulfilled + // promise. + return mediaKeySession.closed; + }).then(function(result) { + assert_equals(result, undefined); + test.done(); + }); + + // release() should result in the closed promise being + // fulfilled. + return mediaKeySession.close(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Test MediaKeySession closed event.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-playback.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-playback.html new file mode 100644 index 000000000..29f53b31d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-playback.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys() again after playback</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + promise_test(function(test) + { + var video = document.getElementById('testVideo'); + var keyId = stringToUint8Array('0123456789012345'); + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var content = 'webm/test-encrypted.webm'; + var duration = 0.2; + + return createMediaKeys(keyId, rawKey).then(function(mediaKeys) { + return video.setMediaKeys(mediaKeys); + }).then(function() { + return playVideoAndWaitForTimeupdate(video, content, duration); + }).then(function() { + // Now create a second MediaKeys. + return createMediaKeys(keyId, rawKey); + }).then(function(mediaKeys) { + // video is currently playing, so should not be able to + // change MediaKeys now. + assert_false(video.ended); + return video.setMediaKeys(mediaKeys); + }).then(function() { + assert_unreached('Able to change MediaKeys while playing.'); + }, function(error) { + // Error expected. + assert_equals(error.name, 'InvalidStateError'); + return Promise.resolve('success'); + }); + }, 'setMediaKeys() again after playback'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-resetting-src.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-resetting-src.html new file mode 100644 index 000000000..8f6891b79 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-again-after-resetting-src.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys() again after resetting src</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + promise_test(function(test) + { + var video = document.getElementById('testVideo'); + var keyId = stringToUint8Array('0123456789012345'); + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + var content = 'webm/test-encrypted.webm'; + var duration = 0.2; + + return createMediaKeys(keyId, rawKey).then(function(mediaKeys) { + return video.setMediaKeys(mediaKeys); + }).then(function() { + return playVideoAndWaitForTimeupdate(video, content, duration); + }).then(function() { + // Now create a second MediaKeys and repeat. + return createMediaKeys(keyId, rawKey); + }).then(function(mediaKeys) { + // MediaKeys is use by previous video, so clear .src + // so that MediaKeys can be assigned. + video.src = ''; + return video.setMediaKeys(mediaKeys); + }).then(function() { + return playVideoAndWaitForTimeupdate(video, content, duration); + }); + }, 'setMediaKeys() again after resetting src'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-at-same-time.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-at-same-time.html new file mode 100644 index 000000000..01fd7b194 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-at-same-time.html @@ -0,0 +1,109 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Set MediaKeys multiple times in parallel</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="video"></video> + <div id="log"></div> + <script> + // Wait for an 'encrypted' event as a promise. + function wait_for_encrypted_event(video) + { + return new Promise(function(resolve) { + video.addEventListener('encrypted', function listener(e) { + video.removeEventListener('encrypted', listener); + resolve(); + }); + }); + }; + + // Return a promise that calls setMediaKeys() and returns 1 if + // resolved, 0 if rejected. If |must_succeed| is true, then + // setMediaKeys() should not fail. + function setMediaKeys_as_count(video, mediaKeys, must_succeed) + { + return video.setMediaKeys(mediaKeys).then(function() { + return 1; + }, function() { + assert_false(must_succeed); + return 0; + }); + }; + + // Return the sum of the results from |promises|. Each promise + // must return a number. + function count_promise_results(promises) + { + var count = 0; + var result = Promise.resolve(null); + + promises.forEach(function(promise) { + result = result.then(function() { + return promise; + }).then(function(i) { + count += i; + }); + }); + + return result.then(function() { return count; }); + }; + + promise_test(function(test) + { + var video = document.getElementById('video'); + var content = 'webm/test-encrypted.webm'; + var access; + var mediaKeys1; + var mediaKeys2; + var mediaKeys3; + var mediaKeys4; + var mediaKeys5; + + // Start a video now so that it is waiting for MediaKeys + // in order to continue. + video.src = content; + video.play(); + return wait_for_encrypted_event(video).then(function() { + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)); + }).then(function(result) { + access = result; + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys1 = result; + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys2 = result; + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys3 = result; + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys4 = result; + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys5 = result; + // Create 5 calls to setMediaKeys(). The first one must + // succeed, the others are optional. + var p1 = setMediaKeys_as_count(video, mediaKeys1, true); + var p2 = setMediaKeys_as_count(video, mediaKeys2, false); + var p3 = setMediaKeys_as_count(video, mediaKeys3, false); + var p4 = setMediaKeys_as_count(video, mediaKeys4, false); + var p5 = setMediaKeys_as_count(video, mediaKeys5, false); + return count_promise_results([p1, p2, p3, p4, p5]); + }).then(function(count) { + // At least one of the setMediaKeys() calls should have + // succeeded. + assert_greater_than(count, 0); + }); + }, 'Set MediaKeys multiple times in parallel.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-different-mediakeys.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-different-mediakeys.html new file mode 100644 index 000000000..31cc61079 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-different-mediakeys.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys() multiple times with different MediaKeys.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="video"></video> + <div id="log"></div> + <script> + promise_test(function(test) + { + var video = document.getElementById('video'); + var content = 'webm/test-encrypted.webm'; + var keySystemAccess; + var mediaKeys1; + var mediaKeys2; + + assert_equals(video.mediaKeys, null); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + keySystemAccess = access; + // Create a mediaKeys. + return keySystemAccess.createMediaKeys(); + }).then(function(result) { + mediaKeys1 = result; + assert_not_equals(mediaKeys1, null); + // Create a second mediaKeys. + return keySystemAccess.createMediaKeys(); + }).then(function(result) { + mediaKeys2 = result; + assert_not_equals(mediaKeys2, null); + // Set mediaKeys1 on video. + return video.setMediaKeys(mediaKeys1); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys1); + // Set mediaKeys2 on video (switching MediaKeys). + return video.setMediaKeys(mediaKeys2); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys2); + // Clear mediaKeys from video. + return video.setMediaKeys(null); + }).then(function() { + assert_equals(video.mediaKeys, null); + // Set mediaKeys1 on video again. + return video.setMediaKeys(mediaKeys1); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys1); + // Load the media element to create the WebMediaPlayer. + video.src = content; + // Set mediaKeys2 on video (switching MediaKeys) not + // supported after WebMediaPlayer is created. + return video.setMediaKeys(mediaKeys2); + }).then(function() { + assert_unreached('Switching mediaKeys after setting src should have failed.'); + }, function(error) { + assert_true(video.mediaKeys === mediaKeys1); + assert_equals(error.name, 'InvalidStateError'); + assert_not_equals(error.message, ''); + // Return something so the promise resolves properly. + return Promise.resolve(); + }).then(function() { + // Set null mediaKeys on video (clearing MediaKeys) not + // supported after WebMediaPlayer is created. + return video.setMediaKeys(null); + }).then(function() { + assert_unreached('Clearing mediaKeys after setting src should have failed.'); + }, function(error) { + assert_true(video.mediaKeys === mediaKeys1); + assert_equals(error.name, 'InvalidStateError'); + assert_not_equals(error.message, ''); + return Promise.resolve(); + }); + }, 'setMediaKeys() multiple times with different MediaKeys.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-the-same-mediakeys.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-the-same-mediakeys.html new file mode 100644 index 000000000..64ed315e0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-multiple-times-with-the-same-mediakeys.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys() multiple times with the same MediaKeys.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="video"></video> + <div id="log"></div> + <script> + promise_test(function(test) + { + var video = document.getElementById('video'); + var content = 'webm/test-encrypted.webm'; + var mediaKeys; + + assert_equals(video.mediaKeys, null); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + assert_not_equals(mediaKeys, null); + // Set mediaKeys on video should work. + return video.setMediaKeys(mediaKeys); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys); + // Set mediaKeys on video again should return a resolved + // promise. + return video.setMediaKeys(mediaKeys); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys); + // Load the media element to create the WebMediaPlayer. + video.src = content; + // Set mediaKeys again on video should still return a + // resolved promise. + return video.setMediaKeys(mediaKeys); + }).then(function() { + assert_true(video.mediaKeys === mediaKeys); + }); + }, 'setMediaKeys() multiple times with the same MediaKeys.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-to-multiple-video-elements.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-to-multiple-video-elements.html new file mode 100644 index 000000000..fb8386e8c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys-to-multiple-video-elements.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys() on multiple video elements.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="video1"></video> + <video id="video2"></video> + <div id="log"></div> + <script> + promise_test(function(test) + { + var video1 = document.getElementById('video1'); + var video2 = document.getElementById('video2'); + var mediaKeys; + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + // Assignment to video1 should work. + return video1.setMediaKeys(mediaKeys); + }).then(function() { + // Assignment to video2 should fail. + return video2.setMediaKeys(mediaKeys); + }).then(function() { + assert_unreached('Second setMediaKeys should have failed.'); + }, function(error) { + assert_equals(error.name, 'QuotaExceededError'); + assert_not_equals(error.message, ''); + // Return something so the promise resolves properly. + return Promise.resolve(); + }).then(function() { + // Now clear it from video1. + return video1.setMediaKeys(null); + }).then(function() { + // Should be assignable to video2. + return video2.setMediaKeys(mediaKeys); + }); + }, 'setMediaKeys() on multiple video elements.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys.html new file mode 100644 index 000000000..96b0fed97 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-setmediakeys.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>setMediaKeys</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="video"></video> + <div id="log"></div> + <script> + async_test(function(test) + { + var mediaKeys; + var video = document.getElementById('video'); + assert_not_equals(video, null); + + // Test MediaKeys assignment. + assert_equals(video.mediaKeys, null); + assert_equals(typeof video.setMediaKeys, 'function'); + + // Try setting mediaKeys to null. + video.setMediaKeys(null).then(function(result) { + assert_equals(video.mediaKeys, null); + + // Try setting mediaKeys to the wrong type of object. + return video.setMediaKeys(new Date()); + }).then(function(result) { + assert_unreached('setMediaKeys did not fail when setting to Date()'); + }, function(error) { + // TypeError expected. + assert_equals(error.name, 'TypeError'); + + // Create a MediaKeys object and assign it to video. + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()); + }).then(function(access) { + assert_equals(access.keySystem, 'org.w3.clearkey'); + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + assert_not_equals(mediaKeys, null); + assert_equals(typeof mediaKeys.createSession, 'function'); + return video.setMediaKeys(mediaKeys); + }).then(function(result) { + assert_not_equals(video.mediaKeys, null); + assert_true(video.mediaKeys === mediaKeys); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error); + }); + }, 'Setting MediaKeys on a video object.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-syntax.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-syntax.html new file mode 100644 index 000000000..5c4c667cb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-syntax.html @@ -0,0 +1,1017 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test EME syntax</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <script> + // Since promises catch any exception and convert it into a + // rejected Promise, there is no current way to have the W3C + // test framework report a failed test. For now, simply force + // a timeout to indicate failure. + // FIXME: Once W3C test framework handles Promises, fix this. + + // This function checks that calling |testCase.func| returns a + // rejected Promise with the error.name equal to + // |testCase.exception|. + function test_exception(testCase /*...*/) + { + var func = testCase.func; + var exception = testCase.exception; + var args = Array.prototype.slice.call(arguments, 1); + + // Currently blink throws for TypeErrors rather than returning + // a rejected promise (http://crbug.com/359386). + // FIXME: Remove try/catch once they become failed promises. + try { + return func.apply(null, args).then( + function(result) + { + assert_unreached(format_value(func)); + }, + function(error) + { + assert_equals(error.name, exception, format_value(func)); + assert_not_equals(error.message, "", format_value(func)); + } + ); + } catch (e) { + // Only allow 'TypeError' exceptions to be thrown. + // Everything else should be a failed promise. + assert_equals('TypeError', exception, format_value(func)); + assert_equals(e.name, exception, format_value(func)); + } + } + + var kRequestMediaKeySystemAccessExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess(); } + }, + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey'); } + }, + // Invalid key systems. Note that JavaScript converts all these + // values into strings by calling toString(), so they fail due + // to the key system not being supported, not due to the type. + { + exception: 'NotSupportedError', + func: function() { return navigator.requestMediaKeySystemAccess(null, [{}]); } + }, + { + exception: 'NotSupportedError', + func: function() { return navigator.requestMediaKeySystemAccess(undefined, [{}]); } + }, + { + exception: 'NotSupportedError', + func: function() { return navigator.requestMediaKeySystemAccess(1, [{}]); } + }, + { + exception: 'InvalidAccessError', + func: function() { return navigator.requestMediaKeySystemAccess(new Uint8Array(0), [{}]); } + }, + { + exception: 'InvalidAccessError', + func: function() { return navigator.requestMediaKeySystemAccess('', [{}]); } + }, + { + exception: 'NotSupportedError', + func: function() { return navigator.requestMediaKeySystemAccess('unsupported', [{}]); } + }, + // Non-ASCII names. + { + exception: 'NotSupportedError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3\u263A.clearkey', [{}]); } + }, + // Empty sequence of MediaKeySystemConfiguration. + { + exception: 'InvalidAccessError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey', []); } + }, + // Invalid sequences of MediaKeySystemConfigurations. + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey', {}); } + }, + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey', "invalid"); } + }, + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}, 6]); } + }, + { + exception: 'TypeError', + func: function() { return navigator.requestMediaKeySystemAccess('org.w3.clearkey', ["invalid", "upsupported"]); } + } + ]; + + async_test(function(test) + { + var createPromises = kRequestMediaKeySystemAccessExceptionsTestCases.map(function(testCase) { + return test_exception(testCase); + }); + + Promise.all(createPromises).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'requestMediaKeySystemAccess() tests failed'); + }); + }, 'Test Navigator.requestMediaKeySystemAccess() exceptions.'); + + async_test(function(test) + { + assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function'); + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + assert_not_equals(access, null); + assert_equals(typeof access, 'object'); + assert_equals(access.keySystem, 'org.w3.clearkey'); + assert_equals(typeof access.getConfiguration, 'function'); + assert_equals(typeof access.createMediaKeys, 'function'); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'requestMediaKeySystemAccess() tests failed'); + }); + }, 'Test Navigator.requestMediaKeySystemAccess().'); + + async_test(function(test) + { + var access; + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(result) { + access = result; + assert_equals(access.keySystem, 'org.w3.clearkey'); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + assert_not_equals(mediaKeys, null); + assert_equals(typeof mediaKeys, 'object'); + assert_equals(typeof mediaKeys.createSession, 'function'); + assert_equals(typeof mediaKeys.setServerCertificate, 'function'); + + // Test creation of a second MediaKeys. + // The extra parameter is ignored. + return access.createMediaKeys('extra'); + }).then(function(mediaKeys) { + assert_not_equals(mediaKeys, null); + assert_equals(typeof mediaKeys, 'object'); + assert_equals(typeof mediaKeys.createSession, 'function'); + assert_equals(typeof mediaKeys.setServerCertificate, 'function'); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'create() tests failed'); + }); + }, 'Test MediaKeySystemAccess createMediaKeys().'); + + var kCreateSessionExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name the first 60 characters is not + // enough to determine which test failed. + + // Invalid parameters. + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(''); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(null); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(undefined); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(1); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession(new Uint8Array(0)); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.createSession('TEMPORARY'); } + } + ]; + + // This function checks that calling createSession() with an + // unsupported session type doesn't create a MediaKeySession object. + // Since requestMediaKeySystemAccess() is called without specifying + // persistent sessions, only temporary sessions will be allowed. + function test_unsupported_sessionType(mediaKeys) + { + var mediaKeySession = 'test'; + + try { + mediaKeySession = mediaKeys.createSession('persistent-license'); + assert_unreached('Session should not be created.'); + } catch (error) { + assert_equals(error.name, 'NotSupportedError'); + assert_not_equals(error.message, ""); + + // Since createSession() failed, |mediaKeySession| is not + // touched. + assert_equals(mediaKeySession, 'test'); + } + } + + async_test(function(test) + { + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var sessionPromises = kCreateSessionExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys); + }); + sessionPromises = sessionPromises.concat(test_unsupported_sessionType(mediaKeys)); + + assert_not_equals(sessionPromises.length, 0); + return Promise.all(sessionPromises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'createSession() tests failed'); + }); + }, 'Test MediaKeys createSession() exceptions.'); + + var kGenerateRequestExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name the first 60 characters is not + // enough to determine which test failed. Even with the + // shortened name, the error message for the last couple of + // tests is the same. + // Too few parameters. + { + exception: 'TypeError', + func: function(mk1) { return mk1.createSession().generateRequest(); } + }, + { + exception: 'TypeError', + func: function(mk2) { return mk2.createSession().generateRequest(''); } + }, + { + exception: 'TypeError', + func: function(mk3) { return mk3.createSession().generateRequest(null); } + }, + { + exception: 'TypeError', + func: function(mk4) { return mk4.createSession().generateRequest(undefined); } + }, + { + exception: 'TypeError', + func: function(mk5) { return mk5.createSession().generateRequest(1); } + }, + { + exception: 'TypeError', + func: function(mk6) { return mk6.createSession().generateRequest(new Uint8Array(0)); } + }, + { + exception: 'TypeError', + func: function(mk7, _, initData) { return mk7.createSession().generateRequest(initData); } + }, + // Invalid parameters. + { + exception: 'InvalidAccessError', + func: function(mk8, _, initData) { return mk8.createSession().generateRequest('', initData); } + }, + // Not supported initDataTypes. + { + exception: 'NotSupportedError', + func: function(mk9, _, initData) { return mk9.createSession().generateRequest(null, initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk10, _, initData) { return mk10.createSession().generateRequest(undefined, initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk11, _, initData) { return mk11.createSession().generateRequest(1, initData); } + }, + { + exception: 'InvalidAccessError', + func: function(mk12, _, initData) { return mk12.createSession().generateRequest(new Uint8Array(0), initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk13, _, initData) { return mk13.createSession().generateRequest('unsupported', initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk14, _, initData) { return mk14.createSession().generateRequest('video/webm', initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk15, _, initData) { return mk15.createSession().generateRequest('video/mp4', initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk16, _, initData) { return mk16.createSession().generateRequest('video/cenc', initData); } + }, + { + exception: 'NotSupportedError', + func: function(mk17, _, initData) { return mk17.createSession().generateRequest('web\u263A', initData); } + } + ]; + + var kTypeSpecificGenerateRequestExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name the first 60 characters is not + // enough to determine which test failed. Even with the + // shortened name, the error message for the last couple of + // tests is the same. + + // Too few parameters. + { + exception: 'TypeError', + func: function(mk1, type) { return mk1.createSession().generateRequest(type); } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function(mk2, type) { return mk2.createSession().generateRequest(type, ''); } + }, + { + exception: 'TypeError', + func: function(mk3, type) { return mk3.createSession().generateRequest(type, null); } + }, + { + exception: 'TypeError', + func: function(mk4, type) { return mk4.createSession().generateRequest(type, undefined); } + }, + { + exception: 'TypeError', + func: function(mk5, type) { return mk5.createSession().generateRequest(type, 1); } + }, + { + exception: 'InvalidAccessError', + func: function(mk6, type) { return mk6.createSession().generateRequest(type, new Uint8Array(0)); } + } + ]; + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var initData = stringToUint8Array('init data'); + var sessionPromises = kGenerateRequestExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys, '', initData); + }); + + // Test that WebM sessions generate the expected error, if + // supported. + if (isWebmSupported) { + var WebmSessionPromises = kTypeSpecificGenerateRequestExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys, 'webm', getInitData('webm')); + }); + sessionPromises = sessionPromises.concat(WebmSessionPromises); + } + + // Repeat for MP4, if supported. + if (isCencSupported) { + var mp4SessionPromises = kTypeSpecificGenerateRequestExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys, 'cenc', getInitData('cenc')); + }); + sessionPromises = sessionPromises.concat(mp4SessionPromises); + } + + assert_not_equals(sessionPromises.length, 0); + return Promise.all(sessionPromises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'generateRequest() tests failed'); + }); + }, 'Test MediaKeys generateRequest() exceptions.'); + + var kLoadExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function(mk1) { return mk1.createSession('temporary').load(); } + }, + // 'temporary' sessions are never allowed, so always return + // 'InvalidAccessError'. + { + exception: 'InvalidAccessError', + func: function(mk3) { return mk3.createSession('temporary').load(''); } + }, + { + exception: 'InvalidAccessError', + func: function(mk4) { return mk4.createSession('temporary').load(1); } + }, + { + exception: 'InvalidAccessError', + func: function(mk5) { return mk5.createSession('temporary').load('!@#$%^&*()'); } + }, + { + exception: 'InvalidAccessError', + func: function(mk6) { return mk6.createSession('temporary').load('1234'); } + } + ]; + + async_test(function(test) + { + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var initData = stringToUint8Array('init data'); + var sessionPromises = kLoadExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys); + }); + + assert_not_equals(sessionPromises.length, 0); + return Promise.all(sessionPromises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'load() tests failed'); + }); + }, 'Test MediaKeys load() exceptions.'); + + // All calls to |func| in this group are supposed to succeed. + // However, the spec notes that some things are optional for + // Clear Key. In particular, support for persistent sessions + // is optional. Since some implementations won't support some + // features, a NotSupportedError is treated as a success + // if |isNotSupportedAllowed| is true. + var kCreateSessionTestCases = [ + // Use the default sessionType. + { + func: function(mk) { return mk.createSession(); }, + isNotSupportedAllowed: false + }, + // Try variations of sessionType. + { + func: function(mk) { return mk.createSession('temporary'); }, + isNotSupportedAllowed: false + }, + { + func: function(mk) { return mk.createSession(undefined); }, + isNotSupportedAllowed: false + }, + { + // Since this is optional, some Clear Key implementations + // will succeed, others will return a "NotSupportedError". + // Both are allowed results. + func: function(mk) { return mk.createSession('persistent-license'); }, + isNotSupportedAllowed: true + }, + // Try additional parameter, which should be ignored. + { + func: function(mk) { return mk.createSession('temporary', 'extra'); }, + isNotSupportedAllowed: false + } + ]; + + // This function checks that calling |testCase.func| creates a + // MediaKeySession object with some default values. It also + // allows for an NotSupportedError to be generated and treated as a + // success, if allowed. See comment above kCreateSessionTestCases. + function test_createSession(testCase, mediaKeys) + { + var mediaKeySession; + try { + mediaKeySession = testCase.func.call(null, mediaKeys); + } catch (e) { + assert_true(testCase.isNotSupportedAllowed); + return; + } + + assert_equals(typeof mediaKeySession, 'object'); + assert_equals(typeof mediaKeySession.addEventListener, 'function'); + assert_equals(typeof mediaKeySession.sessionId, 'string'); + assert_equals(typeof mediaKeySession.expiration, 'number'); + assert_equals(typeof mediaKeySession.closed, 'object'); + assert_equals(typeof mediaKeySession.keyStatuses, 'object'); + assert_equals(typeof mediaKeySession.onkeystatuseschange, 'object'); + assert_equals(typeof mediaKeySession.onmessage, 'object'); + assert_equals(typeof mediaKeySession.generateRequest, 'function'); + assert_equals(typeof mediaKeySession.load, 'function'); + assert_equals(typeof mediaKeySession.update, 'function'); + assert_equals(typeof mediaKeySession.close, 'function'); + assert_equals(typeof mediaKeySession.remove, 'function'); + assert_equals(mediaKeySession.sessionId, ''); + assert_equals(typeof mediaKeySession.onopen, 'undefined'); + assert_equals(typeof mediaKeySession.onclose, 'undefined'); + assert_equals(typeof mediaKeySession.onerror, 'undefined'); + } + + async_test(function(test) + { + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + kCreateSessionTestCases.map(function(testCase) { + test_createSession(testCase, mediaKeys); + }); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'createSession() tests failed'); + }); + }, 'Test MediaKeys createSession().'); + + // This function checks that calling generateRequest() works for + // various sessions. |testCase.func| creates a MediaKeySession + // object, and then generateRequest() is called on that object. It + // allows for an NotSupportedError to be generated and treated as a + // success, if allowed. See comment above kCreateSessionTestCases. + function test_generateRequest(testCase, mediaKeys, type, initData) + { + try { + var mediaKeySession = testCase.func.call(null, mediaKeys); + return mediaKeySession.generateRequest(type, initData); + } catch (e) { + assert_true(testCase.isNotSupportedAllowed); + } + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var sessionPromises = []; + + // Test that WebM sessions generate the expected error, if + // supported. + if (isWebmSupported) { + var WebmSessionPromises = kCreateSessionTestCases.map(function(testCase) { + return test_generateRequest(testCase, mediaKeys, 'webm', getInitData('webm')); + }); + sessionPromises = sessionPromises.concat(WebmSessionPromises); + } + + // Repeat for MP4, if supported. + if (isCencSupported) { + var mp4SessionPromises = kCreateSessionTestCases.map(function(testCase) { + return test_generateRequest(testCase, mediaKeys, 'cenc', getInitData('cenc')); + }); + sessionPromises = sessionPromises.concat(mp4SessionPromises); + } + + assert_not_equals(sessionPromises.length, 0); + return Promise.all(sessionPromises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'generateRequest() tests failed'); + }); + }, 'Test MediaKeys generateRequest().'); + + var kUpdateSessionExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name (mediaKeySession) the first 60 + // characters is not enough to determine which test failed. + + // Too few parameters. + { + exception: 'TypeError', + func: function(s) { return s.update(); } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function(s) { return s.update(''); } + }, + { + exception: 'TypeError', + func: function(s) { return s.update(null); } + }, + { + exception: 'TypeError', + func: function(s) { return s.update(undefined); } + }, + { + exception: 'TypeError', + func: function(s) { return s.update(1); } + }, + { + exception: 'InvalidAccessError', + func: function(s) { return s.update(new Uint8Array(0)); } + } + ]; + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + var WebmSessionPromises = kUpdateSessionExceptionsTestCases.map(function(testCase) { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest('webm', getInitData('webm')).then(function(result) { + return test_exception(testCase, mediaKeySession); + }); + }); + promises = promises.concat(WebmSessionPromises); + } + + if (isCencSupported) { + var mp4SessionPromises = kUpdateSessionExceptionsTestCases.map(function(testCase) { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest('cenc', getInitData('cenc')).then(function(result) { + return test_exception(testCase, mediaKeySession); + }); + }); + promises = promises.concat(mp4SessionPromises); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'update() tests failed'); + }); + }, 'Test MediaKeySession update() exceptions.'); + + function create_update_test(mediaKeys, type, initData) + { + var mediaKeySession = mediaKeys.createSession(); + var promise = mediaKeySession.generateRequest(type, initData).then(function(result) { + var validLicense = stringToUint8Array(createJWKSet(createJWK(stringToUint8Array('123'), stringToUint8Array('1234567890abcdef')))); + return mediaKeySession.update(validLicense); + }).then(function(result) { + // Call update() with a different license and an extra + // parameter. The extra parameter is ignored. + var validLicense = stringToUint8Array(createJWKSet(createJWK(stringToUint8Array('4567890'), stringToUint8Array('01234567890abcde')))); + return mediaKeySession.update(validLicense, 'extra'); + }); + return promise; + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + promises.push(create_update_test(mediaKeys, 'webm', getInitData('webm'))); + } + + if (isCencSupported) { + promises.push(create_update_test(mediaKeys, 'cenc', getInitData('cenc'))); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'update() tests failed'); + }); + }, 'Test MediaKeySession update().'); + + function create_close_exception_test(mediaKeys, type, initData) + { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.close().then(function(result) { + assert_unreached('close() should not succeed if session uninitialized'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + // Return something so the promise resolves. + return Promise.resolve(); + }); + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + promises.push(create_close_exception_test(mediaKeys, 'webm', getInitData('webm'))); + } + + if (isCencSupported) { + promises.push(create_close_exception_test(mediaKeys, 'cenc', getInitData('cenc'))); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'close() exception tests failed'); + }); + }, 'Test MediaKeySession close() exceptions.'); + + + function create_close_test(mediaKeys, type, initData) + { + var mediaKeySession = mediaKeys.createSession(); + var promise = mediaKeySession.generateRequest(type, initData).then(function(result) { + return mediaKeySession.close(); + }).then(function(result) { + // Call close() again with an extra parameter. The extra + // parameter is ignored. + return mediaKeySession.close('extra'); + }); + return promise; + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + promises.push(create_close_test(mediaKeys, 'webm', getInitData('webm'))); + } + + if (isCencSupported) { + promises.push(create_close_test(mediaKeys, 'cenc', getInitData('cenc'))); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'close() tests failed'); + }); + }, 'Test MediaKeySession close().'); + + function create_remove_exception_test(mediaKeys, type, initData) + { + // remove() on an uninitialized session should fail. + var mediaKeySession = mediaKeys.createSession('temporary'); + return mediaKeySession.remove().then(function(result) { + assert_unreached('remove() should not succeed if session uninitialized'); + }, function(error) { + assert_equals(error.name, 'InvalidStateError'); + + // remove() on a temporary session should fail. + return mediaKeySession.generateRequest(type, initData); + }).then(function(result) { + return mediaKeySession.remove(); + }).then(function(result) { + assert_unreached('remove() should not succeed for temporary sessions'); + }, function(error) { + assert_equals(error.name, 'InvalidAccessError'); + }); + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + promises.push(create_remove_exception_test(mediaKeys, 'webm', getInitData('webm'))); + } + + if (isCencSupported) { + promises.push(create_remove_exception_test(mediaKeys, 'cenc', getInitData('cenc'))); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'remove() exception tests failed'); + }); + }, 'Test MediaKeySession remove() exceptions.'); + + function create_remove_test(mediaKeys, type, initData) + { + // Clear Key may not support persistent-license sessions. + var mediaKeySession; + try { + mediaKeySession = mediaKeys.createSession('persistent-license'); + } catch (error) { + // Not supported, so return a resolved promise. + assert_equals(error.name, 'NotSupportedError'); + return Promise.resolve(); + } + return mediaKeySession.generateRequest(type, initData).then(function(result) { + return mediaKeySession.remove(); + }); + } + + async_test(function(test) + { + var isWebmSupported; + var isCencSupported; + + isInitDataTypeSupported('webm').then(function(result) { + isWebmSupported = result; + return isInitDataTypeSupported('cenc'); + }).then(function(result) { + isCencSupported = result; + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); + }).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = []; + + if (isWebmSupported) { + promises.push(create_remove_test(mediaKeys, 'webm', getInitData('webm'))); + } + + if (isCencSupported) { + promises.push(create_remove_test(mediaKeys, 'cenc', getInitData('cenc'))); + } + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'remove() tests failed'); + }); + }, 'Test MediaKeySession remove().'); + + var kSetServerCertificateExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function(mk) { return mk.setServerCertificate(); } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function(mk) { return mk.setServerCertificate(''); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.setServerCertificate(null); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.setServerCertificate(undefined); } + }, + { + exception: 'TypeError', + func: function(mk) { return mk.setServerCertificate(1); } + }, + // Empty array. + { + exception: 'InvalidAccessError', + func: function(mk) { return mk.setServerCertificate(new Uint8Array(0)); } + } + ]; + + async_test(function(test) + { + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = kSetServerCertificateExceptionsTestCases.map(function(testCase) { + return test_exception(testCase, mediaKeys); + }); + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'setServerCertificate() exception tests failed'); + }); + }, 'Test MediaKeys setServerCertificate() exceptions.'); + + // All calls to |func| in this group are expected to resolve. + var kSetServerCertificateTestCases = [ + { + // Pass in ArrayBufferView + func: function(mk) { + var cert = new Uint8Array(200); + assert_true(ArrayBuffer.isView(cert)); + return mk.setServerCertificate(cert); + }, + expected: false, + }, + { + // Pass in ArrayBuffer + func: function(mk) { + var buffer = new ArrayBuffer(200); + assert_false(ArrayBuffer.isView(buffer)); + return mk.setServerCertificate(buffer); + }, + expected: false, + } + ]; + + async_test(function(test) + { + var expected_result; + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var promises = kSetServerCertificateTestCases.map(function(testCase) { + return testCase.func.call(null, mediaKeys); + }); + expected_result = kSetServerCertificateTestCases.map(function(testCase) { + return testCase.expected; + }); + + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function(result) { + assert_array_equals(result, expected_result); + test.done(); + }).catch(function(error) { + forceTestFailureFromPromise(test, error, 'setServerCertificate() test failed'); + }); + }, 'Test MediaKeys setServerCertificate().'); + + + // FIXME: Add syntax checks for MediaKeys.IsTypeSupported(). + // FIXME: Add syntax checks for MediaKeyError and MediaKeySession events. + // FIXME: Add HTMLMediaElement syntax checks, e.g. setMediaKeys, mediakeys, onencrypted. + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-unique-origin.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-unique-origin.html new file mode 100644 index 000000000..ffb67679f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-unique-origin.html @@ -0,0 +1,79 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Unique origin is unable to create MediaKeys</title> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // When the sandbox attribute is present on an iframe, it will + // treat the content as being from a unique origin. So try to + // call createMediaKeys() inside an iframe and it should fail. + + function load_iframe(src, sandbox) { + return new Promise(function(resolve) { + var iframe = document.createElement('iframe'); + iframe.onload = function() { resolve(iframe); }; + iframe.sandbox = sandbox; + iframe.src = src; + document.documentElement.appendChild(iframe); + }); + } + + function wait_for_message() { + return new Promise(function(resolve) { + self.addEventListener('message', function listener(e) { + resolve(e.data); + self.removeEventListener('message', listener); + }); + }); + } + + promise_test(function(test) { + var script = 'data:text/html,' + + '<script>' + + ' window.onmessage = function(e) {' + + ' navigator.requestMediaKeySystemAccess(\'org.w3.clearkey\', [{' + + ' initDataTypes: [ \'keyids\' ],' + + ' audioCapabilities: [' + + ' { contentType: \'audio/mp4; codecs="mp4a.40.2"\' },' + + ' { contentType: \'audio/webm; codecs="opus"\' }' + + ' ]' + + ' }]).then(function(access) {' + + ' return access.createMediaKeys();' + + ' }).then(function(mediaKeys) {' + + ' window.parent.postMessage({result: \'allowed\'}, \'*\');' + + ' }, function(error) {' + + ' window.parent.postMessage({result: \'failed\'}, \'*\');' + + ' });' + + ' };' + + '<\/script>'; + + // Verify that this page can create a MediaKeys first. + navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{ + initDataTypes: [ 'keyids' ], + audioCapabilities: [ + { contentType: 'audio/mp4; codecs="mp4a.40.2"' }, + { contentType: 'audio/webm; codecs="opus"' } + ] + }]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + // Success, so now create the iframe and try there. + return load_iframe(script, 'allow-scripts') + }).then(function(iframe) { + iframe.contentWindow.postMessage({}, '*'); + return wait_for_message(); + }).then(function(message) { + assert_equals(message.result, 'failed'); + }); + }, 'Unique origin is unable to create MediaKeys'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-update-disallowed-input.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-update-disallowed-input.html new file mode 100644 index 000000000..e829a885c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-update-disallowed-input.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Test handling of invalid responses for update().</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <div id="log"></div> + <script> + // This test passes |response| to update() as a JSON Web Key Set. + // CDMs other than Clear Key won't expect |response| in this format. + + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + + function repeat(pattern, count) { + var result = ''; + while (count > 1) { + if (count & 1) result += pattern; + count >>= 1; + pattern += pattern; + } + return result + pattern; + } + + function createReallyLongJWKSet() + { + // This is just a standard JWKSet with a lot of + // extra items added to the end. Key ID and key + // doesn't really matter. + var jwkSet = '{"keys":[{' + + '"kty":"oct",' + + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",' + + '"kid":"MDEyMzQ1Njc4OTAxMjM0NQ"' + + '}]'; + return jwkSet + repeat(',"test":"unknown"', 4000) + '}'; + } + + function processMessage(event) + { + var jwkSet = createReallyLongJWKSet(); + assert_greater_than(jwkSet.length, 65536); + var jwkSetArray = stringToUint8Array(jwkSet); + mediaKeySession.update(jwkSetArray).then(function() { + forceTestFailureFromPromise(test, 'Error: update() succeeded'); + }, function(error) { + assert_equals(error.name, 'InvalidAccessError'); + test.done(); + }); + } + + navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, processMessage, test); + return mediaKeySession.generateRequest(initDataType, initData); + }); + }, 'update() with response longer than 64Kb characters.'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-utils.js b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-utils.js new file mode 100644 index 000000000..5fbcdf689 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-utils.js @@ -0,0 +1,333 @@ +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> + +var consoleDiv = null; + +function consoleWrite(text) +{ + if (!consoleDiv && document.body) { + consoleDiv = document.createElement('div'); + document.body.appendChild(consoleDiv); + } + var span = document.createElement('span'); + span.appendChild(document.createTextNode(text)); + span.appendChild(document.createElement('br')); + consoleDiv.appendChild(span); +} + +// Returns a promise that is fulfilled with true if |initDataType| is supported, +// or false if not. +function isInitDataTypeSupported(initDataType) +{ + return navigator.requestMediaKeySystemAccess( + "org.w3.clearkey", getSimpleConfigurationForInitDataType(initDataType)) + .then(function() { return true; }, function() { return false; }); +} + +function getInitData(initDataType) +{ + if (initDataType == 'webm') { + return new Uint8Array([ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + ]); + } + + if (initDataType == 'cenc') { + return new Uint8Array([ + 0x00, 0x00, 0x00, 0x34, // size = 52 + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x01, // version = 1 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x01, // key count + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // key + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + } + + if (initDataType == 'keyids') { + var keyId = new Uint8Array([ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + ]); + return stringToUint8Array(createKeyIDs(keyId)); + } + + throw 'initDataType ' + initDataType + ' not supported.'; +} + +// Returns an array of audioCapabilities that includes entries for a set of +// codecs that should cover all user agents. +function getPossibleAudioCapabilities() +{ + return [ + { contentType: 'audio/mp4; codecs="mp4a.40.2"' }, + { contentType: 'audio/webm; codecs="opus"' }, + ]; +} + +// Returns a trivial MediaKeySystemConfiguration that should be accepted, +// possibly as a subset of the specified capabilities, by all user agents. +function getSimpleConfiguration() +{ + return [ { + initDataTypes : [ 'webm', 'cenc', 'keyids' ], + audioCapabilities: getPossibleAudioCapabilities() + } ]; +} + +// Returns a MediaKeySystemConfiguration for |initDataType| that should be +// accepted, possibly as a subset of the specified capabilities, by all +// user agents. +function getSimpleConfigurationForInitDataType(initDataType) +{ + return [ { + initDataTypes: [ initDataType ], + audioCapabilities: getPossibleAudioCapabilities() + } ]; +} + +// Returns a MediaKeySystemConfiguration for |mediaFile| that specifies +// both audio and video capabilities for the specified file.. +function getConfigurationForFile(mediaFile) +{ + if (mediaFile.toLowerCase().endsWith('webm')) { + return [ { + initDataTypes: [ 'webm' ], + audioCapabilities: [ { contentType: 'audio/webm; codecs="opus"' } ], + videoCapabilities: [ { contentType: 'video/webm; codecs="vp8"' } ] + } ]; + } + + // NOTE: Supporting other mediaFormats is not currently implemented as + // Chromium only tests with WebM files. + throw 'mediaFile ' + mediaFile + ' not supported.'; +} + +function waitForEventAndRunStep(eventName, element, func, stepTest) +{ + var eventCallback = function(event) { + if (func) + func(event); + } + if (stepTest) + eventCallback = stepTest.step_func(eventCallback); + + element.addEventListener(eventName, eventCallback, true); +} + +// Copied from LayoutTests/resources/js-test.js. +// See it for details of why this is necessary. +function asyncGC(callback) +{ + GCController.collectAll(); + setTimeout(callback, 0); +} + +function createGCPromise() +{ + // Run gc() as a promise. + return new Promise( + function(resolve, reject) { + asyncGC(resolve); + }); +} + +function delayToAllowEventProcessingPromise() +{ + return new Promise( + function(resolve, reject) { + setTimeout(resolve, 0); + }); +} + +function stringToUint8Array(str) +{ + var result = new Uint8Array(str.length); + for(var i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; +} + +function arrayBufferAsString(buffer) +{ + // MediaKeySession.keyStatuses iterators return an ArrayBuffer, + // so convert it into a printable string. + return String.fromCharCode.apply(null, new Uint8Array(buffer)); +} + +function dumpKeyStatuses(keyStatuses) +{ + consoleWrite("for (var entry of keyStatuses)"); + for (var entry of keyStatuses) { + consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]); + } + consoleWrite("for (var keyId of keyStatuses.keys())"); + for (var keyId of keyStatuses.keys()) { + consoleWrite(arrayBufferAsString(keyId)); + } + consoleWrite("for (var status of keyStatuses.values())"); + for (var status of keyStatuses.values()) { + consoleWrite(status); + } + consoleWrite("for (var entry of keyStatuses.entries())"); + for (var entry of keyStatuses.entries()) { + consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]); + } + consoleWrite("keyStatuses.forEach()"); + keyStatuses.forEach(function(status, keyId) { + consoleWrite(arrayBufferAsString(keyId) + ": " + status); + }); +} + +// Verify that |keyStatuses| contains just the keys in |keys.expected| +// and none of the keys in |keys.unexpected|. All keys should have status +// 'usable'. Example call: verifyKeyStatuses(mediaKeySession.keyStatuses, +// { expected: [key1], unexpected: [key2] }); +function verifyKeyStatuses(keyStatuses, keys) +{ + var expected = keys.expected || []; + var unexpected = keys.unexpected || []; + + // |keyStatuses| should have same size as number of |keys.expected|. + assert_equals(keyStatuses.size, expected.length); + + // All |keys.expected| should be found. + expected.map(function(key) { + assert_true(keyStatuses.has(key)); + assert_equals(keyStatuses.get(key), 'usable'); + }); + + // All |keys.unexpected| should not be found. + unexpected.map(function(key) { + assert_false(keyStatuses.has(key)); + assert_equals(keyStatuses.get(key), undefined); + }); +} + +// Encodes |data| into base64url string. There is no '=' padding, and the +// characters '-' and '_' must be used instead of '+' and '/', respectively. +function base64urlEncode(data) +{ + var result = btoa(String.fromCharCode.apply(null, data)); + return result.replace(/=+$/g, '').replace(/\+/g, "-").replace(/\//g, "_"); +} + +// Decode |encoded| using base64url decoding. +function base64urlDecode(encoded) +{ + return atob(encoded.replace(/\-/g, "+").replace(/\_/g, "/")); +} + +// For Clear Key, the License Format is a JSON Web Key (JWK) Set, which contains +// a set of cryptographic keys represented by JSON. These helper functions help +// wrap raw keys into a JWK set. +// See: +// https://w3c.github.io/encrypted-media/#clear-key-license-format +// http://tools.ietf.org/html/draft-ietf-jose-json-web-key +// +// Creates a JWK from raw key ID and key. +// |keyId| and |key| are expected to be ArrayBufferViews, not base64-encoded. +function createJWK(keyId, key) +{ + var jwk = '{"kty":"oct","alg":"A128KW","kid":"'; + jwk += base64urlEncode(keyId); + jwk += '","k":"'; + jwk += base64urlEncode(key); + jwk += '"}'; + return jwk; +} + +// Creates a JWK Set from multiple JWKs. +function createJWKSet() +{ + var jwkSet = '{"keys":['; + for (var i = 0; i < arguments.length; i++) { + if (i != 0) + jwkSet += ','; + jwkSet += arguments[i]; + } + jwkSet += ']}'; + return jwkSet; +} + +// Clear Key can also support Key IDs Initialization Data. +// ref: http://w3c.github.io/encrypted-media/keyids-format.html +// Each parameter is expected to be a key id in an Uint8Array. +function createKeyIDs() +{ + var keyIds = '{"kids":["'; + for (var i = 0; i < arguments.length; i++) { + if (i != 0) + keyIds += '","'; + keyIds += base64urlEncode(arguments[i]); + } + keyIds += '"]}'; + return keyIds; +} + +function forceTestFailureFromPromise(test, error, message) +{ + // Promises convert exceptions into rejected Promises. Since there is + // currently no way to report a failed test in the test harness, errors + // are reported using force_timeout(). + if (message) + consoleWrite(message + ': ' + error.message); + else if (error) + consoleWrite(error); + + test.force_timeout(); + test.done(); +} + +function extractSingleKeyIdFromMessage(message) +{ + var json = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(message))); + // Decode the first element of 'kids'. + assert_equals(1, json.kids.length); + var decoded_key = base64urlDecode(json.kids[0]); + // Convert to an Uint8Array and return it. + return stringToUint8Array(decoded_key); +} + +// Create a MediaKeys object for Clear Key with 1 session. KeyId and key +// required for the video are already known and provided. Returns a promise +// that resolves to the MediaKeys object created. +function createMediaKeys(keyId, key) +{ + var mediaKeys; + var mediaKeySession; + var request = stringToUint8Array(createKeyIDs(keyId)); + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, key))); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getSimpleConfigurationForInitDataType('keyids')).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + mediaKeys = result; + mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest('keyids', request); + }).then(function() { + return mediaKeySession.update(jwkSet); + }).then(function() { + return Promise.resolve(mediaKeys); + }); +} + +// Play the specified |content| on |video|. Returns a promise that is resolved +// after the video plays for |duration| seconds. +function playVideoAndWaitForTimeupdate(video, content, duration) +{ + video.src = content; + video.play(); + return new Promise(function(resolve) { + video.addEventListener('timeupdate', function listener(event) { + if (event.target.currentTime < duration) + return; + video.removeEventListener('timeupdate', listener); + resolve('success'); + }); + }); +} diff --git a/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-waiting-for-a-key.html b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-waiting-for-a-key.html new file mode 100644 index 000000000..2af37cfb9 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/migrated_to_root_disabled/encrypted-media-waiting-for-a-key.html @@ -0,0 +1,168 @@ +<!DOCTYPE html> +<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> +<html> + <head> + <title>Waiting for a key.</title> + <script src="encrypted-media-utils.js"></script> +<!-- + Test has been migrated to the root directory and is being disabled here. + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +--> + </head> + <body> + <video id="testVideo"></video> + <div id="log"></div> + <script> + // For debugging timeouts, keep track of the number of the + // various events received. + var debugEncryptedEventCount = 0; + var debugWaitingForKeyEventCount = 0; + var debugTimeUpdateEventCount = 0; + var debugMessage = ''; + + promise_test(function(test) + { + var video = document.getElementById('testVideo'); + var content = 'webm/test-encrypted.webm'; + var initData; + var initDataType; + var mediaKeySession; + + test.timeout = function() + { + var message = 'timeout. message = ' + debugMessage + + ', encrypted: ' + debugEncryptedEventCount + + ', waitingforkey: ' + debugWaitingForKeyEventCount + + ', timeupdate: ' + debugTimeUpdateEventCount; + test.force_timeout(); + test.timeout_id = null; + test.set_status(2, message); + test.done(); + }; + + // As this code doesn't wait for the 'message' event to avoid + // race conditions with 'waitingforkey', specify the key ID and + // key used by the encrypted content. + var keyId = stringToUint8Array('0123456789012345'); + var rawKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); + + return navigator.requestMediaKeySystemAccess('org.w3.clearkey', getConfigurationForFile(content)).then(function(access) { + debugMessage = 'createMediaKeys()'; + return access.createMediaKeys(); + }).then(function(mediaKeys) { + debugMessage = 'setMediaKeys()'; + return video.setMediaKeys(mediaKeys); + }).then(function() { + video.src = content; + video.play(); + debugMessage = 'wait_for_encrypted_event()'; + return wait_for_encrypted_event(video); + }).then(function(e) { + // Received the 'encrypted' event(s), so keep a copy of + // the initdata for use when creating the session later. + initData = e.initData; + initDataType = e.initDataType; + + // Wait until the video indicates that it needs a key to + // continue. + debugMessage = 'wait_for_waitingforkey_event()'; + return wait_for_waitingforkey_event(video); + }).then(function() { + // Make sure the video is NOT paused and not progressing + // before a key is provided. This requires the video + // to NOT have a clear lead. + assert_false(video.paused); + assert_equals(video.currentTime, 0); + + // Create a session. + mediaKeySession = video.mediaKeys.createSession(); + debugMessage = 'generateRequest()'; + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + // generateRequest() will cause a 'message' event to + // occur specifying the keyId that is needed, but we + // ignore it since we already know what keyId is needed. + // Add the key needed to decrypt. + var jwkSet = stringToUint8Array(createJWKSet(createJWK(keyId, rawKey))); + debugMessage = 'update()'; + return mediaKeySession.update(jwkSet); + }).then(function() { + // Video should start playing now that it can decrypt the + // streams, so wait until a little bit of the video has + // played. + debugMessage = 'wait_for_timeupdate_event()'; + return wait_for_timeupdate_event(video); + }); + + // Typical test duration is 6 seconds on release builds + // (12 seconds on debug). Since the test is timing out anyway, + // make the duration 5 seconds so that the timeout function + // is actually called (instead of simply aborting the test). + }, 'Waiting for a key.', { timeout: 5000 }); + + // Wait for a pair of 'encrypted' events. Promise resolved on + // second event. + function wait_for_encrypted_event(video) + { + var encryptedEventCount = 0; + return new Promise(function(resolve) { + video.addEventListener('encrypted', function listener(e) { + assert_equals(e.target, video); + assert_true(e instanceof window.MediaEncryptedEvent); + assert_equals(e.type, 'encrypted'); + + // The same decryption key is used by both the audio + // and the video streams so wait for the second event + // to ensure we see both events. + ++debugEncryptedEventCount; + if (++encryptedEventCount != 2) + return; + + video.removeEventListener('encrypted', listener); + resolve(e); + }); + }); + }; + + // Wait for a 'waitingforkey' event. Promise resolved when the + // event is received. + function wait_for_waitingforkey_event(video) + { + var waitingForKeyEventCount = 0; + return new Promise(function(resolve) { + video.addEventListener('waitingforkey', function listener(e) { + assert_equals(e.target, video); + assert_equals(e.type, 'waitingforkey'); + + ++debugWaitingForKeyEventCount; + ++waitingForKeyEventCount; + // TODO(jrummell): waitingforkey event should only + // occur once. http://crbug.com/461903 +// assert_equals(waitingForKeyEventCount, 1, 'Multiple waitingforkey events'); + + video.removeEventListener('waitingforkey', listener); + resolve(e); + }); + }); + }; + + // Wait for a 'timeupdate' event. Promise resolved if |video| has + // played for more than 0.2 seconds. + function wait_for_timeupdate_event(video) + { + return new Promise(function(resolve) { + video.addEventListener('timeupdate', function listener(e) { + assert_equals(e.target, video); + ++debugTimeUpdateEventCount; + if (video.currentTime < 0.2) + return; + video.removeEventListener('timeupdate', listener); + resolve(e); + }); + }); + }; + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted-different-av-keys.webm b/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted-different-av-keys.webm Binary files differnew file mode 100644 index 000000000..5a29f659b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted-different-av-keys.webm diff --git a/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted.webm b/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted.webm Binary files differnew file mode 100644 index 000000000..8d44931e8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/webm/test-encrypted.webm diff --git a/testing/web-platform/tests/encrypted-media/Google/webm/test.webm b/testing/web-platform/tests/encrypted-media/Google/webm/test.webm Binary files differnew file mode 100644 index 000000000..6c2138d4e --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/Google/webm/test.webm diff --git a/testing/web-platform/tests/encrypted-media/OWNERS b/testing/web-platform/tests/encrypted-media/OWNERS new file mode 100644 index 000000000..63b5fe290 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/OWNERS @@ -0,0 +1 @@ +@ddorwin diff --git a/testing/web-platform/tests/encrypted-media/README.md b/testing/web-platform/tests/encrypted-media/README.md new file mode 100644 index 000000000..932c9962d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/README.md @@ -0,0 +1,7 @@ +## Preparing to run tests +The following steps may be necessary when running test from a new server/origin for the first time. +* Some implementations and/or tests may require consent. + When running on such clients, manually run a test to trigger the consent request and choose to persist the consent. +* Some of the tests, such as *-retrieve-*, use pop-ups. + It may be necessary to run these tests manually and choose to always allow pop-ups on the origin. + Related test failures may appear as: "Cannot set property 'onload' of undefined" diff --git a/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.html b/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.html new file mode 100644 index 000000000..00894338a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <!--<script src=/encrypted-media/content/content-metadata.js></script>--> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/check-initdata-type.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: 'org.w3.clearkey' } + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.html b/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.html new file mode 100644 index 000000000..ddf3ecbbb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.html @@ -0,0 +1,40 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeySession closed event with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/events-session-closed-event.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = 'org.w3.clearkey', + contentItem = content['mp4-basic'], + config = { + keysystem: keysystem, + content: contentItem, + initDataType: 'keyids', + initData: getInitData(contentItem,'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-events.html b/testing/web-platform/tests/encrypted-media/clearkey-events.html new file mode 100644 index 000000000..4f3b6222b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-events.html @@ -0,0 +1,44 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Events with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/events.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + getSupportedContent( 'org.w3.clearkey' ) + .then( function( contents ) + { + var content = contents.filter(function(content) { return content.keys; })[0], + handler = new MessageHandler( 'org.w3.clearkey', content ); + + runTest( { keysystem: 'org.w3.clearkey', + content: content, + messagehandler: handler.messagehandler, + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.html b/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.html new file mode 100644 index 000000000..af6e76c2b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test handling of invalid initData for generateRequest()</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/generate-request-disallowed-input.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: 'org.w3.clearkey' + }; + + runTest(config); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.html b/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.html new file mode 100644 index 000000000..09ff934a0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.html @@ -0,0 +1,31 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test handling of invalid Clear Key license</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/invalid-license.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { + keysystem: 'org.w3.clearkey' + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html new file mode 100644 index 000000000..3474f9d51 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html @@ -0,0 +1,51 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/keystatuses-multiple-sessions.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + getSupportedContent( 'org.w3.clearkey' ) + .then( function( contents ) { + + // Select a content item with multiple keys + var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1; } )[ 0 ], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ); + + var config = { keysystem: 'org.w3.clearkey', + content: contentitem, + messagehandler: handler.messagehandler, + initDataType: 'keyids', + initData: getMultikeyInitDatas(contentitem,'keyids') + }; + + runTest(config); + + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.html b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.html new file mode 100644 index 000000000..6edec35cd --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.html @@ -0,0 +1,50 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/keystatuses.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + getSupportedContent( 'org.w3.clearkey' ) + .then( function( contents ) { + + // Select a content item with multiple keys + var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1; } )[ 0 ]; + var handler = new MessageHandler( 'org.w3.clearkey', contentitem ); + var config = { keysystem: 'org.w3.clearkey', + content: contentitem, + messagehandler: handler.messagehandler, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + + } ); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html new file mode 100644 index 000000000..547f01b36 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, playback, destroy license with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-destroy-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html new file mode 100644 index 000000000..99aba6386 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with Clear Key, mp4, event sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-license-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.html new file mode 100644 index 000000000..352a2a7b0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html new file mode 100644 index 000000000..795cf5b60 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with Clear Key, mp4, event sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-usage-record-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html new file mode 100644 index 000000000..a2eb397d6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with Clear Key, mp4, event sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-usage-record.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html new file mode 100644 index 000000000..85510b24b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, playback, retrieve, playback and destroy with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + windowscript: 'resources/clearkey-retrieve-destroy-persistent-license.html', + testcase: 'playback, retrieve, playback and destroy' }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html new file mode 100644 index 000000000..7d8fe57ff --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license playback, retrieve and playback with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + windowscript: 'resources/clearkey-retrieve-persistent-license.html', + testcase: 'playback, retrieve and playback' }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html new file mode 100644 index 000000000..c612b8cd9 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-usage-record, playback and retrieve record in new window, Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + windowscript: 'resources/retrieve-persistent-usage-record.html' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html new file mode 100644 index 000000000..9eca41cc0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, clear then encrypted</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-clear-encrypted'], + handler = new MessageHandler('org.w3.clearkey', contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem, 'keyids'), + duration: 4, + testcase: 'single key, clear then encrypted content' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html new file mode 100644 index 000000000..04ffe0ccd --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html @@ -0,0 +1,58 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, alternate Encrypted and Clear playbacks, Temporary, mp4, Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var encryptedcontentitem = content['mp4-basic'], + clearcontentitem = content['mp4-clear'], + handler = new MessageHandler('org.w3.clearkey', encryptedcontentitem), + configEncrypted = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: encryptedcontentitem.audio.path, + videoPath: encryptedcontentitem.video.path, + audioType: encryptedcontentitem.audio.type, + videoType: encryptedcontentitem.video.type, + initDataType: 'keyids', + initData: getInitData(encryptedcontentitem, 'keyids'), + }, + configClear = { audioPath: clearcontentitem.audio.path, + videoPath: clearcontentitem.video.path, + audioType: clearcontentitem.audio.type, + videoType: clearcontentitem.video.type, + }; + + runTest(configEncrypted,configClear); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html new file mode 100644 index 000000000..1e1902463 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, encrypted then clear</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-encrypted-clear'], + handler = new MessageHandler('org.w3.clearkey', contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem, 'keyids'), + duration: 4, + testcase: 'single key, encrypted then clear content' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.html new file mode 100644 index 000000000..c4d4ea37d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful playback, Temporary session with Clear Key, mp4, validating events</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html new file mode 100644 index 000000000..66313e727 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html @@ -0,0 +1,55 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence, check readyState</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-multikey-sequential'], + handler = new MessageHandler('org.w3.clearkey', contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getMultikeyInitDatas(contentitem, 'keyids'), + duration: 5, + checkReadyState: true + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html new file mode 100644 index 000000000..64b00cd29 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-multikey-sequential'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getMultikeyInitDatas(contentitem,'keyids'), + duration: 5 + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html new file mode 100644 index 000000000..29d1a2eed --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys for audio/video</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-av-multikey'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: 'multikey audio/video' }; + + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html new file mode 100644 index 000000000..8f32120f1 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multisession.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-multikey'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getMultikeyInitDatas(contentitem,'keyids'), + testcase: 'multikey video' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html new file mode 100644 index 000000000..bade71626 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: SETMEDIAKEYS_AFTER_SRC }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html new file mode 100644 index 000000000..1085ce4e7 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: SETMEDIAKEYS_AFTER_UPDATE }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html new file mode 100644 index 000000000..7f362f442 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: SETMEDIAKEYS_IMMEDIATELY }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html new file mode 100644 index 000000000..a49bc28d3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: SETMEDIAKEYS_ONENCRYPTED }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html new file mode 100644 index 000000000..95de680e4 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html @@ -0,0 +1,55 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, two videos</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-two-videos.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement1" width="200px"></video> + <video id="videoelement2" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: [ document.getElementById( 'videoelement1' ), + document.getElementById( 'videoelement2' ) ], + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html new file mode 100644 index 000000000..94d35daa5 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, play, wait for key, continue play</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-waitingforkey.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getMultikeyInitDatas(contentitem,'keyids') + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.html new file mode 100644 index 000000000..909f2af64 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler( 'org.w3.clearkey', contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids'), + testcase: 'single key' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html new file mode 100644 index 000000000..f8402c99a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html @@ -0,0 +1,40 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: requestMediaKeySystemAccess tests, Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/requestmediakeysystemaccess.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var contentitem = content['mp4-basic'], + config = { keysystem: 'org.w3.clearkey', + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids' + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html new file mode 100644 index 000000000..61da9d867 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Reset MediaSource after setMediaKeys for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/reset-src-after-setmediakeys.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-av-multikey'], + config = { + video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contentItem, + initDataType: 'keyids', + initData: getInitData(contentItem,'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path, + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html new file mode 100644 index 000000000..697cf207c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys again after playback with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-again-after-playback.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler('org.w3.clearkey', contentitem); + getSupportedContent('org.w3.clearkey').then( function(contents) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem, 'keyids') + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html new file mode 100644 index 000000000..d695445ef --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys again after resetting src attribute on video element with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + handler = new MessageHandler('org.w3.clearkey', contentitem ); + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + messagehandler: handler.messagehandler, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: 'keyids', + initData: getInitData(contentitem,'keyids') + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html new file mode 100644 index 000000000..91e6b9ec3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple at same time with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-at-same-time.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html new file mode 100644 index 000000000..064d7ed05 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html @@ -0,0 +1,49 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple times with different mediakeys with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic']; + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html new file mode 100644 index 000000000..9e383afc3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html @@ -0,0 +1,49 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple times with the same mediakeys with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic']; + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html new file mode 100644 index 000000000..cf73b8085 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys to multiple video elements with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video1'> + <video id="videoelement1" width="200px"></video> + </div> + <div id='video2'> + <video id="videoelement2" width="200px"></video> + </div> + + <script> + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video1: document.getElementById('videoelement1'), + video2: document.getElementById('videoelement2'), + keysystem: 'org.w3.clearkey', + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.html new file mode 100644 index 000000000..2865052c6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys with Clear Key</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html new file mode 100644 index 000000000..6b4a08a91 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html @@ -0,0 +1,42 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeys attribute, setServerCertificate and setServerCertificate exception syntax for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var contentItem = content['mp4-basic'], + config = { + keysystem: 'org.w3.clearkey', + content: contentItem, + initDataType: 'keyids', + initData: getInitData(contentItem, 'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html new file mode 100644 index 000000000..2748c31a5 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html @@ -0,0 +1,42 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeySession attribute and function syntax for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeysession.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var contentItem = content['mp4-basic'], + config = { + keysystem: 'org.w3.clearkey', + content: contentItem, + initDataType: 'keyids', + initData: getInitData(contentItem, 'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html new file mode 100644 index 000000000..22e72ccc8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html @@ -0,0 +1,42 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test navigator.requestmediakeysystemaccess exception and MediaKeySystemAccess attribute syntax for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeysystemaccess.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var contentItem = content['mp4-basic'], + config = { + keysystem: 'org.w3.clearkey', + content: contentItem, + initDataType: 'keyids', + initData: getInitData(contentItem, 'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.html new file mode 100644 index 000000000..2871862dd --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Unique origin with Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/unique-origin.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-av-multikey'], + config = { + video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.html new file mode 100644 index 000000000..e5061a765 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.html @@ -0,0 +1,28 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test handling of invalid responses for update() for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/update-disallowed-input.js></script> + + </head> + <body> + <div id="log"></div> + <script> + var config = { + keysystem: 'org.w3.clearkey', + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html new file mode 100644 index 000000000..2876a54a4 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Waiting for a key for Clear Key, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/waiting-for-a-key.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-basic'], + handler = new MessageHandler('org.w3.clearkey', contentItem), + config = { + video: document.getElementById('videoelement'), + keysystem: 'org.w3.clearkey', + content: contentItem, + messageHandler: handler.messagehandler, + initDataType: 'keyids', + initData: getInitData(contentItem, 'keyids'), + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path, + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.html b/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.html new file mode 100644 index 000000000..29dc21492 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.html @@ -0,0 +1,35 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test MediaKeySession not callable immediately after CreateSession().</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Message handler for Clear Key --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/not-callable-after-createsession.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: 'org.w3.clearkey' + }; + + runTest(config); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.html b/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.html new file mode 100644 index 000000000..cc1347291 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.html @@ -0,0 +1,36 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test Clear Key handling of non-ASCII responses for update()</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/clearkey-update-non-ascii-input.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var contentItem = content['mp4-basic'], + config = { + keysystem: 'org.w3.clearkey', + content: contentItem, + initDataType: "keyids" + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4 Binary files differnew file mode 100644 index 000000000..526998d6a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..4daf4d563 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..77e869f80 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/content-metadata.js b/testing/web-platform/tests/encrypted-media/content/content-metadata.js new file mode 100644 index 000000000..8ba5bcf06 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/content-metadata.js @@ -0,0 +1,297 @@ +content = addMemberListToObject( { + + 'mp4-clear' : { initDataType: 'cenc', + audio : { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video : { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4' } + }, + + 'mp4-basic' : { assetId: 'mp4-basic', + initDataType: 'cenc', + audio : { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video : { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4' }, + keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ], + key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ], + initDataType: 'cenc', + initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ] + }, + + 'mp4-clear-encrypted' : { + assetId: 'mp4-basic', + initDataType: 'cenc', + audio : { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video : { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4' }, + keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ], + key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ], + initDataType: 'cenc', + initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ] + }, + + 'mp4-encrypted-clear' : { + assetId: 'mp4-basic', + initDataType: 'cenc', + audio : { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video : { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4' }, + keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ], + key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ], + initDataType: 'cenc', + initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ] + }, + + + 'mp4-av-multikey' : { + assetId: 'mp4-basic', + initDataType: 'cenc', + associatedInitData: true, // indicates that initData for one key causes other keys to be returned as well + audio: { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4' }, + video : { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4' }, + keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ], + key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ], + initDataType: 'cenc', + initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' }, + { kid: [ 0x55, 0x8e, 0xe5, 0x41, 0xb9, 0x0a, 0xb2, 0xf3, 0x95, 0x0d, 0x00, 0xad, 0xe3, 0x76, 0x0d, 0x45 ], + key: [ 0x91, 0x03, 0x92, 0x63, 0x01, 0x6d, 0xa6, 0x35, 0x77, 0x0d, 0x57, 0xdb, 0x92, 0xf9, 0x8b, 0xd0 ], + initDataType : 'cenc', + initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQVY7lQbkKsvOVDQCt43YNRRoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFEAZQBXAE8AVgBRAHEANQA4ADcASwBWAEQAUQBDAHQANAAzAFkATgBSAFEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AWQBpAE8ALwAxADYATABzADkANgBFAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ] + }, + + 'mp4-multikey' : { assetId: 'mp4-multikey', + initDataType: 'cenc', + audio: { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4' }, + video: { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4' }, + keys: [ { kid: [ 0x13, 0xa7, 0x53, 0x06, 0xd1, 0x18, 0x91, 0x7b, 0x47, 0xa6, 0xc1, 0x83, 0x64, 0x42, 0x51, 0x6f ], + key: [ 0x8a, 0xaa, 0xd8, 0xc4, 0xdb, 0xde, 0xac, 0xcd, 0xad, 0x26, 0x76, 0xa1, 0xed, 0x38, 0x95, 0x2e ], + variantId: 'key1', + initDataType: 'cenc', + initData: 'AAAAjXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAG0IARIQE6dTBtEYkXtHpsGDZEJRbxoIY2FzdGxhYnMiRGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRNbk5sYzNOcGIyNGlMQ0oyWVhKcFlXNTBTV1FpT2lKclpYa3hJbjA9MgdkZWZhdWx0AAADwnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA6KiAwAAAQABAJgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBCAGwATwBuAEUAeABqAFIAZQA1AEYASABwAHMARwBEAFoARQBKAFIAYgB3AD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAGwAaQBjAC4AcwB0AGEAZwBpAG4AZwAuAGQAcgBtAHQAbwBkAGEAeQAuAGMAbwBtAC8AbABpAGMAZQBuAHMAZQAtAHAAcgBvAHgAeQAtAGgAZQBhAGQAZQByAGEAdQB0AGgALwBkAHIAbQB0AG8AZABhAHkALwBSAGkAZwBoAHQAcwBNAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA8AC8ATABBAF8AVQBSAEwAPgA8AEwAVQBJAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAFUASQBfAFUAUgBMAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEQAUgB0AFAAZwBVAEkALwBiAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=' }, + { kid: [ 0xee, 0x73, 0x56, 0x4e, 0xc8, 0xa8, 0x90, 0xf0, 0x78, 0xef, 0x68, 0x71, 0xfa, 0x4b, 0xe1, 0x8b ], + key: [ 0xe4, 0x4f, 0xe1, 0x45, 0x7c, 0x5e, 0xbc, 0xd8, 0x3e, 0xad, 0xdc, 0xd6, 0x2c, 0xaf, 0x55, 0x18 ], + variantId: 'key2', + initDataType: 'cenc', + initData: 'AAAAjXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAG0IARIQ7nNWTsiokPB472hx+kvhixoIY2FzdGxhYnMiRGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRNbk5sYzNOcGIyNGlMQ0oyWVhKcFlXNTBTV1FpT2lKclpYa3lJbjA9MgdkZWZhdWx0AAADwnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA6KiAwAAAQABAJgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBUAGwAWgB6ADcAcQBqAEkAOABKAEIANAA3ADIAaAB4ACsAawB2AGgAaQB3AD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAGwAaQBjAC4AcwB0AGEAZwBpAG4AZwAuAGQAcgBtAHQAbwBkAGEAeQAuAGMAbwBtAC8AbABpAGMAZQBuAHMAZQAtAHAAcgBvAHgAeQAtAGgAZQBhAGQAZQByAGEAdQB0AGgALwBkAHIAbQB0AG8AZABhAHkALwBSAGkAZwBoAHQAcwBNAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA8AC8ATABBAF8AVQBSAEwAPgA8AEwAVQBJAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAFUASQBfAFUAUgBMAD4APABDAEgARQBDAEsAUwBVAE0APgB4AEQASwBBAFkAMAB2AFoAaABVAFUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=' } ] }, + + 'mp4-basic-key1' : { assetId: 'mp4-multikey-sequential', + variantId: 'key1', + initDataType: 'cenc', + audio: { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video: { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4' }, + keys: [ { kid: [0x8a, 0x0d, 0x85, 0x45, 0x21, 0x05, 0xd4, 0x15, 0x35, 0x8f, 0xea, 0x8f, 0x68, 0xe6, 0xc1, 0x91], + key: [0x76, 0x6f, 0xab, 0xc1, 0x68, 0x3f, 0xf8, 0xef, 0x4e, 0x76, 0x00, 0x24, 0xc5, 0x23, 0x8f, 0x10], + initDataType: 'cenc', + initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQig2FRSEF1BU1j+qPaObBkRoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreEluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFIAWQBVAE4AaQBnAFUAaABGAGQAUQAxAGoAKwBxAFAAYQBPAGIAQgBrAFEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AcQBOAEkAZQBiAFQAWABzAG8AcgBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] + }, + 'mp4-basic-key2' : { assetId: 'mp4-multikey-sequential', + variantId: 'key2', + initDataType: 'cenc', + audio: { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video: { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4' }, + keys: [ { kid: [0xfb, 0xb4, 0xb7, 0xf3, 0x4a, 0xbd, 0x31, 0x87, 0x34, 0x4b, 0xce, 0xc4, 0x5f, 0x96, 0x68, 0x88], + key: [0x26, 0x52, 0xc3, 0x1d, 0xf7, 0x92, 0xd1, 0x7b, 0x08, 0xa6, 0xfa, 0xd3, 0x7c, 0xb6, 0x25, 0x60], + initDataType: 'cenc', + initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQ+7S380q9MYc0S87EX5ZoiBoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreUluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADgANwBlADAAKwA3ADEASwBoAHoARQAwAFMAOAA3AEUAWAA1AFoAbwBpAEEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4ARgB0AGkASQBoADYAUwBKAG0AcABZAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] }, + + 'mp4-multikey-sequential' : { assetId: 'mp4-multikey-sequential', + initDataType: 'cenc', + audio: { type: 'audio/mp4;codecs="mp4a.40.2"', + path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' }, + video: { type: 'video/mp4;codecs="avc1.4d401e"', + path: '/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4' }, + keys: [ { kid: [0x8a, 0x0d, 0x85, 0x45, 0x21, 0x05, 0xd4, 0x15, 0x35, 0x8f, 0xea, 0x8f, 0x68, 0xe6, 0xc1, 0x91], + key: [0x76, 0x6f, 0xab, 0xc1, 0x68, 0x3f, 0xf8, 0xef, 0x4e, 0x76, 0x00, 0x24, 0xc5, 0x23, 0x8f, 0x10], + variantId: 'key1', + initDataType: 'cenc', + initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQig2FRSEF1BU1j+qPaObBkRoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreEluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFIAWQBVAE4AaQBnAFUAaABGAGQAUQAxAGoAKwBxAFAAYQBPAGIAQgBrAFEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AcQBOAEkAZQBiAFQAWABzAG8AcgBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' }, + { kid: [0xfb, 0xb4, 0xb7, 0xf3, 0x4a, 0xbd, 0x31, 0x87, 0x34, 0x4b, 0xce, 0xc4, 0x5f, 0x96, 0x68, 0x88], + key: [0x26, 0x52, 0xc3, 0x1d, 0xf7, 0x92, 0xd1, 0x7b, 0x08, 0xa6, 0xfa, 0xd3, 0x7c, 0xb6, 0x25, 0x60], + variantId: 'key2', + initDataType: 'cenc', + initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQ+7S380q9MYc0S87EX5ZoiBoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreUluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADgANwBlADAAKwA3ADEASwBoAHoARQAwAFMAOAA3AEUAWAA1AFoAbwBpAEEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4ARgB0AGkASQBoADYAUwBKAG0AcABZAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] }, + + 'webm' : { audio : { type: 'audio/webm; codecs="opus"' }, + video : { type: 'video/webm; codecs="vp8"', + path: '/encrypted-media/content/test-encrypted.webm' }, + keys : [ { kid: [48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53], + key: [0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, + 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c ] } ] + }, + 'webm-multikey' : + { audio : { type: 'audio/webm; codecs="opus"' }, + video : { type: 'video/webm; codecs="vp8"', + path: '/encrypted-media/content/test-encrypted-different-av-keys.webm' }, + keys : [ { kid: [48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53], + key: [ 0x7A, 0x7A, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B, + 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A ] }, + { kid: [49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54], + key: [ 0x30, 0x30, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B, + 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A ] } ] + }, +} ); + +function addMemberListToObject( o ) +{ + var items = [ ]; + for( var item in o ) + { + if ( !o.hasOwnProperty( item ) ) continue; + + o[item].name = item; + items.push( o[item] ); + } + + o._items = items; + + return o; +} + +function getInitData( contentitem, initDataType ) +{ + if (initDataType == 'webm') { + return new Uint8Array( contentitem.keys[ 0 ].kid ); // WebM initData supports only a single key + } + + if (initDataType == 'cenc') { + + var size = 36 + contentitem.keys.length * 16, + kids = contentitem.keys.map( function( k ) { return k.kid; } ); + + return new Uint8Array(Array.prototype.concat.call( [ + 0x00, 0x00, size / 256, size % 256, // size + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x01, // version = 1 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, kids.length ], // key count ] + Array.prototype.concat.apply( [], kids ), + [ 0x00, 0x00, 0x00, 0x00 ]// datasize + )); + } + if (initDataType == 'keyids') { + + return toUtf8( { kids: contentitem.keys.map( function( k ) { return base64urlEncode( new Uint8Array( k.kid ) ); } ) } ); + } + throw 'initDataType ' + initDataType + ' not supported.'; +} + +function getSingleKeyInitData( kid, initDataType ) +{ + if (initDataType == 'webm') { + return new Uint8Array( kid ); + } + + if (initDataType == 'cenc') { + + var size = 52; + + return new Uint8Array(Array.prototype.concat.call( [ + 0x00, 0x00, size / 256, size % 256, // size + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x01, // version = 1 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x01 ], // key count ] + kid, + [ 0x00, 0x00, 0x00, 0x00 ]// datasize + )); + } + if (initDataType == 'keyids') { + + return toUtf8( { kids: [ base64urlEncode( new Uint8Array( kid ) ) ] } ); + } + throw 'initDataType ' + initDataType + ' not supported.'; +} + +function getMultikeyInitDatas( contentitem, initDataType ) +{ + return contentitem.keys.map( function( k ) { return getSingleKeyInitData( k.kid, initDataType ); } ); +} + +function getProprietaryInitDatas( contentitem ) +{ + var keysWithInitData = contentitem.keys.filter( function( k ) { return k.initData; } ); + return { initDataType: contentitem.initDataType, + initDatas : keysWithInitData.map( function( k ) { return k.initData; } ), + variantIds: keysWithInitData.map( function( k ) { return k.variantId; } ) + }; +} + +// Returns a promise that resolves to the following object +// { supported: boolean, // whether the content is supported at all +// content: <the content item>, // the content item description +// initDataTypes: <list of initDataTypes> +// } +// +// Note: we test initData types one at a time since some versions of Edge don't support testing several at once +// +function isContentSupportedForInitDataTypes( keysystem, initDataTypes, contentitem ) +{ + return Promise.all( initDataTypes.map( function( initDataType ) { + var configuration = { initDataTypes : [ initDataType ], + audioCapabilities: [ { contentType: contentitem.audio.type } ], + videoCapabilities: [ { contentType: contentitem.video.type } ] + }; + return navigator.requestMediaKeySystemAccess( keysystem, [ configuration ] ).then( function( access ) { + return { supported: true, initDataType: access.getConfiguration().initDataTypes[ 0 ] }; + }, function() { + return { supported: false }; + } ); + } ) ).then( function( results ) { + + var initDataTypes = results.filter( function( result ) { return result.supported; } ) + .map( function( result ) { return result.initDataType; } ); + + return initDataTypes.length > 0 ? + { content: contentitem, supported: true, initDataTypes: initDataTypes } + : { content: contentitem, supported: false }; + } ); +} + +// Returns a promise that resolves to { content:, supported:, initDataTypes: } object +function isContentSupported( keysystem, contentitem ) +{ + return isContentSupportedForInitDataTypes( keysystem, [ 'cenc', 'webm', 'keyids' ], contentitem ); +} + +// Returns a Promise resolving to an array of supported content for the key system +function getSupportedContent( keysystem ) +{ + return Promise.all( content._items.map( isContentSupported.bind( null, keysystem ) ) ). + then( function( results ) + { + return results.filter( function( r ) { return r.supported; } ).map( function( r ) { return r.content; } ); + } ); +} + +// Returns a Promise resolving to an array of { content:, initDataType: } pairs for the key system +function getSupportedContentAndInitDataTypes( keysystem ) +{ + return Promise.all( content._items.map( isContentSupported.bind( null, keysystem ) ) ). + then( function( results ) + { + return results.filter( function( r ) { return r.supported; } ); + } ); +} + +// gets a configuration object for provided piece of content +function getSimpleConfigurationForContent( contentitem ) +{ + return { initDataTypes: [ 'keyids', 'webm', 'cenc' ], + audioCapabilities: [ { contentType: contentitem.audio.type } ], + videoCapabilities: [ { contentType: contentitem.video.type } ] }; +} diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..33ac63f6b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..dca23449a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..53a461e8a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4 Binary files differnew file mode 100644 index 000000000..f59284cfe --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..d837ac650 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..156a799a9 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..659a61cdc --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4 new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key1_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 Binary files differnew file mode 100644 index 000000000..0b9b457a6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_key2_dashinit.mp4 diff --git a/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.html b/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.html new file mode 100644 index 000000000..6b3324027 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <!--<script src=/encrypted-media/content/content-metadata.js></script>--> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/check-initdata-type.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: getSupportedKeySystem() } + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.html b/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.html new file mode 100644 index 000000000..425d17646 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.html @@ -0,0 +1,39 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeySession closed event with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/events-session-closed-event.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(), + contentItem = content['mp4-basic'], + config = { + keysystem: keysystem, + content: contentItem, + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-events.html b/testing/web-platform/tests/encrypted-media/drm-events.html new file mode 100644 index 000000000..880376d60 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-events.html @@ -0,0 +1,71 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Events with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/events.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(); + + getSupportedContentAndInitDataTypes( keysystem ) + .then( function( supported ) + { + // This test requires initData for supported content. + // We prefer explciit initData configured for the content, but + // otherwise we will generate initData for a supported initDataType + // FIXME: Move me to a utility function + var content, + initDataType, + initData; + + var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.keys && s.content.initDataType; } ); + if ( contentWithExplicitInitData.length > 0 ) + { + content = contentWithExplicitInitData[ 0 ].content; + initDataType = content.keys[ 0 ].initDataType; + initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData ); + } + else + { + content = supported[ 0 ].content; + initDataType = supported[ 0 ].initDataTypes[ 0 ]; + initData = getInitData( content, initDataType ); + } + + var handler = new MessageHandler( keysystem, content ); + + runTest( { keysystem: keysystem, + content: content, + messagehandler: handler.messagehandler, + initDataType: initDataType, + initData: initData + } ); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-expiration.html b/testing/web-platform/tests/encrypted-media/drm-expiration.html new file mode 100644 index 000000000..6dec51147 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-expiration.html @@ -0,0 +1,67 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Expiration with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/expiration.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(); + + getSupportedContentAndInitDataTypes( keysystem ).then( function( supported ) { + // This test requires initData for supported content. + // We prefer explicit initData configured for the content, but + // otherwise we will generate initData for a supported initDataType + // FIXME: Move me to a utility function + var content, + initDataType, + initData; + + var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.initDataType && s.content.keys; } ); + if ( contentWithExplicitInitData.length > 0 ) { + content = contentWithExplicitInitData[ 0 ].content; + initDataType = content.keys[ 0 ].initDataType; + initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData ); + } else { + content = supported[ 0 ].content; + initDataType = supported[ 0 ].initDataTypes[ 0 ]; + initData = getInitData( content, initDataType ); + } + + var handler = new MessageHandler( keysystem, content ); + + runTest( { keysystem: keysystem, + content: content, + messagehandler: handler.messagehandler, + initDataType: initDataType, + initData: initData, + expiration: Date.now().valueOf() + 120000 // Two minutes from now + } ); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.html b/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.html new file mode 100644 index 000000000..70c46edc7 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test handling of invalid initData for generateRequest()</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/generate-request-disallowed-input.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: getSupportedKeySystem() + }; + + runTest(config); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-invalid-license.html b/testing/web-platform/tests/encrypted-media/drm-invalid-license.html new file mode 100644 index 000000000..9584f499c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-invalid-license.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test handling of invalid DRM license</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/invalid-license.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(), + config = { + keysystem: keysystem + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.html b/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.html new file mode 100644 index 000000000..8ef745c4f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.html @@ -0,0 +1,55 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys for audio/video</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM server --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/keystatuses-multiple-sessions.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(); + getSupportedContent( keysystem ) + .then( function( contents ) { + + // Select a content item with multiple keys and initData + var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1 && item.initDataType && !item.associatedInitData; } )[ 0 ], + handler = new MessageHandler( keysystem, contentitem ), + config = { keysystem: keysystem, + content: contentitem, + messagehandler: handler.messagehandler, + initDataType: contentitem.initDataType, + initData: getProprietaryInitDatas(contentitem).initDatas.map( base64DecodeToUnit8Array ) + }; + + runTest(config); + + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-keystatuses.html b/testing/web-platform/tests/encrypted-media/drm-keystatuses.html new file mode 100644 index 000000000..de7ff395d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-keystatuses.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/keystatuses.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(); + getSupportedContent( keysystem ).then( function( contents ) { + // Select a content item with multiple keys and initData that retrieves all keys + var contentitem = contents.filter( function( item ) { + return item.keys && item.keys.length > 1 && item.initDataType && item.associatedInitData; + } )[ 0 ]; + + var handler = new MessageHandler( keysystem, contentitem ); + var config = { keysystem: keysystem, + content: contentitem, + messagehandler: handler.messagehandler, + initDataType: contentitem.initDataType, + initData: base64DecodeToUnit8Array( getProprietaryInitDatas(contentitem).initDatas[ 0 ] ) + }; + + runTest(config); + + } ); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.html b/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.html new file mode 100644 index 000000000..9e4aff330 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Encrypted fired on encrypted media file with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/onencrypted.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-av-multikey'], + config = { + video: document.getElementById('videoelement'), + content: contentItem, + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path, + initDataType: contentItem.initDataType, + keys: contentItem.keys + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html new file mode 100644 index 000000000..59350fb15 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, destroy the license</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-destroy-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.html new file mode 100644 index 000000000..3df5fffd2 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, event sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-license-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.html new file mode 100644 index 000000000..066e0040f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html new file mode 100644 index 000000000..b0c82621a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with DRM, mp4, event sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-usage-record-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + servercertificate: handler.servercertificate + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html new file mode 100644 index 000000000..1a9f8fb6f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-persistent-usage-record.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + servercertificate: handler.servercertificate + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html new file mode 100644 index 000000000..3a1646174 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, retrieve license, playback and destroy the license</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + windowscript: 'resources/drm-retrieve-destroy-persistent-license.html', + testcase: 'playback, retrieve, playback and destroy' }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html new file mode 100644 index 000000000..416093c14 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, retrieve the license, playback</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + windowscript: 'resources/drm-retrieve-persistent-license.html', + testcase: 'playback, retrieve, playback' }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html new file mode 100644 index 000000000..da5048f29 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-usage-record, playback and retrieve record in new window, DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM server --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + servercertificate: handler.servercertificate, + windowscript: 'resources/drm-retrieve-persistent-usage-record.html' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html new file mode 100644 index 000000000..a8621ba25 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, clear then encrypted</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-clear-encrypted'], + handler = new MessageHandler(keysystem, contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: 'single key, clear then encrypted content', + duration: 4 }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html new file mode 100644 index 000000000..74bd77053 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html @@ -0,0 +1,58 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, alternate Encrypted and Clear playbacks, Temporary, mp4, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + encryptedcontentitem = content['mp4-basic'], + clearcontentitem = content['mp4-clear'], + handler = new MessageHandler(keysystem, encryptedcontentitem), + configEncrypted = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: encryptedcontentitem.audio.path, + videoPath: encryptedcontentitem.video.path, + audioType: encryptedcontentitem.audio.type, + videoType: encryptedcontentitem.video.type, + initDataType: encryptedcontentitem.initDataType + }, + configClear = { audioPath: clearcontentitem.audio.path, + videoPath: clearcontentitem.video.path, + audioType: clearcontentitem.audio.type, + videoType: clearcontentitem.video.type, + }; + + runTest(configEncrypted,configClear); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html new file mode 100644 index 000000000..ed5ff2363 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, encrypted then clear</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-encrypted-clear'], + handler = new MessageHandler(keysystem, contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: 'single key, clear then encrypted content', + duration: 4 }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.html new file mode 100644 index 000000000..9846eeeec --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful playback, temporary session with DRM, mp4, validating events</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-events.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.html new file mode 100644 index 000000000..1a649d869 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, expired license</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-expired.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler(keysystem, contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html new file mode 100644 index 000000000..42d563a5d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html @@ -0,0 +1,58 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys in sequence, check readyState</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-multikey-sequential'], + handler = new MessageHandler(keysystem, contentitem), + initdatas = getProprietaryInitDatas(contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + initData: initdatas.initDatas.map(base64DecodeToUnit8Array), + variantIds: initdatas.variantIds, + duration: 5, + checkReadyState: true + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html new file mode 100644 index 000000000..0b23721b6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html @@ -0,0 +1,57 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys in sequence</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-multikey-sequential'], + handler = new MessageHandler( keysystem, contentitem ), + initdatas = getProprietaryInitDatas(contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + initData: initdatas.initDatas.map(base64DecodeToUnit8Array), + variantIds: initdatas.variantIds, + duration: 5 + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.html new file mode 100644 index 000000000..b29139ed2 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful playback, temporary session with DRM, mp4, multiple keys</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-av-multikey'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: 'multikey audio/video' + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.html new file mode 100644 index 000000000..391ebf907 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.html @@ -0,0 +1,55 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-multisession.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-multikey'], + handler = new MessageHandler( keysystem, contentitem ), + proprietaryInitDatas = getProprietaryInitDatas(contentitem), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + initData: proprietaryInitDatas.initDatas.map( base64DecodeToUnit8Array ), + variantIds: proprietaryInitDatas.variantIds, + testcase: 'multikey video' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html new file mode 100644 index 000000000..20dda66ad --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: SETMEDIAKEYS_AFTER_SRC }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html new file mode 100644 index 000000000..4f81da08d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: SETMEDIAKEYS_AFTER_UPDATE }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html new file mode 100644 index 000000000..c97c571b6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: SETMEDIAKEYS_IMMEDIATELY }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html new file mode 100644 index 000000000..c16809b85 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: SETMEDIAKEYS_ONENCRYPTED }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html new file mode 100644 index 000000000..1aafba40f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, two videos</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM server --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-two-videos.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement1" width="200px"></video> + <video id="videoelement2" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: [ document.getElementById( 'videoelement1' ), + document.getElementById( 'videoelement2' ) ], + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html new file mode 100644 index 000000000..bf970db67 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary-waitingforkey.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentitem = content['mp4-basic'], + keysystem = getSupportedKeySystem(), + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + initData: getProprietaryInitDatas(contentitem).initDatas.map( base64DecodeToUnit8Array ), + }; + + runTest(config); + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.html new file mode 100644 index 000000000..592f2a8a1 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/playback-temporary.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler( keysystem, contentitem ), + config = { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: contentitem.initDataType, + testcase: 'single key' }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html b/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html new file mode 100644 index 000000000..2656f8feb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html @@ -0,0 +1,41 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <meta name="timeout" content="long"> + <title>Encrypted Media Extensions: requestMediaKeySystemAccess tests, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/requestmediakeysystemaccess.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var contentitem = content['mp4-basic'], + keySystem = getSupportedKeySystem(), + config = { keysystem: keySystem, + audioType: contentitem.audio.type, + videoType: contentitem.video.type, + initDataType: getSupportedInitDataTypes( keySystem )[ 0 ] + }; + + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html b/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html new file mode 100644 index 000000000..b91211df4 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html @@ -0,0 +1,46 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Reset MediaSource after setMediaKeys for DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/reset-src-after-setmediakeys.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-av-multikey'], + keysystem = getSupportedKeySystem(), + config = { + video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contentItem, + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path, + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html new file mode 100644 index 000000000..d215036fa --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys again after playback with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-again-after-playback.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler(keysystem, contentitem ); + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html new file mode 100644 index 000000000..d1723b5ce --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys again after resetting src attribute on video element with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic'], + handler = new MessageHandler(keysystem, contentitem ); + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + messagehandler: handler.messagehandler, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html new file mode 100644 index 000000000..581d22f4a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html @@ -0,0 +1,44 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple at same time with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-at-same-time.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(); + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html new file mode 100644 index 000000000..7d3fe0963 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html @@ -0,0 +1,50 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple times with different mediakeys with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic']; + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html new file mode 100644 index 000000000..efc6d1978 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html @@ -0,0 +1,50 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys multiple times with the same mediakeys with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(), + contentitem = content['mp4-basic']; + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contentitem, + audioPath: contentitem.audio.path, + videoPath: contentitem.video.path, + audioType: contentitem.audio.type, + videoType: contentitem.video.type + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html new file mode 100644 index 000000000..bd78cb930 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html @@ -0,0 +1,48 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys to multiple video elements with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video1'> + <video id="videoelement1" width="200px"></video> + </div> + <div id='video2'> + <video id="videoelement2" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(); + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video1: document.getElementById('videoelement1'), + video2: document.getElementById('videoelement2'), + keysystem: keysystem, + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.html new file mode 100644 index 000000000..1a74a6236 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.html @@ -0,0 +1,44 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: setMediaKeys with DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/setmediakeys.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var keysystem = getSupportedKeySystem(); + getSupportedContent( keysystem ).then( function( contents ) { + runTest( { video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contents[ 0 ] + } ); + } ); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.html new file mode 100644 index 000000000..f6d039261 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeys attribute, setServerCertificate and setServerCertificate exception syntax for DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeys.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var keysystem = getSupportedKeySystem(); + var contentItem = content['mp4-basic'], + config = { + keysystem: keysystem, + content: contentItem, + initData: stringToUint8Array(atob(contentItem.keys[0].initData)), + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.html new file mode 100644 index 000000000..0c737df9e --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test MediaKeySession attribute and function syntax for DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeysession.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var keysystem = getSupportedKeySystem(); + var contentItem = content['mp4-basic'], + config = { + keysystem: keysystem, + content: contentItem, + initData: stringToUint8Array(atob(contentItem.keys[0].initData)), + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html new file mode 100644 index 000000000..d54e19437 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Test navigator.requestmediakeysystemaccess exception and MediaKeySystemAccess attribute syntax for DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/syntax-mediakeysystemaccess.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + <script> + var keysystem = getSupportedKeySystem(); + var contentItem = content['mp4-basic'], + config = { + keysystem: keysystem, + content: contentItem, + initData: stringToUint8Array(atob(contentItem.keys[0].initData)), + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.html b/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.html new file mode 100644 index 000000000..a344ae5c0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.html @@ -0,0 +1,44 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Unique origin with DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/unique-origin.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-av-multikey'], + keysystem = getSupportedKeySystem(), + config = { + video: document.getElementById('videoelement'), + keysystem: keysystem, + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.html b/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.html new file mode 100644 index 000000000..508afcacb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.html @@ -0,0 +1,52 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions - Waiting for a key for DRM, mp4</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/waiting-for-a-key.js></script> + + </head> + <body> + <div id='log'></div> + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + var contentItem = content['mp4-basic'], + keysystem = getSupportedKeySystem(), + handler = new MessageHandler( keysystem, contentItem ), + config = { + video: document.getElementById('videoelement'), + keysystem: keysystem, + content: contentItem, + messageHandler: handler.messagehandler, + initDataType: contentItem.initDataType, + audioType: contentItem.audio.type, + videoType: contentItem.video.type, + audioPath: contentItem.audio.path, + videoPath: contentItem.video.path, + }; + runTest(config); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.html b/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.html new file mode 100644 index 000000000..22d9a1359 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.html @@ -0,0 +1,35 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test MediaKeySession not callable immediately after CreateSession(), DRM.</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + + <!-- Message handler for DRM server --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/not-callable-after-createsession.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var config = { keysystem: getSupportedKeySystem() + }; + + runTest(config); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.html b/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.html new file mode 100644 index 000000000..a4b54dac3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.html @@ -0,0 +1,71 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Test that persistent license cannot be ingested into temporary session</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Web Platform Test Harness scripts --> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Content metadata --> + <script src=/encrypted-media/content/content-metadata.js></script> + + <!-- Message handler for DRM servers --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + <!-- The script for this specific test --> + <script src=/encrypted-media/scripts/temporary-license-type.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + var keysystem = getSupportedKeySystem(); + + getSupportedContentAndInitDataTypes( keysystem ) + .then( function( supported ) + { + // This test requires initData for supported content. + // We prefer explicit initData configured for the content, but + // otherwise we will generate initData for a supported initDataType + // FIXME: Move me to a utility function + var content, + initDataType, + initData; + + var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.keys && s.content.initDataType; } ); + if ( contentWithExplicitInitData.length > 0 ) + { + content = contentWithExplicitInitData[ 0 ].content; + initDataType = content.keys[ 0 ].initDataType; + initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData ); + } + else + { + content = supported[ 0 ].content; + initDataType = supported[ 0 ].initDataTypes[ 0 ]; + initData = getInitData( content, initDataType ); + } + + var handler = new MessageHandler( keysystem, content, 'persistent-license' ); + + runTest( { keysystem: keysystem, + content: content, + messagehandler: handler.messagehandler, + initDataType: initDataType, + initData: initData + } ); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/idlharness.html b/testing/web-platform/tests/encrypted-media/idlharness.html new file mode 100644 index 000000000..e65ad5e30 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/idlharness.html @@ -0,0 +1,51 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extentions IDL test</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/resources/WebIDLParser.js></script> + <script src=/resources/idlharness.js></script> + <script src=/encrypted-media/util/fetch.js></script> + </head> + <body> + <h1 class="instructions">Description</h1> + <p class="instructions"> + This test verifies that implementations of the Encrypted Media Extensions API match its WebIDL definition. + </p> + + <div id='log'></div> + + <script> + setup(function() { + + fetch( 'EncryptedMediaExtensions.idl') + .then( function( response ) { + if ( !response.ok ) throw new Error( 'IDL fetch failed' ); + return response.text(); + } ) + .then( function( idls ) { + + var idl_array = new IdlArray(); + idl_array.add_untested_idls("[PrimaryGlobal] interface Window {};"); + idl_array.add_untested_idls("interface Navigator {};"); + idl_array.add_untested_idls("interface ArrayBuffer {};"); + idl_array.add_untested_idls("interface HTMLMediaElement {};"); + idl_array.add_untested_idls("interface Event {};"); + idl_array.add_untested_idls("interface EventTarget {};"); + + idl_array.add_idls(idls); + + idl_array.test(); + + done(); + + } ); + + }, {explicit_done: true}); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js new file mode 100644 index 000000000..576e0ad04 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js @@ -0,0 +1,80 @@ +(function() { + + if ( /CrKey\/[0-9]+\.[0-9a-z]+\.[0-9a-z]+/i.exec( navigator.userAgent ) ) { + + var castscript = document.createElement('script'); + castscript.type = 'text/javascript'; + castscript.src = 'https://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js' + document.head.appendChild( castscript ); + + var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator ), + _setMediaKeys = HTMLMediaElement.prototype.setMediaKeys, + _load = MediaKeySession.prototype.load; + + MediaKeySession.prototype.load = function load() + { + return _load.call( this ).then( function( success ) + { + return success ? this.remove() : false; + }.bind( this ) ); + }; + + function MediaKeys( mediaKeys ) + { + this._mediaKeys = mediaKeys; + } + + MediaKeys.prototype.setServerCertificate = function setServerCertificate( certificate ) + { + return this._mediaKeys.setServerCertificate( certificate ); + }; + + MediaKeys.prototype.createSession = function createSession( sessionType ) { + + if ( sessionType === 'persistent-usage-record' ) + { + return cast.receiver.eme.KeySession.createSession( this._mediaKeys, 'persistent-release-message' ); + } + + return this._mediaKeys.createSession( sessionType ); + }; + + function MediaKeySystemAccess( access ) + { + this._access = mediaKeySystemAccess; + } + + Object.defineProperty( MediaKeySystemAccess.prototype, 'keySystem', { get: function() { return this._access.keySystem; } } ); + + MediaKeySystemAccess.prototype.getConfiguration = function getConfiguration() { return this._access.getConfiguration(); }; + + MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKeys() { + + return this._access.createMediaKey().then( function( mediaKeys ) { return new MediaKeys( mediaKeys ); } ); + + }; + + HTMLMediaElement.prototype.setMediaKeys = function setMediaKeys( mediaKeys ) + { + if ( mediaKeys instanceof MediaKeys ) + { + return _setMediaKeys.call( this, mediaKeys._mediaKeys ); + } + else + { + return _setMediaKeys.call( this, mediaKeys ); + } + }; + + navigator.requestMediaKeySystemAccess = function requestMediaKeySystemAccess( keysystem, supportedConfigurations ) { + + if ( keysystem !== 'com.chromecast.playready' ) + { + return _requestMediaKeySystemAccess( keysystem, supportedConfigurations ); + } + + return _requestMediaKeySystemAccess( keysystem, supportedConfigurations ) + .then( function( access ) { return new MediaKeySystemAccess( access ); } ); + }; + } +})();
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js new file mode 100644 index 000000000..2f11497cc --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js @@ -0,0 +1,37 @@ +(function(){ + if( navigator.userAgent.toLowerCase().indexOf('edge') === -1 + && navigator.userAgent.toLowerCase().indexOf('chrome') > -1){ + + if ( ( /chrome\/([0-9]*)\./.exec( navigator.userAgent.toLowerCase() )[1] | 0 ) < 54 ) { + + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=622956 + // Chrome does not fire the empty keystatuschange event when a session is closed + var _mediaKeySessionClose = MediaKeySession.prototype.close; + var _mediaKeySessionKeyStatusesGetter = Object.getOwnPropertyDescriptor( MediaKeySession.prototype, 'keyStatuses' ).get; + var _emptyMediaKeyStatusMap = { size: 0, + has: function() { return false; }, + get: function() { return undefined; }, + entries:function() { return []; }, // this may not be correct, I think it should be some iterator thing + keys: function() { return []; }, + values: function() { return []; }, + forEach:function() { return; } }; + + MediaKeySession.prototype.close = function close() + { + this.__closed = true; + + setTimeout( function() { + this.dispatchEvent( new Event( 'keystatuseschange' ) ); + }.bind( this ), 0 ); + + return _mediaKeySessionClose.call( this ); + }; + + Object.defineProperty( MediaKeySession.prototype, 'keyStatuses', { get: function() { + + return this.__closed ? _emptyMediaKeyStatusMap : _mediaKeySessionKeyStatusesGetter.call( this ); + + } } ); + } + } +}()); diff --git a/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js new file mode 100644 index 000000000..057ea3e03 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js @@ -0,0 +1,510 @@ +(function(){ + + // Save platform functions that will be modified + var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator ), + _setMediaKeys = HTMLMediaElement.prototype.setMediaKeys; + + // Allow us to modify the target of Events + Object.defineProperties( Event.prototype, { + target: { get: function() { return this._target || this.currentTarget; }, + set: function( newtarget ) { this._target = newtarget; } } + } ); + + var EventTarget = function(){ + this.listeners = {}; + }; + + EventTarget.prototype.listeners = null; + + EventTarget.prototype.addEventListener = function(type, callback){ + if(!(type in this.listeners)) { + this.listeners[type] = []; + } + this.listeners[type].push(callback); + }; + + EventTarget.prototype.removeEventListener = function(type, callback){ + if(!(type in this.listeners)) { + return; + } + var stack = this.listeners[type]; + for(var i = 0, l = stack.length; i < l; i++){ + if(stack[i] === callback){ + stack.splice(i, 1); + return this.removeEventListener(type, callback); + } + } + }; + + EventTarget.prototype.dispatchEvent = function(event){ + if(!(event.type in this.listeners)) { + return; + } + var stack = this.listeners[event.type]; + event.target = this; + for(var i = 0, l = stack.length; i < l; i++) { + stack[i].call(this, event); + } + }; + + function MediaKeySystemAccessProxy( keysystem, access, configuration ) + { + this._keysystem = keysystem; + this._access = access; + this._configuration = configuration; + } + + Object.defineProperties( MediaKeySystemAccessProxy.prototype, { + keysystem: { get: function() { return this._keysystem; } } + }); + + MediaKeySystemAccessProxy.prototype.getConfiguration = function getConfiguration() + { + return this._configuration; + }; + + MediaKeySystemAccessProxy.prototype.createMediaKeys = function createMediaKeys() + { + return new Promise( function( resolve, reject ) { + + this._access.createMediaKeys() + .then( function( mediaKeys ) { resolve( new MediaKeysProxy( mediaKeys ) ); }) + .catch( function( error ) { reject( error ); } ); + + }.bind( this ) ); + }; + + function MediaKeysProxy( mediaKeys ) + { + this._mediaKeys = mediaKeys; + this._sessions = [ ]; + this._videoelement = undefined; + this._onTimeUpdateListener = MediaKeysProxy.prototype._onTimeUpdate.bind( this ); + } + + MediaKeysProxy.prototype._setVideoElement = function _setVideoElement( videoElement ) + { + if ( videoElement !== this._videoelement ) + { + if ( this._videoelement ) + { + this._videoelement.removeEventListener( 'timeupdate', this._onTimeUpdateListener ); + } + + this._videoelement = videoElement; + + if ( this._videoelement ) + { + this._videoelement.addEventListener( 'timeupdate', this._onTimeUpdateListener ); + } + } + }; + + MediaKeysProxy.prototype._onTimeUpdate = function( event ) + { + this._sessions.forEach( function( session ) { + + if ( session._sessionType === 'persistent-usage-record' ) + { + session._onTimeUpdate( event ); + } + + } ); + }; + + MediaKeysProxy.prototype._removeSession = function _removeSession( session ) + { + var index = this._sessions.indexOf( session ); + if ( index !== -1 ) this._sessions.splice( index, 1 ); + }; + + MediaKeysProxy.prototype.createSession = function createSession( sessionType ) + { + if ( !sessionType || sessionType === 'temporary' ) return this._mediaKeys.createSession(); + + var session = new MediaKeySessionProxy( this, sessionType ); + this._sessions.push( session ); + + return session; + }; + + MediaKeysProxy.prototype.setServerCertificate = function setServerCertificate( certificate ) + { + return this._mediaKeys.setServerCertificate( certificate ); + }; + + function MediaKeySessionProxy( mediaKeysProxy, sessionType ) + { + EventTarget.call( this ); + + this._mediaKeysProxy = mediaKeysProxy + this._sessionType = sessionType; + this._sessionId = ""; + + // MediaKeySessionProxy states + // 'created' - After initial creation + // 'loading' - Persistent license session waiting for key message to load stored keys + // 'active' - Normal active state - proxy all key messages + // 'removing' - Release message generated, waiting for ack + // 'closed' - Session closed + this._state = 'created'; + + this._closed = new Promise( function( resolve ) { this._resolveClosed = resolve; }.bind( this ) ); + } + + MediaKeySessionProxy.prototype = Object.create( EventTarget.prototype ); + + Object.defineProperties( MediaKeySessionProxy.prototype, { + + sessionId: { get: function() { return this._sessionId; } }, + expiration: { get: function() { return NaN; } }, + closed: { get: function() { return this._closed; } }, + keyStatuses:{ get: function() { return this._session.keyStatuses; } }, // TODO this will fail if examined too early + _kids: { get: function() { return this._keys.map( function( key ) { return key.kid; } ); } }, + }); + + MediaKeySessionProxy.prototype._createSession = function _createSession() + { + this._session = this._mediaKeysProxy._mediaKeys.createSession(); + + this._session.addEventListener( 'message', MediaKeySessionProxy.prototype._onMessage.bind( this ) ); + this._session.addEventListener( 'keystatuseschange', MediaKeySessionProxy.prototype._onKeyStatusesChange.bind( this ) ); + }; + + MediaKeySessionProxy.prototype._onMessage = function _onMessage( event ) + { + switch( this._state ) + { + case 'loading': + this._session.update( toUtf8( { keys: this._keys } ) ) + .then( function() { + this._state = 'active'; + this._loaded( true ); + }.bind(this)).catch( this._loadfailed ); + + break; + + case 'active': + this.dispatchEvent( event ); + break; + + default: + // Swallow the event + break; + } + }; + + MediaKeySessionProxy.prototype._onKeyStatusesChange = function _onKeyStatusesChange( event ) + { + switch( this._state ) + { + case 'active' : + case 'removing' : + this.dispatchEvent( event ); + break; + + default: + // Swallow the event + break; + } + }; + + MediaKeySessionProxy.prototype._onTimeUpdate = function _onTimeUpdate( event ) + { + if ( !this._firstTime ) this._firstTime = Date.now(); + this._latestTime = Date.now(); + this._store(); + }; + + MediaKeySessionProxy.prototype._queueMessage = function _queueMessage( messageType, message ) + { + setTimeout( function() { + + var messageAsArray = toUtf8( message ).buffer; + + this.dispatchEvent( new MediaKeyMessageEvent( 'message', { messageType: messageType, message: messageAsArray } ) ); + + }.bind( this ) ); + }; + + function _storageKey( sessionId ) + { + return sessionId; + } + + MediaKeySessionProxy.prototype._store = function _store() + { + var data; + + if ( this._sessionType === 'persistent-usage-record' ) + { + data = { kids: this._kids }; + if ( this._firstTime ) data.firstTime = this._firstTime; + if ( this._latestTime ) data.latestTime = this._latestTime; + } + else + { + data = { keys: this._keys }; + } + + window.localStorage.setItem( _storageKey( this._sessionId ), JSON.stringify( data ) ); + }; + + MediaKeySessionProxy.prototype._load = function _load( sessionId ) + { + var store = window.localStorage.getItem( _storageKey( sessionId ) ); + if ( store === null ) return false; + + var data; + try { data = JSON.parse( store ) } catch( error ) { + return false; + } + + if ( data.kids ) + { + this._sessionType = 'persistent-usage-record'; + this._keys = data.kids.map( function( kid ) { return { kid: kid }; } ); + if ( data.firstTime ) this._firstTime = data.firstTime; + if ( data.latestTime ) this._latestTime = data.latestTime; + } + else + { + this._sessionType = 'persistent-license'; + this._keys = data.keys; + } + + return true; + }; + + MediaKeySessionProxy.prototype._clear = function _clear() + { + window.localStorage.removeItem( _storageKey( this._sessionId ) ); + }; + + MediaKeySessionProxy.prototype.generateRequest = function generateRequest( initDataType, initData ) + { + if ( this._state !== 'created' ) return Promise.reject( new InvalidStateError() ); + + this._createSession(); + + this._state = 'active'; + + return this._session.generateRequest( initDataType, initData ) + .then( function() { + this._sessionId = Math.random().toString(36).slice(2); + }.bind( this ) ); + }; + + MediaKeySessionProxy.prototype.load = function load( sessionId ) + { + if ( this._state !== 'created' ) return Promise.reject( new InvalidStateError() ); + + return new Promise( function( resolve, reject ) { + + try + { + if ( !this._load( sessionId ) ) + { + resolve( false ); + + return; + } + + this._sessionId = sessionId; + + if ( this._sessionType === 'persistent-usage-record' ) + { + var msg = { kids: this._kids }; + if ( this._firstTime ) msg.firstTime = this._firstTime; + if ( this._latestTime ) msg.latestTime = this._latestTime; + + this._queueMessage( 'license-release', msg ); + + this._state = 'removing'; + + resolve( true ); + } + else + { + this._createSession(); + + this._state = 'loading'; + this._loaded = resolve; + this._loadfailed = reject; + + var initData = { kids: this._kids }; + + this._session.generateRequest( 'keyids', toUtf8( initData ) ); + } + } + catch( error ) + { + reject( error ); + } + }.bind( this ) ); + }; + + MediaKeySessionProxy.prototype.update = function update( response ) + { + return new Promise( function( resolve, reject ) { + + switch( this._state ) { + + case 'active' : + + var message = fromUtf8( response ); + + // JSON Web Key Set + this._keys = message.keys; + + this._store(); + + resolve( this._session.update( response ) ); + + break; + + case 'removing' : + + this._state = 'closed'; + + this._clear(); + + this._mediaKeysProxy._removeSession( this ); + + this._resolveClosed(); + + delete this._session; + + resolve(); + + break; + + default: + reject( new InvalidStateError() ); + } + + }.bind( this ) ); + }; + + MediaKeySessionProxy.prototype.close = function close() + { + if ( this._state === 'closed' ) return Promise.resolve(); + + this._state = 'closed'; + + this._mediaKeysProxy._removeSession( this ); + + this._resolveClosed(); + + var session = this._session; + if ( !session ) return Promise.resolve(); + + this._session = undefined; + + return session.close(); + }; + + MediaKeySessionProxy.prototype.remove = function remove() + { + if ( this._state !== 'active' || !this._session ) return Promise.reject( new DOMException('InvalidStateError('+this._state+')') ); + + this._state = 'removing'; + + this._mediaKeysProxy._removeSession( this ); + + return this._session.close() + .then( function() { + + var msg = { kids: this._kids }; + + if ( this._sessionType === 'persistent-usage-record' ) + { + if ( this._firstTime ) msg.firstTime = this._firstTime; + if ( this._latestTime ) msg.latestTime = this._latestTime; + } + + this._queueMessage( 'license-release', msg ); + + }.bind( this ) ) + }; + + HTMLMediaElement.prototype.setMediaKeys = function setMediaKeys( mediaKeys ) + { + if ( mediaKeys instanceof MediaKeysProxy ) + { + mediaKeys._setVideoElement( this ); + return _setMediaKeys.call( this, mediaKeys._mediaKeys ); + } + else + { + return _setMediaKeys.call( this, mediaKeys ); + } + }; + + navigator.requestMediaKeySystemAccess = function( keysystem, configurations ) + { + // First, see if this is supported by the platform + return new Promise( function( resolve, reject ) { + + _requestMediaKeySystemAccess( keysystem, configurations ) + .then( function( access ) { resolve( access ); } ) + .catch( function( error ) { + + if ( error instanceof TypeError ) reject( error ); + + if ( keysystem !== 'org.w3.clearkey' ) reject( error ); + + if ( !configurations.some( is_persistent_configuration ) ) reject( error ); + + // Shallow copy the configurations, swapping out the labels and omitting the sessiontypes + var configurations_copy = configurations.map( function( config, index ) { + + var config_copy = copy_configuration( config ); + config_copy.label = index.toString(); + return config_copy; + + } ); + + // And try again with these configurations + _requestMediaKeySystemAccess( keysystem, configurations_copy ) + .then( function( access ) { + + // Create the supported configuration based on the original request + var configuration = access.getConfiguration(), + original_configuration = configurations[ configuration.label ]; + + // If the original configuration did not need persistent session types, then we're done + if ( !is_persistent_configuration( original_configuration ) ) resolve( access ); + + // Create the configuration that we will return + var returned_configuration = copy_configuration( configuration ); + + if ( original_configuration.label ) + returned_configuration.label = original_configuration; + else + delete returned_configuration.label; + + returned_configuration.sessionTypes = original_configuration.sessionTypes; + + resolve( new MediaKeySystemAccessProxy( keysystem, access, returned_configuration ) ); + } ) + .catch( function( error ) { reject( error ); } ); + } ); + } ); + }; + + function is_persistent_configuration( configuration ) + { + return configuration.sessionTypes && + ( configuration.sessionTypes.indexOf( 'persistent-usage-record' ) !== -1 + || configuration.sessionTypes.indexOf( 'persistent-license' ) !== -1 ); + } + + function copy_configuration( src ) + { + var dst = {}; + [ 'label', 'initDataTypes', 'audioCapabilities', 'videoCapabilities', 'distinctiveIdenfifier', 'persistentState' ] + .forEach( function( item ) { if ( src[item] ) dst[item] = src[item]; } ); + return dst; + } +}()); diff --git a/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js b/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js new file mode 100644 index 000000000..886144459 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js @@ -0,0 +1,144 @@ +(function() { + + // This polyfill fixes the following problems with Edge browser + // (1) Various maplike methods for keystatuses are not supported or suported incorrectly + // (2) Key Ids exposed in keystatuses are incorrect (byte swaps) + if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) { + /////////////////////////////////////////////////////////////////////////////////////////////// + // The following function is the core of this JS patch. The rest of this file is infrastructure + // required to enable this function + /////////////////////////////////////////////////////////////////////////////////////////////// + function _proxyKeyStatusesChange( event ) { + this._keyStatuses.clear(); + var keyStatuses = []; + this._session.keyStatuses.forEach( function( keyId, status ) { + var newKeyId = new Uint8Array( keyId ); + + function swap( arr, a, b ) { var t = arr[a]; arr[a] = arr[b]; arr[b] = t; } + swap( newKeyId, 0, 3 ); + swap( newKeyId, 1, 2 ); + swap( newKeyId, 4, 5 ); + swap( newKeyId, 6, 7 ); + + keyStatuses.push( { key: newKeyId, status: status, ord: arrayBufferAsString( newKeyId ) } ); + }); + + function lexicographical( a, b ) { return a < b ? -1 : a === b ? 0 : +1; } + function lexicographicalkey( a, b ) { return lexicographical( a.ord, b.ord ); } + + keyStatuses.sort( lexicographicalkey ).forEach( function( obj ) { + this._keyStatuses._set( obj.key, obj.status ); + }.bind( this ) ); + + this.dispatchEvent( event ); + }; + /////////////////////////////////////////////////////////////////////////////////////////////// + + // Override MediaKeys.createSession + var _mediaKeysCreateSession = MediaKeys.prototype.createSession; + MediaKeys.prototype.createSession = function ( sessionType ) { + return new MediaKeySession( _mediaKeysCreateSession.call( this, sessionType ) ); + }; + + // MediaKeySession proxy + function MediaKeySession( session ) { + EventTarget.call( this ); + this._session = session; + this._keyStatuses = new MediaKeyStatusMap(); + this._session.addEventListener("keystatuseschange",this._onKeyStatusesChange.bind(this)); + this._session.addEventListener("message",this.dispatchEvent.bind(this)); + } + + MediaKeySession.prototype = Object.create( EventTarget.prototype ); + + Object.defineProperties( MediaKeySession.prototype, { + sessionId: { get: function() { return this._session.sessionId; } }, + expiration: { get: function() { return this._session.expiration; } }, + closed: { get: function() { return this._session.closed; } }, + keyStatuses:{ get: function() { return this._keyStatuses; } } + }); + + [ "generateRequest", "load", "update", "remove", "close" ].forEach( function( fnname ) { + MediaKeySession.prototype[ fnname ] = function() { + return window.MediaKeySession.prototype[ fnname ].apply( this._session, arguments ); + } + } ); + + MediaKeySession.prototype._onKeyStatusesChange = _proxyKeyStatusesChange; + + // MediaKeyStatusMap proxy + // + // We need a proxy class to replace the broken MediaKeyStatusMap one. We cannot use a + // regular Map directly because we need get and has methods to compare by value not + // as references. + function MediaKeyStatusMap() { this._map = new Map(); } + + Object.defineProperties( MediaKeyStatusMap.prototype, { + size: { get: function() { return this._map.size; } }, + forEach: { get: function() { return function( f ) { return this._map.forEach( f ); } } }, + entries: { get: function() { return function() { return this._map.entries(); } } }, + values: { get: function() { return function() { return this._map.values(); } } }, + keys: { get: function() { return function() { return this._map.keys(); } } }, + clear: { get: function() { return function() { return this._map.clear(); } } } } ); + + MediaKeyStatusMap.prototype[ Symbol.iterator ] = function() { return this._map[ Symbol.iterator ]() }; + + MediaKeyStatusMap.prototype.has = function has( keyId ) { + for ( var k of this._map.keys() ) { if ( arrayBufferEqual( k, keyId ) ) return true; } + return false; + }; + + MediaKeyStatusMap.prototype.get = function get( keyId ) { + for ( var k of this._map.entries() ) { if ( arrayBufferEqual( k[ 0 ], keyId ) ) return k[ 1 ]; } + }; + + MediaKeyStatusMap.prototype._set = function _set( keyId, status ) { + this._map.set( new Uint8Array( keyId ), status ); + }; + + function arrayBufferEqual(buf1, buf2) + { + if (buf1.byteLength !== buf2.byteLength) return false; + var a1 = Array.from( new Int8Array(buf1) ), a2 = Array.from( new Int8Array(buf2) ); + return a1.every( function( x, i ) { return x === a2[i]; } ); + } + + // EventTarget + function EventTarget(){ + this.listeners = {}; + }; + + EventTarget.prototype.listeners = null; + + EventTarget.prototype.addEventListener = function(type, callback){ + if(!(type in this.listeners)) { + this.listeners[type] = []; + } + this.listeners[type].push(callback); + }; + + EventTarget.prototype.removeEventListener = function(type, callback){ + if(!(type in this.listeners)) { + return; + } + var stack = this.listeners[type]; + for(var i = 0, l = stack.length; i < l; i++){ + if(stack[i] === callback){ + stack.splice(i, 1); + return this.removeEventListener(type, callback); + } + } + }; + + EventTarget.prototype.dispatchEvent = function(event){ + if(!(event.type in this.listeners)) { + return; + } + var stack = this.listeners[event.type]; + event.target = this; + for(var i = 0, l = stack.length; i < l; i++) { + stack[i].call(this, event); + } + }; + } +})(); diff --git a/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js new file mode 100644 index 000000000..7f86f0c05 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js @@ -0,0 +1,193 @@ +(function() { + + // This polyfill fixes the following problems with Edge browser + // (1) To retrieve a persisted usage record, you must use session type 'persistent-release-message' instead of 'persistent-usage-record' + // (2) To retrieve a persisted usage record, you must call remove() after calling load() + // (3) On providing a license release acknowledgement, the session does not automatically close as is should + // (4) Retrieval of the usage record at the end of an active session is not supported + + if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) { + + var _mediaKeySystemAccessCreateMediaKeys = MediaKeySystemAccess.prototype.createMediaKeys; + _mediaKeysCreateSession = MediaKeys.prototype.createSession; + + // MediaKeySession proxy + function MediaKeySession( mediaKeys, session ) + { + EventTarget.call( this ); + + this._mediaKeys = mediaKeys; + this._session = session; + this._sessionId = undefined; + this._removing = false; + + session.addEventListener( 'message', this.dispatchEvent.bind( this ) ); + session.addEventListener( 'keystatuseschange', this.dispatchEvent.bind( this ) ); + session.closed.then( function() { if ( !this._removing ) this._resolveClosed(); }.bind ( this ) ); + + this._closed = new Promise( function( resolve ) { this._resolveClosed = resolve; }.bind( this ) ); + } + + MediaKeySession.prototype = Object.create( EventTarget.prototype ); + + Object.defineProperties( MediaKeySession.prototype, { + sessionId: { get: function() { return this._sessionId ? this._sessionId : this._session.sessionId; } }, + expiration: { get: function() { return this._session.expiration; } }, + closed: { get: function() { return this._closed; } }, + keyStatuses:{ get: function() { return this._session.keyStatuses; } } + }); + + // load() + // + // Use a surrogate 'persistent-release-message' session to obtain the release message + // + MediaKeySession.prototype.load = function load( sessionId ) + { + if ( this.sessionId ) return Promise.reject( new DOMException('InvalidAccessError') ); + + this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' ); + this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) ); + + return this._surrogate.load( sessionId ).then( function( success ) { + if (!success) return false; + + this._sessionId = sessionId; + this._removing = true; + this._session.close(); + + return this._surrogate.remove().then( function() { return true; } ); + }.bind( this ) ); + }; + + // remove() + // + // On an existing session, use a surrogate 'persistent-release-message' session to obtain the release message + // + MediaKeySession.prototype.remove = function remove() + { + if ( this._sessionId !== undefined ) return Promise.reject( new DOMException('InvalidAccessError') ); + if ( this.sessionId === undefined ) return Promise.reject( new DOMException('InvalidAccessError') ); + + this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' ); + this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) ); + this._removing = true; + this._sessionId = this._session.sessionId; + + var self = this; + + return Promise.all( [ self._session.close(), self._session.closed ] ).then( function() { + return self._surrogate.load( self._sessionId ); + }).then( function( success ) { + if ( !success ) { + throw new DOMException('InvalidAccessError'); + } + + return self._surrogate.remove(); + }).then( function() { return true; } ); + } + + // update() + // + // For a normal session, pass through, otherwise update the surrogate and close the proxy + MediaKeySession.prototype.update = function update( message ) + { + if ( !this._removing ) return this._session.update( message ); + + return this._surrogate.update( message ).then( function() { + this._sessionId = undefined; + this._resolveClosed(); + }.bind( this ) ); + }; + + // close() - pass through + // + MediaKeySession.prototype.close = function close() + { + if ( !this._removing ) return this._session.close(); + this._resolveClosed(); + return Promise.resolve(); + }; + + // generateRequest() - pass through + // + MediaKeySession.prototype.generateRequest = function generateRequest( initDataType, initData ) + { + if ( this.sessionId ) Promise.reject( new DOMException('InvalidAccessError') ); + return this._session.generateRequest( initDataType, initData ); + }; + + // Wrap PlayReady persistent-usage-record sessions in our Proxy + MediaKeys.prototype.createSession = function createSession( sessionType ) { + + var session = _mediaKeysCreateSession.call( this, sessionType ); + if ( this._keySystem !== 'com.microsoft.playready' || sessionType !== 'persistent-usage-record' ) + { + return session; + } + + return new MediaKeySession( this, session ); + + }; + + // + // Annotation polyfills - annotate not otherwise available data + // + + // Annotate MediaKeys with the keysystem + MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKeys() + { + return _mediaKeySystemAccessCreateMediaKeys.call( this ).then( function( mediaKeys ) { + mediaKeys._keySystem = this.keySystem; + return mediaKeys; + }.bind( this ) ); + }; + + // + // Utilities + // + + // Allow us to modify the target of Events + Object.defineProperties( Event.prototype, { + target: { get: function() { return this._target || this.currentTarget; }, + set: function( newtarget ) { this._target = newtarget; } } + } ); + + // Make an EventTarget base class + function EventTarget(){ + this.listeners = {}; + }; + + EventTarget.prototype.listeners = null; + + EventTarget.prototype.addEventListener = function(type, callback){ + if(!(type in this.listeners)) { + this.listeners[type] = []; + } + this.listeners[type].push(callback); + }; + + EventTarget.prototype.removeEventListener = function(type, callback){ + if(!(type in this.listeners)) { + return; + } + var stack = this.listeners[type]; + for(var i = 0, l = stack.length; i < l; i++){ + if(stack[i] === callback){ + stack.splice(i, 1); + return this.removeEventListener(type, callback); + } + } + }; + + EventTarget.prototype.dispatchEvent = function(event){ + if(!(event.type in this.listeners)) { + return; + } + var stack = this.listeners[event.type]; + event.target = this; + for(var i = 0, l = stack.length; i < l; i++) { + stack[i].call(this, event); + } + }; + } +})(); diff --git a/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js new file mode 100644 index 000000000..ce241af36 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js @@ -0,0 +1,23 @@ +(function(){ + if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){ + + // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1282142 + // Firefox does not correctly reject the Clear Key session types it does not support + var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator ); + + navigator.requestMediaKeySystemAccess = function( keysystem, configurations ) + { + if ( keysystem !== 'org.w3.clearkey' ) return _requestMediaKeySystemAccess( keysystem, configurations ); + + var supported_configurations = configurations.filter( function( c ) { + + return !c.sessionTypes || ( c.sessionTypes.length === 1 && c.sessionTypes[ 0 ] === 'temporary' ); + + } ); + + if ( supported_configurations.length === 0 ) return Promise.reject( new DOMException( 'None of the requested configurations were supported.' ) ); + + return _requestMediaKeySystemAccess( keysystem, supported_configurations ); + } + } +}());
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py b/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py new file mode 100644 index 000000000..b4248569a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +import os, re, os.path, glob + +head = re.compile( r"^(\s*</head>)", re.MULTILINE ) +runtest = re.compile( r"runTest\(\s*(\S.*?)\s*\)", re.DOTALL ) + +scripts = ''' + <!-- Polyfill files (NOTE: These are added by auto-generation script) --> + <script src=/encrypted-media/polyfill/chrome-polyfill.js></script> + <script src=/encrypted-media/polyfill/firefox-polyfill.js></script> + <script src=/encrypted-media/polyfill/edge-persistent-usage-record.js></script> + <script src=/encrypted-media/polyfill/edge-keystatuses.js></script> + <script src=/encrypted-media/polyfill/clearkey-polyfill.js></script>''' + +def process_file( infile, outfile ) : + with open( outfile, "w" ) as output : + with open( infile, "r" ) as input : + output.write( runtest.sub( r"runTest( \1, 'polyfill: ' )", head.sub( scripts + r"\1", input.read() ) ) ) + +if __name__ == '__main__' : + if (not os.getcwd().endswith('polyfill')) : + print "Please run from polyfill directory" + exit( 1 ) + + for infile in glob.glob( "../*.html" ) : + process_file( infile, os.path.basename( infile ) ) + + for infile in glob.glob( "../resources/*.html" ) : + process_file( infile, os.path.join( "resources", os.path.basename( infile ) ) )
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html new file mode 100644 index 000000000..b1bec547e --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html @@ -0,0 +1,106 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, retrieve and destroy, ClearKey</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + // Wait for a message from the main window with details of our task + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }, + assertions = [ ]; + + var _mediaKeys, + _mediaKeySession; + + config.video = document.getElementById('videoelement'); + config.messagehandler = (new MessageHandler( 'org.w3.clearkey')).messagehandler; + + function onComplete() { + window.opener.postMessage(assertions, '*'); + } + + function onFailure(error) { + assertions.push( { actual: false, expected: true, message: error.toString() } ); + onComplete(); + } + + function onMessage( messageevent ) + { + assertions.push( { expected: true, actual: messageevent instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } ); + assertions.push( { expected: 'message', actual: messageevent.type, message: "event type is message" } ); + assertions.push( { expected: 'license-release', actual: messageevent.messageType, message: "message type is license-release" } ); + + config.messagehandler( messageevent.messageType, messageevent.message ) + .then( function( response ) { + messageevent.target.update( response ).catch(onFailure); + }); + } + + function onTimeupdate(event) { + if ( config.video.currentTime > ( config.duration || 1 ) ) { + config.video.pause(); + config.video.removeAttribute('src'); + config.video.load(); + _mediaKeySession.remove(); + } + } + + function onClosed() { + // Try and reload and check this fails + var mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + mediaKeySession.load( event.data.sessionId ).then( function( success ) { + assertions.push( { expected: false, actual: success, message: "Load of removed session should fail" } ); + onComplete(); + }).catch(onFailure); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return config.video.setMediaKeys(mediaKeys); + }).then(function() { + config.video.addEventListener('timeupdate', onTimeupdate, true); + _mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + _mediaKeySession.addEventListener( 'message', onMessage ); + _mediaKeySession.closed.then(onClosed); + return _mediaKeySession.load( event.data.sessionId ); + }).then(function( success ) { + assertions.push( { actual: success, expected: true, message: "Expect load session to succeed" } ); + if ( !success ) throw new DOMException(); + return testmediasource(config); + }).then(function(source) { + config.video.src = URL.createObjectURL(source); + config.video.play(); + }) + .catch(onFailure); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html new file mode 100644 index 000000000..78ca4e1bb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html @@ -0,0 +1,74 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, retrieve and playback, ClearKey</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + // Wait for a message from the main window with details of our task + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }, + assertions = [ ]; + + var _mediaKeySession; + + config.video = document.getElementById('videoelement'); + + function onComplete() { + window.opener.postMessage(assertions, '*'); + } + + function onFailure(error) { + assertions.push( { actual: false, expected: true, message: error.toString() } ); + onComplete(); + } + + function onTimeupdate(event) { + if ( config.video.currentTime > ( config.duration || 1 ) ) { + config.video.pause(); + _mediaKeySession.close() + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + config.video.setMediaKeys(mediaKeys); + config.video.addEventListener('timeupdate', onTimeupdate, true); + _mediaKeySession = mediaKeys.createSession( 'persistent-license' ); + _mediaKeySession.closed.then(onComplete); + return _mediaKeySession.load(event.data.sessionId); + }).then(function( success ) { + if ( !success ) throw new DOMException( 'Could not load session' ); + return testmediasource(config); + }).then(function(source) { + config.video.src = URL.createObjectURL(source); + config.video.play(); + }) + .catch(onFailure); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html new file mode 100644 index 000000000..21a05e879 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html @@ -0,0 +1,107 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, retrieve and destroy, drm</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + + <!-- Message handler for DRM keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + // Wait for a message from the main window with details of our task + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }, + assertions = [ ]; + + var _mediaKeys, + _mediaKeySession; + + config.video = document.getElementById('videoelement'); + config.messagehandler = (new MessageHandler( config.keysystem, undefined, 'persistent-license' ) ).messagehandler; + +function onComplete() { + window.opener.postMessage(assertions, '*'); + } + + function onFailure(error) { + assertions.push( { actual: false, expected: true, message: error.toString() } ); + onComplete(); + } + + function onMessage( messageevent ) + { + assertions.push( { expected: true, actual: messageevent instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } ); + assertions.push( { expected: 'message', actual: messageevent.type, message: "event type is message" } ); + assertions.push( { expected: 'license-release', actual: messageevent.messageType, message: "message type is license-release" } ); + + config.messagehandler( messageevent.messageType, messageevent.message ) + .then( function( response ) { + messageevent.target.update( response ).catch(onFailure); + }); + } + + function onTimeupdate(event) { + if ( config.video.currentTime > ( config.duration || 1 ) ) { + config.video.pause(); + config.video.removeAttribute('src'); + config.video.load(); + _mediaKeySession.remove(); + } + } + + function onClosed() { + // Try and reload and check this fails + var mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + mediaKeySession.load( event.data.sessionId ).then( function( success ) { + assertions.push( { expected: false, actual: success, message: "Load of removed session should fail" } ); + onComplete(); + }).catch(onFailure); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return config.video.setMediaKeys(mediaKeys); + }).then(function() { + config.video.addEventListener('timeupdate', onTimeupdate, true); + _mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + _mediaKeySession.addEventListener( 'message', onMessage ); + _mediaKeySession.closed.then(onClosed); + return _mediaKeySession.load( event.data.sessionId ); + }).then(function( success ) { + assertions.push( { actual: success, expected: true, message: "Expect load session to succeed" } ); + if ( !success ) throw new DOMException(); + return testmediasource(config); + }).then(function(source) { + config.video.src = URL.createObjectURL(source); + config.video.play(); + }) + .catch(onFailure); + } ); + + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html new file mode 100644 index 000000000..6f3ed80ff --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html @@ -0,0 +1,72 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: persistent-license, retrieve and playback, DRM</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + <script src=/encrypted-media/util/testmediasource.js></script> + </head> + <body> + <div id='log'></div> + + <div id='video'> + <video id="videoelement" width="200px"></video> + </div> + + <script> + // Wait for a message from the main window with details of our task + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }, + assertions = [ ]; + + var _mediaKeySession; + config.video = document.getElementById('videoelement'); + + function onComplete() { + window.opener.postMessage(assertions, '*'); + } + + function onFailure(error) { + assertions.push( { actual: false, expected: true, message: error.toString() } ); + onComplete(); + } + + function onTimeupdate(event) { + if ( config.video.currentTime > ( config.duration || 1 ) ) { + config.video.pause(); + _mediaKeySession.close() + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + config.video.setMediaKeys(mediaKeys); + config.video.addEventListener('timeupdate', onTimeupdate, true); + _mediaKeySession = mediaKeys.createSession( 'persistent-license' ); + _mediaKeySession.closed.then(onComplete); + return _mediaKeySession.load(event.data.sessionId); + }).then(function( success ) { + if ( !success ) throw new DOMException( 'Could not load session' ); + return testmediasource(config); + }).then(function(source) { + config.video.src = URL.createObjectURL(source); + config.video.play(); + }) + .catch(onFailure); + } ); + + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html new file mode 100644 index 000000000..935f77748 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html @@ -0,0 +1,71 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Retrieve stored persistent-usage-record</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/drm-messagehandler.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-usage-record' ] }, + assertions = [ ], + _mediaKeys, + _mediaKeySession; + + config.messagehandler = (new MessageHandler( config.keysystem, undefined, 'persistent-usage-record' ) ).messagehandler; + + function onFailure(error) { + assertions.push( { actual: false, expected: true, message: error } ); + window.opener.postMessage(assertions, '*'); + } + + function onMessage( event ) + { + assertions.push( { expected: true, actual: event instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } ); + assertions.push( { expected: 'message', actual: event.type, message: "event type is message" } ); + assertions.push( { expected: 'license-release', actual: event.messageType, message: "message type is license-release" } ); + + config.messagehandler( event.messageType, event.message ).then( function( response ) { + event.target.update( response ).catch( onFailure ); + }); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true; + }).then( function( success ) { + _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' ); + _mediaKeySession.addEventListener( 'message', onMessage ); + _mediaKeySession.closed.then( function() { + window.opener.postMessage(assertions, '*'); + }); + return _mediaKeySession.load( event.data.sessionId ); + }).then(function( success ) { + if ( !success ) { + assertions.push( { actual: success, expected: true, message: "Error loading session" } ); + window.opener.postMessage(assertions, '*'); + } + }).catch( onFailure ); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html new file mode 100644 index 000000000..339e3c3ae --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html @@ -0,0 +1,93 @@ +<!doctype html> +<html> + <head> + <meta charset=utf-8> + <title>Encrypted Media Extensions: Retrieve stored persistent-usage-record</title> + <link rel="help" href="https://w3c.github.io/encrypted-media/"> + + <!-- Helper scripts for Encrypted Media Extensions tests --> + <script src=/encrypted-media/util/utils.js></script> + <script src=/encrypted-media/util/fetch.js></script> + <script src=/encrypted-media/util/utf8.js></script> + + <!-- Message handler for Clear Key keysystem --> + <script src=/encrypted-media/util/clearkey-messagehandler.js></script> + + </head> + <body> + <div id='log'></div> + + <script> + + window.addEventListener( 'message', function( event ) { + + var config = event.data.config, + configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-usage-record' ] }, + assertions = [ ]; + + config.messagehandler = (new MessageHandler('org.w3.keysystem')).messagehandler; + + function onMessage( event ) + { + assertions.push( { expected: true, actual: event instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } ); + assertions.push( { expected: 'message', actual: event.type, message: "event type is message" } ); + assertions.push( { expected: 'license-release', actual: event.messageType, message: "message type is license-release" } ); + + var release = fromUtf8( event.message ); + + consoleWrite( JSON.stringify( release ) ); + + assertions.push( { expected: 1, actual: release.kids.length, message: "release message contains a single key" } ); + assertions.push( { expected: true, actual: ( typeof release.firstTime === 'number' ), message: "firstTime is a number" } ); + assertions.push( { expected: true, actual: ( typeof release.latestTime === 'number' ), message: "latestTime is a number" } ); + + var duration = release.latestTime - release.firstTime; + assertions.push( { expected: true, actual: ( duration >= 2000 ), message: "duration >= 2s" } ); + assertions.push( { expected: true, actual: ( duration < 4000 ), message: "duration < 4s" } ); + + config.messagehandler( event.messageType, event.message ) + .then( function( response ) { + + event.target.update( response ).catch(function(error) { + + assertions.push( { actual: false, expected: true, message: error } ); + + window.opener.postMessage(assertions, '*'); + }); + }); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ).then(function(access) { + + return access.createMediaKeys(); + + }).then(function(mediaKeys) { + + var mediaKeySession = mediaKeys.createSession( 'persistent-usage-record' ); + + mediaKeySession.addEventListener( 'message', onMessage ); + mediaKeySession.closed.then( function() { + + window.opener.postMessage(assertions, '*'); + + }); + + return mediaKeySession.load( event.data.sessionId ); + + }).catch(function(error) { + + assertions.push( { actual: false, expected: true, message: error.toString() } ); + + window.opener.postMessage(assertions, '*'); + + }); + + + } ); + + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js b/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js new file mode 100644 index 000000000..5c7cb6e4b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js @@ -0,0 +1,35 @@ + function runTest( config, qualifier ) + { + function checkInitDataType(initDataType) + { + return isInitDataTypeSupported(initDataType).then(function(result) { + // If |initDataType| is not supported, simply succeed. + if (!result) + return Promise.resolve('Not supported'); + + return navigator.requestMediaKeySystemAccess( config.keysystem, getSimpleConfigurationForInitDataType(initDataType)) + .then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + var initData = getInitData(initDataType); + return mediaKeySession.generateRequest(initDataType, initData); + }); + }); + } + + promise_test(function() + { + return checkInitDataType('webm'); + }, testnamePrefix( qualifier, config.keysystem ) + ' support for "webm".'); + + promise_test(function() + { + return checkInitDataType('cenc'); + }, testnamePrefix( qualifier, config.keysystem ) + ' support for "cenc".'); + + promise_test(function() + { + return checkInitDataType('keyids'); + }, testnamePrefix( qualifier, config.keysystem ) + ' support for "keyids".'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js b/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js new file mode 100644 index 000000000..b34c493fd --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js @@ -0,0 +1,48 @@ +// This test is only applicable to clearkey +function runTest(config, qualifier) +{ + var testname = testnamePrefix(qualifier, config.keysystem) + ' test handling of non-ASCII responses for update()'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType) { + configuration.initDataTypes = [config.initDataType]; + } + + promise_test(function (test) { + var initDataType; + var initData; + var mediaKeySession; + var messageEventFired = false; + + return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function (access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(config.content, initDataType); + return access.createMediaKeys(); + }).then(function (mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + var eventWatcher = new EventWatcher(test, mediaKeySession, ['message']); + var promise = eventWatcher.wait_for('message'); + mediaKeySession.generateRequest(initDataType, initData); + return promise; + }).then(function (messageEvent) { + // |jwkSet| contains a non-ASCII character \uDC00. + var jwkSet = '{"keys":[{' + + '"kty":"oct",' + + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",' + + '"kid":"MDEyMzQ1Njc4O\uDC00TAxMjM0NQ"' + + '}]}'; + messageEventFired = true; + return messageEvent.target.update(stringToUint8Array(jwkSet)); + }).then(function () { + assert_unreached('Error: update() should fail because the processed message has non-ASCII character.'); + }).catch(function (error) { + if(messageEventFired){ + assert_equals(error.name, 'TypeError'); + } + else { + assert_unreached('Error: ' + error.name); + } + }); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js b/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js new file mode 100644 index 000000000..44f683eac --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js @@ -0,0 +1,52 @@ +function runTest(config, qualifier) +{ + var testname = testnamePrefix(qualifier, config.keysystem) + ' test MediaKeySession closed event.'; + + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{ + contentType: config.audioType + }], + videoCapabilities: [{ + contentType: config.videoType + }], + sessionTypes: ['temporary'] + }; + + promise_test(function (test) { + var initDataType; + var initData; + var mediaKeySession; + + return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function (access) { + initDataType = access.getConfiguration().initDataTypes[0]; + return access.createMediaKeys(); + }).then(function (mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + if(config.initData) { + initData = config.initData; + } else { + initData = stringToUint8Array(atob(config.content.keys[0].initData)); + } + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function() { + // close() should result in the closed promise being + // fulfilled. + return mediaKeySession.close(); + }).then(function (result) { + assert_equals(result, undefined); + // Wait for the session to be closed. + return mediaKeySession.closed; + }).then(function (result) { + assert_equals(result, undefined); + // Now that the session is closed, verify that the + // closed attribute immediately returns a fulfilled + // promise. + return mediaKeySession.closed; + }).then(function (result) { + assert_equals(result, undefined); + }).catch(function(error) { + assert_unreached('Error: ' + error.name); + }); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/events.js b/testing/web-platform/tests/encrypted-media/scripts/events.js new file mode 100644 index 000000000..85c86ae78 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/events.js @@ -0,0 +1,59 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + ', basic events'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function processMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'message'); + assert_in_array(event.messageType,['license-request', 'individualization-request']); + + config.messagehandler( event.messageType, event.message ).then(function(response) { + waitForEventAndRunStep('keystatuseschange', mediaKeySession, test.step_func(processKeyStatusesChange), test); + return mediaKeySession.update( response ); + }).catch(onFailure); + } + + function processKeyStatusesChange(event) + { + assert_true(event instanceof Event); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'keystatuseschange'); + test.done(); + } + + navigator.requestMediaKeySystemAccess(config.keysystem,[configuration]).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + + if (config.initDataType && config.initData) { + initData = config.initData; + } else { + initData = getInitData(config.content, initDataType); + } + + return access.createMediaKeys(); + }).then(test.step_func(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + waitForEventAndRunStep('message', mediaKeySession, test.step_func(processMessage), test); + return mediaKeySession.generateRequest(initDataType, initData); + })).catch(onFailure); + }, testname ); + +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/expiration.js b/testing/web-platform/tests/encrypted-media/scripts/expiration.js new file mode 100644 index 000000000..96b7fbfee --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/expiration.js @@ -0,0 +1,43 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + ', expiration'; + + var configuration = getSimpleConfigurationForContent(config.content); + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) { + + var _mediaKeys, + _mediaKeySession; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array(event.messageType, [ 'license-request', 'individualization-request' ] ); + + config.messagehandler(event.messageType, event.message, {expiration: config.expiration}).then(function(response) { + return event.target.update(response); + }).then(test.step_func(function() { + assert_approx_equals(event.target.expiration, config.expiration, 4000, "expiration attribute should equal provided expiration time"); + test.done(); + })).catch(onFailure); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + _mediaKeySession = _mediaKeys.createSession( 'temporary' ); + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + return _mediaKeySession.generateRequest(config.initDataType, config.initData); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js b/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js new file mode 100644 index 000000000..19e0c3555 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js @@ -0,0 +1,73 @@ +function runTest(config,qualifier) { + var tests = [ ], initData, keyId; + function push_test(keysystem, initDataType, initData, testname) { + tests.push({ keysystem: keysystem, initDataType: initDataType, initData: initData, testname: testname }); + } + + initData = new Uint8Array(70000); + push_test(config.keysystem, 'webm', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, webm, initData longer than 64Kb characters'); + + initData = new Uint8Array(70000); + push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, initData longer than 64Kb characters'); + + initData = new Uint8Array(70000); + push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, initData longer than 64Kb characters'); + + // Invalid 'pssh' box as the size specified is larger than what + // is provided. + initData = new Uint8Array([ + 0x00, 0x00, 0xff, 0xff, // size = huge + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x00, // version = 0 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, invalid initdata (invalid pssh)'); + + // Invalid data as type = 'psss'. + initData = new Uint8Array([ + 0x00, 0x00, 0x00, 0x00, // size = 0 + 0x70, 0x73, 0x73, 0x73, // 'psss' + 0x00, // version = 0 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, invalid initdata (not pssh)'); + + // Valid key ID size must be at least 1 character for keyids. + keyId = new Uint8Array(0); + initData = stringToUint8Array(createKeyIDs(keyId)); + push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, invalid initdata (too short key ID)'); + + // Valid key ID size must be less than 512 characters for keyids. + keyId = new Uint8Array(600); + initData = stringToUint8Array(createKeyIDs(keyId)); + push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, invalid initdata (too long key ID)'); + + Promise.all( tests.map(function(testspec) { + return isInitDataTypeSupported(testspec.keysystem,testspec.initDataType); + })).then(function(results) { + tests.filter(function(testspec, i) { return results[i]; } ).forEach(function(testspec) { + promise_test(function(test) { + // Create a "temporary" session for |keysystem| and call generateRequest() + // with the provided initData. generateRequest() should fail with an + // InvalidAccessError. Returns a promise that is resolved + // if the error occurred and rejected otherwise. + return navigator.requestMediaKeySystemAccess(testspec.keysystem, getSimpleConfigurationForInitDataType(testspec.initDataType)).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession("temporary"); + return mediaKeySession.generateRequest(testspec.initDataType, testspec.initData); + }).then(test.step_func(function() { + assert_unreached('generateRequest() succeeded unexpectedly'); + }), test.step_func(function(error) { + assert_equals(error.name, 'TypeError'); + })); + },testspec.testname); + }); + }); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js b/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js new file mode 100644 index 000000000..992eef5dc --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js @@ -0,0 +1,33 @@ +function runTest(config) +{ + promise_test(function (test) { + var initDataType; + var initData; + var keySystem = config.keysystem; + var invalidLicense = new Uint8Array([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77]); + var messageEventFired = false; + + return navigator.requestMediaKeySystemAccess(keySystem, getSimpleConfiguration()).then(function (access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var keySession = mediaKeys.createSession(); + var eventWatcher = new EventWatcher(test, keySession, ['message']); + var promise = eventWatcher.wait_for('message'); + keySession.generateRequest(initDataType, initData); + return promise; + }).then(function (messageEvent) { + messageEventFired = true; + return messageEvent.target.update(invalidLicense); + }).then(function () { + assert_unreached('Error: update() should fail because of an invalid license.'); + }).catch(function (error) { + if(messageEventFired) { + assert_equals(error.name, 'TypeError'); + } else { + assert_unreached('Error: ' + error.name); + } + }); + }, 'Update with invalid Clear Key license'); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js b/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js new file mode 100644 index 000000000..e9bf10e88 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js @@ -0,0 +1,103 @@ +function runTest(config,qualifier) +{ + var testname = testnamePrefix(qualifier, config.keysystem) + ', temporary, keystatuses, multiple sessions'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) configuration.initDataTypes = [config.initDataType]; + + async_test(function(test) + { + var mediaKeySession1; + var mediaKeySession2; + + // Even though key ids are uint8, using printable values so that + // they can be verified easily. + var key1 = new Uint8Array(config.content.keys[0].kid), + key2 = new Uint8Array(config.content.keys[1].kid), + variant1 = config.content.keys[0].variantId, + variant2 = config.content.keys[1].variantId; + + function onFailure(error) { + forceTestFailureFromPromise(test,error); + } + + function processMessage1(event) + { + // This should only be called for session1. + assert_equals(event.target, mediaKeySession1); + + // No keys added yet. + verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [], unexpected: [key1, key2]}); + + // Add key1 to session1. + config.messagehandler(event.messageType, event.message, {variantId:variant1}).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + + } + + function processKeyStatusesChange1(event) + { + // This should only be called for session1. + assert_equals(event.target, mediaKeySession1); + + // Check that keyStatuses contains the expected key1 only. + verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]}); + + // Now trigger a message event on session2. + mediaKeySession2.generateRequest(config.initDataType, config.initData[1]).catch(onFailure); + } + + function processMessage2(event) + { + // This should only be called for session2. + assert_equals(event.target, mediaKeySession2); + + // session2 has no keys added yet. + verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [], unexpected: [key1, key2]}); + + // session1 should still have 1 key. + verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]}); + + // Add key2 to session2. + config.messagehandler(event.messageType, event.message, {variantId:variant2}).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + } + + function processKeyStatusesChange2(event) + { + // This should only be called for session2. + assert_equals(event.target, mediaKeySession2); + + // Check that keyStatuses contains the expected key2 only. + verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [key2], unexpected: [key1]}); + + // session1 should still have 1 key. + verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]}); + + test.done(); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession1 = mediaKeys.createSession(); + mediaKeySession2 = mediaKeys.createSession(); + + // There should be no keys defined on either session. + verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [], unexpected: [key1, key2]}); + verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [], unexpected: [key1, key2]}); + + // Bind all the event handlers now. + waitForEventAndRunStep('message', mediaKeySession1, processMessage1, test); + waitForEventAndRunStep('message', mediaKeySession2, processMessage2, test); + waitForEventAndRunStep('keystatuseschange', mediaKeySession1, processKeyStatusesChange1, test); + waitForEventAndRunStep('keystatuseschange', mediaKeySession2, processKeyStatusesChange2, test); + + // Generate a request on session1. + return mediaKeySession1.generateRequest(config.initDataType, config.initData[0]); + }).catch(onFailure); + }, testname ); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js b/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js new file mode 100644 index 000000000..8d33dd421 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js @@ -0,0 +1,165 @@ +function runTest(config,qualifier) +{ + var testname = testnamePrefix(qualifier, config.keysystem) + ', temporary, keystatuses'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) + { + var mediaKeySession; + var initDataType; + var initData; + var closed = false; + + // Even though key ids are uint8, using printable values so that + // they can be verified easily. + var key1 = new Uint8Array(config.content.keys[0].kid), + key2 = new Uint8Array(config.content.keys[1].kid), + key1String = arrayBufferAsString(key1), + key2String = arrayBufferAsString(key2); + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function processMessage(event) + { + // No keys added yet. + assert_equals(mediaKeySession.keyStatuses.size, 0); + + waitForEventAndRunStep('keystatuseschange', mediaKeySession, processKeyStatusesChange, test); + + // Add keys to session + config.messagehandler(event.messageType, event.message).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + } + + function checkKeyStatusFor2Keys() + { + // Two keys added, so both should show up in |keyStatuses|. + assert_equals(mediaKeySession.keyStatuses.size, 2); + + // Check |keyStatuses| for 2 entries. + var result = []; + for (let item of mediaKeySession.keyStatuses) { + result.push({ key: arrayBufferAsString(item[0]), value: item[1] }); + } + function lexicographical( a, b ) { return a < b ? -1 : a === b ? 0 : +1; } + function lexicographicalkey( a, b ) { return lexicographical( a.key, b.key ); } + var expected1 = [{ key: key1String, value: 'usable'}, { key: key2String, value: 'usable'}].sort( lexicographicalkey ); + var expected2 = [{ key: key1String, value: 'status-pending'}, { key: key2String, value: 'status-pending'}].sort( lexicographicalkey ); + assert_in_array( JSON.stringify(result), + [ JSON.stringify(expected1),JSON.stringify(expected2) ], + "keystatuses should have the two expected keys with keystatus 'usable' or 'status-pending'"); + + // |keyStatuses| must contain both keys. + result = []; + for (var key of mediaKeySession.keyStatuses.keys()) { + result.push(arrayBufferAsString(key)); + } + assert_array_equals(result, + [key1String, key2String].sort( lexicographical ), + "keyStatuses.keys() should return an iterable over the two expected keys"); + + // Both values in |mediaKeySession| should be 'usable' or 'status-pending'. + result = []; + for (var value of mediaKeySession.keyStatuses.values()) { + result.push(value); + } + + assert_equals( result.length, 2, "keyStatuses.values() should have two elements" ); + assert_equals( result[0], result[1], "the values in keyStatuses.values() should be equal" ); + assert_in_array( result[0], [ 'usable', 'status-pending' ] ); + + // Check |keyStatuses.entries()|. + result = []; + for (var entry of mediaKeySession.keyStatuses.entries()) { + result.push({ key: arrayBufferAsString(entry[0]), value: entry[1] }); + } + assert_in_array(JSON.stringify(result), + [ JSON.stringify(expected1), JSON.stringify(expected2) ], + "keyStatuses.entries() should return an iterable over the two expected keys, with keystatus 'usable' or 'status-pending'"); + + // forEach() should return both entries. + result = []; + mediaKeySession.keyStatuses.forEach(function(status, keyId) { + result.push({ key: arrayBufferAsString(keyId), value: status }); + }); + assert_in_array(JSON.stringify(result), + [ JSON.stringify(expected1), JSON.stringify(expected2) ], + "keyStatuses.forEach() should iterate over the two expected keys, with keystatus 'usable' or 'status-pending'"); + + // has() and get() should return the expected values. + assert_true(mediaKeySession.keyStatuses.has(key1), "keyStatuses should have key1"); + assert_true(mediaKeySession.keyStatuses.has(key2), "keyStatuses should have key2"); + assert_in_array(mediaKeySession.keyStatuses.get(key1), [ 'usable', 'status-pending' ], "key1 should have status 'usable' or 'status-pending'"); + assert_in_array(mediaKeySession.keyStatuses.get(key2), [ 'usable', 'status-pending' ], "key2 should have status 'usable' or 'status-pending'"); + + // Try some invalid keyIds. + var invalid1 = key1.subarray(0, key1.length - 1); + assert_false(mediaKeySession.keyStatuses.has(invalid1), "keystatuses should not have invalid key (1)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid1), undefined, "keystatus value for invalid key should be undefined (1)"); + + var invalid2 = key1.subarray(1); + assert_false(mediaKeySession.keyStatuses.has(invalid2), "keystatuses should not have invalid key (2)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid2), undefined, "keystatus value for invalid key should be undefined (2)"); + + var invalid3 = new Uint8Array(key1); + invalid3[0] += 1; + assert_false(mediaKeySession.keyStatuses.has(invalid3), "keystatuses should not have invalid key (3)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid3), undefined, "keystatus value for invalid key should be undefined (3)"); + + var invalid4 = new Uint8Array(key1); + invalid4[invalid4.length - 1] -= 1; + assert_false(mediaKeySession.keyStatuses.has(invalid4), "keystatuses should not have invalid key (4)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid4), undefined, "keystatus value for invalid key should be undefined (4)"); + + var invalid5 = new Uint8Array(key1.length + 1); + invalid5.set(key1, 1); // First element will be 0. + assert_false(mediaKeySession.keyStatuses.has(invalid5), "keystatuses should not have invalid key (5)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid5), undefined, "keystatus value for invalid key should be undefined (5)"); + + var invalid6 = new Uint8Array(key1.length + 1); + invalid6.set(key1, 0); // Last element will be 0. + assert_false(mediaKeySession.keyStatuses.has(invalid6), "keystatuses should not have invalid key (6)"); + assert_equals(mediaKeySession.keyStatuses.get(invalid6), undefined, "keystatus value for invalid key should be undefined (6)"); + } + + function processKeyStatusesChange(event) + { + if (!closed) + { + // The first keystatuseschange (caused by update()) + // should include both keys. + checkKeyStatusFor2Keys(); + + mediaKeySession.close().catch(onFailure); + closed = true; + } + else + { + // The second keystatuseschange (caused by close()) + // should not have any keys. + assert_equals(mediaKeySession.keyStatuses.size, 0); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(test.step_func(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + + // There should be no keys defined yet. + //verifyKeyStatuses(mediaKeySession.keyStatuses, { expected: [], unexpected: [key1, key2] }); + + waitForEventAndRunStep('message', mediaKeySession, processMessage, test); + return mediaKeySession.generateRequest(config.initDataType, config.initData); + })).catch(onFailure); + }, testname ); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js b/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js new file mode 100644 index 000000000..2642c71e0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js @@ -0,0 +1,50 @@ + function runTest(config,qualifier) { + // After creation, the MediaKeySession object is not + // callable, and we should get a InvalidStateError. + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + var arbitraryResponse = new Uint8Array([0x00, 0x11]); + return mediaKeySession.update(arbitraryResponse).then(function(result) { + assert_unreached('update() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, update() immediately after createSession()'); + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + return mediaKeySession.close().then(function(result) { + assert_unreached('close() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, close() immediately after createSession()'); + + promise_test(function() + { + return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + + return mediaKeySession.remove().then(function(result) { + assert_unreached('remove() succeeded unexpectedly.'); + }).catch(function(error) { + assert_equals(error.name, 'InvalidStateError'); + }); + }); + }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, remove() immediately after createSession()'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js b/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js new file mode 100644 index 000000000..7c969a9e5 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js @@ -0,0 +1,47 @@ +function runTest(config) { + var expectedInitData = []; + expectedInitData.push(stringToUint8Array(atob(config.keys[0].initData))); + expectedInitData.push(stringToUint8Array(atob(config.keys[1].initData))); + + // Will get 2 identical events, one for audio, one for video. + var expectedEvents = 2; + var currentData; + + async_test(function (test) { + var video = config.video, + mediaSource, + onEncrypted = function (event) { + currentData = new Uint8Array(event.initData); + assert_equals(event.target, config.video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + assert_equals(event.initDataType, 'cenc'); + // At this point we do not know if the event is related to audio or video. So check for both expected init data + assert_true(checkInitData(currentData, expectedInitData[0]) || checkInitData(currentData, expectedInitData[1])); + + if (--expectedEvents === 0) { + test.done(); + } + }; + + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + return testmediasource(config).then(test.step_func(function (source) { + mediaSource = source; + config.video.src = URL.createObjectURL(mediaSource); + video.play(); + })); + }, 'encrypted fired on encrypted media file.' + ); +} + +function checkInitData(data, expectedData) { + if (data.length !== expectedData.length) { + return false; + } + for (var i = 0; i < data.length; i++) { + if (data[i] !== expectedData[i]) { + return false; + } + } + return true; +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js new file mode 100644 index 000000000..2726d8639 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js @@ -0,0 +1,93 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix( qualifier, config.keysystem ) + + ', persistent-license, ' + + /video\/([^;]*)/.exec( config.videoType )[ 1 ] + + ', playback, destroy and acknowledge'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }; + + async_test( function(test) { + + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _sessionId, + _startedReleaseSequence = false; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + config.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update(response); + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ).then( test.step_func(function() { + assert_not_equals( _mediaKeySession.sessionId, undefined, "SessionId should be defined" ); + _sessionId = _mediaKeySession.sessionId; + })).catch(onFailure); + } + + function onTimeupdate(event) { + if (_video.currentTime > ( config.duration || 1 ) && !_startedReleaseSequence) { + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + _video.removeAttribute('src'); + _video.load(); + + _startedReleaseSequence = true; + _mediaKeySession.closed.then(onClosed); + _mediaKeySession.remove().catch(onFailure); + } + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + function onClosed() { + // Try and reload and check this fails + var mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + mediaKeySession.load(_sessionId).then( test.step_func(function(success) { + assert_false( success, "Load of removed session shouold fail" ); + test.done(); + })).catch(onFailure); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + _mediaKeySession = _mediaKeys.createSession('persistent-license'); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js new file mode 100644 index 000000000..e2c0988ba --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js @@ -0,0 +1,128 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-license, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, check events'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }; + + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _receivedTimeupdateEvent = false, + _startedReleaseSequence = false, + _events = [ ]; + + function recordEventFunc( eventType ) { + return function() { _events.push( eventType ); }; + } + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals( event.target, _mediaKeySession ); + assert_true( event instanceof window.MediaKeyMessageEvent ); + assert_equals( event.type, 'message'); + + if (!_startedReleaseSequence) { + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + } else { + assert_equals(event.messageType, 'license-release'); + } + + if (event.messageType !== 'individualization-request') { + _events.push(event.messageType); + } + + config.messagehandler(event.messageType, event.message ).then(function(response) { + _events.push(event.messageType + '-response'); + return _mediaKeySession.update(response); + }).then(test.step_func(function() { + _events.push('updated'); + if (event.messageType === 'license-release') { + assert_array_equals(_events, + [ + 'generaterequest', + 'license-request', + 'license-request-response', + 'updated', + 'keystatuseschange', + 'playing', + 'remove', + 'keystatuseschange', + 'license-release', + 'license-release-response', + 'closed-promise', + 'updated' + ], + "Expected events sequence" ); + test.done(); + } + })).catch(onFailure); + } + + function onKeyStatusesChange(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.Event); + assert_equals(event.type, 'keystatuseschange'); + _events.push('keystatuseschange'); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ).then(recordEventFunc('generaterequest') + ).catch(onFailure); + } + + function onTimeupdate(event) { + if ( _video.currentTime > ( config.duration || 1 ) && !_receivedTimeupdateEvent ) { + _receivedTimeupdateEvent = true; + _video.pause(); + _video.removeAttribute('src'); + _video.load(); + + _startedReleaseSequence = true; + _mediaKeySession.remove().then(recordEventFunc('remove')).catch(onFailure); + } + } + + function onPlaying(event) { + _events.push( 'playing' ); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + _mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + waitForEventAndRunStep('keystatuseschange', _mediaKeySession, onKeyStatusesChange, test); + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.closed.then( recordEventFunc( 'closed-promise' ) ); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js new file mode 100644 index 000000000..a1361d88b --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js @@ -0,0 +1,75 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-license, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + 'playback'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }; + + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals( event.target, _mediaKeySession ); + assert_true( event instanceof window.MediaKeyMessageEvent ); + assert_equals( event.type, 'message'); + + assert_in_array( event.messageType, [ 'license-request', 'individualization-request' ] ); + + config.messagehandler(event.messageType, event.message).then( function( response ) { + return _mediaKeySession.update(response) + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ).catch(onFailure); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1)) { + _video.pause(); + test.done(); + } + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + _mediaKeySession = _mediaKeys.createSession( 'persistent-license' ); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js new file mode 100644 index 000000000..84e595ecf --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js @@ -0,0 +1,113 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-usage-record, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, check events'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-usage-record' ] }; + + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _sessionId, + _timeupdateEvent = false, + _events = [ ]; + + function recordEventFunc(eventType) { + return function() { _events.push(eventType); }; + } + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals( event.target, _mediaKeySession ); + assert_true( event instanceof window.MediaKeyMessageEvent ); + assert_equals( event.type, 'message'); + + if ( event.messageType !== 'individualization-request' ) { + _events.push( event.messageType ); + } + + config.messagehandler(event.messageType, event.message).then(function(response) { + _events.push(event.messageType + '-response'); + return _mediaKeySession.update(response); + }).then(test.step_func(function() { + _events.push('update-done'); + if (event.messageType === 'license-release') { + consoleWrite(_events); + assert_array_equals(_events, + [ 'encrypted', + 'generaterequest-done', + 'license-request', + 'license-request-response', + 'update-done', + 'keystatuseschange', + 'playing', + 'remove-done', + 'keystatuseschange', + 'license-release', + 'license-release-response', + 'closed-promise', + 'update-done' + ], + "Expected events sequence" ); + test.done(); + } + + if ( event.messageType === 'license-request' ) { + _video.setMediaKeys(_mediaKeys); + } + })).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + _events.push(event.type); + _mediaKeySession.generateRequest( config.initDataType || event.initDataType, + config.initData || event.initData ).then( function() { + _events.push( 'generaterequest-done' ); + _sessionId = _mediaKeySession.sessionId; + }).catch(onFailure); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1) && !_timeupdateEvent) { + _timeupdateEvent = true; + _video.pause(); + _mediaKeySession.remove().then(recordEventFunc('remove-done')).catch(onFailure); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, recordEventFunc('playing'), test); + + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + + _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' ); + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + waitForEventAndRunStep('keystatuseschange', _mediaKeySession, recordEventFunc('keystatuseschange'), test); + _mediaKeySession.closed.then(recordEventFunc('closed-promise')); + return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true; + }).then(function( success ) { + return testmediasource(config); + }).then(function(source) { + _video.src = URL.createObjectURL(source); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js new file mode 100644 index 000000000..966a0ae19 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js @@ -0,0 +1,102 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-usage-record, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + 'playback'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-usage-record' ] }; + + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _releaseSequence = false; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + // event instance verification failing on CastTV + // assert_true( event instanceof window.MediaKeyMessageEvent ); + assert_equals(event.type, 'message'); + + if (!_releaseSequence) + { + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + } + else + { + assert_equals(event.messageType, 'license-release'); + } + + config.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update(response); + }).then(function() { + if(event.messageType === 'license-request') { + return _video.setMediaKeys(_mediaKeys); + } else if(event.messageType === 'license-release') { + test.done(); + } + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ) + .catch(onFailure); + } + + function onClosed(event) { + _video.src = ""; + _video.setMediaKeys( null ); + } + + function onTimeupdate(event) { + if (_video.currentTime > ( config.duration || 1) && !_releaseSequence) { + _video.removeEventListener('timeupdate', onTimeupdate ); + _video.pause(); + _releaseSequence = true; + + _mediaKeySession.closed.then(test.step_func(onClosed)); + _mediaKeySession.remove().catch(onFailure); + + _video.removeEventListener('timeupdate', onTimeupdate); + } + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + _mediaKeySession = _mediaKeys.createSession('persistent-usage-record'); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true; + }).then(function(success) { + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js new file mode 100644 index 000000000..fd58d24f2 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js @@ -0,0 +1,106 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-license, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', ' + config.testcase; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-license' ] }; + + + async_test( function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _sessionId; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ).then( function() { + _sessionId = _mediaKeySession.sessionId; + }).catch(onFailure); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update(response); + }).catch(onFailure); + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1)) { + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + _video.removeAttribute('src'); + _video.load() + + _mediaKeySession.closed.then(test.step_func(onClosed)); + _mediaKeySession.close(); + } + } + + function onClosed() { + // Open a new window in which we will attempt to play with the persisted license + var win = window.open(config.windowscript); + + // Lisen for an event from the new window containing its test assertions + window.addEventListener('message', test.step_func(function(messageEvent) { + messageEvent.data.forEach(test.step_func(function(assertion) { + assert_equals(assertion.actual, assertion.expected, assertion.message); + })); + + win.close(); + test.done(); + })); + + // Delete things which can't be cloned and posted over to the new window + delete config.video; + delete config.messagehandler; + + // Post the config and session id to the new window when it is ready + win.onload = function() { + win.postMessage({config: config, sessionId: _sessionId}, '*'); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + _video.setMediaKeys( mediaKeys ); + _mediaKeySession = _mediaKeys.createSession('persistent-license'); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js new file mode 100644 index 000000000..657e02610 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js @@ -0,0 +1,108 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', persistent-usage-record, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, retrieve in new window'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'persistent-usage-record' ] }; + + + async_test( function( test ) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _sessionId, + _isClosing = false; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initDataType || event.initDataType, + config.initData || event.initData ).then( function() { + _sessionId = _mediaKeySession.sessionId; + }).catch(onFailure); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array( event.messageType,['license-request', 'individualization-request']); + + config.messagehandler( event.messageType, event.message ).then(function(response) { + return _mediaKeySession.update(response); + }).then(function() { + _video.setMediaKeys(_mediaKeys); + }).catch(onFailure); + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + function onTimeupdate(event) { + if (!_isClosing && _video.currentTime > (config.duration || 1)) { + _isClosing = true; + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + _mediaKeySession.closed.then( test.step_func(onClosed)); + _mediaKeySession.close(); + } + } + + function onClosed(event) { + _video.src = ""; + _video.setMediaKeys( null ); + + var win = window.open(config.windowscript); + window.addEventListener('message', test.step_func(function(event) { + event.data.forEach(test.step_func(function(assertion) { + assert_equals(assertion.actual, assertion.expected, assertion.message); + })); + + win.close(); + test.done(); + })); + + delete config.video; + delete config.messagehandler; + + win.onload = function() { + win.postMessage({ config: config, sessionId: _sessionId }, '*'); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(mediaKeys); + }).then(function(){ + _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' ); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true; + }).then(function(success) { + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js new file mode 100644 index 000000000..66781add3 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js @@ -0,0 +1,107 @@ +function runTest(configEncrypted,configClear,qualifier) { + + var testname = testnamePrefix(qualifier, configEncrypted.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(configEncrypted.videoType)[1] + + ', playback, encrypted and clear sources'; + + var configuration = { initDataTypes: [ configEncrypted.initDataType ], + audioCapabilities: [ { contentType: configEncrypted.audioType } ], + videoCapabilities: [ { contentType: configEncrypted.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + var playbackCount = 0, + _video = configEncrypted.video, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + configEncrypted.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update( response ); + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest(configEncrypted.initData ? configEncrypted.initDataType : event.initDataType, + configEncrypted.initData || event.initData).then(function(){ + return _video.setMediaKeys(_mediaKeys); + }).catch(onFailure); + } + + function onPlaying(event) + { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeUpdate, true); + } + + function onTimeUpdate(event) { + if (_video.currentTime < (configEncrypted.duration || 0.5)) { + return; + } + + _video.removeEventListener('timeupdate', onTimeUpdate, true); + + resetSrc().then(function(){ + if (playbackCount >= 2) { + test.done(); + } else { + playbackCount++; + startPlayback(); + } + }).catch(onFailure); + } + + function resetSrc() { + _video.pause(); + _video.removeAttribute('src'); + _video.load(); + return _video.setMediaKeys(null); + } + + function startPlayback() { + // Alternate between encrypted and unencrypted files. + if (playbackCount % 2) { + // Unencrypted files don't require MediaKeys + testmediasource( configClear ).then(function( source ) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + } else { + navigator.requestMediaKeySystemAccess(configEncrypted.keysystem, [ configuration ]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + _mediaKeySession = _mediaKeys.createSession( 'temporary' ); + }).then(function() { + return testmediasource(configEncrypted); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + } + } + + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', video, onPlaying, test); + startPlayback(); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js new file mode 100644 index 000000000..dd05ba76c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js @@ -0,0 +1,134 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, check events'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource, + _timeupdateEvent = false, + _events = [ ]; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array( event.messageType, ['license-request', 'individualization-request']); + + if (event.messageType !== 'individualization-request') { + _events.push(event.messageType); + } + + config.messagehandler(event.messageType, event.message).then(function(response) { + _events.push('license-response'); + waitForEventAndRunStep('keystatuseschange', _mediaKeySession, onKeyStatusesChange, test); + return _mediaKeySession.update( response ); + }).then(function() { + _events.push('updated'); + }).catch(onFailure); + } + + function onKeyStatusesChange(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.Event); + assert_equals(event.type, 'keystatuseschange'); + var hasKeys = false, pendingKeys = false; + _mediaKeySession.keyStatuses.forEach(function(value, keyid) { + assert_in_array(value, ['status-pending', 'usable']); + hasKeys = true; + pendingKeys = pendingKeys || (value === 'status-pending'); + }); + + if (!hasKeys) { + _events.push('emptykeyslist'); + } else if (!pendingKeys ) { + _events.push('allkeysusable'); + _video.setMediaKeys(_mediaKeys).catch(onFailure); + } else { + assert_unreached('unexpected ' + event.type + ' event'); + } + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ).then(function() { + _events.push('generaterequest'); + }).catch(onFailure); + } + + function onClosed(event) { + _events.push('closed-promise'); + setTimeout(test.step_func(function() { + assert_array_equals(_events, + [ + 'generaterequest', + 'license-request', + 'license-response', + 'updated', + 'allkeysusable', + 'playing', + 'closed', + 'closed-promise', + 'emptykeyslist' + ], + "Expected events sequence"); + test.done(); + } ), 0); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1) && !_timeupdateEvent) { + _timeupdateEvent = true; + _video.pause(); + + _mediaKeySession.closed.then(test.step_func(onClosed)); + _mediaKeySession.close().then(function() { + _events.push('closed'); + }).catch(onFailure); + } + } + + function onPlaying(event) { + _events.push('playing'); + + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + _mediaKeySession = _mediaKeys.createSession('temporary'); + + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + }).then(function() { + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js new file mode 100644 index 000000000..76fedbb7d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js @@ -0,0 +1,84 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', expired license'; + + var configuration = { initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + sessionTypes: ['temporary'] }; + + async_test(function(test) { + + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // Only create the session for the first encrypted event + if (_mediaKeySession !== undefined) return; + + var initDataType = config.initData ? config.initDataType : event.initDataType; + var initData = config.initData || event.initData; + + _mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest(initDataType, initData).catch(onFailure); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + var expiration = Date.now().valueOf(); + config.messagehandler(event.messageType, event.message, expiration).then(function(response) { + return event.target.update(response); + }).then(test.step_func(function(){ + assert_approx_equals(event.target.expiration, expiration, 2000, "expiration attribute should equal provided expiration time"); + test.step_timeout(function() { + _video.play(); + test.step_timeout(function() { test.done(); }, 2000); + }, 5000); + })).catch(onFailure); + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', test.step_func(onTimeupdate), true); + } + + function onTimeupdate(event) { + _video.pause(); + assert_unreached("Playback should not start with expired license"); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function(){ + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-multisession.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-multisession.js new file mode 100644 index 000000000..8ff98cb05 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-multisession.js @@ -0,0 +1,91 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback with multiple keys and sessions, ' + + config.testcase; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + + var _video = config.video, + _mediaKeys, + _mediaKeySessions = []; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + consoleWrite("message " + event.messageType); + assert_any(assert_equals, event.target, _mediaKeySessions); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message, {variantId: event.target._variantId}).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + } + + function onWaitingForKey(event) { + consoleWrite("waitingforkey"); + } + + function onPlaying(event) { + consoleWrite("playing"); + waitForEventAndRunStep('pause', _video, onStopped, test); + waitForEventAndRunStep('waiting', _video, onStopped, test); + waitForEventAndRunStep('stalled', _video, onStopped, test); + } + + function onStopped(event) { + consoleWrite( event.type ); + if (_mediaKeySessions.length < config.initData.length) { + var mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + mediaKeySession._variantId = config.variantIds ? config.variantIds[_mediaKeySessions.length] : undefined; + mediaKeySession.generateRequest(config.initDataType, config.initData[_mediaKeySessions.length]).catch(onFailure); + _mediaKeySessions.push(mediaKeySession); + } + } + + function onTimeupdate(event) { + if ( _video.currentTime > (config.duration || 1)) { + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function(){ + waitForEventAndRunStep('waitingforkey', _video, onWaitingForKey, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + + var mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + _mediaKeySessions.push(mediaKeySession); + mediaKeySession._variantId = config.variantIds ? config.variantIds[0] : undefined; + return mediaKeySession.generateRequest(config.initDataType, config.initData[0]); + }).then(function() { + return testmediasource(config); + }).then(function(source) { + _video.src = URL.createObjectURL(source); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js new file mode 100644 index 000000000..597e8f9b0 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js @@ -0,0 +1,122 @@ +function runTest(config,qualifier) { + + // config.initData contains a list of keys. We expect those to be needed in order and get + // one waitingforkey event for each one. + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', successful playback, temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', multiple keys, sequential' + + (config.checkReadyState ? ', readyState' : ''); + + var configuration = { initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + sessionTypes: ['temporary'] }; + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySessions = [], + _mediaSource, + _waitingForKey = false, + _playingCount = 0, + _canplayCount = 0, + _timeupdateWhileWaitingCount = 0; + + function startNewSession() { + assert_less_than(_mediaKeySessions.length, config.initData.length); + var mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + _mediaKeySessions.push(mediaKeySession); + mediaKeySession.variantId = config.variantIds ? config.variantIds[_mediaKeySessions.length - 1] : undefined; + mediaKeySession.generateRequest(config.initDataType, config.initData[_mediaKeySessions.length - 1]).catch(onFailure); + } + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + var firstMessage = !_video.src; + config.messagehandler(event.messageType, event.message, {variantId: event.target.variantId}).then(function(response) { + return event.target.update(response); + }).then(function(){ + if (firstMessage) { + _video.src = URL.createObjectURL(_mediaSource); + return _mediaSource.done; + } else if (event.target.keyStatuses.size > 0){ + _waitingForKey = false; + return Promise.resolve(); + } + }).then(function(){ + if (firstMessage) { + _video.play(); + } + }).catch(onFailure); + } + + function onWaitingForKey(event) { + _waitingForKey = true; + if (config.checkReadyState) { + // This test does not start playing until the first license has been provided, + // so this event should occur when transitioning between keys. + // Thus, the frame at the current playback position is available and readyState + // should be HAVE_CURRENT_DATA. + assert_equals(_video.readyState, _video.HAVE_CURRENT_DATA, "Video readyState should be HAVE_CURRENT_DATA on watingforkey event"); + } + startNewSession(); + } + + function onPlaying(event) { + _playingCount++; + assert_equals(_mediaKeySessions.length, _playingCount, "Should get one 'playing' event per key / session added"); + assert_less_than_equal(_playingCount, 2, "Should not get more than two 'playing' events."); + } + + function onCanPlay(event) { + _canplayCount++; + assert_equals(_mediaKeySessions.length, _canplayCount, "Should get one 'canplay' event per key / session added"); + assert_less_than_equal(_canplayCount, 2, "Should not get more than two 'canplay' events."); + } + + function onTimeupdate(event) { + // We should not receive 'timeupdate' events due to playing while waiting for a key, except + // when we first start waiting for key we should change the readyState to HAVE_CURRENT_DATA + // which will trigger the "If the previous ready state was HAVE_FUTURE_DATA or more, and + // the new ready state is HAVE_CURRENT_DATA or less" case of the readyState change + // algorithm which requires a "timeupdate" event be fired. + if (_waitingForKey) { + assert_equals(++_timeupdateWhileWaitingCount, 1, "Should only receive one timeupdate while waiting for key"); + assert_equals(_video.readyState, _video.HAVE_CURRENT_DATA, "Video readyState should be HAVE_CURRENT_DATA while wating for key"); + } + + if (_video.currentTime > config.duration) { + assert_equals(_mediaKeySessions.length, config.initData.length, "It should require all keys to reach end of content"); + assert_equals(_timeupdateWhileWaitingCount, 1, "Should have only received exactly one timeupdate while waiting for key"); + _video.pause(); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function(){ + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', test.step_func(onTimeupdate), true); + + waitForEventAndRunStep('waitingforkey', _video, onWaitingForKey, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + waitForEventAndRunStep('canplay', _video, onCanPlay, test); + + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + startNewSession(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js new file mode 100644 index 000000000..3e9027aea --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js @@ -0,0 +1,74 @@ +function runTest(config,qualifier) { + + // This test assumes one session is required for each provided initData + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback with multiple sessions, ' + + config.testcase; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySessions = [], + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_any(assert_equals, event.target, _mediaKeySessions); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message, {variantId: event.target._variantId}).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1)) { + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + waitForEventAndRunStep('playing', _video, onPlaying, test); + + config.initData.forEach(function(initData,i) { + var mediaKeySession = _mediaKeys.createSession( 'temporary' ); + mediaKeySession._variantId = config.variantIds ? config.variantIds[i] : undefined; + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + _mediaKeySessions.push(mediaKeySession); + mediaKeySession.generateRequest(config.initDataType, initData).catch(onFailure); + } ); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js new file mode 100644 index 000000000..c3da83c1a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js @@ -0,0 +1,103 @@ +SETMEDIAKEYS_IMMEDIATELY = 0; +SETMEDIAKEYS_AFTER_SRC = 1; +SETMEDIAKEYS_ONENCRYPTED = 2; +SETMEDIAKEYS_AFTER_UPDATE = 3; + +function runTest(config,qualifier) { + + var testcase = (config.testcase === SETMEDIAKEYS_IMMEDIATELY) ? 'setMediaKeys first' + : (config.testcase === SETMEDIAKEYS_AFTER_SRC) ? 'setMediaKeys after setting video.src' + : (config.testcase === SETMEDIAKEYS_ONENCRYPTED) ? 'setMediaKeys in encrypted event' + : (config.testcase === SETMEDIAKEYS_AFTER_UPDATE) ? 'setMediaKeys after updating session' + : 'unknown'; + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, ' + testcase; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array( event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update( response ); + }).then(function() { + if (config.testcase === SETMEDIAKEYS_AFTER_UPDATE) { + return _video.setMediaKeys(_mediaKeys); + } + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + var promise = ( config.testcase === SETMEDIAKEYS_ONENCRYPTED ) + ? _video.setMediaKeys(_mediaKeys) + : Promise.resolve(); + + promise.then( function() { + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + return _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ); + }).catch(onFailure); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1)) { + _video.pause(); + test.done(); + } + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(test.step_func(function(mediaKeys) { + _mediaKeys = mediaKeys; + if ( config.testcase === SETMEDIAKEYS_IMMEDIATELY ) { + return _video.setMediaKeys( _mediaKeys ); + } + })).then(function(){ + _mediaKeySession = _mediaKeys.createSession( 'temporary' ); + + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + + return testmediasource(config); + }).then(test.step_func(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + + if (config.testcase === SETMEDIAKEYS_AFTER_SRC) { + return _video.setMediaKeys(_mediaKeys); + } + })).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js new file mode 100644 index 000000000..7d63cd604 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js @@ -0,0 +1,81 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback two videos'; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + promise_test(function(test) + { + var promises = config.video.map(function(video) { return play_video_as_promise(test,video); }); + return Promise.all(promises); + + }, testname); + + function play_video_as_promise(test, _video) { + var _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array( event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message).then(function(response) { + return _mediaKeySession.update(response); + }).catch(onFailure); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + + _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData).catch(onFailure); + } + + function wait_for_timeupdate_message(video) + { + return new Promise(function(resolve) { + video.addEventListener('timeupdate', function listener(event) { + if (event.target.currentTime > (config.duration || 1)) + { + video.removeEventListener('timeupdate', listener); + resolve(event); + } + }); + }); + }; + + return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + _mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + return wait_for_timeupdate_message(_video); + }).catch(onFailure); + } +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js new file mode 100644 index 000000000..8fc67bff1 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js @@ -0,0 +1,69 @@ +function runTest(config,qualifier) { + + // config.initData contains a list of keys. We expect those to be needed in order and get + // one waitingforkey event for each one. + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', successful playback, temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', waitingforkey event, ' + + config.initData.length + ' key' + (config.initData.length > 1 ? 's' : ''); + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + var _video = config.video, + _mediaKeys, + _mediaKeySessions = [], + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + config.messagehandler( event.messageType, event.message ).then( function( response ) { + return event.target.update( response ); + }).catch(onFailure); + } + + function onWaitingForKey(event) { + // Expect one waitingforkey event for each initData we were given + assert_less_than(_mediaKeySessions.length, config.initData.length); + var mediaKeySession = _mediaKeys.createSession( 'temporary' ); + waitForEventAndRunStep('message', mediaKeySession, onMessage, test); + _mediaKeySessions.push(mediaKeySession); + mediaKeySession.generateRequest(config.initDataType, config.initData[_mediaKeySessions.length - 1]).catch(onFailure); + } + + function onTimeupdate(event) { + if (_video.currentTime > (config.duration || 1)) { + assert_equals(_mediaKeySessions.length, config.initData.length); + _video.removeEventListener('timeupdate', onTimeupdate); + _video.pause(); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function(){ + waitForEventAndRunStep('waitingforkey', _video, onWaitingForKey, test); + + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js new file mode 100644 index 000000000..53dd3e65d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js @@ -0,0 +1,80 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + + ', temporary, ' + + /video\/([^;]*)/.exec(config.videoType)[1] + + ', playback, ' + config.testcase; + + var configuration = { initDataTypes: [ config.initDataType ], + audioCapabilities: [ { contentType: config.audioType } ], + videoCapabilities: [ { contentType: config.videoType } ], + sessionTypes: [ 'temporary' ] }; + + async_test(function(test) { + + var _video = config.video, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onEncrypted(event) { + assert_equals(event.target, _video); + assert_true(event instanceof window.MediaEncryptedEvent); + assert_equals(event.type, 'encrypted'); + + // Only create the session for the firs encrypted event + if (_mediaKeySession !== undefined) return; + + var initDataType = config.initData ? config.initDataType : event.initDataType; + var initData = config.initData || event.initData; + + _mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( initDataType, initData ).catch(onFailure); + } + + function onMessage(event) { + assert_equals(event.target, _mediaKeySession); + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.type, 'message'); + + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message).then(function(response) { + return event.target.update(response); + }).catch(onFailure); + } + + function onPlaying(event) { + // Not using waitForEventAndRunStep() to avoid too many + // EVENT(onTimeUpdate) logs. + _video.addEventListener('timeupdate', onTimeupdate, true); + } + + function onTimeupdate(event) { + if ( _video.currentTime > (config.duration || 1)) { + _video.pause(); + test.done(); + } + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(mediaKeys) { + _mediaKeys = mediaKeys; + return _video.setMediaKeys(_mediaKeys); + }).then(function(){ + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + waitForEventAndRunStep('playing', _video, onPlaying, test); + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + _video.src = URL.createObjectURL(_mediaSource); + _video.play(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js b/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js new file mode 100644 index 000000000..98be50bb8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js @@ -0,0 +1,320 @@ +function runTest(config, qualifier) { + + var prefix = testnamePrefix(qualifier, config.keysystem) + ', requestMediaKeySystemAccess: '; + + function expect_error(keySystem, configurations, expectedError, testname) { + + var audioCapabilities = configurations.length ? configurations[0].audioCapabilities : undefined, + videoCapabilities = configurations.length ? configurations[0].videoCapabilities : undefined, + audiocontenttypes = audioCapabilities ? audioCapabilities.map( function(ac) { return "'" + ac.contentType + "'"; } ).join(',') : '', + videocontenttypes = videoCapabilities ? videoCapabilities.map( function(ac) { return "'" + ac.contentType + "'"; } ).join(',') : '', + modifiedtestname = testname.replace( '%ks', keySystem ).replace( '%audiocontenttype', audiocontenttypes ).replace( '%videocontenttype', videocontenttypes ); + + promise_test(function(test) { + return navigator.requestMediaKeySystemAccess(keySystem, configurations).then(function(a) { + assert_unreached('Unexpected requestMediaKeySystemAccess() success.'); + }, function(e) { + assert_equals(e.name, expectedError); + }); + }, prefix + modifiedtestname + ' should result in ' + expectedError ); + } + + function assert_subset(actual, expected, path) { + if (typeof expected == 'string') { + assert_equals(actual, expected, path); + } else { + if (expected.hasOwnProperty('length')) { + assert_equals(actual.length, expected.length, path + '.length'); + } + for (property in expected) { + assert_subset(actual[property], expected[property], path + '.' + property); + } + } + } + + function expect_config(keySystem, configurations, expectedConfiguration, testname) { + promise_test(function(test) { + return navigator.requestMediaKeySystemAccess(keySystem, configurations).then(function(a) { + assert_subset(a.getConfiguration(), expectedConfiguration, testname + ': '); + }); + }, testname); + } + + // Tests for Key System. + expect_error('', [{}], 'InvalidAccessError', 'Empty Key System (%ks)'); + expect_error('com.example.unsupported', [{}], 'NotSupportedError', 'Unsupported Key System (%ks)'); + expect_error(config.keysystem + '.', [{}], 'NotSupportedError', 'Key System ending in "." (%ks)'); + expect_error(config.keysystem.toUpperCase(), [{}], 'NotSupportedError', 'Capitalized Key System (%ks)'); + expect_error(config.keysystem + '\u028F', [{}], 'NotSupportedError', 'Non-ASCII Key System (%ks)'); + + // Parent of Clear Key not supported. + expect_error(config.keysystem.match(/^(.*?)\./)[1], [{}], 'NotSupportedError', 'Root domain of Key System alone (%ks)'); + expect_error(config.keysystem.match(/^(.*?)\./)[0], [{}], 'NotSupportedError', 'Root domain of Key System, with dot (%ks)'); + expect_error(config.keysystem.match(/^(.*?\..*?)\./)[1], [{}], 'NotSupportedError', 'Domain of Key System along (%ks)'); + expect_error(config.keysystem.match(/^(.*?\..*?)\./)[0], [{}], 'NotSupportedError', 'Domain of Key System, with dot (%ks)'); + + // Child of Clear Key not supported. + expect_error(config.keysystem+'.foo', [{}], 'NotSupportedError', 'Child of Key System'); + + // Prefixed Clear Key not supported. + expect_error('webkit-'+config.keysystem, [{}], 'NotSupportedError', 'Prefixed Key System'); + + // Incomplete names. + expect_error(config.keysystem.substr(0,7)+config.keysystem.substr(8), [{}], 'NotSupportedError', 'Incomplete Key System name (%ks)'); + expect_error(config.keysystem.substr(0,config.keysystem.length-1), [{}], 'NotSupportedError', 'Incomplete Key System name (%ks)'); + + // Spaces in key system name not supported. + expect_error(' '+config.keysystem, [{}], 'NotSupportedError', 'Leading space in Key System name (%ks)'); + expect_error(config.keysystem.substr(0,6) + ' ' + config.keysystem.substr(6), [{}], 'NotSupportedError', 'Extra space in Key System name (%ks)'); + expect_error(config.keysystem + ' ', [{}], 'NotSupportedError', 'Trailing space in Key System name (%ks)'); + + // Extra dots in key systems names not supported. + expect_error('.' + config.keysystem, [{}], 'NotSupportedError', 'Leading dot in Key System name (%ks)'); + expect_error(config.keysystem.substr(0,6) + '.' + config.keysystem.substr(6), [{}], 'NotSupportedError', 'Trailing dot in Key System name (%ks)'); + expect_error(config.keysystem + '.', [{}], 'NotSupportedError', 'Trailing dot in Key System name (%ks)'); + + // Key system name is case sensitive. + if (config.keysystem !== config.keysystem.toUpperCase()) { + expect_error(config.keysystem.toUpperCase(), [{}], 'NotSupportedError', 'Key System name is case sensitive (%ks)'); + } + + if (config.keysystem !== config.keysystem.toLowerCase()) { + expect_error(config.keysystem.toLowerCase(), [{}], 'NotSupportedError', 'Key System name is case sensitive (%ks)'); + } + + // Tests for trivial configurations. + expect_error(config.keysystem, [], 'InvalidAccessError', 'Empty supportedConfigurations'); + expect_config(config.keysystem, [{}], {}, 'Empty configuration'); + + // Various combinations of supportedConfigurations. + expect_config(config.keysystem, [{ + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + }], { + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + }, 'Basic supported configuration'); + + expect_config(config.keysystem, [{ + initDataTypes: ['fakeidt', config.initDataType], + audioCapabilities: [{contentType: 'audio/fake'}, {contentType: config.audioType}], + videoCapabilities: [{contentType: 'video/fake'}, {contentType: config.videoType}], + }], { + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + }, 'Partially supported configuration'); + + expect_config(config.keysystem, [{ + audioCapabilities: [{contentType: config.audioType}], + }], { + audioCapabilities: [{contentType: config.audioType}], + }, 'Supported audio codec'); + + expect_config(config.keysystem, [{ + audioCapabilities: [{contentType: config.audioType.replace(/^(.*?);(.*)/, "$1; $2")}], + }], { + audioCapabilities: [{contentType: config.audioType.replace(/^(.*?);(.*)/, "$1; $2")}], + }, 'ContentType formatting must be preserved'); + + expect_error(config.keysystem, [{ + audioCapabilities: [{contentType: 'audio/webm; codecs=fake'}], + }], 'NotSupportedError', 'Unsupported audio codec (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [{contentType: 'video/webm; codecs=fake'}], + }], 'NotSupportedError', 'Unsupported video codec (%videocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs=mp4a'}, + {contentType: 'audio/webm; codecs=mp4a.40.2'} + ], + }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [{contentType: config.videoType}], + }], 'NotSupportedError', 'Video codec specified in audio field (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: config.audioType}], + }], 'NotSupportedError', 'Audio codec specified in video field (%videocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs=avc1'}, + {contentType: 'audio/webm; codecs=avc1.42e01e'} + ], + }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/mp4; codecs=vorbis'} + ], + }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)'); + + expect_config(config.keysystem, [ + {initDataTypes: ['fakeidt']}, + {initDataTypes: [config.initDataType]} + ], {initDataTypes: [config.initDataType]}, 'Two configurations, one supported'); + + expect_config(config.keysystem, [ + {initDataTypes: [config.initDataType]}, + {} + ], {initDataTypes: [config.initDataType]}, 'Two configurations, both supported'); + + // Audio MIME type does not support video codecs. + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs="vp8,vorbis"'}, + {contentType: 'audio/webm; codecs="vorbis, vp8"'}, + {contentType: 'audio/webm; codecs="vp8"'} + ], + }], 'NotSupportedError', 'Audio MIME type does not support video codecs (webm) (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/mp4; codecs="avc1"'}, + {contentType: 'audio/mp4; codecs="avc1.4d401e"'}, + ], + }], 'NotSupportedError', 'Audio MIME type does not support video codecs (mp4) (%audiocontenttype)'); + + // Video MIME type does not support audio codecs. + expect_error(config.keysystem, [{ + videoCapabilities: [ + {contentType: 'video/webm; codecs="vp8,vorbis"'}, + {contentType: 'video/webm; codecs="vorbis, vp8"'}, + {contentType: 'video/webm; codecs="vorbis"'} + ], + }], 'NotSupportedError', 'Video MIME type does not support audio codecs (webm) (%videocontenttype)'); + + expect_error(config.keysystem, [{ + videoCapabilities: [ + {contentType: 'video/mp4; codecs="mp4a"'}, + {contentType: 'video/mp4; codecs="mp4a.40.2"'} + ], + }], 'NotSupportedError', 'Video MIME type does not support audio codecs (mp4) (%videocontenttype)'); + + // WebM does not support AVC1/AAC. + expect_error(config.keysystem, [{ + audioCapabilities: [ + {contentType: 'audio/webm; codecs="aac"'}, + {contentType: 'audio/webm; codecs="avc1"'}, + {contentType: 'audio/webm; codecs="vp8,aac"'} + ], + }], 'NotSupportedError', 'WebM audio does not support AVC1/AAC (%audiocontenttype)'); + + expect_error(config.keysystem, [{ + videoCapabilities: [ + {contentType: 'video/webm; codecs="aac"'}, + {contentType: 'video/webm; codecs="avc1"'}, + {contentType: 'video/webm; codecs="vp8,aac"'} + ], + }], 'NotSupportedError', 'WebM video does not support AVC1/AAC (%videocontenttype)'); + + // Extra space is allowed in contentType. + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: ' ' + config.videoType}], + }], { + videoCapabilities: [{contentType: ' ' + config.videoType}], + }, 'Leading space in contentType'); + + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?);(.*)/, "$1 ;$2")}], + }], { + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?);(.*)/, "$1 ;$2")}], + }, 'Space before ; in contentType'); + + + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType + ' '}], + }], { + videoCapabilities: [{contentType: config.videoType + ' '}], + }, 'Trailing space in contentType'); + + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\")(.*)/, "$1 $2")}], + }], { + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\")(.*)/, "$1 $2")}], + }, 'Space at start of codecs parameter'); + + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\".*)\"/, "$1 \"")}], + }], { + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\".*)\"/, "$1 \"")}], + }, 'Space at end of codecs parameter'); + + // contentType is not case sensitive (except the codec names). + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: 'V' + config.videoType.substr(1)}], + }], { + videoCapabilities: [{contentType: 'V' + config.videoType.substr(1)}], + }, 'Video/' ); + + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?)c(odecs.*)/, "$1C$2")}], + }], { + videoCapabilities: [{contentType: config.videoType.replace( /^(.*?)c(odecs.*)/, "$1C$2")}], + }, 'Codecs='); + + var t = config.videoType.match(/(.*?)(;.*)/); + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: t[1].toUpperCase() + t[2]}], + }], { + videoCapabilities: [{contentType: t[1].toUpperCase() + t[2]}], + }, 'Upper case MIME type'); + + t = config.videoType.match(/(.*?)codecs(.*)/); + expect_config(config.keysystem, [{ + videoCapabilities: [{contentType: t[1] + 'CODECS' + t[2]}], + }], { + videoCapabilities: [{contentType: t[1] + 'CODECS' + t[2]}], + }, 'CODECS='); + + // Unrecognized attributes are not allowed. + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: 'video/webm; foo="bar"'}], + }], 'NotSupportedError', 'Unrecognized foo with webm (%videocontenttype)'); + + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: 'video/mp4; foo="bar"'}], + }], 'NotSupportedError', 'Unrecognized foo with mp4 (%videocontenttype)'); + + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: config.videoType + '; foo="bar"'}], + }], 'NotSupportedError', 'Unrecognized foo with codecs (%videocontenttype)'); + + // Invalid contentTypes. + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: 'fake'}], + }], 'NotSupportedError', 'contentType: %videocontenttype'); + + expect_error(config.keysystem, [{ + audioCapabilities: [{contentType: 'audio/fake'}], + }], 'NotSupportedError', 'contentType: %audiocontenttype'); + + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: 'video/fake'}], + }], 'NotSupportedError', 'contentType: %videocontenttype'); + + // The actual codec names are case sensitive. + t = config.videoType.match( /(.*?codecs=\")(.*?\")(.*)/ ); + if (t[2] !== t[2].toUpperCase()) { + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: t[1] + t[2].toUpperCase() + t[3] }], + }], 'NotSupportedError', 'contentType: %videocontenttype'); + } + + if (t[2] !== t[2].toLowerCase()) { + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: t[1] + t[2].toLowerCase() + t[3] }], + }], 'NotSupportedError', 'contentType: %videocontenttype'); + } + + // Extra comma is not allowed in codecs. + expect_error(config.keysystem, [{ + videoCapabilities: [{contentType: t[1] + ',' + t[2] + t[3] }], + }], 'NotSupportedError', 'contentType: %videocontenttype'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js new file mode 100644 index 000000000..acddd8dd5 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js @@ -0,0 +1,61 @@ +function runTest(config) +{ + async_test(function(test) { + var mediaKeys; + var mediaSource; + var encryptedEventIndex = 0; + var video = config.video; + var keysystem = config.keysystem; + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{ + contentType: config.audioType + }], + videoCapabilities: [{ + contentType: config.videoType + }], + sessionTypes: ['temporary'] + }; + + assert_not_equals(video, null); + + var onEncrypted = function(event) { + ++encryptedEventIndex; + assert_equals(video.mediaKeys, mediaKeys); + + // This event is fired once for the audio stream and once + // for the video stream each time .src is set. + if (encryptedEventIndex === 2) { + // Finished first video; Create new media source and wait for two more encrypted events + return testmediasource(config).then(function (source) { + video.src = URL.createObjectURL(source); + }).catch(function (error) { + forceTestFailureFromPromise(test, error) + }); + } else if (encryptedEventIndex === 4) { + // Finished second video. + test.done(); + } + }; + + // Create a MediaKeys object and assign it to video. + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]).then(test.step_func(function (access) { + assert_equals(access.keySystem, keysystem); + return access.createMediaKeys(); + })).then(test.step_func(function (result) { + mediaKeys = result; + assert_not_equals(mediaKeys, null); + return video.setMediaKeys(mediaKeys); + })).then(test.step_func(function () { + assert_equals(video.mediaKeys, mediaKeys); + return testmediasource(config); + })).then(function (source) { + waitForEventAndRunStep('encrypted', video, onEncrypted, test); + mediaSource = source; + video.src = URL.createObjectURL(mediaSource); + }).catch(function (error) { + forceTestFailureFromPromise(test, error); + }); + + }, 'Reset src after setMediaKeys().'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js new file mode 100644 index 000000000..772bfcaa8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js @@ -0,0 +1,79 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix(qualifier, config.keysystem) + + ', setmediakeys again after playback'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) { + var _video = config.video, + _access, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + config.messagehandler(event.messageType, event.message).then( function(response) { + _mediaKeySession.update(response).catch(onFailure).then(function() { + _video.play(); + }); + }); + } + + function onEncrypted(event) { + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ) + .catch(onFailure); + } + + function playVideo() + { + return new Promise(function(resolve) { + _mediaKeySession = _mediaKeys.createSession('temporary'); + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + _video.src = URL.createObjectURL(_mediaSource); + resolve('success'); + }); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + _access = access; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true; + }).then(function( success ) { + return testmediasource(config); + }).then(function(source) { + _mediaSource = source; + return playVideo(); + }).then(function(results) { + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + return waitForEvent('playing', _video); + }).then(test.step_func(function(result) { + assert_false(_video.ended); + return _video.setMediaKeys(_mediaKeys); + })).then(function() { + // Able to change MediaKeys while playing. + // This is not required to fail. + _video.src=''; + test.done(); + }, test.step_func(function(error) { + assert_in_array(error.name, ['InvalidStateError','NotSupportedError']); + _video.src=''; + test.done(); + })).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js new file mode 100644 index 000000000..a87060098 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js @@ -0,0 +1,79 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix(qualifier, config.keysystem) + + ', setmediakeys again after resetting src'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) { + var _video = config.video, + _access, + _mediaKeys, + _mediaKeySession, + _mediaSource; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function onMessage(event) { + config.messagehandler(event.messageType, event.message).then(function(response) { + _mediaKeySession.update(response).catch(onFailure).then(function() { + _video.play(); + }); + }); + } + + function onEncrypted(event) { + waitForEventAndRunStep('message', _mediaKeySession, onMessage, test); + _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType, + config.initData || event.initData ) + .catch(onFailure); + } + + function playVideoAndWaitForTimeupdate() + { + return new Promise(function(resolve) { + testmediasource(config).then(function(source) { + _mediaKeySession = _mediaKeys.createSession('temporary'); + _video.src = URL.createObjectURL(source); + }); + _video.addEventListener('timeupdate', function listener(event) { + if (event.target.currentTime < (config.duration || 1)) + return; + _video.removeEventListener('timeupdate', listener); + resolve('success'); + }); + }); + } + + waitForEventAndRunStep('encrypted', _video, onEncrypted, test); + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + _access = access; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true; + }).then(function( success ) { + return playVideoAndWaitForTimeupdate(); + }).then(function(results) { + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + _video.src = ''; + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true; + }).then(function( success ) { + return playVideoAndWaitForTimeupdate(); + }).then(function() { + _video.src = ''; + test.done(); + }).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js new file mode 100644 index 000000000..6d67d95b1 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js @@ -0,0 +1,59 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix(qualifier, config.keysystem) + + ', setmediakeys at same time'; + + var configuration = getSimpleConfigurationForContent(config.content); + + async_test(function(test) { + var _video = config.video, + _access, + _mediaKeys1, + _mediaKeys2, + _mediaKeys3, + _mediaKeys4, + _mediaKeys5; + + // Test MediaKeys assignment. + assert_equals(_video.mediaKeys, null); + assert_equals(typeof _video.setMediaKeys, 'function'); + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function setMediaKeys(mediaKeys) { + return _video.setMediaKeys(mediaKeys) + .then(function() {return 1}, function() {return 0}) + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + _access = access; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys1 = result; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys2 = result; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys3 = result; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys4 = result; + return _access.createMediaKeys(); + }).then(function(result) { + _mediaKeys5 = result; + return Promise.all([ + setMediaKeys(_mediaKeys1), + setMediaKeys(_mediaKeys2), + setMediaKeys(_mediaKeys3), + setMediaKeys(_mediaKeys4), + setMediaKeys(_mediaKeys5) + ]); + }).then(function(results) { + var sum = results.reduce((a, b) => a + b, 0); + assert_in_array(sum,[1,5]); + test.done(); + }).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js new file mode 100644 index 000000000..6f0bd93f2 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js @@ -0,0 +1,86 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix( qualifier, config.keysystem ) + + ', setmediakeys multiple times with different mediakeys'; + + var configuration = getSimpleConfigurationForContent( config.content ); + + async_test (function (test) { + var _video = config.video, + _access, + _mediaKeys1, + _mediaKeys2, + fail; + + // Test MediaKeys assignment. + assert_equals(_video.mediaKeys, null); + assert_equals(typeof _video.setMediaKeys, 'function'); + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + _access = access; + return _access.createMediaKeys(); + }).then(test.step_func(function(result) { + _mediaKeys1 = result; + assert_not_equals(_mediaKeys1, null); + // Create a second mediaKeys. + return _access.createMediaKeys(); + })).then(test.step_func(function(result) { + _mediaKeys2 = result; + assert_not_equals(_mediaKeys2, null); + // Set _mediaKeys1 on video. + return _video.setMediaKeys(_mediaKeys1); + })).then(test.step_func(function() { + assert_equals(_video.mediaKeys, _mediaKeys1); + // Set _mediaKeys2 on video (switching MediaKeys). + return _video.setMediaKeys(_mediaKeys2); + })).then(test.step_func(function() { + assert_equals(_video.mediaKeys, _mediaKeys2); + // Clear mediaKeys from video. + return _video.setMediaKeys(null); + })).then(test.step_func(function() { + assert_equals(_video.mediaKeys, null); + // Set _mediaKeys1 on video again. + return _video.setMediaKeys(_mediaKeys1); + })).then(test.step_func(function() { + assert_equals(_video.mediaKeys, _mediaKeys1); + return testmediasource(config); + })).then(function(source) { + // Set src attribute on Video Element + _video.src = URL.createObjectURL(source); + // Set mediaKeys2 on video element (switching MediaKeys) need not + // fail after src attribute is set. + return _video.setMediaKeys(_mediaKeys2); + })).then(test.step_func(function() { + // Switching setMediaKeys after setting src attribute on video element + // is not required to fail. + assert_equals(_video2.mediaKeys, _mediaKeys2); + fail = false; + return Promise.resolve(); + }, test.step_func(function(error) { + fail = true; + assert_equals(_video.mediaKeys, _mediaKeys1); + assert_in_array(error.name, ['InvalidStateError','NotSupportedError']); + assert_not_equals(error.message, ''); + // Return something so the promise resolves properly. + return Promise.resolve(); + })).then(function() { + // Set null mediaKeys on video (clearing MediaKeys) not + // supported after src attribute is set. + return _video.setMediaKeys(null); + }).then(test.step_func(function() { + assert_unreached('Clearing mediaKeys after setting src should have failed.'); + }), test.step_func(function(error) { + if(fail) { + assert_equals(_video.mediaKeys, _mediaKeys1); + } else { + assert_equals(_video.mediaKeys, _mediaKeys2); + } + assert_is_array(error.name, ['InvalidStateError','ReferenceError']); + assert_not_equals(error.message, ''); + test.done(); + })).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js new file mode 100644 index 000000000..f6af8267f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js @@ -0,0 +1,46 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix( qualifier, config.keysystem ) + + ', setmediakeys multiple times with the same mediakeys'; + + var configuration = getSimpleConfigurationForContent( config.content ); + + if ( config.initDataType && config.initData ) { + configuration.initDataTypes = [ config.initDataType ]; + } + + async_test (function (test) { + var _video = config.video, + _mediaKeys; + + // Test MediaKeys assignment. + assert_equals(_video.mediaKeys, null); + assert_equals(typeof _video.setMediaKeys, 'function'); + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + return access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + // Set mediaKeys for first time on video should work. + return _video.setMediaKeys(_mediaKeys); + }).then(function(result) { + assert_equals(_video.mediaKeys, _mediaKeys); + // Set mediaKeys on video again should return a resolved promise. + return _video.setMediaKeys(_mediaKeys); + }).then(function (result) { + assert_equals(_video.mediaKeys, _mediaKeys); + return testmediasource(config); + }).then(function(source) { + // Set src attribute on Video Element + _video.src = URL.createObjectURL(source); + // Set mediaKeys again on video should still return a resolved promise. + return _video.setMediaKeys(_mediaKeys); + }).then(function() { + assert_equals(_video.mediaKeys, _mediaKeys); + test.done(); + }).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js new file mode 100644 index 000000000..d98f33f0c --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js @@ -0,0 +1,54 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix(qualifier, config.keysystem) + + ', setMediaKeys to multiple video elements'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if ( config.initDataType && config.initData ) { + configuration.initDataTypes = [ config.initDataType ]; + } + + async_test (function (test) { + var _video1 = config.video1, + _video2 = config.video2, + _mediaKeys; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + assert_equals(access.keySystem, config.keysystem) + return access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + assert_not_equals(_mediaKeys, null); + assert_equals(typeof _mediaKeys.createSession, 'function'); + return _video1.setMediaKeys(_mediaKeys); + }).then(function(result) { + assert_not_equals(_video1.mediaKeys, null); + assert_true(_video1.mediaKeys === _mediaKeys); + // The specification allows this to fail, but it is not required to fail. + return _video2.setMediaKeys(_mediaKeys); + }).then(function(result) { + // Second setMediaKeys is not required to fail. + assert_true(_video2.mediaKeys === _mediaKeys); + return Promise.resolve(); + }, function(error) { + assert_equals(error.name, 'QuotaExceededError'); + assert_not_equals(error.message, ''); + // Return something so the promise resolves properly. + return Promise.resolve(); + }).then(function() { + // Now clear it from video1. + return _video1.setMediaKeys(null); + }).then(function() { + // Should be assignable to video2. + return _video2.setMediaKeys(_mediaKeys); + }).then(function(result) { + assert_not_equals(_video2.mediaKeys, null); + assert_true(_video2.mediaKeys === _mediaKeys); + test.done(); + }).catch(onFailure); + }, testname); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js new file mode 100644 index 000000000..34b124e31 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js @@ -0,0 +1,49 @@ +function runTest(config, qualifier) { + var testname = testnamePrefix( qualifier, config.keysystem ) + + ', setMediaKeys'; + + var configuration = getSimpleConfigurationForContent( config.content ); + + if ( config.initDataType && config.initData ) { + configuration.initDataTypes = [ config.initDataType ]; + } + + async_test (function (test) { + var _video = config.video, + _mediaKeys; + + // Test MediaKeys assignment. + assert_equals(_video.mediaKeys, null); + assert_equals(typeof _video.setMediaKeys, 'function'); + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + // Try setting mediaKeys to null. + _video.setMediaKeys(null).then(function(result) { + assert_equals(_video.mediaKeys, null); + + // setMediaKeys should fail when setting to the wrong type of object - Date. + return _video.setMediaKeys(new Date()); + }).then(function (result) { + assert_unreached('setMediaKeys should fail when setting to wrong kind of object (Date)'); + }, function(error) { + // The error should be TypeError. + assert_equals(error.name, 'setMediaKeys should return a TypeError when setting to wrong kind of object (Date)'); + return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]); + }).then(function(access) { + assert_equals(access.keySystem, config.keysystem) + return access.createMediaKeys(); + }).then(function(result) { + _mediaKeys = result; + assert_not_equals(_mediaKeys, null); + assert_equals(typeof _mediaKeys.createSession, 'function'); + return _video.setMediaKeys(_mediaKeys); + }).then(function(result) { + assert_not_equals(_video.mediaKeys, null); + assert_equals(_video.mediaKeys, _mediaKeys); + test.done(); + }).catch(onFailure); + }, testname); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js new file mode 100644 index 000000000..4ec6551e8 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js @@ -0,0 +1,184 @@ +function runTest(config) { + var keysystem = config.keysystem; + var testname = testnamePrefix(null, config.keysystem); + var initDataType = config.initDataType; + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + sessionTypes: ['temporary'] + }; + + function createMediaKeysAttributeTest() { + return new Promise(function (resolve, reject) { + var access; + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function'); + assert_true(isTypeSupported, "initDataType should be supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (result) { + access = result; + assert_equals(access.keySystem, keysystem); + return access.createMediaKeys(); + }).then(function (mediaKeys) { + assert_not_equals(mediaKeys, null); + assert_equals(typeof mediaKeys, 'object'); + assert_equals(typeof mediaKeys.createSession, 'function'); + assert_equals(typeof mediaKeys.setServerCertificate, 'function'); + + // Test creation of a second MediaKeys. + // The extra parameter is ignored. + return access.createMediaKeys('extra'); + }).then(function (mediaKeys) { + assert_not_equals(mediaKeys, null); + assert_equals(typeof mediaKeys, 'object'); + assert_equals(typeof mediaKeys.createSession, 'function'); + assert_equals(typeof mediaKeys.setServerCertificate, 'function'); + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + + promise_test(function() { + return createMediaKeysAttributeTest(); + }, testname + ' test MediaKeys attribute syntax'); + + var kSetServerCertificateExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(); + } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(''); + } + }, + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(null); + } + }, + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(undefined); + } + }, + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(1); + } + }, + // Empty array. + { + exception: 'TypeError', + func: function (mk) { + return mk.setServerCertificate(new Uint8Array(0)); + } + } + ]; + + + function setServerCertificateTestExceptions() { + return new Promise(function(resolve, reject) { + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function'); + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var promises = kSetServerCertificateExceptionsTestCases.map(function (testCase) { + return test_exception(testCase, mediaKeys); + }); + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return setServerCertificateTestExceptions(); + }, testname + ' test MediaKeys setServerCertificate() exceptions.'); + + // All calls to |func| in this group resolve. setServerCertificate with these cert may either resolve with true + // for clearkey or throw a DOMException. + var kSetServerCertificateTestCases = [ + { + // Pass in ArrayBufferView + func: function (mk) { + var cert = new Uint8Array(200); + assert_true(ArrayBuffer.isView(cert)); + + return new Promise(function (resolve, reject) { + mk.setServerCertificate(cert).then(function (value) { + resolve(value); + }).catch(function (error) { + if (Object.prototype.toString.call(error) === "[object DOMException]") { + resolve(false); + } + }); + }) + }, + expected: false + }, + { + // Pass in ArrayBuffer. + func: function (mk) { + var cert = new ArrayBuffer(200); + assert_false(ArrayBuffer.isView(cert)); + return new Promise(function (resolve) { + mk.setServerCertificate(cert).then(function (resolveValue) { + resolve(resolveValue); + }).catch(function (error) { + if (Object.prototype.toString.call(error) === "[object DOMException]") { + resolve(false); + } + }); + }) + }, + expected: false + } + ]; + function setServerCertificateTest(){ + return new Promise(function(resolve, reject){ + var expected_result; + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function'); + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var promises = kSetServerCertificateTestCases.map(function (testCase) { + return testCase.func.call(null, mediaKeys); + }); + expected_result = kSetServerCertificateTestCases.map(function (testCase) { + return testCase.expected; + }); + assert_not_equals(promises.length, 0); + return Promise.all(promises); + }).then(function (result) { + assert_array_equals(result, expected_result); + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return setServerCertificateTest(); + }, testname + ' test MediaKeys setServerCertificate() syntax with non-empty certificate.'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js new file mode 100644 index 000000000..3663a7b93 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js @@ -0,0 +1,445 @@ +function runTest(config) { + var keysystem = config.keysystem; + var testname = testnamePrefix(null, config.keysystem); + var initDataType = config.initDataType; + var initData = config.initData; + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + sessionTypes: ['temporary'] + }; + + var kTypeSpecificGenerateRequestExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name the first 60 characters is not + // enough to determine which test failed. Even with the + // shortened name, the error message for the last couple of + // tests is the same. + + // Too few parameters. + { + exception: 'TypeError', + func: function (mk1, type) { + return mk1.createSession().generateRequest(type); + } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function (mk2, type) { + return mk2.createSession().generateRequest(type, ''); + } + }, + { + exception: 'TypeError', + func: function (mk3, type) { + return mk3.createSession().generateRequest(type, null); + } + }, + { + exception: 'TypeError', + func: function (mk4, type) { + return mk4.createSession().generateRequest(type, undefined); + } + }, + { + exception: 'TypeError', + func: function (mk5, type) { + return mk5.createSession().generateRequest(type, 1); + } + }, + // (new Uint8Array(0)) returns empty array. So 'TypeError' should + // be returned. + { + exception: 'TypeError', + func: function (mk6, type) { + return mk6.createSession().generateRequest(type, new Uint8Array(0)); + } + } + ]; + function generateRequestTestExceptions(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var mp4SessionPromises = kTypeSpecificGenerateRequestExceptionsTestCases.map(function (testCase) { + return test_exception(testCase, mediaKeys, initDataType, initData); + }); + assert_not_equals(mp4SessionPromises.length, 0); + return Promise.all(mp4SessionPromises); + }).then(function (result) { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return generateRequestTestExceptions(); + }, testname + ' test MediaKeySession generateRequest() exceptions.'); + + var kLoadExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function (mk1) { + return mk1.createSession('temporary').load(); + } + }, + { + exception: 'TypeError', + func: function (mk3) { + return mk3.createSession('temporary').load(''); + } + }, + { + exception: 'TypeError', + func: function (mk4) { + return mk4.createSession('temporary').load(1); + } + }, + { + exception: 'TypeError', + func: function (mk5) { + return mk5.createSession('temporary').load('!@#$%^&*()'); + } + }, + { + exception: 'TypeError', + func: function (mk6) { + return mk6.createSession('temporary').load('1234'); + } + } + ]; + function loadTestExceptions(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var sessionPromises = kLoadExceptionsTestCases.map(function (testCase) { + return test_exception(testCase, mediaKeys); + }); + assert_not_equals(sessionPromises.length, 0); + return Promise.all(sessionPromises); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return loadTestExceptions(); + }, testname + ' test MediaKeySession load() exceptions.'); + + // All calls to |func| in this group are supposed to succeed. + // However, the spec notes that some things are optional for + // Clear Key. In particular, support for persistent sessions + // is optional. Since some implementations won't support some + // features, a NotSupportedError is treated as a success + // if |isNotSupportedAllowed| is true. + var kCreateSessionTestCases = [ + // Use the default sessionType. + { + func: function(mk) { return mk.createSession(); }, + isNotSupportedAllowed: false + }, + // Try variations of sessionType. + { + func: function(mk) { return mk.createSession('temporary'); }, + isNotSupportedAllowed: false + }, + { + func: function(mk) { return mk.createSession(undefined); }, + isNotSupportedAllowed: false + }, + { + // Since this is optional, some Clear Key implementations + // will succeed, others will return a "NotSupportedError". + // Both are allowed results. + func: function(mk) { return mk.createSession('persistent-license'); }, + isNotSupportedAllowed: true + }, + // Try additional parameter, which should be ignored. + { + func: function(mk) { return mk.createSession('temporary', 'extra'); }, + isNotSupportedAllowed: false + } + ]; + // This function checks that calling generateRequest() works for + // various sessions. |testCase.func| creates a MediaKeySession + // object, and then generateRequest() is called on that object. It + // allows for an NotSupportedError to be generated and treated as a + // success, if allowed. See comment above kCreateSessionTestCases. + function test_generateRequest(testCase, mediaKeys, type, initData) { + var mediaKeySession; + try { + mediaKeySession = testCase.func.call(null, mediaKeys); + } catch (e) { + assert_true(testCase.isNotSupportedAllowed); + assert_equals(e.name, 'NotSupportedError'); + return Promise.resolve('not supported'); + } + return mediaKeySession.generateRequest(type, initData); + } + function generateRequestForVariousSessions(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType should be supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var mp4SessionPromises = kCreateSessionTestCases.map(function (testCase) { + return test_generateRequest(testCase, mediaKeys, initDataType, initData); + }); + assert_not_equals(mp4SessionPromises.length, 0); + return Promise.all(mp4SessionPromises); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return generateRequestForVariousSessions(); + }, testname + ' test if MediaKeySession generateRequest() resolves for various sessions'); + + var kUpdateSessionExceptionsTestCases = [ + // Tests in this set use a shortened parameter name due to + // format_value() only returning the first 60 characters as the + // result. With a longer name (mediaKeySession) the first 60 + // characters is not enough to determine which test failed. + + // Too few parameters. + { + exception: 'TypeError', + func: function (s) { + return s.update(); + } + }, + // Invalid parameters. + { + exception: 'TypeError', + func: function (s) { + return s.update(''); + } + }, + { + exception: 'TypeError', + func: function (s) { + return s.update(null); + } + }, + { + exception: 'TypeError', + func: function (s) { + return s.update(undefined); + } + }, + { + exception: 'TypeError', + func: function (s) { + return s.update(1); + } + }, + // (new Uint8Array(0)) returns empty array. So 'TypeError' should + // be returned. + { + exception: 'TypeError', + func: function (s) { + return s.update(new Uint8Array(0)); + } + } + ]; + + function updateTestExceptions(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + var mp4SessionPromises = kUpdateSessionExceptionsTestCases.map(function (testCase) { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.generateRequest(initDataType, initData).then(function (result) { + return test_exception(testCase, mediaKeySession); + }); + }); + assert_not_equals(mp4SessionPromises.length, 0); + return Promise.all(mp4SessionPromises); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return updateTestExceptions(); + }, testname + ' test MediaKeySession update() exceptions.'); + + function create_close_exception_test(mediaKeys) { + var mediaKeySession = mediaKeys.createSession(); + return mediaKeySession.close().then(function (result) { + assert_unreached('close() should not succeed if session uninitialized'); + }).catch(function (error) { + assert_equals(error.name, 'InvalidStateError'); + // Return something so the promise resolves. + return Promise.resolve(); + }); + } + function closeTestExceptions(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + return create_close_exception_test(mediaKeys); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }); + } + promise_test(function() { + return closeTestExceptions(); + }, testname + ' test MediaKeySession close() exceptions.'); + + function create_remove_exception_test(mediaKeys, type, initData) { + // remove() on an uninitialized session should fail. + var mediaKeySession = mediaKeys.createSession('temporary'); + return mediaKeySession.remove().then(function (result) { + assert_unreached('remove() should not succeed if session uninitialized'); + }, function (error) { + assert_equals(error.name, 'InvalidStateError'); + }); + } + function removeTestException(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + return create_remove_exception_test(mediaKeys, initDataType, initData); + }).then(function () { + resolve(); + }).catch(function (error) { + reject(error); + }); + }); + } + promise_test(function() { + return removeTestException(); + }, testname + ' test MediaKeySession remove() exceptions.'); + + // All calls to |func| in this group are supposed to succeed. + // However, the spec notes that some things are optional for + // Clear Key. In particular, support for persistent sessions + // is optional. Since some implementations won't support some + // features, a NotSupportedError is treated as a success + // if |isNotSupportedAllowed| is true. + var kCreateSessionTestCases = [ + // Use the default sessionType. + { + func: function (mk) { + return mk.createSession(); + }, + isNotSupportedAllowed: false + }, + // Try variations of sessionType. + { + func: function (mk) { + return mk.createSession('temporary'); + }, + isNotSupportedAllowed: false + }, + { + func: function (mk) { + return mk.createSession(undefined); + }, + isNotSupportedAllowed: false + }, + { + // Since this is optional, some Clear Key implementations + // will succeed, others will return a "NotSupportedError". + // Both are allowed results. + func: function (mk) { + return mk.createSession('persistent-license'); + }, + isNotSupportedAllowed: true + }, + // Try additional parameter, which should be ignored. + { + func: function (mk) { + return mk.createSession('temporary', 'extra'); + }, + isNotSupportedAllowed: false + } + ]; + + // This function checks that calling |testCase.func| creates a + // MediaKeySession object with some default values. It also + // allows for an NotSupportedError to be generated and treated as a + // success, if allowed. See comment above kCreateSessionTestCases. + function test_createSession(testCase, mediaKeys) { + var mediaKeySession; + try { + mediaKeySession = testCase.func.call(null, mediaKeys); + } catch (e) { + assert_true(testCase.isNotSupportedAllowed); + return; + } + assert_equals(typeof mediaKeySession, 'object'); + assert_equals(typeof mediaKeySession.addEventListener, 'function'); + assert_equals(typeof mediaKeySession.sessionId, 'string'); + assert_equals(typeof mediaKeySession.expiration, 'number'); + assert_equals(typeof mediaKeySession.closed, 'object'); + assert_equals(typeof mediaKeySession.keyStatuses, 'object'); + assert_equals(typeof mediaKeySession.onkeystatuseschange, 'object'); + assert_equals(typeof mediaKeySession.onmessage, 'object'); + assert_equals(typeof mediaKeySession.generateRequest, 'function'); + assert_equals(typeof mediaKeySession.load, 'function'); + assert_equals(typeof mediaKeySession.update, 'function'); + assert_equals(typeof mediaKeySession.close, 'function'); + assert_equals(typeof mediaKeySession.remove, 'function'); + assert_equals(mediaKeySession.sessionId, ''); + } + function createSessionTest(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + kCreateSessionTestCases.map(function (testCase) { + test_createSession(testCase, mediaKeys); + }); + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return createSessionTest(); + }, testname + ' test MediaKeySession attribute syntax.'); + + +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js new file mode 100644 index 000000000..045494164 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js @@ -0,0 +1,144 @@ +function runTest(config) { + var keysystem = config.keysystem; + var testname = testnamePrefix(null, config.keysystem); + var initDataType = config.initDataType; + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{contentType: config.audioType}], + videoCapabilities: [{contentType: config.videoType}], + sessionTypes: ['temporary'] + }; + + var kRequestMediaKeySystemAccessExceptionsTestCases = [ + // Too few parameters. + { + exception: 'TypeError', + func: function () { + return navigator.requestMediaKeySystemAccess(); + } + }, + { + exception: 'TypeError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem); + } + }, + // Invalid key systems. Note that JavaScript converts all these + // values into strings by calling toString(), so they fail due + // to the key system not being supported, not due to the type. + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(null, [{}]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(undefined, [{}]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(1, [{}]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(new Uint8Array(0), [{}]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess('', [{}]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess('unsupported', [{}]); + } + }, + // Non-ASCII names. + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem + '\u263A', [{}]); + } + }, + // Empty sequence of MediaKeySystemConfiguration. + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem, []); + } + }, + // Invalid sequences of MediaKeySystemConfigurations. + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem, {}); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem, "invalid"); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem, [{}, 6]); + } + }, + { + exception: 'NotSupportedError', + func: function () { + return navigator.requestMediaKeySystemAccess(keysystem, ["invalid", "upsupported"]); + } + } + ]; + + function requestMediaKeySystemAccessTestExceptions(){ + return new Promise(function(resolve, reject){ + var createPromises = kRequestMediaKeySystemAccessExceptionsTestCases.map(function (testCase) { + return test_exception(testCase); + }); + Promise.all(createPromises).then(function (result) { + resolve(); + }).catch(function (error) { + reject(error); + }); + }) + } + promise_test(function() { + return requestMediaKeySystemAccessTestExceptions(); + }, testname + ' test requestMediaKeySystemAccess() exceptions.'); + + function requestMediaKeySystemAccessTestAttributes(){ + return new Promise(function(resolve, reject){ + isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) { + assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function'); + assert_true(isTypeSupported, "initDataType not supported"); + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]); + }).then(function (access) { + assert_not_equals(access, null); + assert_equals(typeof access, 'object'); + assert_equals(access.keySystem, keysystem); + assert_equals(typeof access.getConfiguration, 'function'); + assert_equals(typeof access.createMediaKeys, 'function'); + resolve(); + }).catch(function(error){ + reject(error); + }) + }) + } + promise_test(function() { + return requestMediaKeySystemAccessTestAttributes(); + }, testname + ' test MediaKeySystemAccess attribute syntax.'); + +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js b/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js new file mode 100644 index 000000000..cb0b0e67f --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js @@ -0,0 +1,61 @@ +function runTest(config,qualifier) { + + var testname = testnamePrefix(qualifier, config.keysystem) + ', cannot load persistent license into temporary session'; + + var configuration = getSimpleConfigurationForContent(config.content); + + if (config.initDataType && config.initData) { + configuration.initDataTypes = [config.initDataType]; + } + + async_test(function(test) + { + var initDataType; + var initData; + var mediaKeySession; + + function onFailure(error) { + forceTestFailureFromPromise(test, error); + } + + function processMessage(event) + { + assert_true(event instanceof window.MediaKeyMessageEvent); + assert_equals(event.target, mediaKeySession); + assert_equals(event.type, 'message'); + assert_in_array(event.messageType, ['license-request', 'individualization-request']); + + config.messagehandler(event.messageType, event.message).then( function(response) { + mediaKeySession.update(response).then( test.step_func( function() { + if ( event.messageType !== 'license-request' ) { + return; + } + assert_unreached( "Update with incorrect license type should fail" ) + } ) ).catch( test.step_func( function( error ) { + if ( event.messageType !== 'license-request' ) { + forceTestFailureFromPromise(test, error); + return; + } + + assert_equals(error.name, 'TypeError' ); + test.done(); + } ) ); + }).catch(onFailure); + } + + navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + if (config.initDataType && config.initData) { + initData = config.initData; + } else { + initData = getInitData(config.content, initDataType); + } + return access.createMediaKeys(); + }).then(test.step_func(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession('temporary'); + waitForEventAndRunStep('message', mediaKeySession, test.step_func(processMessage), test); + return mediaKeySession.generateRequest(initDataType, initData); + })).catch(onFailure); + }, testname ); + +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js b/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js new file mode 100644 index 000000000..523eb84a6 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js @@ -0,0 +1,64 @@ +function runTest(config) { + // When the sandbox attribute is present on an iframe, it will + // treat the content as being from a unique origin. So try to + // call createMediaKeys() inside an iframe and it should fail. + + function load_iframe(src, sandbox) { + return new Promise(function (resolve) { + var iframe = document.createElement('iframe'); + iframe.onload = function () { + resolve(iframe); + }; + iframe.sandbox = sandbox; + iframe.src = src; + document.documentElement.appendChild(iframe); + }); + } + + function wait_for_message() { + return new Promise(function (resolve) { + self.addEventListener('message', function listener(e) { + resolve(e.data); + self.removeEventListener('message', listener); + }); + }); + } + + promise_test(function (test) { + var script = 'data:text/html,' + + '<script>' + + ' window.onmessage = function(e) {' + + ' navigator.requestMediaKeySystemAccess("' + config.keysystem + '", [{' + + ' initDataTypes: [\"' + config.initDataType + '\"],' + + ' audioCapabilities: [' + + ' { contentType:\'' + config.audioType + '\'},' + + ' ]' + + ' }]).then(function(access) {' + + ' return access.createMediaKeys();' + + ' }).then(function(mediaKeys) {' + + ' window.parent.postMessage({result: \'allowed\'}, \'*\');' + + ' }, function(error) {' + + ' window.parent.postMessage({result: \'failed\'}, \'*\');' + + ' });' + + ' };' + + '<\/script>'; + + // Verify that this page can create a MediaKeys first. + navigator.requestMediaKeySystemAccess(config.keysystem, [{ + initDataTypes: [config.initDataType], + audioCapabilities: [ + {contentType: config.audioType}, + ] + }]).then(function (access) { + return access.createMediaKeys(); + }).then(function (mediaKeys) { + // Success, so now create the iframe and try there. + return load_iframe(script, 'allow-scripts') + }).then(function (iframe) { + iframe.contentWindow.postMessage({}, '*'); + return wait_for_message(); + }).then(function (message) { + assert_equals(message.result, 'failed'); + }); + }, 'Unique origin is unable to create MediaKeys'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js b/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js new file mode 100644 index 000000000..b5adaf7f1 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js @@ -0,0 +1,45 @@ +function runTest(config) +{ + // This test passes |response| to update() as a JSON Web Key Set. + // CDMs other than Clear Key won't expect |response| in this format. + promise_test(function(test) { + var initDataType; + var initData; + var keySystem = config.keysystem; + var mediaKeySession; + + function createReallyLongJWKSet() + { + // This is just a standard JWKSet with a lot of + // extra items added to the end. Key ID and key + // doesn't really matter. + var jwkSet = '{"keys":[{' + + '"kty":"oct",' + + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",' + + '"kid":"MDEyMzQ1Njc4OTAxMjM0NQ"' + + '}]'; + return jwkSet + ',"test":"unknown"'.repeat(4000) + '}'; + } + + return navigator.requestMediaKeySystemAccess(keySystem, getSimpleConfiguration()).then(function(access) { + initDataType = access.getConfiguration().initDataTypes[0]; + initData = getInitData(initDataType); + return access.createMediaKeys(); + }).then(function(mediaKeys) { + mediaKeySession = mediaKeys.createSession(); + var eventWatcher = new EventWatcher(test, mediaKeySession, ['message']); + var promise = eventWatcher.wait_for('message'); + mediaKeySession.generateRequest(initDataType, initData); + return promise; + }).then(function () { + var jwkSet = createReallyLongJWKSet(); + assert_greater_than(jwkSet.length, 65536); + var jwkSetArray = stringToUint8Array(jwkSet); + return mediaKeySession.update(jwkSetArray); + }).then(function () { + assert_unreached('update() with a response longer than 64Kb succeed'); + }).catch(function (error) { + assert_equals(error.name, 'TypeError'); + }); + }, 'update() with invalid response (longer than 64Kb characters) should fail.'); +} diff --git a/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js b/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js new file mode 100644 index 000000000..fee70e24a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js @@ -0,0 +1,166 @@ +function runTest(config) +{ + // For debugging timeouts, keep track of the number of the + // various events received. + var debugEncryptedEventFired = false; + var debugWaitingForKeyEventFired = false; + var debugTimeUpdateEventCount = 0; + var debugMessage = ''; + + // Set global option explicit_timeout to true and control + // the timeout in the promise test below. + setup({ + explicit_timeout: true + }); + + promise_test(function (test) { + var video = config.video; + var keysystem = config.keysystem; + var configuration = { + initDataTypes: [config.initDataType], + audioCapabilities: [{ + contentType: config.audioType + }], + videoCapabilities: [{ + contentType: config.videoType + }], + sessionTypes: ['temporary'] + }; + var initData; + var initDataType; + var mediaKeySession; + // As this code doesn't wait for the 'message' event for clearkey to avoid + // race conditions with 'waitingforkey', specify the key ID and + // key used by the encrypted content. + var keyId = new Uint8Array(config.content.keys[0].kid); + var rawKey = new Uint8Array(config.content.keys[0].key); + // Use the message handler for non clearkey drm + var handler = config.messageHandler || null; + + // Override timeout() to use custom message instead of default + // message "Test timed out" + test.timeout = function () { + var message = 'timeout. message = ' + debugMessage + + ', encrypted: ' + debugEncryptedEventFired + + ', waitingforkey: ' + debugWaitingForKeyEventFired + + ', timeupdate count: ' + debugTimeUpdateEventCount; + + this.timeout_id = null; + this.set_status(this.TIMEOUT, message); + this.phase = this.phases.HAS_RESULT; + this.done(); + }; + + return navigator.requestMediaKeySystemAccess(keysystem, [configuration]).then(function (access) { + debugMessage = 'createMediaKeys()'; + return access.createMediaKeys(); + }).then(function (mediaKeys) { + debugMessage = 'setMediaKeys()'; + return video.setMediaKeys(mediaKeys); + }).then(function () { + return testmediasource(config); + }).then(function (source) { + debugMessage = 'wait_for_encrypted_event()'; + mediaSource = source; + video.src = URL.createObjectURL(mediaSource); + video.play(); + return wait_for_encrypted_event(video); + }).then(function (e) { + // Received the 'encrypted' event(s), so keep a copy of + // the initdata for use when creating the session later. + initDataType = config.initData ? config.initDataType : e.initDataType; + initData = config.initData || e.initData; + // Wait until the video indicates that it needs a key to + // continue. + debugMessage = 'wait_for_waitingforkey_event()'; + return wait_for_waitingforkey_event(video); + }).then(function () { + // Make sure the video is NOT paused and not progressing + // before a key is provided. This requires the video + // to NOT have a clear lead. + assert_false(video.paused); + assert_less_than(video.currentTime, 0.2); + // Create a session. + mediaKeySession = video.mediaKeys.createSession('temporary'); + debugMessage = 'generateRequest()'; + return mediaKeySession.generateRequest(initDataType, initData); + }).then(function () { + // generateRequest() will cause a 'message' event to + // occur specifying the keyId that is needed + // Add the key needed to decrypt. + return wait_for_message_event(mediaKeySession, handler); + }).then(function () { + // Video should start playing now that it can decrypt the + // streams, so wait until a little bit of the video has + // played. + debugMessage = 'wait_for_timeupdate_event()'; + return wait_for_timeupdate_event(video); + }).catch(function (error) { + assert_unreached('Error: ' + error.name); + }); + + // Typical test duration is 6 seconds on release builds + // (12 seconds on debug). + }, 'Waiting for a key.', {timeout: 20000}); + + // Wait for an 'encrypted' event + function wait_for_encrypted_event(video) + { + return new Promise(function (resolve) { + video.addEventListener('encrypted', function listener(e) { + assert_equals(e.target, video); + assert_true(e instanceof window.MediaEncryptedEvent); + assert_equals(e.type, 'encrypted'); + debugEncryptedEventFired = true; + video.removeEventListener('encrypted', listener); + resolve(e); + }); + }); + }; + + // Wait for a 'waitingforkey' event. Promise resolved when the + // event is received. + function wait_for_waitingforkey_event(video) + { + return new Promise(function (resolve) { + video.addEventListener('waitingforkey', function listener(e) { + assert_equals(e.target, video); + assert_equals(e.type, 'waitingforkey'); + debugWaitingForKeyEventFired = true; + video.removeEventListener('waitingforkey', listener); + resolve(e); + }); + }); + }; + + // Wait for a 'timeupdate' event. Promise resolved if |video| has + // played for more than 0.2 seconds. + function wait_for_timeupdate_event(video) + { + return new Promise(function (resolve) { + video.addEventListener('timeupdate', function listener(e) { + assert_equals(e.target, video); + ++debugTimeUpdateEventCount; + if (video.currentTime < 0.2) + return; + video.removeEventListener('timeupdate', listener); + resolve(e); + }); + }); + }; + + // We need to wait for the message even if for non clearkey DRMs. + function wait_for_message_event(mediaKeySession, handler) + { + return new Promise(function (resolve, reject) { + mediaKeySession.addEventListener('message', function listener(e) { + assert_equals(e.target, mediaKeySession); + assert_equals(e.type, 'message'); + video.removeEventListener('message', listener); + return handler(e.messageType, e.message).then(function (response) { + return e.target.update(response) + }).then(resolve, reject); + }); + }); + } +} diff --git a/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js b/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js new file mode 100644 index 000000000..c91a57f6d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js @@ -0,0 +1,64 @@ +// Expect utf8decoder and utf8decoder to be TextEncoder('utf-8') and TextDecoder('utf-8') respectively + +function MessageHandler( keysystem, content ) { + this._keysystem = keysystem; + this._content = content; + this.messagehandler = MessageHandler.prototype.messagehandler.bind( this ); + this.servercertificate = undefined; +} + +MessageHandler.prototype.messagehandler = function messagehandler( messageType, message ) +{ + if ( messageType === 'license-request' ) + { + var request = fromUtf8( message ); + + var keys = request.kids.map( function( kid ) { + + var key; + for( var i=0; i < this._content.keys.length; ++i ) + { + if ( base64urlEncode( this._content.keys[ i ].kid ) === kid ) + { + key = base64urlEncode( this._content.keys[ i ].key ); + break; + } + } + + return { kty: 'oct', kid: kid, k: key }; + + }.bind( this ) ); + + return Promise.resolve( toUtf8( { keys: keys } ) ); + } + else if ( messageType === 'license-release' ) + { + var release = fromUtf8( message ); + + // TODO: Check the license release message here + + return Promise.resolve( toUtf8( { kids: release.kids } ) ); + } + + throw new TypeError( 'Unsupported message type for ClearKey' ); +}; + +MessageHandler.prototype.createJWKSet = function createJWKSet(keyId, key) { + var jwkSet = '{"keys":['; + for (var i = 0; i < arguments.length; i++) { + if (i != 0) + jwkSet += ','; + jwkSet += arguments[i]; + } + jwkSet += ']}'; + return jwkSet; +}; + +MessageHandler.prototype.createJWK = function createJWK(keyId, key) { + var jwk = '{"kty":"oct","alg":"A128KW","kid":"'; + jwk += base64urlEncode(keyId); + jwk += '","k":"'; + jwk += base64urlEncode(key); + jwk += '"}'; + return jwk; +};
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js b/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js new file mode 100644 index 000000000..256c069e5 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js @@ -0,0 +1,262 @@ +(function(){ +// Expect utf8decoder and utf8decoder to be TextEncoder('utf-8') and TextDecoder('utf-8') respectively +// +// drmconfig format: +// { <keysystem> : { "serverURL" : <the url for the server>, +// "httpRequestHeaders" : <map of HTTP request headers>, +// "servertype" : "microsoft" | "drmtoday", // affects how request parameters are formed +// "certificate" : <base64 encoded server certificate> } } +// + +drmtodaysecret = Uint8Array.from( [144, 34, 109, 76, 134, 7, 97, 107, 98, 251, 140, 28, 98, 79, 153, 222, 231, 245, 154, 226, 193, 1, 213, 207, 152, 204, 144, 15, 13, 2, 37, 236] ); + +drmconfig = { + "com.widevine.alpha": [ { + "serverURL": "https://lic.staging.drmtoday.com/license-proxy-widevine/cenc/", + "servertype" : "drmtoday", + "merchant" : "w3c-eme-test", + "secret" : drmtodaysecret + } ], + "com.microsoft.playready": [ { + "serverURL": "http://playready-testserver.azurewebsites.net/rightsmanager.asmx", + "servertype": "microsoft", + "sessionTypes" : [ "persistent-usage-record" ], + "certificate" : "Q0hBSQAAAAEAAAUEAAAAAAAAAAJDRVJUAAAAAQAAAfQAAAFkAAEAAQAAAFjt9G6KdSncCkrjbTQPN+/2AAAAAAAAAAAAAAAJIPbrW9dj0qydQFIomYFHOwbhGZVGP2ZsPwcvjh+NFkP/////AAAAAAAAAAAAAAAAAAAAAAABAAoAAABYxw6TjIuUUmvdCcl00t4RBAAAADpodHRwOi8vcGxheXJlYWR5LmRpcmVjdHRhcHMubmV0L3ByL3N2Yy9yaWdodHNtYW5hZ2VyLmFzbXgAAAAAAQAFAAAADAAAAAAAAQAGAAAAXAAAAAEAAQIAAAAAADBRmRRpqV4cfRLcWz9WoXIGZ5qzD9xxJe0CSI2mXJQdPHEFZltrTkZtdmurwVaEI2etJY0OesCeOCzCqmEtTkcAAAABAAAAAgAAAAcAAAA8AAAAAAAAAAVEVEFQAAAAAAAAABVNZXRlcmluZyBDZXJ0aWZpY2F0ZQAAAAAAAAABAAAAAAABAAgAAACQAAEAQGHic/IPbmLCKXxc/MH20X/RtjhXH4jfowBWsQE1QWgUUBPFId7HH65YuQJ5fxbQJCT6Hw0iHqKzaTkefrhIpOoAAAIAW+uRUsdaChtq/AMUI4qPlK2Bi4bwOyjJcSQWz16LAFfwibn5yHVDEgNA4cQ9lt3kS4drx7pCC+FR/YLlHBAV7ENFUlQAAAABAAAC/AAAAmwAAQABAAAAWMk5Z0ovo2X0b2C9K5PbFX8AAAAAAAAAAAAAAARTYd1EkpFovPAZUjOj2doDLnHiRSfYc89Fs7gosBfar/////8AAAAAAAAAAAAAAAAAAAAAAAEABQAAAAwAAAAAAAEABgAAAGAAAAABAAECAAAAAABb65FSx1oKG2r8AxQjio+UrYGLhvA7KMlxJBbPXosAV/CJufnIdUMSA0DhxD2W3eRLh2vHukIL4VH9guUcEBXsAAAAAgAAAAEAAAAMAAAABwAAAZgAAAAAAAAAgE1pY3Jvc29mdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFBsYXlSZWFkeSBTTDAgTWV0ZXJpbmcgUm9vdCBDQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDEuMC4wLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEACAAAAJAAAQBArAKJsEIDWNG5ulOgLvSUb8I2zZ0c5lZGYvpIO56Z0UNk/uC4Mq3jwXQUUN6m/48V5J/vuLDhWu740aRQc1dDDAAAAgCGTWHP8iVuQixWizwoABz7PhUnZYWEugUht5sYKNk23h2Cao/D5uf6epDVyilG8fZKLvufXc/+fkNOtEKT+sWr" + }, + { + "serverURL": "http://playready.directtaps.net/pr/svc/rightsmanager.asmx", + "servertype": "microsoft", + "sessionTypes" : [ "persistent-usage-record" ], + "certificate" : "Q0hBSQAAAAEAAAUEAAAAAAAAAAJDRVJUAAAAAQAAAfQAAAFkAAEAAQAAAFjt9G6KdSncCkrjbTQPN+/2AAAAAAAAAAAAAAAJIPbrW9dj0qydQFIomYFHOwbhGZVGP2ZsPwcvjh+NFkP/////AAAAAAAAAAAAAAAAAAAAAAABAAoAAABYxw6TjIuUUmvdCcl00t4RBAAAADpodHRwOi8vcGxheXJlYWR5LmRpcmVjdHRhcHMubmV0L3ByL3N2Yy9yaWdodHNtYW5hZ2VyLmFzbXgAAAAAAQAFAAAADAAAAAAAAQAGAAAAXAAAAAEAAQIAAAAAADBRmRRpqV4cfRLcWz9WoXIGZ5qzD9xxJe0CSI2mXJQdPHEFZltrTkZtdmurwVaEI2etJY0OesCeOCzCqmEtTkcAAAABAAAAAgAAAAcAAAA8AAAAAAAAAAVEVEFQAAAAAAAAABVNZXRlcmluZyBDZXJ0aWZpY2F0ZQAAAAAAAAABAAAAAAABAAgAAACQAAEAQGHic/IPbmLCKXxc/MH20X/RtjhXH4jfowBWsQE1QWgUUBPFId7HH65YuQJ5fxbQJCT6Hw0iHqKzaTkefrhIpOoAAAIAW+uRUsdaChtq/AMUI4qPlK2Bi4bwOyjJcSQWz16LAFfwibn5yHVDEgNA4cQ9lt3kS4drx7pCC+FR/YLlHBAV7ENFUlQAAAABAAAC/AAAAmwAAQABAAAAWMk5Z0ovo2X0b2C9K5PbFX8AAAAAAAAAAAAAAARTYd1EkpFovPAZUjOj2doDLnHiRSfYc89Fs7gosBfar/////8AAAAAAAAAAAAAAAAAAAAAAAEABQAAAAwAAAAAAAEABgAAAGAAAAABAAECAAAAAABb65FSx1oKG2r8AxQjio+UrYGLhvA7KMlxJBbPXosAV/CJufnIdUMSA0DhxD2W3eRLh2vHukIL4VH9guUcEBXsAAAAAgAAAAEAAAAMAAAABwAAAZgAAAAAAAAAgE1pY3Jvc29mdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFBsYXlSZWFkeSBTTDAgTWV0ZXJpbmcgUm9vdCBDQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDEuMC4wLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEACAAAAJAAAQBArAKJsEIDWNG5ulOgLvSUb8I2zZ0c5lZGYvpIO56Z0UNk/uC4Mq3jwXQUUN6m/48V5J/vuLDhWu740aRQc1dDDAAAAgCGTWHP8iVuQixWizwoABz7PhUnZYWEugUht5sYKNk23h2Cao/D5uf6epDVyilG8fZKLvufXc/+fkNOtEKT+sWr" + }, + { + "serverURL": "https://lic.staging.drmtoday.com/license-proxy-headerauth/drmtoday/RightsManager.asmx", + "servertype" : "drmtoday", + "sessionTypes" : [ "temporary", "persistent-usage-record", "persistent-license" ], + "merchant" : "w3c-eme-test", + "secret" : drmtodaysecret + } ] +}; + + +var keySystemWrappers = { + // Key System wrappers map messages and pass to a handler, then map the response and return to caller + // + // function wrapper(handler, messageType, message, params) + // + // where: + // Promise<response> handler(messageType, message, responseType, headers, params); + // + + 'com.widevine.alpha': function(handler, messageType, message, params) { + return handler.call(this, messageType, new Uint8Array(message), 'json', null, params).then(function(response){ + return base64DecodeToUnit8Array(response.license); + }); + }, + + 'com.microsoft.playready': function(handler, messageType, message, params) { + var msg, xmlDoc; + var licenseRequest = null; + var headers = {}; + var parser = new DOMParser(); + var dataview = new Uint16Array(message); + + msg = String.fromCharCode.apply(null, dataview); + xmlDoc = parser.parseFromString(msg, 'application/xml'); + + if (xmlDoc.getElementsByTagName('Challenge')[0]) { + var challenge = xmlDoc.getElementsByTagName('Challenge')[0].childNodes[0].nodeValue; + if (challenge) { + licenseRequest = atob(challenge); + } + } + + var headerNameList = xmlDoc.getElementsByTagName('name'); + var headerValueList = xmlDoc.getElementsByTagName('value'); + for (var i = 0; i < headerNameList.length; i++) { + headers[headerNameList[i].childNodes[0].nodeValue] = headerValueList[i].childNodes[0].nodeValue; + } + // some versions of the PlayReady CDM return 'Content' instead of 'Content-Type', + // but the license server expects 'Content-Type', so we fix it up here. + if (headers.hasOwnProperty('Content')) { + headers['Content-Type'] = headers.Content; + delete headers.Content; + } + + return handler.call(this, messageType, licenseRequest, 'arraybuffer', headers, params).catch(function(response){ + return response.text().then( function( error ) { throw error; } ); + }); + } +}; + +const requestConstructors = { + // Server request construction functions + // + // Promise<request> constructRequest(config, sessionType, content, messageType, message, params) + // + // request = { url: ..., headers: ..., body: ... } + // + // content = { assetId: ..., variantId: ..., key: ... } + // params = { expiration: ... } + + 'drmtoday': function(config, sessionType, content, messageType, message, headers, params) { + var optData = JSON.stringify({merchant: config.merchant, userId:"12345", sessionId:""}); + var crt = {}; + if (messageType === 'license-request') { + crt = {assetId: content.assetId, + outputProtection: {digital : false, analogue: false, enforce: false}, + storeLicense: (sessionType === 'persistent-license')}; + + if (!params || params.expiration === undefined) { + crt.profile = {purchase: {}}; + } else { + crt.profile = {rental: {absoluteExpiration: (new Date(params.expiration)).toISOString(), + playDuration: 3600000 } }; + } + + if (content.variantId !== undefined) { + crt.variantId = content.variantId; + } + } + + return JWT.encode("HS256", {optData: optData, crt: JSON.stringify([crt])}, config.secret).then(function(jwt){ + headers = headers || {}; + headers['x-dt-auth-token'] = jwt; + return {url: config.serverURL, headers: headers, body: message}; + }); + }, + + 'microsoft': function(config, sessionType, content, messageType, message, headers, params) { + var url = config.serverURL; + if (messageType === 'license-request') { + url += "?"; + if (sessionType === 'temporary' || sessionType === 'persistent-usage-record') { + url += "UseSimpleNonPersistentLicense=1&"; + } + if (sessionType === 'persistent-usage-record') { + url += "SecureStop=1&"; + } + url += "PlayEnablers=B621D91F-EDCC-4035-8D4B-DC71760D43E9&"; // disable output protection + url += "ContentKey=" + btoa(String.fromCharCode.apply(null, content.key)); + return url; + } + + // TODO: Include expiration time in URL + return Promise.resolve({url: url, headers: headers, body: message}); + } +}; + +MessageHandler = function(keysystem, content, sessionType) { + sessionType = sessionType || "temporary"; + + this._keysystem = keysystem; + this._content = content; + this._sessionType = sessionType; + try { + this._drmconfig = drmconfig[this._keysystem].filter(function(drmconfig) { + return drmconfig.sessionTypes === undefined || (drmconfig.sessionTypes.indexOf(sessionType) !== -1); + })[0]; + this._requestConstructor = requestConstructors[this._drmconfig.servertype]; + + this.messagehandler = keySystemWrappers[keysystem].bind(this, MessageHandler.prototype.messagehandler); + + if (this._drmconfig && this._drmconfig.certificate) { + this.servercertificate = stringToUint8Array(atob(this._drmconfig.certificate)); + } + } catch(e) { + return null; + } +} + +MessageHandler.prototype.messagehandler = function messagehandler(messageType, message, responseType, headers, params) { + + var variantId = params ? params.variantId : undefined; + var key; + if( variantId ) { + var keys = this._content.keys.filter(function(k){return k.variantId === variantId;}); + if (keys[0]) key = keys[0].key; + } + if (!key) { + key = this._content.keys[0].key; + } + + var content = {assetId: this._content.assetId, + variantId: variantId, + key: key}; + + return this._requestConstructor(this._drmconfig, this._sessionType, content, messageType, message, headers, params).then(function(request){ + return fetch(request.url, { + method: 'POST', + headers: request.headers, + body: request.body }); + }).then(function(fetchresponse){ + if(fetchresponse.status !== 200) { + throw fetchresponse; + } + + if(responseType === 'json') { + return fetchresponse.json(); + } else if(responseType === 'arraybuffer') { + return fetchresponse.arrayBuffer(); + } + }); +} + +})(); + +(function() { + + var subtlecrypto = window.crypto.subtle; + + // Encoding / decoding utilities + function b64pad(b64) { return b64+"==".substr(0,(b64.length%4)?(4-b64.length%4):0); } + function str2b64url(str) { return btoa(str).replace(/=+$/g, '').replace(/\+/g, "-").replace(/\//g, "_"); } + function b64url2str(b64) { return atob(b64pad(b64.replace(/\-/g, "+").replace(/\_/g, "/"))); } + function str2ab(str) { return Uint8Array.from( str.split(''), function(s){return s.charCodeAt(0)} ); } + function ab2str(ab) { return String.fromCharCode.apply(null, new Uint8Array(ab)); } + + function jwt2webcrypto(alg) { + if (alg === "HS256") return {name: "HMAC", hash: "SHA-256", length: 256}; + else if (alg === "HS384") return { name: "HMAC", hash: "SHA-384", length: 384}; + else if (alg === "HS512") return { name: "HMAC", hash: "SHA-512", length: 512}; + else throw new Error("Unrecognized JWT algorithm: " + alg); + } + + JWT = { + encode: function encode(alg, claims, secret) { + var algorithm = jwt2webcrypto(alg); + if (secret.byteLength !== algorithm.length / 8) throw new Error("Unexpected secret length: " + secret.byteLength); + + if (!claims.iat) claims.iat = (Date.now() / 1000) | 0; + if (!claims.jti) { + var nonce = new Uint8Array(16); + window.crypto.getRandomValues(nonce); + claims.jti = str2b64url( ab2str(nonce) ); + } + + var header = {typ: "JWT", alg: alg}; + var plaintext = str2b64url(JSON.stringify(header)) + '.' + str2b64url(JSON.stringify(claims)); + return subtlecrypto.importKey("raw", secret, algorithm, false, [ "sign" ]).then( function(key) { + return subtlecrypto.sign(algorithm, key, str2ab(plaintext)); + }).then(function(hmac){ + return plaintext + '.' + str2b64url(ab2str(hmac)); + }); + }, + + decode: function decode(jwt, secret) { + var jwtparts = jwt.split('.'); + var header = JSON.parse( b64url2str(jwtparts[0])); + var claims = JSON.parse( b64url2str(jwtparts[1])); + var hmac = str2ab(b64url2str(jwtparts[2])); + var algorithm = jwt2webcrypto(header.alg); + if (secret.byteLength !== algorithm.length / 8) throw new Error("Unexpected secret length: " + secret.byteLength); + + return subtlecrypto.importKey("raw", secret, algorithm, false, ["sign", "verify"]).then(function(key) { + return subtlecrypto.verify(algorithm, key, hmac, str2ab(jwtparts[0] + '.' + jwtparts[1])); + }).then(function(success){ + if (!success) throw new Error("Invalid signature"); + return claims; + }); + } + }; +})(); diff --git a/testing/web-platform/tests/encrypted-media/util/fetch.js b/testing/web-platform/tests/encrypted-media/util/fetch.js new file mode 100644 index 000000000..d14d00bdb --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/fetch.js @@ -0,0 +1,456 @@ +// https://github.com/github/fetch +// +// Copyright (c) 2014-2016 GitHub, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(function(self) { + 'use strict'; + + if (self.fetch) { + return + } + + var support = { + searchParams: 'URLSearchParams' in self, + iterable: 'Symbol' in self && 'iterator' in Symbol, + blob: 'FileReader' in self && 'Blob' in self && (function() { + try { + new Blob() + return true + } catch(e) { + return false + } + })(), + formData: 'FormData' in self, + arrayBuffer: 'ArrayBuffer' in self + } + + function normalizeName(name) { + if (typeof name !== 'string') { + name = String(name) + } + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name') + } + return name.toLowerCase() + } + + function normalizeValue(value) { + if (typeof value !== 'string') { + value = String(value) + } + return value + } + + // Build a destructive iterator for the value list + function iteratorFor(items) { + var iterator = { + next: function() { + var value = items.shift() + return {done: value === undefined, value: value} + } + } + + if (support.iterable) { + iterator[Symbol.iterator] = function() { + return iterator + } + } + + return iterator + } + + function Headers(headers) { + this.map = {} + + if (headers instanceof Headers) { + headers.forEach(function(value, name) { + this.append(name, value) + }, this) + + } else if (headers) { + Object.getOwnPropertyNames(headers).forEach(function(name) { + this.append(name, headers[name]) + }, this) + } + } + + Headers.prototype.append = function(name, value) { + name = normalizeName(name) + value = normalizeValue(value) + var list = this.map[name] + if (!list) { + list = [] + this.map[name] = list + } + list.push(value) + } + + Headers.prototype['delete'] = function(name) { + delete this.map[normalizeName(name)] + } + + Headers.prototype.get = function(name) { + var values = this.map[normalizeName(name)] + return values ? values[0] : null + } + + Headers.prototype.getAll = function(name) { + return this.map[normalizeName(name)] || [] + } + + Headers.prototype.has = function(name) { + return this.map.hasOwnProperty(normalizeName(name)) + } + + Headers.prototype.set = function(name, value) { + this.map[normalizeName(name)] = [normalizeValue(value)] + } + + Headers.prototype.forEach = function(callback, thisArg) { + Object.getOwnPropertyNames(this.map).forEach(function(name) { + this.map[name].forEach(function(value) { + callback.call(thisArg, value, name, this) + }, this) + }, this) + } + + Headers.prototype.keys = function() { + var items = [] + this.forEach(function(value, name) { items.push(name) }) + return iteratorFor(items) + } + + Headers.prototype.values = function() { + var items = [] + this.forEach(function(value) { items.push(value) }) + return iteratorFor(items) + } + + Headers.prototype.entries = function() { + var items = [] + this.forEach(function(value, name) { items.push([name, value]) }) + return iteratorFor(items) + } + + if (support.iterable) { + Headers.prototype[Symbol.iterator] = Headers.prototype.entries + } + + function consumed(body) { + if (body.bodyUsed) { + return Promise.reject(new TypeError('Already read')) + } + body.bodyUsed = true + } + + function fileReaderReady(reader) { + return new Promise(function(resolve, reject) { + reader.onload = function() { + resolve(reader.result) + } + reader.onerror = function() { + reject(reader.error) + } + }) + } + + function readBlobAsArrayBuffer(blob) { + var reader = new FileReader() + reader.readAsArrayBuffer(blob) + return fileReaderReady(reader) + } + + function readBlobAsText(blob) { + var reader = new FileReader() + reader.readAsText(blob) + return fileReaderReady(reader) + } + + function Body() { + this.bodyUsed = false + + this._initBody = function(body) { + this._bodyInit = body + if (typeof body === 'string') { + this._bodyText = body + } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { + this._bodyBlob = body + } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { + this._bodyFormData = body + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this._bodyText = body.toString() + } else if (!body) { + this._bodyText = '' + } else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) { + // Only support ArrayBuffers for POST method. + // Receiving ArrayBuffers happens via Blobs, instead. + } else { + throw new Error('unsupported BodyInit type') + } + + if (!this.headers.get('content-type')) { + if (typeof body === 'string') { + this.headers.set('content-type', 'text/plain;charset=UTF-8') + } else if (this._bodyBlob && this._bodyBlob.type) { + this.headers.set('content-type', this._bodyBlob.type) + } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { + this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') + } + } + } + + if (support.blob) { + this.blob = function() { + var rejected = consumed(this) + if (rejected) { + return rejected + } + + if (this._bodyBlob) { + return Promise.resolve(this._bodyBlob) + } else if (this._bodyFormData) { + throw new Error('could not read FormData body as blob') + } else { + return Promise.resolve(new Blob([this._bodyText])) + } + } + + this.arrayBuffer = function() { + return this.blob().then(readBlobAsArrayBuffer) + } + + this.text = function() { + var rejected = consumed(this) + if (rejected) { + return rejected + } + + if (this._bodyBlob) { + return readBlobAsText(this._bodyBlob) + } else if (this._bodyFormData) { + throw new Error('could not read FormData body as text') + } else { + return Promise.resolve(this._bodyText) + } + } + } else { + this.text = function() { + var rejected = consumed(this) + return rejected ? rejected : Promise.resolve(this._bodyText) + } + } + + if (support.formData) { + this.formData = function() { + return this.text().then(decode) + } + } + + this.json = function() { + return this.text().then(JSON.parse) + } + + return this + } + + // HTTP methods whose capitalization should be normalized + var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] + + function normalizeMethod(method) { + var upcased = method.toUpperCase() + return (methods.indexOf(upcased) > -1) ? upcased : method + } + + function Request(input, options) { + options = options || {} + var body = options.body + if (Request.prototype.isPrototypeOf(input)) { + if (input.bodyUsed) { + throw new TypeError('Already read') + } + this.url = input.url + this.credentials = input.credentials + if (!options.headers) { + this.headers = new Headers(input.headers) + } + this.method = input.method + this.mode = input.mode + if (!body) { + body = input._bodyInit + input.bodyUsed = true + } + } else { + this.url = input + } + + this.credentials = options.credentials || this.credentials || 'omit' + if (options.headers || !this.headers) { + this.headers = new Headers(options.headers) + } + this.method = normalizeMethod(options.method || this.method || 'GET') + this.mode = options.mode || this.mode || null + this.referrer = null + + if ((this.method === 'GET' || this.method === 'HEAD') && body) { + throw new TypeError('Body not allowed for GET or HEAD requests') + } + this._initBody(body) + } + + Request.prototype.clone = function() { + return new Request(this) + } + + function decode(body) { + var form = new FormData() + body.trim().split('&').forEach(function(bytes) { + if (bytes) { + var split = bytes.split('=') + var name = split.shift().replace(/\+/g, ' ') + var value = split.join('=').replace(/\+/g, ' ') + form.append(decodeURIComponent(name), decodeURIComponent(value)) + } + }) + return form + } + + function headers(xhr) { + var head = new Headers() + var pairs = (xhr.getAllResponseHeaders() || '').trim().split('\n') + pairs.forEach(function(header) { + var split = header.trim().split(':') + var key = split.shift().trim() + var value = split.join(':').trim() + head.append(key, value) + }) + return head + } + + Body.call(Request.prototype) + + function Response(bodyInit, options) { + if (!options) { + options = {} + } + + this.type = 'default' + this.status = options.status + this.ok = this.status >= 200 && this.status < 300 + this.statusText = options.statusText + this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers) + this.url = options.url || '' + this._initBody(bodyInit) + } + + Body.call(Response.prototype) + + Response.prototype.clone = function() { + return new Response(this._bodyInit, { + status: this.status, + statusText: this.statusText, + headers: new Headers(this.headers), + url: this.url + }) + } + + Response.error = function() { + var response = new Response(null, {status: 0, statusText: ''}) + response.type = 'error' + return response + } + + var redirectStatuses = [301, 302, 303, 307, 308] + + Response.redirect = function(url, status) { + if (redirectStatuses.indexOf(status) === -1) { + throw new RangeError('Invalid status code') + } + + return new Response(null, {status: status, headers: {location: url}}) + } + + self.Headers = Headers + self.Request = Request + self.Response = Response + + self.fetch = function(input, init) { + return new Promise(function(resolve, reject) { + var request + if (Request.prototype.isPrototypeOf(input) && !init) { + request = input + } else { + request = new Request(input, init) + } + + var xhr = new XMLHttpRequest() + + function responseURL() { + if ('responseURL' in xhr) { + return xhr.responseURL + } + + // Avoid security warnings on getResponseHeader when not allowed by CORS + if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) { + return xhr.getResponseHeader('X-Request-URL') + } + + return + } + + xhr.onload = function() { + var options = { + status: xhr.status, + statusText: xhr.statusText, + headers: headers(xhr), + url: responseURL() + } + var body = 'response' in xhr ? xhr.response : xhr.responseText + resolve(new Response(body, options)) + } + + xhr.onerror = function() { + reject(new TypeError('Network request failed')) + } + + xhr.ontimeout = function() { + reject(new TypeError('Network request failed')) + } + + xhr.open(request.method, request.url, true) + + if (request.credentials === 'include') { + xhr.withCredentials = true + } + + if ('responseType' in xhr && support.blob) { + xhr.responseType = 'blob' + } + + request.headers.forEach(function(value, name) { + xhr.setRequestHeader(name, value) + }) + + xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) + }) + } + self.fetch.polyfill = true +})(typeof self !== 'undefined' ? self : this);
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/util/testmediasource.js b/testing/web-platform/tests/encrypted-media/util/testmediasource.js new file mode 100644 index 000000000..62c2d577d --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/testmediasource.js @@ -0,0 +1,43 @@ +function testmediasource(config) { + + return new Promise(function(resolve, reject) { + // Fetch the media resources + var fetches = [config.audioPath, config.videoPath].map(function(path) { + return fetch(path).then(function(response) { + if (!response.ok) throw new Error('Resource fetch failed'); + return response.arrayBuffer(); + }); + }); + + Promise.all(fetches).then(function(resources) { + config.audioMedia = resources[0]; + config.videoMedia = resources[1]; + + // Create media source + var source = new MediaSource(); + + // Create and fill source buffers when the media source is opened + source.addEventListener('sourceopen', onSourceOpen); + + function onSourceOpen(event) { + var audioSourceBuffer = source.addSourceBuffer(config.audioType), + videoSourceBuffer = source.addSourceBuffer(config.videoType); + + audioSourceBuffer.appendBuffer(config.audioMedia); + videoSourceBuffer.appendBuffer(config.videoMedia); + + function endOfStream() { + if (audioSourceBuffer.updating || videoSourceBuffer.updating) { + setTimeout(endOfStream, 250); + } else { + source.endOfStream(); + } + } + + endOfStream(); + } + + resolve(source); + }); + }); +}
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/util/utf8.js b/testing/web-platform/tests/encrypted-media/util/utf8.js new file mode 100644 index 000000000..5b1176013 --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/utf8.js @@ -0,0 +1,22 @@ +if ( typeof TextEncoder !== "undefined" && typeof TextDecoder !== "undefined" ) +{ + utf8encoder = new TextEncoder('utf-8'); + utf8decoder = new TextDecoder('utf-8'); +} +else +{ + utf8encoder = { encode: function( text ) + { + var result = new Uint8Array(text.length); + for(var i = 0; i < text.length; i++) { result[i] = text.charCodeAt(i); } + return result; + } }; + + utf8decoder = { decode: function( buffer ) + { + return String.fromCharCode.apply(null, new Uint8Array(buffer)); + } }; +} + +toUtf8 = function( o ) { return utf8encoder.encode( JSON.stringify( o ) ); } +fromUtf8 = function( t ) { return JSON.parse( utf8decoder.decode( t ) ); }
\ No newline at end of file diff --git a/testing/web-platform/tests/encrypted-media/util/utils.js b/testing/web-platform/tests/encrypted-media/util/utils.js new file mode 100644 index 000000000..98ac8c44a --- /dev/null +++ b/testing/web-platform/tests/encrypted-media/util/utils.js @@ -0,0 +1,271 @@ +function testnamePrefix( qualifier, keysystem ) { + return ( qualifier || '' ) + ( keysystem === 'org.w3.clearkey' ? keysystem : 'drm' ); +} + +function getInitData(initDataType) { + + // FIXME: This is messed up, because here we are hard coding the key ids for the different content + // that we use for clearkey testing: webm and mp4. For keyids we return the mp4 one + // + // The content used with the DRM today servers has a different key id altogether + + if (initDataType == 'webm') { + return new Uint8Array([ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + ]); + } + + if (initDataType == 'cenc') { + return new Uint8Array([ + 0x00, 0x00, 0x00, 0x34, // size + 0x70, 0x73, 0x73, 0x68, // 'pssh' + 0x01, // version = 1 + 0x00, 0x00, 0x00, // flags + 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID + 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B, + 0x00, 0x00, 0x00, 0x01, // key count + 0x00, 0x00, 0x00, 0x00, 0x03, 0xd2, 0xfc, 0x41, // key id + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 // datasize + ]); + } + if (initDataType == 'keyids') { + var keyId = new Uint8Array([ + 0x00, 0x00, 0x00, 0x00, 0x03, 0xd2, 0xfc, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ]); + return stringToUint8Array(createKeyIDs(keyId)); + } + throw 'initDataType ' + initDataType + ' not supported.'; +} + +function stringToUint8Array(str) +{ + var result = new Uint8Array(str.length); + for(var i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; +} +// Encodes |data| into base64url string. There is no '=' padding, and the +// characters '-' and '_' must be used instead of '+' and '/', respectively. +function base64urlEncode(data) { + var result = btoa(String.fromCharCode.apply(null, data)); + return result.replace(/=+$/g, '').replace(/\+/g, "-").replace(/\//g, "_"); +} +// Decode |encoded| using base64url decoding. +function base64urlDecode(encoded) { + return atob(encoded.replace(/\-/g, "+").replace(/\_/g, "/")); +} +// Decode |encoded| using base64 to a Uint8Array +function base64DecodeToUnit8Array(encoded) { + return new Uint8Array( atob( encoded ).split('').map( function(c){return c.charCodeAt(0);} ) ); +} +// Clear Key can also support Key IDs Initialization Data. +// ref: http://w3c.github.io/encrypted-media/keyids-format.html +// Each parameter is expected to be a key id in an Uint8Array. +function createKeyIDs() { + var keyIds = '{"kids":["'; + for (var i = 0; i < arguments.length; i++) { + if (i != 0) keyIds += '","'; + keyIds += base64urlEncode(arguments[i]); + } + keyIds += '"]}'; + return keyIds; +} + +function getSupportedKeySystem() { + var userAgent = navigator.userAgent.toLowerCase(); + var keysystem = undefined; + if (userAgent.indexOf('edge') > -1 ) { + keysystem = 'com.microsoft.playready'; + } else if ( userAgent.indexOf('chrome') > -1 || userAgent.indexOf('firefox') > -1 ) { + keysystem = 'com.widevine.alpha'; + } + return keysystem; +} + +function waitForEventAndRunStep(eventName, element, func, stepTest) +{ + var eventCallback = function(event) { + if (func) + func(event); + } + + element.addEventListener(eventName, stepTest.step_func(eventCallback), true); +} + +function waitForEvent(eventName, element) { + return new Promise(function(resolve) { + element.addEventListener(eventName, resolve, true); + }) +} + +var consoleDiv = null; + +function consoleWrite(text) +{ + if (!consoleDiv && document.body) { + consoleDiv = document.createElement('div'); + document.body.appendChild(consoleDiv); + } + var span = document.createElement('span'); + span.appendChild(document.createTextNode(text)); + span.appendChild(document.createElement('br')); + consoleDiv.appendChild(span); +} + +function forceTestFailureFromPromise(test, error, message) +{ + // Promises convert exceptions into rejected Promises. Since there is + // currently no way to report a failed test in the test harness, errors + // are reported using force_timeout(). + if (message) + consoleWrite(message + ': ' + error.message); + else if (error) + consoleWrite(error); + + test.force_timeout(); + test.done(); +} + +// Returns an array of audioCapabilities that includes entries for a set of +// codecs that should cover all user agents. +function getPossibleAudioCapabilities() +{ + return [ + { contentType: 'audio/mp4; codecs="mp4a.40.2"' }, + { contentType: 'audio/webm; codecs="opus"' }, + ]; +} + +// Returns a trivial MediaKeySystemConfiguration that should be accepted, +// possibly as a subset of the specified capabilities, by all user agents. +function getSimpleConfiguration() +{ + return [ { + initDataTypes : [ 'webm', 'cenc', 'keyids' ], + audioCapabilities: getPossibleAudioCapabilities() + } ]; +} + +// Returns a MediaKeySystemConfiguration for |initDataType| that should be +// accepted, possibly as a subset of the specified capabilities, by all +// user agents. +function getSimpleConfigurationForInitDataType(initDataType) +{ + return [ { + initDataTypes: [ initDataType ], + audioCapabilities: getPossibleAudioCapabilities() + } ]; +} + +// Returns a promise that is fulfilled with true if |initDataType| is supported, +// by keysystem or false if not. +function isInitDataTypeSupported(keysystem,initDataType) +{ + return navigator.requestMediaKeySystemAccess( + keysystem, getSimpleConfigurationForInitDataType(initDataType)) + .then(function() { return true; }, function() { return false; }); +} + +function getSupportedInitDataTypes( keysystem ) +{ + return [ 'cenc', 'keyids', 'webm' ].filter( isInitDataTypeSupported.bind( null, keysystem ) ); +} + +function arrayBufferAsString(buffer) +{ + var array = []; + Array.prototype.push.apply( array, new Uint8Array( buffer ) ); + return '0x' + array.map( function( x ) { return x < 16 ? '0'+x.toString(16) : x.toString(16); } ).join(''); +} + +function dumpKeyStatuses(keyStatuses) +{ + var userAgent = navigator.userAgent.toLowerCase(); + if (userAgent.indexOf('edge') === -1) { + consoleWrite("for (var entry of keyStatuses)"); + for (var entry of keyStatuses) { + consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]); + } + consoleWrite("for (var keyId of keyStatuses.keys())"); + for (var keyId of keyStatuses.keys()) { + consoleWrite(arrayBufferAsString(keyId)); + } + consoleWrite("for (var status of keyStatuses.values())"); + for (var status of keyStatuses.values()) { + consoleWrite(status); + } + consoleWrite("for (var entry of keyStatuses.entries())"); + for (var entry of keyStatuses.entries()) { + consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]); + } + consoleWrite("keyStatuses.forEach()"); + keyStatuses.forEach(function(status, keyId) { + consoleWrite(arrayBufferAsString(keyId) + ": " + status); + }); + } else { + consoleWrite("keyStatuses.forEach()"); + keyStatuses.forEach(function(keyId, status) { + consoleWrite(arrayBufferAsString(keyId) + ": " + status); + }); + } +} + +// Verify that |keyStatuses| contains just the keys in |keys.expected| +// and none of the keys in |keys.unexpected|. All keys should have status +// 'usable'. Example call: verifyKeyStatuses(mediaKeySession.keyStatuses, +// { expected: [key1], unexpected: [key2] }); +function verifyKeyStatuses(keyStatuses, keys) +{ + var expected = keys.expected || []; + var unexpected = keys.unexpected || []; + + // |keyStatuses| should have same size as number of |keys.expected|. + assert_equals(keyStatuses.size, expected.length, "keystatuses should have expected size"); + + // All |keys.expected| should be found. + expected.map(function(key) { + assert_true(keyStatuses.has(key), "keystatuses should have the expected keys"); + assert_equals(keyStatuses.get(key), 'usable', "keystatus value should be 'usable'"); + }); + + // All |keys.unexpected| should not be found. + unexpected.map(function(key) { + assert_false(keyStatuses.has(key), "keystatuses should not have unexpected keys"); + assert_equals(keyStatuses.get(key), undefined, "keystatus for unexpected key should be undefined"); + }); +} + +// This function checks that calling |testCase.func| returns a +// rejected Promise with the error.name equal to +// |testCase.exception|. +function test_exception(testCase /*...*/) { + var func = testCase.func; + var exception = testCase.exception; + var args = Array.prototype.slice.call(arguments, 1); + + // Currently blink throws for TypeErrors rather than returning + // a rejected promise (http://crbug.com/359386). + // FIXME: Remove try/catch once they become failed promises. + try { + return func.apply(null, args).then( + function (result) { + assert_unreached(format_value(func)); + }, + function (error) { + assert_equals(error.name, exception, format_value(func)); + assert_not_equals(error.message, "", format_value(func)); + } + ); + } catch (e) { + // Only allow 'TypeError' exceptions to be thrown. + // Everything else should be a failed promise. + assert_equals('TypeError', exception, format_value(func)); + assert_equals(e.name, exception, format_value(func)); + } +} + + |