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/Google | |
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/Google')
42 files changed, 4800 insertions, 0 deletions
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 |