summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/encrypted-media
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/encrypted-media
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/encrypted-media')
-rw-r--r--testing/web-platform/tests/encrypted-media/META.yml6
-rw-r--r--testing/web-platform/tests/encrypted-media/README.md7
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-check-encryption-scheme.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-check-status-for-hdcp.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.https.html40
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-events.https.html43
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html31
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-invalid-license.https.html30
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html50
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-keystatuses.https.html49
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted-segmented.https.html59
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html58
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html54
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html54
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html39
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html46
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html42
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html48
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html48
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html46
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.https.html40
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html41
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html41
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html41
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.https.html42
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html28
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html51
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.https.html31
-rw-r--r--testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.https.html36
-rw-r--r--testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4bin0 -> 166614 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4bin0 -> 85332 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4bin0 -> 90594 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/content-metadata.js274
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4bin0 -> 238401 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4bin0 -> 241564 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4bin0 -> 1425859 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4bin0 -> 475456 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4bin0 -> 241049 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4bin0 -> 241862 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4bin0 -> 246574 bytes
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-check-encryption-scheme.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-check-initdata-type.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-check-status-for-hdcp.https.html32
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.https.html39
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-events.https.html71
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-expiration.https.html67
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.https.html31
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-invalid-license.https.html31
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html55
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-keystatuses.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.https.html46
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html54
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html58
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html57
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html56
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html55
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration-keystatus.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html54
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html53
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html39
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html45
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html44
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html50
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html50
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html48
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.https.html40
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html42
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html42
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html42
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.https.html43
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html52
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.https.html31
-rw-r--r--testing/web-platform/tests/encrypted-media/drm-temporary-license-type.https.html71
-rw-r--r--testing/web-platform/tests/encrypted-media/encrypted-media-default-feature-policy.https.sub.html20
-rw-r--r--testing/web-platform/tests/encrypted-media/encrypted-media-supported-by-feature-policy.tentative.html11
-rw-r--r--testing/web-platform/tests/encrypted-media/idlharness.https.html36
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js80
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js37
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js510
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js144
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js193
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js23
-rw-r--r--testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py32
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html105
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html74
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html106
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html77
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html70
-rw-r--r--testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html92
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/check-encryption-scheme.js46
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js35
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/check-status-for-hdcp.js26
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js52
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js52
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/events.js59
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/expiration.js43
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js72
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/invalid-license.js38
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js103
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/keystatuses.js165
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js50
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/onencrypted.js48
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js95
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js158
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js77
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js109
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js104
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js115
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js114
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-segmented-sources.js109
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js109
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js131
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js95
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js122
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js76
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration-keystatus.js78
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration.js80
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js105
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js83
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js71
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js82
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js341
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js61
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js79
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js79
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js59
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js98
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js46
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js54
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js50
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js184
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js452
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js147
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js61
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/unique-origin.js64
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js43
-rw-r--r--testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js166
-rw-r--r--testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js64
-rw-r--r--testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js265
-rw-r--r--testing/web-platform/tests/encrypted-media/util/testmediasource.js49
-rw-r--r--testing/web-platform/tests/encrypted-media/util/utf8.js2
-rw-r--r--testing/web-platform/tests/encrypted-media/util/utils.js293
185 files changed, 12183 insertions, 0 deletions
diff --git a/testing/web-platform/tests/encrypted-media/META.yml b/testing/web-platform/tests/encrypted-media/META.yml
new file mode 100644
index 0000000000..b09e3b3c4e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/META.yml
@@ -0,0 +1,6 @@
+spec: https://w3c.github.io/encrypted-media/
+suggested_reviewers:
+ - cpearce
+ - joeyparrish
+ - jrummell-chromium
+ - jyavenard
diff --git a/testing/web-platform/tests/encrypted-media/README.md b/testing/web-platform/tests/encrypted-media/README.md
new file mode 100644
index 0000000000..932c9962d5
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/README.md
@@ -0,0 +1,7 @@
+## Preparing to run tests
+The following steps may be necessary when running test from a new server/origin for the first time.
+* Some implementations and/or tests may require consent.
+ When running on such clients, manually run a test to trigger the consent request and choose to persist the consent.
+* Some of the tests, such as *-retrieve-*, use pop-ups.
+ It may be necessary to run these tests manually and choose to always allow pop-ups on the origin.
+ Related test failures may appear as: "Cannot set property 'onload' of undefined"
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-check-encryption-scheme.https.html b/testing/web-platform/tests/encrypted-media/clearkey-check-encryption-scheme.https.html
new file mode 100644
index 0000000000..eb580ea5f8
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-check-encryption-scheme.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Check encryptionScheme with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-encryption-scheme.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: 'org.w3.clearkey' }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.https.html b/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.https.html
new file mode 100644
index 0000000000..00894338ae
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-check-initdata-type.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-initdata-type.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: 'org.w3.clearkey' }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-check-status-for-hdcp.https.html b/testing/web-platform/tests/encrypted-media/clearkey-check-status-for-hdcp.https.html
new file mode 100644
index 0000000000..5ec3b26285
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-check-status-for-hdcp.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Check HDCP status with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-status-for-hdcp.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: 'org.w3.clearkey' }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.https.html b/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.https.html
new file mode 100644
index 0000000000..ddf3ecbbbf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-events-session-closed-event.https.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeySession closed event with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/events-session-closed-event.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = 'org.w3.clearkey',
+ contentItem = content['mp4-basic'],
+ config = {
+ keysystem: keysystem,
+ content: contentItem,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem,'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-events.https.html b/testing/web-platform/tests/encrypted-media/clearkey-events.https.html
new file mode 100644
index 0000000000..7563eb33bd
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-events.https.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Events with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' )
+ .then( function( contents )
+ {
+ var content = contents.filter(function(content) { return content.keys; })[0],
+ handler = new MessageHandler( 'org.w3.clearkey', content );
+
+ runTest( { keysystem: 'org.w3.clearkey',
+ content: content,
+ messagehandler: handler.messagehandler,
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html b/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html
new file mode 100644
index 0000000000..9f86d89b47
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test handling of invalid initData for generateRequest()</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/generate-request-disallowed-input.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: 'org.w3.clearkey'
+ };
+
+ runTest(config);
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.https.html b/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.https.html
new file mode 100644
index 0000000000..702f934d2d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-invalid-license.https.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test handling of invalid Clear Key license</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/invalid-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = {
+ keysystem: 'org.w3.clearkey'
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html
new file mode 100644
index 0000000000..3dec1ad165
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/keystatuses-multiple-sessions.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' )
+ .then( function( contents ) {
+
+ // Select a content item with multiple keys
+ var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1; } )[ 0 ],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem );
+
+ var config = { keysystem: 'org.w3.clearkey',
+ content: contentitem,
+ messagehandler: handler.messagehandler,
+ initDataType: 'keyids',
+ initData: getMultikeyInitDatas(contentitem,'keyids')
+ };
+
+ runTest(config);
+
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.https.html b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.https.html
new file mode 100644
index 0000000000..3acce4d436
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-keystatuses.https.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/keystatuses.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' )
+ .then( function( contents ) {
+
+ // Select a content item with multiple keys
+ var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1; } )[ 0 ];
+ var handler = new MessageHandler( 'org.w3.clearkey', contentitem );
+ var config = { keysystem: 'org.w3.clearkey',
+ content: contentitem,
+ messagehandler: handler.messagehandler,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+
+ } );
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html
new file mode 100644
index 0000000000..2fb1db4dcc
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, playback, destroy license with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-destroy-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html
new file mode 100644
index 0000000000..66720946d4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with Clear Key, mp4, event sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-license-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html
new file mode 100644
index 0000000000..b65cf5337f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html
new file mode 100644
index 0000000000..11b3e8f15c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with Clear Key, mp4, event sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-usage-record-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html
new file mode 100644
index 0000000000..3f0d55e413
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with Clear Key, mp4, event sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-usage-record.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html
new file mode 100644
index 0000000000..c8838d2b7d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, playback, retrieve, playback and destroy with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ windowscript: 'resources/clearkey-retrieve-destroy-persistent-license.html',
+ testcase: 'playback, retrieve, playback and destroy' };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html
new file mode 100644
index 0000000000..072b885d21
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license playback, retrieve and playback with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ windowscript: 'resources/clearkey-retrieve-persistent-license.html',
+ testcase: 'playback, retrieve and playback' };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html
new file mode 100644
index 0000000000..63e792c298
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-usage-record, playback and retrieve record in new window, Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ windowscript: 'resources/retrieve-persistent-usage-record.html' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted-segmented.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted-segmented.https.html
new file mode 100644
index 0000000000..e402688aac
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted-segmented.https.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, clear then encrypted using segmented media</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-encrypted-clear-segmented-sources.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var encryptedcontentitem = content['mp4-basic'],
+ clearcontentitem = content['mp4-clear'],
+ handler = new MessageHandler('org.w3.clearkey', encryptedcontentitem),
+ configEncrypted = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: encryptedcontentitem.audio.path,
+ videoPath: encryptedcontentitem.video.path,
+ audioType: encryptedcontentitem.audio.type,
+ videoType: encryptedcontentitem.video.type,
+ duration: 4,
+ initDataType: 'keyids',
+ initData: getInitData(encryptedcontentitem, 'keyids'),
+ },
+ configClear = { audioPath: clearcontentitem.audio.path,
+ videoPath: clearcontentitem.video.path,
+ audioType: clearcontentitem.audio.type,
+ videoType: clearcontentitem.video.type,
+ duration: 4,
+ };
+
+ runTest(configEncrypted,configClear);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html
new file mode 100644
index 0000000000..b8d7cf978e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, clear then encrypted</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-clear-encrypted'],
+ handler = new MessageHandler('org.w3.clearkey', contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem, 'keyids'),
+ duration: 4,
+ testcase: 'single key, clear then encrypted content' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html
new file mode 100644
index 0000000000..73df333979
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, alternate Encrypted and Clear playbacks, Temporary, mp4, Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var encryptedcontentitem = content['mp4-basic'],
+ clearcontentitem = content['mp4-clear'],
+ handler = new MessageHandler('org.w3.clearkey', encryptedcontentitem),
+ configEncrypted = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: encryptedcontentitem.audio.path,
+ videoPath: encryptedcontentitem.video.path,
+ audioType: encryptedcontentitem.audio.type,
+ videoType: encryptedcontentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(encryptedcontentitem, 'keyids'),
+ },
+ configClear = { audioPath: clearcontentitem.audio.path,
+ videoPath: clearcontentitem.video.path,
+ audioType: clearcontentitem.audio.type,
+ videoType: clearcontentitem.video.type,
+ };
+
+ runTest(configEncrypted,configClear);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html
new file mode 100644
index 0000000000..9ab8fd854c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, encrypted then clear</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-encrypted-clear'],
+ handler = new MessageHandler('org.w3.clearkey', contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem, 'keyids'),
+ duration: 4,
+ testcase: 'single key, encrypted then clear content' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html
new file mode 100644
index 0000000000..be40082fa8
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful playback, Temporary session with Clear Key, mp4, validating events</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html
new file mode 100644
index 0000000000..ff5bb47639
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence, check readyState</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-multikey-sequential'],
+ handler = new MessageHandler('org.w3.clearkey', contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getMultikeyInitDatas(contentitem, 'keyids'),
+ duration: 5,
+ checkReadyState: true
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html
new file mode 100644
index 0000000000..a001e6a4d7
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-multikey-sequential'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getMultikeyInitDatas(contentitem,'keyids'),
+ duration: 5
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html
new file mode 100644
index 0000000000..b036a051a4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys for audio/video</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-av-multikey'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: 'multikey audio/video' };
+
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html
new file mode 100644
index 0000000000..b64befda17
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, multiple keys in sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multisession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-multikey'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getMultikeyInitDatas(contentitem,'keyids'),
+ testcase: 'multikey video' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html
new file mode 100644
index 0000000000..209f08231b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: SETMEDIAKEYS_AFTER_SRC };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html
new file mode 100644
index 0000000000..1b1242ba39
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: SETMEDIAKEYS_AFTER_UPDATE };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html
new file mode 100644
index 0000000000..2448484778
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: SETMEDIAKEYS_IMMEDIATELY };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
new file mode 100644
index 0000000000..b7a9ede97d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: SETMEDIAKEYS_ONENCRYPTED };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html
new file mode 100644
index 0000000000..ea69fc41e7
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, two videos</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-two-videos.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement1" width="200px"></video>
+ <video id="videoelement2" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: [ document.getElementById( 'videoelement1' ),
+ document.getElementById( 'videoelement2' ) ],
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html
new file mode 100644
index 0000000000..443aec81b7
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4, play, wait for key, continue play</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-waitingforkey.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getMultikeyInitDatas(contentitem,'keyids')
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.https.html
new file mode 100644
index 0000000000..f6bff6992a
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-playback-temporary.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler( 'org.w3.clearkey', contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids'),
+ testcase: 'single key' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html
new file mode 100644
index 0000000000..c768bc4c86
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: requestMediaKeySystemAccess tests, Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/requestmediakeysystemaccess.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ config = { keysystem: 'org.w3.clearkey',
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids'
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html
new file mode 100644
index 0000000000..0acd27fbff
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Reset MediaSource after setMediaKeys for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/reset-src-after-setmediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-av-multikey'],
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem,'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path,
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html
new file mode 100644
index 0000000000..b744182be2
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys again after playback with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-again-after-playback.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler('org.w3.clearkey', contentitem);
+ getSupportedContent('org.w3.clearkey').then( function(contents) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem, 'keyids')
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html
new file mode 100644
index 0000000000..4700f5d2cc
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys again after resetting src attribute on video element with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ handler = new MessageHandler('org.w3.clearkey', contentitem );
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ messagehandler: handler.messagehandler,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: 'keyids',
+ initData: getInitData(contentitem,'keyids')
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html
new file mode 100644
index 0000000000..860cb6cb22
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys multiple at same time with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-at-same-time.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
new file mode 100644
index 0000000000..088e3c2d7c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys multiple times with different mediakeys with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'];
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
new file mode 100644
index 0000000000..a38d1305fe
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys multiple times with the same mediakeys with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'];
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html
new file mode 100644
index 0000000000..de85169d61
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys to multiple video elements with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video1'>
+ <video id="videoelement1" width="200px"></video>
+ </div>
+ <div id='video2'>
+ <video id="videoelement2" width="200px"></video>
+ </div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video1: document.getElementById('videoelement1'),
+ video2: document.getElementById('videoelement2'),
+ keysystem: 'org.w3.clearkey',
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.https.html
new file mode 100644
index 0000000000..ea04f95408
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-setmediakeys.https.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys with Clear Key</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ getSupportedContent( 'org.w3.clearkey' ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html
new file mode 100644
index 0000000000..e76f509616
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeys attribute, setServerCertificate and setServerCertificate exception syntax for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem, 'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html
new file mode 100644
index 0000000000..447560d74b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeySession attribute and function syntax for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeysession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem, 'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html
new file mode 100644
index 0000000000..1991f588fe
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test navigator.requestmediakeysystemaccess exception and MediaKeySystemAccess attribute syntax for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeysystemaccess.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem, 'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.https.html
new file mode 100644
index 0000000000..0823a9e882
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-unique-origin.https.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Unique origin with Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/unique-origin.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-av-multikey'],
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html
new file mode 100644
index 0000000000..e5061a7654
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test handling of invalid responses for update() for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/update-disallowed-input.js></script>
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var config = {
+ keysystem: 'org.w3.clearkey',
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html b/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html
new file mode 100644
index 0000000000..03f0787fcd
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Waiting for a key for Clear Key, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/waiting-for-a-key.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-basic'],
+ handler = new MessageHandler('org.w3.clearkey', contentItem),
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ messageHandler: handler.messagehandler,
+ initDataType: 'keyids',
+ initData: getInitData(contentItem, 'keyids'),
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path,
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.https.html b/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.https.html
new file mode 100644
index 0000000000..ca0622d9fc
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-not-callable-after-createsession.https.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test MediaKeySession not callable immediately after CreateSession().</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/not-callable-after-createsession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: 'org.w3.clearkey'
+ };
+
+ runTest(config);
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.https.html b/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.https.html
new file mode 100644
index 0000000000..cc13472914
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/clearkey-update-non-ascii-input.https.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test Clear Key handling of non-ASCII responses for update()</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/clearkey-update-non-ascii-input.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: 'org.w3.clearkey',
+ content: contentItem,
+ initDataType: "keyids"
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4
new file mode 100644
index 0000000000..526998d6ac
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4
new file mode 100644
index 0000000000..4daf4d5633
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4
new file mode 100644
index 0000000000..77e869f808
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/content-metadata.js b/testing/web-platform/tests/encrypted-media/content/content-metadata.js
new file mode 100644
index 0000000000..580cc2bdfe
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/content-metadata.js
@@ -0,0 +1,274 @@
+content = addMemberListToObject( {
+
+ 'mp4-clear' : { initDataType: 'cenc',
+ audio : { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' },
+ video : { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4' }
+ },
+
+ 'mp4-basic' : { assetId: 'mp4-basic',
+ initDataType: 'cenc',
+ audio : { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' },
+ video : { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4' },
+ keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ],
+ key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ],
+ initDataType: 'cenc',
+ initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ]
+ },
+
+ 'mp4-clear-encrypted' : {
+ assetId: 'mp4-basic',
+ initDataType: 'cenc',
+ audio : { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' },
+ video : { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4' },
+ keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ],
+ key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ],
+ initDataType: 'cenc',
+ initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ]
+ },
+
+ 'mp4-encrypted-clear' : {
+ assetId: 'mp4-basic',
+ initDataType: 'cenc',
+ audio : { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' },
+ video : { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4' },
+ keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ],
+ key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ],
+ initDataType: 'cenc',
+ initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ]
+ },
+
+
+ 'mp4-av-multikey' : {
+ assetId: 'mp4-basic',
+ initDataType: 'cenc',
+ associatedInitData: true, // indicates that initData for one key causes other keys to be returned as well
+ audio: { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_enc_dashinit.mp4' },
+ video : { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4' },
+ keys : [ { kid: [ 0xad, 0x13, 0xf9, 0xea, 0x2b, 0xe6, 0x98, 0xb8, 0x75, 0xf5, 0x04, 0xa8, 0xe3, 0xcc, 0xea, 0x64 ],
+ key: [ 0xbe, 0x7d, 0xf8, 0xa3, 0x66, 0x7a, 0x6a, 0x8f, 0xd5, 0x64, 0xd0, 0xed, 0x81, 0x33, 0x9a, 0x95 ],
+ initDataType: 'cenc',
+ initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQrRP56ivmmLh19QSo48zqZBoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADYAdgBrAFQAcgBlAFkAcgB1AEoAaAAxADkAUQBTAG8ANAA4AHoAcQBaAEEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AagBZAEYATgBmADAAeQBmADQAaQBzAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' },
+ { kid: [ 0x55, 0x8e, 0xe5, 0x41, 0xb9, 0x0a, 0xb2, 0xf3, 0x95, 0x0d, 0x00, 0xad, 0xe3, 0x76, 0x0d, 0x45 ],
+ key: [ 0x91, 0x03, 0x92, 0x63, 0x01, 0x6d, 0xa6, 0x35, 0x77, 0x0d, 0x57, 0xdb, 0x92, 0xf9, 0x8b, 0xd0 ],
+ initDataType : 'cenc',
+ initData: 'AAAAcXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAFEIARIQVY7lQbkKsvOVDQCt43YNRRoIY2FzdGxhYnMiKGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRjMmx1WjJ4bEluMD0yB2RlZmF1bHQAAAMacHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAAC+voCAAABAAEA8AI8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFEAZQBXAE8AVgBRAHEANQA4ADcASwBWAEQAUQBDAHQANAAzAFkATgBSAFEAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AWQBpAE8ALwAxADYATABzADkANgBFAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwADoALwAvAHAAbABhAHkAcgBlAGEAZAB5AC4AZABpAHIAZQBjAHQAdABhAHAAcwAuAG4AZQB0AC8AcAByAC8AcwB2AGMALwByAGkAZwBoAHQAcwBtAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA/AFAAbABhAHkAUgBpAGcAaAB0AD0AMQAmAGEAbQBwADsAVQBzAGUAUwBpAG0AcABsAGUATgBvAG4AUABlAHIAcwBpAHMAdABlAG4AdABMAGkAYwBlAG4AcwBlAD0AMQA8AC8ATABBAF8AVQBSAEwAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==' } ]
+ },
+
+ 'mp4-multikey' : { assetId: 'mp4-multikey',
+ initDataType: 'cenc',
+ audio: { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_2keys_2sess.mp4' },
+ video: { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4' },
+ keys: [ { kid: [ 0x13, 0xa7, 0x53, 0x06, 0xd1, 0x18, 0x91, 0x7b, 0x47, 0xa6, 0xc1, 0x83, 0x64, 0x42, 0x51, 0x6f ],
+ key: [ 0x8a, 0xaa, 0xd8, 0xc4, 0xdb, 0xde, 0xac, 0xcd, 0xad, 0x26, 0x76, 0xa1, 0xed, 0x38, 0x95, 0x2e ],
+ variantId: 'key1',
+ initDataType: 'cenc',
+ initData: 'AAAAjXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAG0IARIQE6dTBtEYkXtHpsGDZEJRbxoIY2FzdGxhYnMiRGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRNbk5sYzNOcGIyNGlMQ0oyWVhKcFlXNTBTV1FpT2lKclpYa3hJbjA9MgdkZWZhdWx0AAADwnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA6KiAwAAAQABAJgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBCAGwATwBuAEUAeABqAFIAZQA1AEYASABwAHMARwBEAFoARQBKAFIAYgB3AD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAGwAaQBjAC4AcwB0AGEAZwBpAG4AZwAuAGQAcgBtAHQAbwBkAGEAeQAuAGMAbwBtAC8AbABpAGMAZQBuAHMAZQAtAHAAcgBvAHgAeQAtAGgAZQBhAGQAZQByAGEAdQB0AGgALwBkAHIAbQB0AG8AZABhAHkALwBSAGkAZwBoAHQAcwBNAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA8AC8ATABBAF8AVQBSAEwAPgA8AEwAVQBJAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAFUASQBfAFUAUgBMAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEQAUgB0AFAAZwBVAEkALwBiAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=' },
+ { kid: [ 0xee, 0x73, 0x56, 0x4e, 0xc8, 0xa8, 0x90, 0xf0, 0x78, 0xef, 0x68, 0x71, 0xfa, 0x4b, 0xe1, 0x8b ],
+ key: [ 0xe4, 0x4f, 0xe1, 0x45, 0x7c, 0x5e, 0xbc, 0xd8, 0x3e, 0xad, 0xdc, 0xd6, 0x2c, 0xaf, 0x55, 0x18 ],
+ variantId: 'key2',
+ initDataType: 'cenc',
+ initData: 'AAAAjXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAG0IARIQ7nNWTsiokPB472hx+kvhixoIY2FzdGxhYnMiRGV5SmhjM05sZEVsa0lqb2laVzFsTFhSbGMzUXRNbk5sYzNOcGIyNGlMQ0oyWVhKcFlXNTBTV1FpT2lKclpYa3lJbjA9MgdkZWZhdWx0AAADwnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA6KiAwAAAQABAJgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBUAGwAWgB6ADcAcQBqAEkAOABKAEIANAA3ADIAaAB4ACsAawB2AGgAaQB3AD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcABzADoALwAvAGwAaQBjAC4AcwB0AGEAZwBpAG4AZwAuAGQAcgBtAHQAbwBkAGEAeQAuAGMAbwBtAC8AbABpAGMAZQBuAHMAZQAtAHAAcgBvAHgAeQAtAGgAZQBhAGQAZQByAGEAdQB0AGgALwBkAHIAbQB0AG8AZABhAHkALwBSAGkAZwBoAHQAcwBNAGEAbgBhAGcAZQByAC4AYQBzAG0AeAA8AC8ATABBAF8AVQBSAEwAPgA8AEwAVQBJAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAFUASQBfAFUAUgBMAD4APABDAEgARQBDAEsAUwBVAE0APgB4AEQASwBBAFkAMAB2AFoAaABVAFUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=' } ] },
+
+
+ 'mp4-multikey-sequential' : { assetId: 'mp4-multikey-sequential',
+ initDataType: 'cenc',
+ audio: { type: 'audio/mp4;codecs="mp4a.40.2"',
+ path: '/encrypted-media/content/audio_aac-lc_128k_dashinit.mp4' },
+ video: { type: 'video/mp4;codecs="avc1.4d401e"',
+ path: '/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4' },
+ keys: [ { kid: [0x8a, 0x0d, 0x85, 0x45, 0x21, 0x05, 0xd4, 0x15, 0x35, 0x8f, 0xea, 0x8f, 0x68, 0xe6, 0xc1, 0x91],
+ key: [0x76, 0x6f, 0xab, 0xc1, 0x68, 0x3f, 0xf8, 0xef, 0x4e, 0x76, 0x00, 0x24, 0xc5, 0x23, 0x8f, 0x10],
+ variantId: 'key1',
+ initDataType: 'cenc',
+ initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQig2FRSEF1BU1j+qPaObBkRoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreEluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AFIAWQBVAE4AaQBnAFUAaABGAGQAUQAxAGoAKwBxAFAAYQBPAGIAQgBrAFEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AcQBOAEkAZQBiAFQAWABzAG8AcgBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' },
+ { kid: [0xfb, 0xb4, 0xb7, 0xf3, 0x4a, 0xbd, 0x31, 0x87, 0x34, 0x4b, 0xce, 0xc4, 0x5f, 0x96, 0x68, 0x88],
+ key: [0x26, 0x52, 0xc3, 0x1d, 0xf7, 0x92, 0xd1, 0x7b, 0x08, 0xa6, 0xfa, 0xd3, 0x7c, 0xb6, 0x25, 0x60],
+ variantId: 'key2',
+ initDataType: 'cenc',
+ initData: 'AAAAlXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAHUIARIQ+7S380q9MYc0S87EX5ZoiBoIY2FzdGxhYnMiTGV5SmhjM05sZEVsa0lqb2liWEEwTFcxMWJIUnBhMlY1TFhObGNYVmxiblJwWVd3aUxDSjJZWEpwWVc1MFNXUWlPaUpyWlhreUluMD0yB2RlZmF1bHQAAANYcHNzaAAAAACaBPB5mEBChquS5lvgiF+VAAADODgDAAABAAEALgM8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+ADgANwBlADAAKwA3ADEASwBoAHoARQAwAFMAOAA3AEUAWAA1AFoAbwBpAEEAPQA9ADwALwBLAEkARAA+ADwATABBAF8AVQBSAEwAPgBoAHQAdABwAHMAOgAvAC8AbABpAGMALgBzAHQAYQBnAGkAbgBnAC4AZAByAG0AdABvAGQAYQB5AC4AYwBvAG0ALwBsAGkAYwBlAG4AcwBlAC0AcAByAG8AeAB5AC0AaABlAGEAZABlAHIAYQB1AHQAaAAvAGQAcgBtAHQAbwBkAGEAeQAvAFIAaQBnAGgAdABzAE0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwATABVAEkAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAtAHUAaQAuAGUAeABhAG0AcABsAGUALgBjAG8AbQA8AC8ATABVAEkAXwBVAFIATAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4ARgB0AGkASQBoADYAUwBKAG0AcABZAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A' } ] },
+
+ 'webm' : { audio : { type: 'audio/webm; codecs="opus"' },
+ video : { type: 'video/webm; codecs="vp8"',
+ path: '/encrypted-media/content/test-encrypted.webm' },
+ keys : [ { kid: [48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53],
+ key: [0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
+ 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c ] } ]
+ },
+ 'webm-multikey' :
+ { audio : { type: 'audio/webm; codecs="opus"' },
+ video : { type: 'video/webm; codecs="vp8"',
+ path: '/encrypted-media/content/test-encrypted-different-av-keys.webm' },
+ keys : [ { kid: [48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53],
+ key: [ 0x7A, 0x7A, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B,
+ 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A ] },
+ { kid: [49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54],
+ key: [ 0x30, 0x30, 0x62, 0xF1, 0x68, 0x14, 0xD2, 0x7B,
+ 0x68, 0xEF, 0x12, 0x2A, 0xFC, 0xE4, 0xAE, 0x0A ] } ]
+ },
+} );
+
+function addMemberListToObject( o )
+{
+ var items = [ ];
+ for( var item in o )
+ {
+ if ( !o.hasOwnProperty( item ) ) continue;
+
+ o[item].name = item;
+ items.push( o[item] );
+ }
+
+ o._items = items;
+
+ return o;
+}
+
+function getInitData( contentitem, initDataType )
+{
+ if (initDataType == 'webm') {
+ return new Uint8Array( contentitem.keys[ 0 ].kid ); // WebM initData supports only a single key
+ }
+
+ if (initDataType == 'cenc') {
+
+ var size = 36 + contentitem.keys.length * 16,
+ kids = contentitem.keys.map( function( k ) { return k.kid; } );
+
+ return new Uint8Array(Array.prototype.concat.call( [
+ 0x00, 0x00, size / 256, size % 256, // size
+ 0x70, 0x73, 0x73, 0x68, // 'pssh'
+ 0x01, // version = 1
+ 0x00, 0x00, 0x00, // flags
+ 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
+ 0x00, 0x00, 0x00, kids.length ], // key count ]
+ Array.prototype.concat.apply( [], kids ),
+ [ 0x00, 0x00, 0x00, 0x00 ]// datasize
+ ));
+ }
+ if (initDataType == 'keyids') {
+
+ return toUtf8( { kids: contentitem.keys.map( function( k ) { return base64urlEncode( new Uint8Array( k.kid ) ); } ) } );
+ }
+ throw 'initDataType ' + initDataType + ' not supported.';
+}
+
+function getSingleKeyInitData( kid, initDataType )
+{
+ if (initDataType == 'webm') {
+ return new Uint8Array( kid );
+ }
+
+ if (initDataType == 'cenc') {
+
+ var size = 52;
+
+ return new Uint8Array(Array.prototype.concat.call( [
+ 0x00, 0x00, size / 256, size % 256, // size
+ 0x70, 0x73, 0x73, 0x68, // 'pssh'
+ 0x01, // version = 1
+ 0x00, 0x00, 0x00, // flags
+ 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
+ 0x00, 0x00, 0x00, 0x01 ], // key count ]
+ kid,
+ [ 0x00, 0x00, 0x00, 0x00 ]// datasize
+ ));
+ }
+ if (initDataType == 'keyids') {
+
+ return toUtf8( { kids: [ base64urlEncode( new Uint8Array( kid ) ) ] } );
+ }
+ throw 'initDataType ' + initDataType + ' not supported.';
+}
+
+function getMultikeyInitDatas( contentitem, initDataType )
+{
+ return contentitem.keys.map( function( k ) { return getSingleKeyInitData( k.kid, initDataType ); } );
+}
+
+function getProprietaryInitDatas( contentitem )
+{
+ var keysWithInitData = contentitem.keys.filter( function( k ) { return k.initData; } );
+ return { initDataType: contentitem.initDataType,
+ initDatas : keysWithInitData.map( function( k ) { return k.initData; } ),
+ variantIds: keysWithInitData.map( function( k ) { return k.variantId; } )
+ };
+}
+
+// Returns a promise that resolves to the following object
+// { supported: boolean, // whether the content is supported at all
+// content: <the content item>, // the content item description
+// initDataTypes: <list of initDataTypes>
+// }
+//
+// Note: we test initData types one at a time since some versions of Edge don't support testing several at once
+//
+function isContentSupportedForInitDataTypes( keysystem, initDataTypes, contentitem )
+{
+ return Promise.all( initDataTypes.map( function( initDataType ) {
+ var configuration = { initDataTypes : [ initDataType ],
+ audioCapabilities: [ { contentType: contentitem.audio.type } ],
+ videoCapabilities: [ { contentType: contentitem.video.type } ]
+ };
+ return navigator.requestMediaKeySystemAccess( keysystem, [ configuration ] ).then( function( access ) {
+ return { supported: true, initDataType: access.getConfiguration().initDataTypes[ 0 ] };
+ }, function() {
+ return { supported: false };
+ } );
+ } ) ).then( function( results ) {
+
+ var initDataTypes = results.filter( function( result ) { return result.supported; } )
+ .map( function( result ) { return result.initDataType; } );
+
+ return initDataTypes.length > 0 ?
+ { content: contentitem, supported: true, initDataTypes: initDataTypes }
+ : { content: contentitem, supported: false };
+ } );
+}
+
+// Returns a promise that resolves to { content:, supported:, initDataTypes: } object
+function isContentSupported( keysystem, contentitem )
+{
+ return isContentSupportedForInitDataTypes( keysystem, [ 'cenc', 'webm', 'keyids' ], contentitem );
+}
+
+// Returns a Promise resolving to an array of supported content for the key system
+function getSupportedContent( keysystem )
+{
+ return Promise.all( content._items.map( isContentSupported.bind( null, keysystem ) ) ).
+ then( function( results )
+ {
+ return results.filter( function( r ) { return r.supported; } ).map( function( r ) { return r.content; } );
+ } );
+}
+
+// Returns a Promise resolving to an array of { content:, initDataType: } pairs for the key system
+function getSupportedContentAndInitDataTypes( keysystem )
+{
+ return Promise.all( content._items.map( isContentSupported.bind( null, keysystem ) ) ).
+ then( function( results )
+ {
+ return results.filter( function( r ) { return r.supported; } );
+ } );
+}
+
+// gets a configuration object for provided piece of content
+function getSimpleConfigurationForContent( contentitem )
+{
+ return { initDataTypes: [ 'keyids', 'webm', 'cenc' ],
+ audioCapabilities: [ { contentType: contentitem.audio.type } ],
+ videoCapabilities: [ { contentType: contentitem.video.type } ] };
+}
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4
new file mode 100644
index 0000000000..33ac63f6bf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4
new file mode 100644
index 0000000000..dca23449af
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_clear_enc_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4
new file mode 100644
index 0000000000..53a461e8ae
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4
new file mode 100644
index 0000000000..f59284cfef
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_2keys_2sess.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4
new file mode 100644
index 0000000000..d837ac6500
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_clear_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4
new file mode 100644
index 0000000000..156a799a9d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_enc_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4 b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4
new file mode 100644
index 0000000000..659a61cdcf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/content/video_512x288_h264-360k_multikey_dashinit.mp4
Binary files differ
diff --git a/testing/web-platform/tests/encrypted-media/drm-check-encryption-scheme.https.html b/testing/web-platform/tests/encrypted-media/drm-check-encryption-scheme.https.html
new file mode 100644
index 0000000000..862591b1b8
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-check-encryption-scheme.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Check encryptionScheme with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-encryption-scheme.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: getSupportedKeySystem() }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.https.html b/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.https.html
new file mode 100644
index 0000000000..6b3324027b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-check-initdata-type.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-initdata-type.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: getSupportedKeySystem() }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-check-status-for-hdcp.https.html b/testing/web-platform/tests/encrypted-media/drm-check-status-for-hdcp.https.html
new file mode 100644
index 0000000000..68c45be69b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-check-status-for-hdcp.https.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Check HDCP status with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <!--<script src=/encrypted-media/content/content-metadata.js></script>-->
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/check-status-for-hdcp.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: getSupportedKeySystem() }
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.https.html b/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.https.html
new file mode 100644
index 0000000000..425d17646c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-events-session-closed-event.https.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeySession closed event with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/events-session-closed-event.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentItem = content['mp4-basic'],
+ config = {
+ keysystem: keysystem,
+ content: contentItem,
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-events.https.html b/testing/web-platform/tests/encrypted-media/drm-events.https.html
new file mode 100644
index 0000000000..5dd2ed774d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-events.https.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Events with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+
+ getSupportedContentAndInitDataTypes( keysystem )
+ .then( function( supported )
+ {
+ // This test requires initData for supported content.
+ // We prefer explciit initData configured for the content, but
+ // otherwise we will generate initData for a supported initDataType
+ // FIXME: Move me to a utility function
+ var content,
+ initDataType,
+ initData;
+
+ var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.keys && s.content.initDataType; } );
+ if ( contentWithExplicitInitData.length > 0 )
+ {
+ content = contentWithExplicitInitData[ 0 ].content;
+ initDataType = content.keys[ 0 ].initDataType;
+ initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData );
+ }
+ else
+ {
+ content = supported[ 0 ].content;
+ initDataType = supported[ 0 ].initDataTypes[ 0 ];
+ initData = getInitData( content, initDataType );
+ }
+
+ var handler = new MessageHandler( keysystem, content );
+
+ runTest( { keysystem: keysystem,
+ content: content,
+ messagehandler: handler.messagehandler,
+ initDataType: initDataType,
+ initData: initData
+ } );
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-expiration.https.html b/testing/web-platform/tests/encrypted-media/drm-expiration.https.html
new file mode 100644
index 0000000000..7a9993af8d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-expiration.https.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Expiration with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/expiration.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+
+ getSupportedContentAndInitDataTypes( keysystem ).then( function( supported ) {
+ // This test requires initData for supported content.
+ // We prefer explicit initData configured for the content, but
+ // otherwise we will generate initData for a supported initDataType
+ // FIXME: Move me to a utility function
+ var content,
+ initDataType,
+ initData;
+
+ var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.initDataType && s.content.keys; } );
+ if ( contentWithExplicitInitData.length > 0 ) {
+ content = contentWithExplicitInitData[ 0 ].content;
+ initDataType = content.keys[ 0 ].initDataType;
+ initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData );
+ } else {
+ content = supported[ 0 ].content;
+ initDataType = supported[ 0 ].initDataTypes[ 0 ];
+ initData = getInitData( content, initDataType );
+ }
+
+ var handler = new MessageHandler( keysystem, content );
+
+ runTest( { keysystem: keysystem,
+ content: content,
+ messagehandler: handler.messagehandler,
+ initDataType: initDataType,
+ initData: initData,
+ expiration: Date.now().valueOf() + 120000 // Two minutes from now
+ } );
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.https.html b/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.https.html
new file mode 100644
index 0000000000..45f2bc6957
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-generate-request-disallowed-input.https.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test handling of invalid initData for generateRequest()</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/generate-request-disallowed-input.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: getSupportedKeySystem()
+ };
+
+ runTest(config);
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-invalid-license.https.html b/testing/web-platform/tests/encrypted-media/drm-invalid-license.https.html
new file mode 100644
index 0000000000..1443386038
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-invalid-license.https.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test handling of invalid DRM license</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/invalid-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ config = {
+ keysystem: keysystem
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html b/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html
new file mode 100644
index 0000000000..61b7c33bdc
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys for audio/video</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM server -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/keystatuses-multiple-sessions.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+ getSupportedContent( keysystem )
+ .then( function( contents ) {
+
+ // Select a content item with multiple keys and initData
+ var contentitem = contents.filter( function( item ) { return item.keys && item.keys.length > 1 && item.initDataType && !item.associatedInitData; } )[ 0 ],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { keysystem: keysystem,
+ content: contentitem,
+ messagehandler: handler.messagehandler,
+ initDataType: contentitem.initDataType,
+ initData: getProprietaryInitDatas(contentitem).initDatas.map( base64DecodeToUnit8Array )
+ };
+
+ runTest(config);
+
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-keystatuses.https.html b/testing/web-platform/tests/encrypted-media/drm-keystatuses.https.html
new file mode 100644
index 0000000000..3fc61a4f7f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-keystatuses.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/keystatuses.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+ getSupportedContent( keysystem ).then( function( contents ) {
+ // Select a content item with multiple keys and initData that retrieves all keys
+ var contentitem = contents.filter( function( item ) {
+ return item.keys && item.keys.length > 1 && item.initDataType && item.associatedInitData;
+ } )[ 0 ];
+
+ var handler = new MessageHandler( keysystem, contentitem );
+ var config = { keysystem: keysystem,
+ content: contentitem,
+ messagehandler: handler.messagehandler,
+ initDataType: contentitem.initDataType,
+ initData: base64DecodeToUnit8Array( getProprietaryInitDatas(contentitem).initDatas[ 0 ] )
+ };
+
+ runTest(config);
+
+ } );
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.https.html
new file mode 100644
index 0000000000..8fc820ce26
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-onencrypted.https.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Encrypted fired on encrypted media file with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/onencrypted.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-av-multikey'],
+ config = {
+ video: document.getElementById('videoelement'),
+ content: contentItem,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path,
+ initDataType: contentItem.initDataType,
+ keys: contentItem.keys
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html
new file mode 100644
index 0000000000..bc3f5b189f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, destroy the license</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-destroy-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html
new file mode 100644
index 0000000000..88660e88f4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, event sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-license-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.https.html
new file mode 100644
index 0000000000..0c1f94b860
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-license.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html
new file mode 100644
index 0000000000..5cbb8021b0
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with DRM, mp4, event sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-usage-record-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ servercertificate: handler.servercertificate
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html
new file mode 100644
index 0000000000..69876be989
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-usage-record session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-persistent-usage-record.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ servercertificate: handler.servercertificate
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html
new file mode 100644
index 0000000000..9bba71f89a
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, retrieve license, playback and destroy the license</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ),
+ config = { content: contentitem,
+ video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ windowscript: 'resources/drm-retrieve-destroy-persistent-license.html',
+ testcase: 'playback, retrieve, playback and destroy' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html
new file mode 100644
index 0000000000..8429d1922d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, persistent-license session with DRM, mp4, retrieve the license, playback</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-license.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-license' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ windowscript: 'resources/drm-retrieve-persistent-license.html',
+ testcase: 'playback, retrieve, playback' };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html
new file mode 100644
index 0000000000..4059bff0cf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: persistent-usage-record, playback and retrieve record in new window, DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM server -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem, 'persistent-usage-record' ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ servercertificate: handler.servercertificate,
+ windowscript: 'resources/drm-retrieve-persistent-usage-record.html' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html
new file mode 100644
index 0000000000..6b6e1ce621
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, clear then encrypted</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-clear-encrypted'],
+ handler = new MessageHandler(keysystem, contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: 'single key, clear then encrypted content',
+ duration: 4 };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html
new file mode 100644
index 0000000000..f4ad811df9
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, alternate Encrypted and Clear playbacks, Temporary, mp4, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ encryptedcontentitem = content['mp4-basic'],
+ clearcontentitem = content['mp4-clear'],
+ handler = new MessageHandler(keysystem, encryptedcontentitem),
+ configEncrypted = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: encryptedcontentitem.audio.path,
+ videoPath: encryptedcontentitem.video.path,
+ audioType: encryptedcontentitem.audio.type,
+ videoType: encryptedcontentitem.video.type,
+ initDataType: encryptedcontentitem.initDataType
+ },
+ configClear = { audioPath: clearcontentitem.audio.path,
+ videoPath: clearcontentitem.video.path,
+ audioType: clearcontentitem.audio.type,
+ videoType: clearcontentitem.video.type,
+ };
+
+ runTest(configEncrypted,configClear);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html
new file mode 100644
index 0000000000..f9cce58a90
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, encrypted then clear</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-encrypted-clear'],
+ handler = new MessageHandler(keysystem, contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: 'single key, clear then encrypted content',
+ duration: 4 };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.https.html
new file mode 100644
index 0000000000..c621de0520
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-events.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful playback, temporary session with DRM, mp4, validating events</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-events.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html
new file mode 100644
index 0000000000..4d9cc71ac7
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, expired license</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-expired.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler(keysystem, contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html
new file mode 100644
index 0000000000..ec69118d69
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys in sequence, check readyState</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-multikey-sequential'],
+ handler = new MessageHandler(keysystem, contentitem),
+ initdatas = getProprietaryInitDatas(contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ initData: initdatas.initDatas.map(base64DecodeToUnit8Array),
+ variantIds: initdatas.variantIds,
+ duration: 5,
+ checkReadyState: true
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html
new file mode 100644
index 0000000000..7f0c23f230
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, multiple keys in sequence</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multikey-sequential.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-multikey-sequential'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ initdatas = getProprietaryInitDatas(contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ initData: initdatas.initDatas.map(base64DecodeToUnit8Array),
+ variantIds: initdatas.variantIds,
+ duration: 5
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html
new file mode 100644
index 0000000000..5be9bda028
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful playback, temporary session with DRM, mp4, multiple keys</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-av-multikey'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: 'multikey audio/video'
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html
new file mode 100644
index 0000000000..e22e4f9350
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-multisession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-multikey'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ proprietaryInitDatas = getProprietaryInitDatas(contentitem),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ initData: proprietaryInitDatas.initDatas.map( base64DecodeToUnit8Array ),
+ variantIds: proprietaryInitDatas.variantIds,
+ testcase: 'multikey video' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration-keystatus.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration-keystatus.html
new file mode 100644
index 0000000000..46cf5c9184
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration-keystatus.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session limited playduration, check keystatus, DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-playduration-keystatus.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ playduration: 2000,
+ testcase: 'single key' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration.html
new file mode 100644
index 0000000000..173e0f0d59
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-playduration.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session limited playduration, DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-playduration.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ playduration: 2000,
+ testcase: 'single key' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html
new file mode 100644
index 0000000000..3560e0ab85
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: SETMEDIAKEYS_AFTER_SRC };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html
new file mode 100644
index 0000000000..f225859dc5
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: SETMEDIAKEYS_AFTER_UPDATE };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html
new file mode 100644
index 0000000000..2c198ef8fe
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: SETMEDIAKEYS_IMMEDIATELY };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
new file mode 100644
index 0000000000..d3efc80f61
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-setMediaKeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: SETMEDIAKEYS_ONENCRYPTED };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html
new file mode 100644
index 0000000000..cbd6c9c659
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4, two videos</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM server -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-two-videos.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement1" width="200px"></video>
+ <video id="videoelement2" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: [ document.getElementById( 'videoelement1' ),
+ document.getElementById( 'videoelement2' ) ],
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html
new file mode 100644
index 0000000000..edd5e37204
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Verify MediaKeySession.keyStatuses with multiple sessions, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary-waitingforkey.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ keysystem = getSupportedKeySystem(),
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ initData: getProprietaryInitDatas(contentitem).initDatas.map( base64DecodeToUnit8Array ),
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.https.html
new file mode 100644
index 0000000000..b0ad0ef0c6
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-playback-temporary.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Successful Playback, Temporary session with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/playback-temporary.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler( keysystem, contentitem ),
+ config = { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: contentitem.initDataType,
+ testcase: 'single key' };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html
new file mode 100644
index 0000000000..ae0165f09e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: requestMediaKeySystemAccess tests, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/requestmediakeysystemaccess.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var contentitem = content['mp4-basic'],
+ keySystem = getSupportedKeySystem(),
+ config = { keysystem: keySystem,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type,
+ initDataType: getSupportedInitDataTypes( keySystem )[ 0 ]
+ };
+
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html
new file mode 100644
index 0000000000..bbcefee8cf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Reset MediaSource after setMediaKeys for DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/reset-src-after-setmediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-av-multikey'],
+ keysystem = getSupportedKeySystem(),
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contentItem,
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path,
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html
new file mode 100644
index 0000000000..a60b764772
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys again after playback with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-again-after-playback.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler(keysystem, contentitem );
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html
new file mode 100644
index 0000000000..bff89c0a44
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys again after resetting src attribute on video element with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'],
+ handler = new MessageHandler(keysystem, contentitem );
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ messagehandler: handler.messagehandler,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html
new file mode 100644
index 0000000000..571d354353
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys multiple at same time with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-at-same-time.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
new file mode 100644
index 0000000000..453ded031c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys multiple times with different mediakeys with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'];
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
new file mode 100644
index 0000000000..adf91b826a
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys multiple times with the same mediakeys with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem(),
+ contentitem = content['mp4-basic'];
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contentitem,
+ audioPath: contentitem.audio.path,
+ videoPath: contentitem.video.path,
+ audioType: contentitem.audio.type,
+ videoType: contentitem.video.type
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html
new file mode 100644
index 0000000000..952815184a
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: setMediaKeys to multiple video elements with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video1'>
+ <video id="videoelement1" width="200px"></video>
+ </div>
+ <div id='video2'>
+ <video id="videoelement2" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video1: document.getElementById('videoelement1'),
+ video2: document.getElementById('videoelement2'),
+ keysystem: keysystem,
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.https.html
new file mode 100644
index 0000000000..45318acaa5
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-setmediakeys.https.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: setMediaKeys with DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/setmediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+ getSupportedContent( keysystem ).then( function( contents ) {
+ runTest( { video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contents[ 0 ]
+ } );
+ } );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html
new file mode 100644
index 0000000000..22fa605f45
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeys attribute, setServerCertificate and setServerCertificate exception syntax for DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeys.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var keysystem = getSupportedKeySystem();
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: keysystem,
+ content: contentItem,
+ initData: stringToUint8Array(atob(contentItem.keys[0].initData)),
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html
new file mode 100644
index 0000000000..ea15884125
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test MediaKeySession attribute and function syntax for DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeysession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var keysystem = getSupportedKeySystem();
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: keysystem,
+ content: contentItem,
+ initData: stringToUint8Array(atob(contentItem.keys[0].initData)),
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html
new file mode 100644
index 0000000000..5714ed35e3
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions - Test navigator.requestmediakeysystemaccess exception and MediaKeySystemAccess attribute syntax for DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/syntax-mediakeysystemaccess.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+ <script>
+ var keysystem = getSupportedKeySystem();
+ var contentItem = content['mp4-basic'],
+ config = {
+ keysystem: keysystem,
+ content: contentItem,
+ initData: stringToUint8Array(atob(contentItem.keys[0].initData)),
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.https.html
new file mode 100644
index 0000000000..3e13ab5a6c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-unique-origin.https.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Unique origin with DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/unique-origin.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-av-multikey'],
+ keysystem = getSupportedKeySystem(),
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html b/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html
new file mode 100644
index 0000000000..dc5197b356
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions - Waiting for a key for DRM, mp4</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/waiting-for-a-key.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ var contentItem = content['mp4-basic'],
+ keysystem = getSupportedKeySystem(),
+ handler = new MessageHandler( keysystem, contentItem ),
+ config = {
+ video: document.getElementById('videoelement'),
+ keysystem: keysystem,
+ content: contentItem,
+ messageHandler: handler.messagehandler,
+ initDataType: contentItem.initDataType,
+ audioType: contentItem.audio.type,
+ videoType: contentItem.video.type,
+ audioPath: contentItem.audio.path,
+ videoPath: contentItem.video.path,
+ };
+ runTest(config);
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.https.html b/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.https.html
new file mode 100644
index 0000000000..c783a179a8
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-not-callable-after-createsession.https.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Test MediaKeySession not callable immediately after CreateSession(), DRM.</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/not-callable-after-createsession.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var config = { keysystem: getSupportedKeySystem()
+ };
+
+ runTest(config);
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.https.html b/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.https.html
new file mode 100644
index 0000000000..90d84cc86b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/drm-temporary-license-type.https.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <meta name="timeout" content="long">
+ <title>Encrypted Media Extensions: Test that persistent license cannot be ingested into temporary session</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Web Platform Test Harness scripts -->
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Content metadata -->
+ <script src=/encrypted-media/content/content-metadata.js></script>
+
+ <!-- Message handler for DRM servers -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ <!-- The script for this specific test -->
+ <script src=/encrypted-media/scripts/temporary-license-type.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ var keysystem = getSupportedKeySystem();
+
+ getSupportedContentAndInitDataTypes( keysystem )
+ .then( function( supported )
+ {
+ // This test requires initData for supported content.
+ // We prefer explicit initData configured for the content, but
+ // otherwise we will generate initData for a supported initDataType
+ // FIXME: Move me to a utility function
+ var content,
+ initDataType,
+ initData;
+
+ var contentWithExplicitInitData = supported.filter( function( s ) { return s.content.keys && s.content.initDataType; } );
+ if ( contentWithExplicitInitData.length > 0 )
+ {
+ content = contentWithExplicitInitData[ 0 ].content;
+ initDataType = content.keys[ 0 ].initDataType;
+ initData = base64DecodeToUnit8Array( content.keys[ 0 ].initData );
+ }
+ else
+ {
+ content = supported[ 0 ].content;
+ initDataType = supported[ 0 ].initDataTypes[ 0 ];
+ initData = getInitData( content, initDataType );
+ }
+
+ var handler = new MessageHandler( keysystem, content, 'persistent-license' );
+
+ runTest( { keysystem: keysystem,
+ content: content,
+ messagehandler: handler.messagehandler,
+ initDataType: initDataType,
+ initData: initData
+ } );
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/encrypted-media-default-feature-policy.https.sub.html b/testing/web-platform/tests/encrypted-media/encrypted-media-default-feature-policy.https.sub.html
new file mode 100644
index 0000000000..a5114262ad
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/encrypted-media-default-feature-policy.https.sub.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=util/utils.js></script>
+ <script>
+ 'use strict';
+ run_all_fp_tests_allow_self(
+ 'https://{{domains[www]}}:{{ports[https][0]}}',
+ 'encrypted-media',
+ 'SecurityError',
+ function() {
+ return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{
+ sessionTypes: [ 'temporary' ],
+ audioCapabilities: getPossibleAudioCapabilities()
+ }]);
+ });
+ </script>
+</body>
diff --git a/testing/web-platform/tests/encrypted-media/encrypted-media-supported-by-feature-policy.tentative.html b/testing/web-platform/tests/encrypted-media/encrypted-media-supported-by-feature-policy.tentative.html
new file mode 100644
index 0000000000..5b2d2240c6
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/encrypted-media-supported-by-feature-policy.tentative.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Test that encrypted-media is advertised in the feature list</title>
+<link rel="help" href="https://w3c.github.io/webappsec-feature-policy/#dom-featurepolicy-features">
+<link rel="help" href="https://github.com/w3c/encrypted-media/pull/432">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+ assert_in_array('encrypted-media', document.featurePolicy.features());
+}, 'document.featurePolicy.features should advertise encrypted-media.');
+</script>
diff --git a/testing/web-platform/tests/encrypted-media/idlharness.https.html b/testing/web-platform/tests/encrypted-media/idlharness.https.html
new file mode 100644
index 0000000000..18c8f89ea2
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/idlharness.https.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extentions IDL test</title>
+ <meta name="timeout" content="long">
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+ </head>
+ <body>
+ <h1 class="instructions">Description</h1>
+ <p class="instructions">
+ This test verifies that implementations of the Encrypted Media Extensions API match its WebIDL definition.
+ </p>
+
+ <div id='log'></div>
+
+ <script>
+ 'use strict';
+
+ idl_test(
+ ['encrypted-media'],
+ ['html', 'dom'],
+ idl_array => {
+ idl_array.add_objects({
+ Navigator: ['navigator'],
+ });
+ }
+ );
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js
new file mode 100644
index 0000000000..576e0ad040
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/cast-polyfill.js
@@ -0,0 +1,80 @@
+(function() {
+
+ if ( /CrKey\/[0-9]+\.[0-9a-z]+\.[0-9a-z]+/i.exec( navigator.userAgent ) ) {
+
+ var castscript = document.createElement('script');
+ castscript.type = 'text/javascript';
+ castscript.src = 'https://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js'
+ document.head.appendChild( castscript );
+
+ var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator ),
+ _setMediaKeys = HTMLMediaElement.prototype.setMediaKeys,
+ _load = MediaKeySession.prototype.load;
+
+ MediaKeySession.prototype.load = function load()
+ {
+ return _load.call( this ).then( function( success )
+ {
+ return success ? this.remove() : false;
+ }.bind( this ) );
+ };
+
+ function MediaKeys( mediaKeys )
+ {
+ this._mediaKeys = mediaKeys;
+ }
+
+ MediaKeys.prototype.setServerCertificate = function setServerCertificate( certificate )
+ {
+ return this._mediaKeys.setServerCertificate( certificate );
+ };
+
+ MediaKeys.prototype.createSession = function createSession( sessionType ) {
+
+ if ( sessionType === 'persistent-usage-record' )
+ {
+ return cast.receiver.eme.KeySession.createSession( this._mediaKeys, 'persistent-release-message' );
+ }
+
+ return this._mediaKeys.createSession( sessionType );
+ };
+
+ function MediaKeySystemAccess( access )
+ {
+ this._access = mediaKeySystemAccess;
+ }
+
+ Object.defineProperty( MediaKeySystemAccess.prototype, 'keySystem', { get: function() { return this._access.keySystem; } } );
+
+ MediaKeySystemAccess.prototype.getConfiguration = function getConfiguration() { return this._access.getConfiguration(); };
+
+ MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKeys() {
+
+ return this._access.createMediaKey().then( function( mediaKeys ) { return new MediaKeys( mediaKeys ); } );
+
+ };
+
+ HTMLMediaElement.prototype.setMediaKeys = function setMediaKeys( mediaKeys )
+ {
+ if ( mediaKeys instanceof MediaKeys )
+ {
+ return _setMediaKeys.call( this, mediaKeys._mediaKeys );
+ }
+ else
+ {
+ return _setMediaKeys.call( this, mediaKeys );
+ }
+ };
+
+ navigator.requestMediaKeySystemAccess = function requestMediaKeySystemAccess( keysystem, supportedConfigurations ) {
+
+ if ( keysystem !== 'com.chromecast.playready' )
+ {
+ return _requestMediaKeySystemAccess( keysystem, supportedConfigurations );
+ }
+
+ return _requestMediaKeySystemAccess( keysystem, supportedConfigurations )
+ .then( function( access ) { return new MediaKeySystemAccess( access ); } );
+ };
+ }
+})(); \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js
new file mode 100644
index 0000000000..2f11497cca
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/chrome-polyfill.js
@@ -0,0 +1,37 @@
+(function(){
+ if( navigator.userAgent.toLowerCase().indexOf('edge') === -1
+ && navigator.userAgent.toLowerCase().indexOf('chrome') > -1){
+
+ if ( ( /chrome\/([0-9]*)\./.exec( navigator.userAgent.toLowerCase() )[1] | 0 ) < 54 ) {
+
+ // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=622956
+ // Chrome does not fire the empty keystatuschange event when a session is closed
+ var _mediaKeySessionClose = MediaKeySession.prototype.close;
+ var _mediaKeySessionKeyStatusesGetter = Object.getOwnPropertyDescriptor( MediaKeySession.prototype, 'keyStatuses' ).get;
+ var _emptyMediaKeyStatusMap = { size: 0,
+ has: function() { return false; },
+ get: function() { return undefined; },
+ entries:function() { return []; }, // this may not be correct, I think it should be some iterator thing
+ keys: function() { return []; },
+ values: function() { return []; },
+ forEach:function() { return; } };
+
+ MediaKeySession.prototype.close = function close()
+ {
+ this.__closed = true;
+
+ setTimeout( function() {
+ this.dispatchEvent( new Event( 'keystatuseschange' ) );
+ }.bind( this ), 0 );
+
+ return _mediaKeySessionClose.call( this );
+ };
+
+ Object.defineProperty( MediaKeySession.prototype, 'keyStatuses', { get: function() {
+
+ return this.__closed ? _emptyMediaKeyStatusMap : _mediaKeySessionKeyStatusesGetter.call( this );
+
+ } } );
+ }
+ }
+}());
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js
new file mode 100644
index 0000000000..057ea3e030
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/clearkey-polyfill.js
@@ -0,0 +1,510 @@
+(function(){
+
+ // Save platform functions that will be modified
+ var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator ),
+ _setMediaKeys = HTMLMediaElement.prototype.setMediaKeys;
+
+ // Allow us to modify the target of Events
+ Object.defineProperties( Event.prototype, {
+ target: { get: function() { return this._target || this.currentTarget; },
+ set: function( newtarget ) { this._target = newtarget; } }
+ } );
+
+ var EventTarget = function(){
+ this.listeners = {};
+ };
+
+ EventTarget.prototype.listeners = null;
+
+ EventTarget.prototype.addEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ this.listeners[type] = [];
+ }
+ this.listeners[type].push(callback);
+ };
+
+ EventTarget.prototype.removeEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[type];
+ for(var i = 0, l = stack.length; i < l; i++){
+ if(stack[i] === callback){
+ stack.splice(i, 1);
+ return this.removeEventListener(type, callback);
+ }
+ }
+ };
+
+ EventTarget.prototype.dispatchEvent = function(event){
+ if(!(event.type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[event.type];
+ event.target = this;
+ for(var i = 0, l = stack.length; i < l; i++) {
+ stack[i].call(this, event);
+ }
+ };
+
+ function MediaKeySystemAccessProxy( keysystem, access, configuration )
+ {
+ this._keysystem = keysystem;
+ this._access = access;
+ this._configuration = configuration;
+ }
+
+ Object.defineProperties( MediaKeySystemAccessProxy.prototype, {
+ keysystem: { get: function() { return this._keysystem; } }
+ });
+
+ MediaKeySystemAccessProxy.prototype.getConfiguration = function getConfiguration()
+ {
+ return this._configuration;
+ };
+
+ MediaKeySystemAccessProxy.prototype.createMediaKeys = function createMediaKeys()
+ {
+ return new Promise( function( resolve, reject ) {
+
+ this._access.createMediaKeys()
+ .then( function( mediaKeys ) { resolve( new MediaKeysProxy( mediaKeys ) ); })
+ .catch( function( error ) { reject( error ); } );
+
+ }.bind( this ) );
+ };
+
+ function MediaKeysProxy( mediaKeys )
+ {
+ this._mediaKeys = mediaKeys;
+ this._sessions = [ ];
+ this._videoelement = undefined;
+ this._onTimeUpdateListener = MediaKeysProxy.prototype._onTimeUpdate.bind( this );
+ }
+
+ MediaKeysProxy.prototype._setVideoElement = function _setVideoElement( videoElement )
+ {
+ if ( videoElement !== this._videoelement )
+ {
+ if ( this._videoelement )
+ {
+ this._videoelement.removeEventListener( 'timeupdate', this._onTimeUpdateListener );
+ }
+
+ this._videoelement = videoElement;
+
+ if ( this._videoelement )
+ {
+ this._videoelement.addEventListener( 'timeupdate', this._onTimeUpdateListener );
+ }
+ }
+ };
+
+ MediaKeysProxy.prototype._onTimeUpdate = function( event )
+ {
+ this._sessions.forEach( function( session ) {
+
+ if ( session._sessionType === 'persistent-usage-record' )
+ {
+ session._onTimeUpdate( event );
+ }
+
+ } );
+ };
+
+ MediaKeysProxy.prototype._removeSession = function _removeSession( session )
+ {
+ var index = this._sessions.indexOf( session );
+ if ( index !== -1 ) this._sessions.splice( index, 1 );
+ };
+
+ MediaKeysProxy.prototype.createSession = function createSession( sessionType )
+ {
+ if ( !sessionType || sessionType === 'temporary' ) return this._mediaKeys.createSession();
+
+ var session = new MediaKeySessionProxy( this, sessionType );
+ this._sessions.push( session );
+
+ return session;
+ };
+
+ MediaKeysProxy.prototype.setServerCertificate = function setServerCertificate( certificate )
+ {
+ return this._mediaKeys.setServerCertificate( certificate );
+ };
+
+ function MediaKeySessionProxy( mediaKeysProxy, sessionType )
+ {
+ EventTarget.call( this );
+
+ this._mediaKeysProxy = mediaKeysProxy
+ this._sessionType = sessionType;
+ this._sessionId = "";
+
+ // MediaKeySessionProxy states
+ // 'created' - After initial creation
+ // 'loading' - Persistent license session waiting for key message to load stored keys
+ // 'active' - Normal active state - proxy all key messages
+ // 'removing' - Release message generated, waiting for ack
+ // 'closed' - Session closed
+ this._state = 'created';
+
+ this._closed = new Promise( function( resolve ) { this._resolveClosed = resolve; }.bind( this ) );
+ }
+
+ MediaKeySessionProxy.prototype = Object.create( EventTarget.prototype );
+
+ Object.defineProperties( MediaKeySessionProxy.prototype, {
+
+ sessionId: { get: function() { return this._sessionId; } },
+ expiration: { get: function() { return NaN; } },
+ closed: { get: function() { return this._closed; } },
+ keyStatuses:{ get: function() { return this._session.keyStatuses; } }, // TODO this will fail if examined too early
+ _kids: { get: function() { return this._keys.map( function( key ) { return key.kid; } ); } },
+ });
+
+ MediaKeySessionProxy.prototype._createSession = function _createSession()
+ {
+ this._session = this._mediaKeysProxy._mediaKeys.createSession();
+
+ this._session.addEventListener( 'message', MediaKeySessionProxy.prototype._onMessage.bind( this ) );
+ this._session.addEventListener( 'keystatuseschange', MediaKeySessionProxy.prototype._onKeyStatusesChange.bind( this ) );
+ };
+
+ MediaKeySessionProxy.prototype._onMessage = function _onMessage( event )
+ {
+ switch( this._state )
+ {
+ case 'loading':
+ this._session.update( toUtf8( { keys: this._keys } ) )
+ .then( function() {
+ this._state = 'active';
+ this._loaded( true );
+ }.bind(this)).catch( this._loadfailed );
+
+ break;
+
+ case 'active':
+ this.dispatchEvent( event );
+ break;
+
+ default:
+ // Swallow the event
+ break;
+ }
+ };
+
+ MediaKeySessionProxy.prototype._onKeyStatusesChange = function _onKeyStatusesChange( event )
+ {
+ switch( this._state )
+ {
+ case 'active' :
+ case 'removing' :
+ this.dispatchEvent( event );
+ break;
+
+ default:
+ // Swallow the event
+ break;
+ }
+ };
+
+ MediaKeySessionProxy.prototype._onTimeUpdate = function _onTimeUpdate( event )
+ {
+ if ( !this._firstTime ) this._firstTime = Date.now();
+ this._latestTime = Date.now();
+ this._store();
+ };
+
+ MediaKeySessionProxy.prototype._queueMessage = function _queueMessage( messageType, message )
+ {
+ setTimeout( function() {
+
+ var messageAsArray = toUtf8( message ).buffer;
+
+ this.dispatchEvent( new MediaKeyMessageEvent( 'message', { messageType: messageType, message: messageAsArray } ) );
+
+ }.bind( this ) );
+ };
+
+ function _storageKey( sessionId )
+ {
+ return sessionId;
+ }
+
+ MediaKeySessionProxy.prototype._store = function _store()
+ {
+ var data;
+
+ if ( this._sessionType === 'persistent-usage-record' )
+ {
+ data = { kids: this._kids };
+ if ( this._firstTime ) data.firstTime = this._firstTime;
+ if ( this._latestTime ) data.latestTime = this._latestTime;
+ }
+ else
+ {
+ data = { keys: this._keys };
+ }
+
+ window.localStorage.setItem( _storageKey( this._sessionId ), JSON.stringify( data ) );
+ };
+
+ MediaKeySessionProxy.prototype._load = function _load( sessionId )
+ {
+ var store = window.localStorage.getItem( _storageKey( sessionId ) );
+ if ( store === null ) return false;
+
+ var data;
+ try { data = JSON.parse( store ) } catch( error ) {
+ return false;
+ }
+
+ if ( data.kids )
+ {
+ this._sessionType = 'persistent-usage-record';
+ this._keys = data.kids.map( function( kid ) { return { kid: kid }; } );
+ if ( data.firstTime ) this._firstTime = data.firstTime;
+ if ( data.latestTime ) this._latestTime = data.latestTime;
+ }
+ else
+ {
+ this._sessionType = 'persistent-license';
+ this._keys = data.keys;
+ }
+
+ return true;
+ };
+
+ MediaKeySessionProxy.prototype._clear = function _clear()
+ {
+ window.localStorage.removeItem( _storageKey( this._sessionId ) );
+ };
+
+ MediaKeySessionProxy.prototype.generateRequest = function generateRequest( initDataType, initData )
+ {
+ if ( this._state !== 'created' ) return Promise.reject( new InvalidStateError() );
+
+ this._createSession();
+
+ this._state = 'active';
+
+ return this._session.generateRequest( initDataType, initData )
+ .then( function() {
+ this._sessionId = Math.random().toString(36).slice(2);
+ }.bind( this ) );
+ };
+
+ MediaKeySessionProxy.prototype.load = function load( sessionId )
+ {
+ if ( this._state !== 'created' ) return Promise.reject( new InvalidStateError() );
+
+ return new Promise( function( resolve, reject ) {
+
+ try
+ {
+ if ( !this._load( sessionId ) )
+ {
+ resolve( false );
+
+ return;
+ }
+
+ this._sessionId = sessionId;
+
+ if ( this._sessionType === 'persistent-usage-record' )
+ {
+ var msg = { kids: this._kids };
+ if ( this._firstTime ) msg.firstTime = this._firstTime;
+ if ( this._latestTime ) msg.latestTime = this._latestTime;
+
+ this._queueMessage( 'license-release', msg );
+
+ this._state = 'removing';
+
+ resolve( true );
+ }
+ else
+ {
+ this._createSession();
+
+ this._state = 'loading';
+ this._loaded = resolve;
+ this._loadfailed = reject;
+
+ var initData = { kids: this._kids };
+
+ this._session.generateRequest( 'keyids', toUtf8( initData ) );
+ }
+ }
+ catch( error )
+ {
+ reject( error );
+ }
+ }.bind( this ) );
+ };
+
+ MediaKeySessionProxy.prototype.update = function update( response )
+ {
+ return new Promise( function( resolve, reject ) {
+
+ switch( this._state ) {
+
+ case 'active' :
+
+ var message = fromUtf8( response );
+
+ // JSON Web Key Set
+ this._keys = message.keys;
+
+ this._store();
+
+ resolve( this._session.update( response ) );
+
+ break;
+
+ case 'removing' :
+
+ this._state = 'closed';
+
+ this._clear();
+
+ this._mediaKeysProxy._removeSession( this );
+
+ this._resolveClosed();
+
+ delete this._session;
+
+ resolve();
+
+ break;
+
+ default:
+ reject( new InvalidStateError() );
+ }
+
+ }.bind( this ) );
+ };
+
+ MediaKeySessionProxy.prototype.close = function close()
+ {
+ if ( this._state === 'closed' ) return Promise.resolve();
+
+ this._state = 'closed';
+
+ this._mediaKeysProxy._removeSession( this );
+
+ this._resolveClosed();
+
+ var session = this._session;
+ if ( !session ) return Promise.resolve();
+
+ this._session = undefined;
+
+ return session.close();
+ };
+
+ MediaKeySessionProxy.prototype.remove = function remove()
+ {
+ if ( this._state !== 'active' || !this._session ) return Promise.reject( new DOMException('InvalidStateError('+this._state+')') );
+
+ this._state = 'removing';
+
+ this._mediaKeysProxy._removeSession( this );
+
+ return this._session.close()
+ .then( function() {
+
+ var msg = { kids: this._kids };
+
+ if ( this._sessionType === 'persistent-usage-record' )
+ {
+ if ( this._firstTime ) msg.firstTime = this._firstTime;
+ if ( this._latestTime ) msg.latestTime = this._latestTime;
+ }
+
+ this._queueMessage( 'license-release', msg );
+
+ }.bind( this ) )
+ };
+
+ HTMLMediaElement.prototype.setMediaKeys = function setMediaKeys( mediaKeys )
+ {
+ if ( mediaKeys instanceof MediaKeysProxy )
+ {
+ mediaKeys._setVideoElement( this );
+ return _setMediaKeys.call( this, mediaKeys._mediaKeys );
+ }
+ else
+ {
+ return _setMediaKeys.call( this, mediaKeys );
+ }
+ };
+
+ navigator.requestMediaKeySystemAccess = function( keysystem, configurations )
+ {
+ // First, see if this is supported by the platform
+ return new Promise( function( resolve, reject ) {
+
+ _requestMediaKeySystemAccess( keysystem, configurations )
+ .then( function( access ) { resolve( access ); } )
+ .catch( function( error ) {
+
+ if ( error instanceof TypeError ) reject( error );
+
+ if ( keysystem !== 'org.w3.clearkey' ) reject( error );
+
+ if ( !configurations.some( is_persistent_configuration ) ) reject( error );
+
+ // Shallow copy the configurations, swapping out the labels and omitting the sessiontypes
+ var configurations_copy = configurations.map( function( config, index ) {
+
+ var config_copy = copy_configuration( config );
+ config_copy.label = index.toString();
+ return config_copy;
+
+ } );
+
+ // And try again with these configurations
+ _requestMediaKeySystemAccess( keysystem, configurations_copy )
+ .then( function( access ) {
+
+ // Create the supported configuration based on the original request
+ var configuration = access.getConfiguration(),
+ original_configuration = configurations[ configuration.label ];
+
+ // If the original configuration did not need persistent session types, then we're done
+ if ( !is_persistent_configuration( original_configuration ) ) resolve( access );
+
+ // Create the configuration that we will return
+ var returned_configuration = copy_configuration( configuration );
+
+ if ( original_configuration.label )
+ returned_configuration.label = original_configuration;
+ else
+ delete returned_configuration.label;
+
+ returned_configuration.sessionTypes = original_configuration.sessionTypes;
+
+ resolve( new MediaKeySystemAccessProxy( keysystem, access, returned_configuration ) );
+ } )
+ .catch( function( error ) { reject( error ); } );
+ } );
+ } );
+ };
+
+ function is_persistent_configuration( configuration )
+ {
+ return configuration.sessionTypes &&
+ ( configuration.sessionTypes.indexOf( 'persistent-usage-record' ) !== -1
+ || configuration.sessionTypes.indexOf( 'persistent-license' ) !== -1 );
+ }
+
+ function copy_configuration( src )
+ {
+ var dst = {};
+ [ 'label', 'initDataTypes', 'audioCapabilities', 'videoCapabilities', 'distinctiveIdenfifier', 'persistentState' ]
+ .forEach( function( item ) { if ( src[item] ) dst[item] = src[item]; } );
+ return dst;
+ }
+}());
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js b/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js
new file mode 100644
index 0000000000..8861444591
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/edge-keystatuses.js
@@ -0,0 +1,144 @@
+(function() {
+
+ // This polyfill fixes the following problems with Edge browser
+ // (1) Various maplike methods for keystatuses are not supported or suported incorrectly
+ // (2) Key Ids exposed in keystatuses are incorrect (byte swaps)
+ if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) {
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ // The following function is the core of this JS patch. The rest of this file is infrastructure
+ // required to enable this function
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+ function _proxyKeyStatusesChange( event ) {
+ this._keyStatuses.clear();
+ var keyStatuses = [];
+ this._session.keyStatuses.forEach( function( keyId, status ) {
+ var newKeyId = new Uint8Array( keyId );
+
+ function swap( arr, a, b ) { var t = arr[a]; arr[a] = arr[b]; arr[b] = t; }
+ swap( newKeyId, 0, 3 );
+ swap( newKeyId, 1, 2 );
+ swap( newKeyId, 4, 5 );
+ swap( newKeyId, 6, 7 );
+
+ keyStatuses.push( { key: newKeyId, status: status, ord: arrayBufferAsString( newKeyId ) } );
+ });
+
+ function lexicographical( a, b ) { return a < b ? -1 : a === b ? 0 : +1; }
+ function lexicographicalkey( a, b ) { return lexicographical( a.ord, b.ord ); }
+
+ keyStatuses.sort( lexicographicalkey ).forEach( function( obj ) {
+ this._keyStatuses._set( obj.key, obj.status );
+ }.bind( this ) );
+
+ this.dispatchEvent( event );
+ };
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ // Override MediaKeys.createSession
+ var _mediaKeysCreateSession = MediaKeys.prototype.createSession;
+ MediaKeys.prototype.createSession = function ( sessionType ) {
+ return new MediaKeySession( _mediaKeysCreateSession.call( this, sessionType ) );
+ };
+
+ // MediaKeySession proxy
+ function MediaKeySession( session ) {
+ EventTarget.call( this );
+ this._session = session;
+ this._keyStatuses = new MediaKeyStatusMap();
+ this._session.addEventListener("keystatuseschange",this._onKeyStatusesChange.bind(this));
+ this._session.addEventListener("message",this.dispatchEvent.bind(this));
+ }
+
+ MediaKeySession.prototype = Object.create( EventTarget.prototype );
+
+ Object.defineProperties( MediaKeySession.prototype, {
+ sessionId: { get: function() { return this._session.sessionId; } },
+ expiration: { get: function() { return this._session.expiration; } },
+ closed: { get: function() { return this._session.closed; } },
+ keyStatuses:{ get: function() { return this._keyStatuses; } }
+ });
+
+ [ "generateRequest", "load", "update", "remove", "close" ].forEach( function( fnname ) {
+ MediaKeySession.prototype[ fnname ] = function() {
+ return window.MediaKeySession.prototype[ fnname ].apply( this._session, arguments );
+ }
+ } );
+
+ MediaKeySession.prototype._onKeyStatusesChange = _proxyKeyStatusesChange;
+
+ // MediaKeyStatusMap proxy
+ //
+ // We need a proxy class to replace the broken MediaKeyStatusMap one. We cannot use a
+ // regular Map directly because we need get and has methods to compare by value not
+ // as references.
+ function MediaKeyStatusMap() { this._map = new Map(); }
+
+ Object.defineProperties( MediaKeyStatusMap.prototype, {
+ size: { get: function() { return this._map.size; } },
+ forEach: { get: function() { return function( f ) { return this._map.forEach( f ); } } },
+ entries: { get: function() { return function() { return this._map.entries(); } } },
+ values: { get: function() { return function() { return this._map.values(); } } },
+ keys: { get: function() { return function() { return this._map.keys(); } } },
+ clear: { get: function() { return function() { return this._map.clear(); } } } } );
+
+ MediaKeyStatusMap.prototype[ Symbol.iterator ] = function() { return this._map[ Symbol.iterator ]() };
+
+ MediaKeyStatusMap.prototype.has = function has( keyId ) {
+ for ( var k of this._map.keys() ) { if ( arrayBufferEqual( k, keyId ) ) return true; }
+ return false;
+ };
+
+ MediaKeyStatusMap.prototype.get = function get( keyId ) {
+ for ( var k of this._map.entries() ) { if ( arrayBufferEqual( k[ 0 ], keyId ) ) return k[ 1 ]; }
+ };
+
+ MediaKeyStatusMap.prototype._set = function _set( keyId, status ) {
+ this._map.set( new Uint8Array( keyId ), status );
+ };
+
+ function arrayBufferEqual(buf1, buf2)
+ {
+ if (buf1.byteLength !== buf2.byteLength) return false;
+ var a1 = Array.from( new Int8Array(buf1) ), a2 = Array.from( new Int8Array(buf2) );
+ return a1.every( function( x, i ) { return x === a2[i]; } );
+ }
+
+ // EventTarget
+ function EventTarget(){
+ this.listeners = {};
+ };
+
+ EventTarget.prototype.listeners = null;
+
+ EventTarget.prototype.addEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ this.listeners[type] = [];
+ }
+ this.listeners[type].push(callback);
+ };
+
+ EventTarget.prototype.removeEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[type];
+ for(var i = 0, l = stack.length; i < l; i++){
+ if(stack[i] === callback){
+ stack.splice(i, 1);
+ return this.removeEventListener(type, callback);
+ }
+ }
+ };
+
+ EventTarget.prototype.dispatchEvent = function(event){
+ if(!(event.type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[event.type];
+ event.target = this;
+ for(var i = 0, l = stack.length; i < l; i++) {
+ stack[i].call(this, event);
+ }
+ };
+ }
+})();
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js
new file mode 100644
index 0000000000..7f86f0c058
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/edge-persistent-usage-record.js
@@ -0,0 +1,193 @@
+(function() {
+
+ // This polyfill fixes the following problems with Edge browser
+ // (1) To retrieve a persisted usage record, you must use session type 'persistent-release-message' instead of 'persistent-usage-record'
+ // (2) To retrieve a persisted usage record, you must call remove() after calling load()
+ // (3) On providing a license release acknowledgement, the session does not automatically close as is should
+ // (4) Retrieval of the usage record at the end of an active session is not supported
+
+ if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) {
+
+ var _mediaKeySystemAccessCreateMediaKeys = MediaKeySystemAccess.prototype.createMediaKeys;
+ _mediaKeysCreateSession = MediaKeys.prototype.createSession;
+
+ // MediaKeySession proxy
+ function MediaKeySession( mediaKeys, session )
+ {
+ EventTarget.call( this );
+
+ this._mediaKeys = mediaKeys;
+ this._session = session;
+ this._sessionId = undefined;
+ this._removing = false;
+
+ session.addEventListener( 'message', this.dispatchEvent.bind( this ) );
+ session.addEventListener( 'keystatuseschange', this.dispatchEvent.bind( this ) );
+ session.closed.then( function() { if ( !this._removing ) this._resolveClosed(); }.bind ( this ) );
+
+ this._closed = new Promise( function( resolve ) { this._resolveClosed = resolve; }.bind( this ) );
+ }
+
+ MediaKeySession.prototype = Object.create( EventTarget.prototype );
+
+ Object.defineProperties( MediaKeySession.prototype, {
+ sessionId: { get: function() { return this._sessionId ? this._sessionId : this._session.sessionId; } },
+ expiration: { get: function() { return this._session.expiration; } },
+ closed: { get: function() { return this._closed; } },
+ keyStatuses:{ get: function() { return this._session.keyStatuses; } }
+ });
+
+ // load()
+ //
+ // Use a surrogate 'persistent-release-message' session to obtain the release message
+ //
+ MediaKeySession.prototype.load = function load( sessionId )
+ {
+ if ( this.sessionId ) return Promise.reject( new DOMException('InvalidAccessError') );
+
+ this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' );
+ this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) );
+
+ return this._surrogate.load( sessionId ).then( function( success ) {
+ if (!success) return false;
+
+ this._sessionId = sessionId;
+ this._removing = true;
+ this._session.close();
+
+ return this._surrogate.remove().then( function() { return true; } );
+ }.bind( this ) );
+ };
+
+ // remove()
+ //
+ // On an existing session, use a surrogate 'persistent-release-message' session to obtain the release message
+ //
+ MediaKeySession.prototype.remove = function remove()
+ {
+ if ( this._sessionId !== undefined ) return Promise.reject( new DOMException('InvalidAccessError') );
+ if ( this.sessionId === undefined ) return Promise.reject( new DOMException('InvalidAccessError') );
+
+ this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' );
+ this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) );
+ this._removing = true;
+ this._sessionId = this._session.sessionId;
+
+ var self = this;
+
+ return Promise.all( [ self._session.close(), self._session.closed ] ).then( function() {
+ return self._surrogate.load( self._sessionId );
+ }).then( function( success ) {
+ if ( !success ) {
+ throw new DOMException('InvalidAccessError');
+ }
+
+ return self._surrogate.remove();
+ }).then( function() { return true; } );
+ }
+
+ // update()
+ //
+ // For a normal session, pass through, otherwise update the surrogate and close the proxy
+ MediaKeySession.prototype.update = function update( message )
+ {
+ if ( !this._removing ) return this._session.update( message );
+
+ return this._surrogate.update( message ).then( function() {
+ this._sessionId = undefined;
+ this._resolveClosed();
+ }.bind( this ) );
+ };
+
+ // close() - pass through
+ //
+ MediaKeySession.prototype.close = function close()
+ {
+ if ( !this._removing ) return this._session.close();
+ this._resolveClosed();
+ return Promise.resolve();
+ };
+
+ // generateRequest() - pass through
+ //
+ MediaKeySession.prototype.generateRequest = function generateRequest( initDataType, initData )
+ {
+ if ( this.sessionId ) Promise.reject( new DOMException('InvalidAccessError') );
+ return this._session.generateRequest( initDataType, initData );
+ };
+
+ // Wrap PlayReady persistent-usage-record sessions in our Proxy
+ MediaKeys.prototype.createSession = function createSession( sessionType ) {
+
+ var session = _mediaKeysCreateSession.call( this, sessionType );
+ if ( this._keySystem !== 'com.microsoft.playready' || sessionType !== 'persistent-usage-record' )
+ {
+ return session;
+ }
+
+ return new MediaKeySession( this, session );
+
+ };
+
+ //
+ // Annotation polyfills - annotate not otherwise available data
+ //
+
+ // Annotate MediaKeys with the keysystem
+ MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKeys()
+ {
+ return _mediaKeySystemAccessCreateMediaKeys.call( this ).then( function( mediaKeys ) {
+ mediaKeys._keySystem = this.keySystem;
+ return mediaKeys;
+ }.bind( this ) );
+ };
+
+ //
+ // Utilities
+ //
+
+ // Allow us to modify the target of Events
+ Object.defineProperties( Event.prototype, {
+ target: { get: function() { return this._target || this.currentTarget; },
+ set: function( newtarget ) { this._target = newtarget; } }
+ } );
+
+ // Make an EventTarget base class
+ function EventTarget(){
+ this.listeners = {};
+ };
+
+ EventTarget.prototype.listeners = null;
+
+ EventTarget.prototype.addEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ this.listeners[type] = [];
+ }
+ this.listeners[type].push(callback);
+ };
+
+ EventTarget.prototype.removeEventListener = function(type, callback){
+ if(!(type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[type];
+ for(var i = 0, l = stack.length; i < l; i++){
+ if(stack[i] === callback){
+ stack.splice(i, 1);
+ return this.removeEventListener(type, callback);
+ }
+ }
+ };
+
+ EventTarget.prototype.dispatchEvent = function(event){
+ if(!(event.type in this.listeners)) {
+ return;
+ }
+ var stack = this.listeners[event.type];
+ event.target = this;
+ for(var i = 0, l = stack.length; i < l; i++) {
+ stack[i].call(this, event);
+ }
+ };
+ }
+})();
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js b/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js
new file mode 100644
index 0000000000..ce241af362
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/firefox-polyfill.js
@@ -0,0 +1,23 @@
+(function(){
+ if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
+
+ // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1282142
+ // Firefox does not correctly reject the Clear Key session types it does not support
+ var _requestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess.bind( navigator );
+
+ navigator.requestMediaKeySystemAccess = function( keysystem, configurations )
+ {
+ if ( keysystem !== 'org.w3.clearkey' ) return _requestMediaKeySystemAccess( keysystem, configurations );
+
+ var supported_configurations = configurations.filter( function( c ) {
+
+ return !c.sessionTypes || ( c.sessionTypes.length === 1 && c.sessionTypes[ 0 ] === 'temporary' );
+
+ } );
+
+ if ( supported_configurations.length === 0 ) return Promise.reject( new DOMException( 'None of the requested configurations were supported.' ) );
+
+ return _requestMediaKeySystemAccess( keysystem, supported_configurations );
+ }
+ }
+}()); \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py b/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py
new file mode 100644
index 0000000000..532037e2a3
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/polyfill/make-polyfill-tests.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+
+from __future__ import print_function
+
+import os, re, os.path, glob
+
+head = re.compile( r"^(\s*</head>)", re.MULTILINE )
+runtest = re.compile( r"runTest\(\s*(\S.*?)\s*\)", re.DOTALL )
+
+scripts = '''
+ <!-- Polyfill files (NOTE: These are added by auto-generation script) -->
+ <script src=/encrypted-media/polyfill/chrome-polyfill.js></script>
+ <script src=/encrypted-media/polyfill/firefox-polyfill.js></script>
+ <script src=/encrypted-media/polyfill/edge-persistent-usage-record.js></script>
+ <script src=/encrypted-media/polyfill/edge-keystatuses.js></script>
+ <script src=/encrypted-media/polyfill/clearkey-polyfill.js></script>'''
+
+def process_file( infile, outfile ) :
+ with open( outfile, "w" ) as output :
+ with open( infile, "r" ) as input :
+ output.write( runtest.sub( r"runTest( \1, 'polyfill: ' )", head.sub( scripts + r"\1", input.read() ) ) )
+
+if __name__ == '__main__' :
+ if (not os.getcwd().endswith('polyfill')) :
+ print("Please run from polyfill directory")
+ exit( 1 )
+
+ for infile in glob.glob( "../*.html" ) :
+ process_file( infile, os.path.basename( infile ) )
+
+ for infile in glob.glob( "../resources/*.html" ) :
+ process_file( infile, os.path.join( "resources", os.path.basename( infile ) ) )
diff --git a/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html
new file mode 100644
index 0000000000..a5a63dbf63
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html
@@ -0,0 +1,105 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, retrieve and destroy, ClearKey</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ // Wait for a message from the main window with details of our task
+ window.addEventListener( 'message', function( event ) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] },
+ assertions = [ ];
+
+ var _mediaKeys,
+ _mediaKeySession;
+
+ config.video = document.getElementById('videoelement');
+ config.messagehandler = (new MessageHandler( 'org.w3.clearkey')).messagehandler;
+
+ function onComplete() {
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+
+ function onFailure(error) {
+ assertions.push( { actual: false, expected: true, message: error.toString() } );
+ onComplete();
+ }
+
+ function onMessage( messageevent )
+ {
+ assertions.push( { expected: true, actual: messageevent instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } );
+ assertions.push( { expected: 'message', actual: messageevent.type, message: "event type is message" } );
+ assertions.push( { expected: 'license-release', actual: messageevent.messageType, message: "message type is license-release" } );
+
+ config.messagehandler( messageevent.messageType, messageevent.message )
+ .then( function( response ) {
+ messageevent.target.update( response ).catch(onFailure);
+ });
+ }
+
+ function onTimeupdate(event) {
+ if ( config.video.currentTime > ( config.duration || 1 ) ) {
+ config.video.pause();
+ config.video.removeAttribute('src');
+ config.video.load();
+ _mediaKeySession.remove();
+ }
+ }
+
+ function onClosed() {
+ // Try and reload and check this fails
+ var mediaKeySession = _mediaKeys.createSession( 'persistent-license' );
+ mediaKeySession.load( event.data.sessionId ).then( function( success ) {
+ assertions.push( { expected: false, actual: success, message: "Load of removed session should fail" } );
+ onComplete();
+ }).catch(onFailure);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] )
+ .then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
+ config.video.addEventListener('timeupdate', onTimeupdate, true);
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-license' );
+ _mediaKeySession.addEventListener( 'message', onMessage );
+ _mediaKeySession.closed.then(onClosed);
+ return _mediaKeySession.load( event.data.sessionId );
+ }).then(function( success ) {
+ assertions.push( { actual: success, expected: true, message: "Expect load session to succeed" } );
+ if ( !success ) throw new DOMException();
+ return testmediasource(config);
+ }).then(function(source) {
+ config.video.src = URL.createObjectURL(source);
+ config.video.play();
+ })
+ .catch(onFailure);
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html
new file mode 100644
index 0000000000..4716b42549
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html
@@ -0,0 +1,74 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, retrieve and playback, ClearKey</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ // Wait for a message from the main window with details of our task
+ window.addEventListener( 'message', function( event ) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] },
+ assertions = [ ];
+
+ var _mediaKeySession;
+
+ config.video = document.getElementById('videoelement');
+
+ function onComplete() {
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+
+ function onFailure(error) {
+ assertions.push( { actual: false, expected: true, message: error.toString() } );
+ onComplete();
+ }
+
+ function onTimeupdate(event) {
+ if ( config.video.currentTime > ( config.duration || 1 ) ) {
+ config.video.pause();
+ _mediaKeySession.close()
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] )
+ .then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
+ config.video.addEventListener('timeupdate', onTimeupdate, true);
+ _mediaKeySession = config.video.mediaKeys.createSession( 'persistent-license' );
+ _mediaKeySession.closed.then(onComplete);
+ return _mediaKeySession.load(event.data.sessionId);
+ }).then(function( success ) {
+ if ( !success ) throw new DOMException( 'Could not load session' );
+ return testmediasource(config);
+ }).then(function(source) {
+ config.video.src = URL.createObjectURL(source);
+ config.video.play();
+ })
+ .catch(onFailure);
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html
new file mode 100644
index 0000000000..6564d8e606
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, retrieve and destroy, drm</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+
+ <!-- Message handler for DRM keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ // Wait for a message from the main window with details of our task
+ window.addEventListener('message', function(event) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['persistent-license']},
+ assertions = [];
+
+ var _mediaKeys,
+ _mediaKeySession;
+
+ config.video = document.getElementById('videoelement');
+ config.messagehandler = (new MessageHandler(config.keysystem, config.content, 'persistent-license')).messagehandler;
+
+ function onComplete() {
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+
+ function onFailure(error) {
+ assertions.push({actual: false, expected: true, message: error.toString()});
+ onComplete();
+ }
+
+ function onMessage( messageevent )
+ {
+ assertions.push({expected: true, actual: messageevent instanceof window.MediaKeyMessageEvent, message: "event is of correct class"});
+ assertions.push({expected: 'message', actual: messageevent.type, message: "event type is message"});
+ assertions.push({expected: 'license-release', actual: messageevent.messageType, message: "message type is license-release"});
+
+ config.messagehandler(messageevent.messageType, messageevent.message)
+ .then( function(response) {
+ return messageevent.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (config.video.currentTime > (config.duration || 1)) {
+ config.video.pause();
+ config.video.removeAttribute('src');
+ config.video.load();
+ _mediaKeySession.remove();
+ }
+ }
+
+ function onClosed() {
+ // Try and reload and check this fails
+ var mediaKeySession = _mediaKeys.createSession('persistent-license');
+ mediaKeySession.load(event.data.sessionId ).then( function(success) {
+ assertions.push({expected: false, actual: success, message: "Load of removed session should fail"});
+ onComplete();
+ }).catch(onFailure);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration] )
+ .then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
+ config.video.addEventListener('timeupdate', onTimeupdate, true);
+ _mediaKeySession = _mediaKeys.createSession('persistent-license');
+ _mediaKeySession.addEventListener('message', onMessage);
+ _mediaKeySession.closed.then(onClosed);
+ return _mediaKeySession.load(event.data.sessionId);
+ }).then(function(success) {
+ assertions.push({actual: success, expected: true, message: "Expect load session to succeed"});
+ if (!success) throw new DOMException();
+ return testmediasource(config);
+ }).then(function(source) {
+ config.video.src = URL.createObjectURL(source);
+ config.video.play();
+ })
+ .catch(onFailure);
+ } );
+
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html
new file mode 100644
index 0000000000..bf554248f4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-license.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: persistent-license, retrieve and playback, DRM</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+ <script src=/encrypted-media/util/testmediasource.js></script>
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <div id='video'>
+ <video id="videoelement" width="200px"></video>
+ </div>
+
+ <script>
+ // Wait for a message from the main window with details of our task
+ window.addEventListener( 'message', function( event ) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] },
+ assertions = [ ];
+
+ var _mediaKeySession;
+ config.video = document.getElementById('videoelement');
+
+ function onComplete() {
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+
+ function onFailure(error) {
+ assertions.push( { actual: false, expected: true, message: error.toString() } );
+ onComplete();
+ }
+
+ function onTimeupdate(event) {
+ if ( config.video.currentTime > ( config.duration || 1 ) ) {
+ config.video.removeEventListener('timeupdate', onTimeupdate);
+ config.video.pause();
+
+ _mediaKeySession.closed
+ .then(onComplete)
+ .catch(onFailure);
+ _mediaKeySession.close()
+ .catch(onFailure);
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] )
+ .then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
+ config.video.addEventListener('timeupdate', onTimeupdate);
+ _mediaKeySession = config.video.mediaKeys.createSession( 'persistent-license' );
+ return _mediaKeySession.load(event.data.sessionId);
+ }).then(function( success ) {
+ if ( !success ) throw new DOMException( 'Could not load session' );
+ return testmediasource(config);
+ }).then(function(source) {
+ config.video.src = URL.createObjectURL(source);
+ config.video.play();
+ })
+ .catch(onFailure);
+ } );
+
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html
new file mode 100644
index 0000000000..d1b3e0c694
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Retrieve stored persistent-usage-record</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/drm-messagehandler.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+ window.addEventListener( 'message', function( event ) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-usage-record' ] },
+ assertions = [ ],
+ _mediaKeys,
+ _mediaKeySession;
+
+ config.messagehandler = (new MessageHandler( config.keysystem, undefined, 'persistent-usage-record' ) ).messagehandler;
+
+ function onFailure(error) {
+ assertions.push( { actual: false, expected: true, message: error } );
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+
+ function onMessage( event )
+ {
+ assertions.push( { expected: true, actual: event instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } );
+ assertions.push( { expected: 'message', actual: event.type, message: "event type is message" } );
+ assertions.push( { expected: 'license-release', actual: event.messageType, message: "message type is license-release" } );
+
+ config.messagehandler( event.messageType, event.message ).then( function( response ) {
+ event.target.update( response ).catch( onFailure );
+ });
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true;
+ }).then( function( success ) {
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' );
+ _mediaKeySession.addEventListener( 'message', onMessage );
+ _mediaKeySession.closed.then( function() {
+ window.opener.postMessage({ testResult: assertions }, '*');
+ });
+ return _mediaKeySession.load( event.data.sessionId );
+ }).then(function( success ) {
+ if ( !success ) {
+ assertions.push( { actual: success, expected: true, message: "Error loading session" } );
+ window.opener.postMessage({ testResult: assertions }, '*');
+ }
+ }).catch( onFailure );
+ });
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html b/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html
new file mode 100644
index 0000000000..c09134b546
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/resources/retrieve-persistent-usage-record.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extensions: Retrieve stored persistent-usage-record</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <!-- Helper scripts for Encrypted Media Extensions tests -->
+ <script src=/encrypted-media/util/utils.js></script>
+ <script src=/encrypted-media/util/utf8.js></script>
+
+ <!-- Message handler for Clear Key keysystem -->
+ <script src=/encrypted-media/util/clearkey-messagehandler.js></script>
+
+ </head>
+ <body>
+ <div id='log'></div>
+
+ <script>
+
+ window.addEventListener( 'message', function( event ) {
+
+ var config = event.data.config,
+ configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-usage-record' ] },
+ assertions = [ ];
+
+ config.messagehandler = (new MessageHandler('org.w3.keysystem')).messagehandler;
+
+ function onMessage( event )
+ {
+ assertions.push( { expected: true, actual: event instanceof window.MediaKeyMessageEvent, message: "event is of correct class" } );
+ assertions.push( { expected: 'message', actual: event.type, message: "event type is message" } );
+ assertions.push( { expected: 'license-release', actual: event.messageType, message: "message type is license-release" } );
+
+ var release = fromUtf8( event.message );
+
+ consoleWrite( JSON.stringify( release ) );
+
+ assertions.push( { expected: 1, actual: release.kids.length, message: "release message contains a single key" } );
+ assertions.push( { expected: true, actual: ( typeof release.firstTime === 'number' ), message: "firstTime is a number" } );
+ assertions.push( { expected: true, actual: ( typeof release.latestTime === 'number' ), message: "latestTime is a number" } );
+
+ var duration = release.latestTime - release.firstTime;
+ assertions.push( { expected: true, actual: ( duration >= 2000 ), message: "duration >= 2s" } );
+ assertions.push( { expected: true, actual: ( duration < 4000 ), message: "duration < 4s" } );
+
+ config.messagehandler( event.messageType, event.message )
+ .then( function( response ) {
+
+ event.target.update( response ).catch(function(error) {
+
+ assertions.push( { actual: false, expected: true, message: error } );
+
+ window.opener.postMessage({ testResult: assertions }, '*');
+ });
+ });
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ] ).then(function(access) {
+
+ return access.createMediaKeys();
+
+ }).then(function(mediaKeys) {
+
+ var mediaKeySession = mediaKeys.createSession( 'persistent-usage-record' );
+
+ mediaKeySession.addEventListener( 'message', onMessage );
+ mediaKeySession.closed.then( function() {
+
+ window.opener.postMessage({ testResult: assertions }, '*');
+
+ });
+
+ return mediaKeySession.load( event.data.sessionId );
+
+ }).catch(function(error) {
+
+ assertions.push( { actual: false, expected: true, message: error.toString() } );
+
+ window.opener.postMessage({ testResult: assertions }, '*');
+
+ });
+
+
+ } );
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/check-encryption-scheme.js b/testing/web-platform/tests/encrypted-media/scripts/check-encryption-scheme.js
new file mode 100644
index 0000000000..ffab4a3491
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/check-encryption-scheme.js
@@ -0,0 +1,46 @@
+function runTest(config, qualifier)
+{
+ function checkEncryptionScheme(encryptionScheme)
+ {
+ var simpleConfig = getSimpleConfiguration();
+ assert_greater_than(simpleConfig[0].audioCapabilities.length, 0);
+ simpleConfig[0].audioCapabilities.forEach(function(capability) {
+ capability.encryptionScheme = encryptionScheme;
+ });
+
+ return navigator.requestMediaKeySystemAccess(config.keysystem, simpleConfig)
+ .then(
+ function(access) {
+ var actualConfiguration = access.getConfiguration();
+ for (let i = 0; i < actualConfiguration.audioCapabilities.length; i++) {
+ const capability = actualConfiguration.audioCapabilities[i];
+
+ // If "encryptionScheme" is not supported, fail.
+ if (!('encryptionScheme' in capability)) {
+ return Promise.reject('Not implemented');
+ }
+
+ // If "encryptionScheme" is supported, it should be returned.
+ assert_equals(capability.encryptionScheme, encryptionScheme);
+ }
+ return Promise.resolve('Supported');
+ },
+ function error() {
+ // CDM does not support "encryptionScheme". Test should still pass.
+ return Promise.resolve('Not supported');
+ });
+ }
+
+ promise_test(
+ () => checkEncryptionScheme('cenc'),
+ testnamePrefix(qualifier, config.keysystem) + ' support for "cenc" encryption scheme.');
+
+ promise_test(
+ () => checkEncryptionScheme('cbcs'),
+ testnamePrefix(qualifier, config.keysystem) + ' support for "cbcs" encryption scheme.');
+
+ promise_test(
+ () => checkEncryptionScheme('cbcs-1-9'),
+ testnamePrefix(qualifier, config.keysystem) +
+ ' support for "cbcs-1-9" encryption scheme.');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js b/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js
new file mode 100644
index 0000000000..5c7cb6e4b9
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/check-initdata-type.js
@@ -0,0 +1,35 @@
+ function runTest( config, qualifier )
+ {
+ function checkInitDataType(initDataType)
+ {
+ return isInitDataTypeSupported(initDataType).then(function(result) {
+ // If |initDataType| is not supported, simply succeed.
+ if (!result)
+ return Promise.resolve('Not supported');
+
+ return navigator.requestMediaKeySystemAccess( config.keysystem, getSimpleConfigurationForInitDataType(initDataType))
+ .then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession();
+ var initData = getInitData(initDataType);
+ return mediaKeySession.generateRequest(initDataType, initData);
+ });
+ });
+ }
+
+ promise_test(function()
+ {
+ return checkInitDataType('webm');
+ }, testnamePrefix( qualifier, config.keysystem ) + ' support for "webm".');
+
+ promise_test(function()
+ {
+ return checkInitDataType('cenc');
+ }, testnamePrefix( qualifier, config.keysystem ) + ' support for "cenc".');
+
+ promise_test(function()
+ {
+ return checkInitDataType('keyids');
+ }, testnamePrefix( qualifier, config.keysystem ) + ' support for "keyids".');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/check-status-for-hdcp.js b/testing/web-platform/tests/encrypted-media/scripts/check-status-for-hdcp.js
new file mode 100644
index 0000000000..ac30819695
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/check-status-for-hdcp.js
@@ -0,0 +1,26 @@
+function runTest(config, qualifier)
+{
+ function checkStatusForMinHdcpVersionPolicy(hdcpVersion)
+ {
+ return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration())
+ .then(function(access) {
+ return access.createMediaKeys();
+ })
+ .then(function(mediaKeys) {
+ // As HDCP policy depends on the hardware running this test,
+ // don't bother checking the result returned as it may or
+ // may not be supported. This simply verifies that
+ // getStatusForPolicy() exists and doesn't blow up.
+ return mediaKeys.getStatusForPolicy({minHdcpVersion: hdcpVersion});
+ });
+ }
+
+ promise_test(
+ () => checkStatusForMinHdcpVersionPolicy(''),
+ testnamePrefix(qualifier, config.keysystem) +
+ ' support for empty HDCP version.');
+
+ promise_test(
+ () => checkStatusForMinHdcpVersionPolicy('1.0'),
+ testnamePrefix(qualifier, config.keysystem) + ' support for HDCP 1.0.');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js b/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js
new file mode 100644
index 0000000000..7a5c073bfa
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/clearkey-update-non-ascii-input.js
@@ -0,0 +1,52 @@
+// This test is only applicable to clearkey
+function runTest(config, qualifier)
+{
+ var testname = testnamePrefix(qualifier, config.keysystem) + ' test handling of non-ASCII responses for update()';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ promise_test(function (test) {
+ var initDataType;
+ var initData;
+ var mediaKeySession;
+ var messageEventFired = false;
+
+ var p = navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function (access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+ initData = getInitData(config.content, initDataType);
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ mediaKeySession = mediaKeys.createSession();
+ var eventWatcher = new EventWatcher(test, mediaKeySession, ['message']);
+ var promise = eventWatcher.wait_for('message');
+ mediaKeySession.generateRequest(initDataType, initData);
+ return promise;
+ }).then(function (messageEvent) {
+ // |jwkSet| contains a non-ASCII character \uDC00.
+ var jwkSet = '{"keys":[{'
+ + '"kty":"oct",'
+ + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",'
+ + '"kid":"MDEyMzQ1Njc4O\uDC00TAxMjM0NQ"'
+ + '}]}';
+ messageEventFired = true;
+ return messageEvent.target.update(stringToUint8Array(jwkSet));
+ }).catch(function (error) {
+ // Ensure we reached the update() call we are trying to test.
+ if (!messageEventFired) {
+ assert_unreached(
+ `Failed to reach the update() call. Error: '${error.name}' '${error.message}'`);
+ }
+
+ // Propagate the error on through.
+ throw error;
+ });
+
+ return promise_rejects_js(
+ test, TypeError, p,
+ 'update() should fail because the processed message has non-ASCII character.');
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js b/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js
new file mode 100644
index 0000000000..44f683eac8
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/events-session-closed-event.js
@@ -0,0 +1,52 @@
+function runTest(config, qualifier)
+{
+ var testname = testnamePrefix(qualifier, config.keysystem) + ' test MediaKeySession closed event.';
+
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{
+ contentType: config.audioType
+ }],
+ videoCapabilities: [{
+ contentType: config.videoType
+ }],
+ sessionTypes: ['temporary']
+ };
+
+ promise_test(function (test) {
+ var initDataType;
+ var initData;
+ var mediaKeySession;
+
+ return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function (access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ mediaKeySession = mediaKeys.createSession();
+ if(config.initData) {
+ initData = config.initData;
+ } else {
+ initData = stringToUint8Array(atob(config.content.keys[0].initData));
+ }
+ return mediaKeySession.generateRequest(initDataType, initData);
+ }).then(function() {
+ // close() should result in the closed promise being
+ // fulfilled.
+ return mediaKeySession.close();
+ }).then(function (result) {
+ assert_equals(result, undefined);
+ // Wait for the session to be closed.
+ return mediaKeySession.closed;
+ }).then(function (result) {
+ assert_equals(result, undefined);
+ // Now that the session is closed, verify that the
+ // closed attribute immediately returns a fulfilled
+ // promise.
+ return mediaKeySession.closed;
+ }).then(function (result) {
+ assert_equals(result, undefined);
+ }).catch(function(error) {
+ assert_unreached('Error: ' + error.name);
+ });
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/events.js b/testing/web-platform/tests/encrypted-media/scripts/events.js
new file mode 100644
index 0000000000..85c86ae78d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/events.js
@@ -0,0 +1,59 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem) + ', basic events';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test)
+ {
+ var initDataType;
+ var initData;
+ var mediaKeySession;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function processMessage(event)
+ {
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.target, mediaKeySession);
+ assert_equals(event.type, 'message');
+ assert_in_array(event.messageType,['license-request', 'individualization-request']);
+
+ config.messagehandler( event.messageType, event.message ).then(function(response) {
+ waitForEventAndRunStep('keystatuseschange', mediaKeySession, test.step_func(processKeyStatusesChange), test);
+ return mediaKeySession.update( response );
+ }).catch(onFailure);
+ }
+
+ function processKeyStatusesChange(event)
+ {
+ assert_true(event instanceof Event);
+ assert_equals(event.target, mediaKeySession);
+ assert_equals(event.type, 'keystatuseschange');
+ test.done();
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem,[configuration]).then(function(access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+
+ if (config.initDataType && config.initData) {
+ initData = config.initData;
+ } else {
+ initData = getInitData(config.content, initDataType);
+ }
+
+ return access.createMediaKeys();
+ }).then(test.step_func(function(mediaKeys) {
+ mediaKeySession = mediaKeys.createSession();
+ waitForEventAndRunStep('message', mediaKeySession, test.step_func(processMessage), test);
+ return mediaKeySession.generateRequest(initDataType, initData);
+ })).catch(onFailure);
+ }, testname );
+
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/expiration.js b/testing/web-platform/tests/encrypted-media/scripts/expiration.js
new file mode 100644
index 0000000000..96b7fbfeef
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/expiration.js
@@ -0,0 +1,43 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem) + ', expiration';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test) {
+
+ var _mediaKeys,
+ _mediaKeySession;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, [ 'license-request', 'individualization-request' ] );
+
+ config.messagehandler(event.messageType, event.message, {expiration: config.expiration}).then(function(response) {
+ return event.target.update(response);
+ }).then(test.step_func(function() {
+ assert_approx_equals(event.target.expiration, config.expiration, 4000, "expiration attribute should equal provided expiration time");
+ test.done();
+ })).catch(onFailure);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ _mediaKeySession = _mediaKeys.createSession( 'temporary' );
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ return _mediaKeySession.generateRequest(config.initDataType, config.initData);
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js b/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js
new file mode 100644
index 0000000000..9fd42ee85f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/generate-request-disallowed-input.js
@@ -0,0 +1,72 @@
+function runTest(config,qualifier) {
+ var tests = [ ], initData, keyId;
+ function push_test(keysystem, initDataType, initData, testname) {
+ tests.push({ keysystem: keysystem, initDataType: initDataType, initData: initData, testname: testname });
+ }
+
+ initData = new Uint8Array(70000);
+ push_test(config.keysystem, 'webm', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, webm, initData longer than 64Kb characters');
+
+ initData = new Uint8Array(70000);
+ push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, initData longer than 64Kb characters');
+
+ initData = new Uint8Array(70000);
+ push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, initData longer than 64Kb characters');
+
+ // Invalid 'pssh' box as the size specified is larger than what
+ // is provided.
+ initData = new Uint8Array([
+ 0x00, 0x00, 0xff, 0xff, // size = huge
+ 0x70, 0x73, 0x73, 0x68, // 'pssh'
+ 0x00, // version = 0
+ 0x00, 0x00, 0x00, // flags
+ 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
+ 0x00, 0x00, 0x00, 0x00 // datasize
+ ]);
+ push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, invalid initdata (invalid pssh)');
+
+ // Invalid data as type = 'psss'.
+ initData = new Uint8Array([
+ 0x00, 0x00, 0x00, 0x00, // size = 0
+ 0x70, 0x73, 0x73, 0x73, // 'psss'
+ 0x00, // version = 0
+ 0x00, 0x00, 0x00, // flags
+ 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
+ 0x00, 0x00, 0x00, 0x00 // datasize
+ ]);
+ push_test(config.keysystem, 'cenc', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, cenc, invalid initdata (not pssh)');
+
+ // Valid key ID size must be at least 1 character for keyids.
+ keyId = new Uint8Array(0);
+ initData = stringToUint8Array(createKeyIDs(keyId));
+ push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, invalid initdata (too short key ID)');
+
+ // Valid key ID size must be less than 512 characters for keyids.
+ keyId = new Uint8Array(600);
+ initData = stringToUint8Array(createKeyIDs(keyId));
+ push_test(config.keysystem, 'keyids', initData, testnamePrefix( qualifier, config.keysystem ) + ', temporary, keyids, invalid initdata (too long key ID)');
+
+ Promise.all( tests.map(function(testspec) {
+ return isInitDataTypeSupported(testspec.keysystem,testspec.initDataType);
+ })).then(function(results) {
+ tests.filter(function(testspec, i) { return results[i]; } ).forEach(function(testspec) {
+ promise_test(function(test) {
+ // Create a "temporary" session for |keysystem| and call generateRequest()
+ // with the provided initData. generateRequest() should fail with an
+ // TypeError. Returns a promise that is resolved
+ // if the error occurred and rejected otherwise.
+ var p = navigator.requestMediaKeySystemAccess(testspec.keysystem, getSimpleConfigurationForInitDataType(testspec.initDataType)).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession("temporary");
+ return mediaKeySession.generateRequest(testspec.initDataType, testspec.initData);
+ });
+
+ return promise_rejects_js(test, TypeError, p,
+ "generateRequest() should fail");
+ }, testspec.testname);
+ });
+ });
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js b/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js
new file mode 100644
index 0000000000..89d43769e5
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/invalid-license.js
@@ -0,0 +1,38 @@
+function runTest(config)
+{
+ promise_test(function (test) {
+ var initDataType;
+ var initData;
+ var keySystem = config.keysystem;
+ var invalidLicense = new Uint8Array([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77]);
+ var messageEventFired = false;
+
+ var p = navigator.requestMediaKeySystemAccess(keySystem, getSimpleConfiguration()).then(function (access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+ initData = getInitData(initDataType);
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var keySession = mediaKeys.createSession();
+ var eventWatcher = new EventWatcher(test, keySession, ['message']);
+ var promise = eventWatcher.wait_for('message');
+ keySession.generateRequest(initDataType, initData);
+ return promise;
+ }).then(function (messageEvent) {
+ messageEventFired = true;
+ return messageEvent.target.update(invalidLicense);
+ }).catch(function (error) {
+ // Ensure we reached the update() call we are trying to test.
+ if (!messageEventFired) {
+ assert_unreached(
+ `Failed to reach the update() call. Error: '${error.name}' '${error.message}'`);
+ }
+
+ // Propagate the error on through.
+ throw error;
+ });
+
+ return promise_rejects_js(
+ test, TypeError, p,
+ 'update() should fail because of an invalid license.');
+ }, 'Update with invalid Clear Key license');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js b/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js
new file mode 100644
index 0000000000..e9bf10e886
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/keystatuses-multiple-sessions.js
@@ -0,0 +1,103 @@
+function runTest(config,qualifier)
+{
+ var testname = testnamePrefix(qualifier, config.keysystem) + ', temporary, keystatuses, multiple sessions';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) configuration.initDataTypes = [config.initDataType];
+
+ async_test(function(test)
+ {
+ var mediaKeySession1;
+ var mediaKeySession2;
+
+ // Even though key ids are uint8, using printable values so that
+ // they can be verified easily.
+ var key1 = new Uint8Array(config.content.keys[0].kid),
+ key2 = new Uint8Array(config.content.keys[1].kid),
+ variant1 = config.content.keys[0].variantId,
+ variant2 = config.content.keys[1].variantId;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test,error);
+ }
+
+ function processMessage1(event)
+ {
+ // This should only be called for session1.
+ assert_equals(event.target, mediaKeySession1);
+
+ // No keys added yet.
+ verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [], unexpected: [key1, key2]});
+
+ // Add key1 to session1.
+ config.messagehandler(event.messageType, event.message, {variantId:variant1}).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+
+ }
+
+ function processKeyStatusesChange1(event)
+ {
+ // This should only be called for session1.
+ assert_equals(event.target, mediaKeySession1);
+
+ // Check that keyStatuses contains the expected key1 only.
+ verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]});
+
+ // Now trigger a message event on session2.
+ mediaKeySession2.generateRequest(config.initDataType, config.initData[1]).catch(onFailure);
+ }
+
+ function processMessage2(event)
+ {
+ // This should only be called for session2.
+ assert_equals(event.target, mediaKeySession2);
+
+ // session2 has no keys added yet.
+ verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [], unexpected: [key1, key2]});
+
+ // session1 should still have 1 key.
+ verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]});
+
+ // Add key2 to session2.
+ config.messagehandler(event.messageType, event.message, {variantId:variant2}).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function processKeyStatusesChange2(event)
+ {
+ // This should only be called for session2.
+ assert_equals(event.target, mediaKeySession2);
+
+ // Check that keyStatuses contains the expected key2 only.
+ verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [key2], unexpected: [key1]});
+
+ // session1 should still have 1 key.
+ verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [key1], unexpected: [key2]});
+
+ test.done();
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ mediaKeySession1 = mediaKeys.createSession();
+ mediaKeySession2 = mediaKeys.createSession();
+
+ // There should be no keys defined on either session.
+ verifyKeyStatuses(mediaKeySession1.keyStatuses, {expected: [], unexpected: [key1, key2]});
+ verifyKeyStatuses(mediaKeySession2.keyStatuses, {expected: [], unexpected: [key1, key2]});
+
+ // Bind all the event handlers now.
+ waitForEventAndRunStep('message', mediaKeySession1, processMessage1, test);
+ waitForEventAndRunStep('message', mediaKeySession2, processMessage2, test);
+ waitForEventAndRunStep('keystatuseschange', mediaKeySession1, processKeyStatusesChange1, test);
+ waitForEventAndRunStep('keystatuseschange', mediaKeySession2, processKeyStatusesChange2, test);
+
+ // Generate a request on session1.
+ return mediaKeySession1.generateRequest(config.initDataType, config.initData[0]);
+ }).catch(onFailure);
+ }, testname );
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js b/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js
new file mode 100644
index 0000000000..8d33dd4210
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/keystatuses.js
@@ -0,0 +1,165 @@
+function runTest(config,qualifier)
+{
+ var testname = testnamePrefix(qualifier, config.keysystem) + ', temporary, keystatuses';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test)
+ {
+ var mediaKeySession;
+ var initDataType;
+ var initData;
+ var closed = false;
+
+ // Even though key ids are uint8, using printable values so that
+ // they can be verified easily.
+ var key1 = new Uint8Array(config.content.keys[0].kid),
+ key2 = new Uint8Array(config.content.keys[1].kid),
+ key1String = arrayBufferAsString(key1),
+ key2String = arrayBufferAsString(key2);
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function processMessage(event)
+ {
+ // No keys added yet.
+ assert_equals(mediaKeySession.keyStatuses.size, 0);
+
+ waitForEventAndRunStep('keystatuseschange', mediaKeySession, processKeyStatusesChange, test);
+
+ // Add keys to session
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function checkKeyStatusFor2Keys()
+ {
+ // Two keys added, so both should show up in |keyStatuses|.
+ assert_equals(mediaKeySession.keyStatuses.size, 2);
+
+ // Check |keyStatuses| for 2 entries.
+ var result = [];
+ for (let item of mediaKeySession.keyStatuses) {
+ result.push({ key: arrayBufferAsString(item[0]), value: item[1] });
+ }
+ function lexicographical( a, b ) { return a < b ? -1 : a === b ? 0 : +1; }
+ function lexicographicalkey( a, b ) { return lexicographical( a.key, b.key ); }
+ var expected1 = [{ key: key1String, value: 'usable'}, { key: key2String, value: 'usable'}].sort( lexicographicalkey );
+ var expected2 = [{ key: key1String, value: 'status-pending'}, { key: key2String, value: 'status-pending'}].sort( lexicographicalkey );
+ assert_in_array( JSON.stringify(result),
+ [ JSON.stringify(expected1),JSON.stringify(expected2) ],
+ "keystatuses should have the two expected keys with keystatus 'usable' or 'status-pending'");
+
+ // |keyStatuses| must contain both keys.
+ result = [];
+ for (var key of mediaKeySession.keyStatuses.keys()) {
+ result.push(arrayBufferAsString(key));
+ }
+ assert_array_equals(result,
+ [key1String, key2String].sort( lexicographical ),
+ "keyStatuses.keys() should return an iterable over the two expected keys");
+
+ // Both values in |mediaKeySession| should be 'usable' or 'status-pending'.
+ result = [];
+ for (var value of mediaKeySession.keyStatuses.values()) {
+ result.push(value);
+ }
+
+ assert_equals( result.length, 2, "keyStatuses.values() should have two elements" );
+ assert_equals( result[0], result[1], "the values in keyStatuses.values() should be equal" );
+ assert_in_array( result[0], [ 'usable', 'status-pending' ] );
+
+ // Check |keyStatuses.entries()|.
+ result = [];
+ for (var entry of mediaKeySession.keyStatuses.entries()) {
+ result.push({ key: arrayBufferAsString(entry[0]), value: entry[1] });
+ }
+ assert_in_array(JSON.stringify(result),
+ [ JSON.stringify(expected1), JSON.stringify(expected2) ],
+ "keyStatuses.entries() should return an iterable over the two expected keys, with keystatus 'usable' or 'status-pending'");
+
+ // forEach() should return both entries.
+ result = [];
+ mediaKeySession.keyStatuses.forEach(function(status, keyId) {
+ result.push({ key: arrayBufferAsString(keyId), value: status });
+ });
+ assert_in_array(JSON.stringify(result),
+ [ JSON.stringify(expected1), JSON.stringify(expected2) ],
+ "keyStatuses.forEach() should iterate over the two expected keys, with keystatus 'usable' or 'status-pending'");
+
+ // has() and get() should return the expected values.
+ assert_true(mediaKeySession.keyStatuses.has(key1), "keyStatuses should have key1");
+ assert_true(mediaKeySession.keyStatuses.has(key2), "keyStatuses should have key2");
+ assert_in_array(mediaKeySession.keyStatuses.get(key1), [ 'usable', 'status-pending' ], "key1 should have status 'usable' or 'status-pending'");
+ assert_in_array(mediaKeySession.keyStatuses.get(key2), [ 'usable', 'status-pending' ], "key2 should have status 'usable' or 'status-pending'");
+
+ // Try some invalid keyIds.
+ var invalid1 = key1.subarray(0, key1.length - 1);
+ assert_false(mediaKeySession.keyStatuses.has(invalid1), "keystatuses should not have invalid key (1)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid1), undefined, "keystatus value for invalid key should be undefined (1)");
+
+ var invalid2 = key1.subarray(1);
+ assert_false(mediaKeySession.keyStatuses.has(invalid2), "keystatuses should not have invalid key (2)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid2), undefined, "keystatus value for invalid key should be undefined (2)");
+
+ var invalid3 = new Uint8Array(key1);
+ invalid3[0] += 1;
+ assert_false(mediaKeySession.keyStatuses.has(invalid3), "keystatuses should not have invalid key (3)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid3), undefined, "keystatus value for invalid key should be undefined (3)");
+
+ var invalid4 = new Uint8Array(key1);
+ invalid4[invalid4.length - 1] -= 1;
+ assert_false(mediaKeySession.keyStatuses.has(invalid4), "keystatuses should not have invalid key (4)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid4), undefined, "keystatus value for invalid key should be undefined (4)");
+
+ var invalid5 = new Uint8Array(key1.length + 1);
+ invalid5.set(key1, 1); // First element will be 0.
+ assert_false(mediaKeySession.keyStatuses.has(invalid5), "keystatuses should not have invalid key (5)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid5), undefined, "keystatus value for invalid key should be undefined (5)");
+
+ var invalid6 = new Uint8Array(key1.length + 1);
+ invalid6.set(key1, 0); // Last element will be 0.
+ assert_false(mediaKeySession.keyStatuses.has(invalid6), "keystatuses should not have invalid key (6)");
+ assert_equals(mediaKeySession.keyStatuses.get(invalid6), undefined, "keystatus value for invalid key should be undefined (6)");
+ }
+
+ function processKeyStatusesChange(event)
+ {
+ if (!closed)
+ {
+ // The first keystatuseschange (caused by update())
+ // should include both keys.
+ checkKeyStatusFor2Keys();
+
+ mediaKeySession.close().catch(onFailure);
+ closed = true;
+ }
+ else
+ {
+ // The second keystatuseschange (caused by close())
+ // should not have any keys.
+ assert_equals(mediaKeySession.keyStatuses.size, 0);
+ test.done();
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(test.step_func(function(mediaKeys) {
+ mediaKeySession = mediaKeys.createSession();
+
+ // There should be no keys defined yet.
+ //verifyKeyStatuses(mediaKeySession.keyStatuses, { expected: [], unexpected: [key1, key2] });
+
+ waitForEventAndRunStep('message', mediaKeySession, processMessage, test);
+ return mediaKeySession.generateRequest(config.initDataType, config.initData);
+ })).catch(onFailure);
+ }, testname );
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js b/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js
new file mode 100644
index 0000000000..2642c71e0e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/not-callable-after-createsession.js
@@ -0,0 +1,50 @@
+ function runTest(config,qualifier) {
+ // After creation, the MediaKeySession object is not
+ // callable, and we should get a InvalidStateError.
+
+ promise_test(function()
+ {
+ return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession();
+
+ var arbitraryResponse = new Uint8Array([0x00, 0x11]);
+ return mediaKeySession.update(arbitraryResponse).then(function(result) {
+ assert_unreached('update() succeeded unexpectedly.');
+ }).catch(function(error) {
+ assert_equals(error.name, 'InvalidStateError');
+ });
+ });
+ }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, update() immediately after createSession()');
+
+ promise_test(function()
+ {
+ return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession();
+
+ return mediaKeySession.close().then(function(result) {
+ assert_unreached('close() succeeded unexpectedly.');
+ }).catch(function(error) {
+ assert_equals(error.name, 'InvalidStateError');
+ });
+ });
+ }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, close() immediately after createSession()');
+
+ promise_test(function()
+ {
+ return navigator.requestMediaKeySystemAccess(config.keysystem, getSimpleConfiguration()).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession();
+
+ return mediaKeySession.remove().then(function(result) {
+ assert_unreached('remove() succeeded unexpectedly.');
+ }).catch(function(error) {
+ assert_equals(error.name, 'InvalidStateError');
+ });
+ });
+ }, testnamePrefix( qualifier, config.keysystem ) + ', temporary, remove() immediately after createSession()');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js b/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js
new file mode 100644
index 0000000000..acf0ffacc0
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/onencrypted.js
@@ -0,0 +1,48 @@
+function runTest(config) {
+ var expectedInitData = [];
+ expectedInitData.push(stringToUint8Array(atob(config.keys[0].initData)));
+ expectedInitData.push(stringToUint8Array(atob(config.keys[1].initData)));
+
+ // Will get 2 identical events, one for audio, one for video.
+ var expectedEvents = 2;
+ var currentData;
+
+ async_test(function (test) {
+ var video = config.video,
+ mediaSource,
+ onEncrypted = function (event) {
+ currentData = new Uint8Array(event.initData);
+ assert_equals(event.target, config.video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+ assert_equals(event.initDataType, 'cenc');
+ // At this point we do not know if the event is related to audio or video. So check for both expected init data
+ assert_true(checkInitData(currentData, expectedInitData[0]) || checkInitData(currentData, expectedInitData[1]));
+
+ if (--expectedEvents === 0) {
+ test.done();
+ }
+ };
+
+ waitForEventAndRunStep('encrypted', video, onEncrypted, test);
+ testmediasource(config).then(function (source) {
+ mediaSource = source;
+ config.video.src = URL.createObjectURL(mediaSource);
+ return source.done;
+ }).then(function(){
+ video.play();
+ });
+ }, 'encrypted fired on encrypted media file.');
+}
+
+function checkInitData(data, expectedData) {
+ if (data.length !== expectedData.length) {
+ return false;
+ }
+ for (var i = 0; i < data.length; i++) {
+ if (data[i] !== expectedData[i]) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js
new file mode 100644
index 0000000000..8a6cacedb4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-destroy-persistent-license.js
@@ -0,0 +1,95 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix( qualifier, config.keysystem )
+ + ', persistent-license, '
+ + /video\/([^;]*)/.exec( config.videoType )[ 1 ]
+ + ', playback, destroy and acknowledge';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] };
+
+ async_test( function(test) {
+
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _sessionId,
+ _startedReleaseSequence = false;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData ).then( test.step_func(function() {
+ assert_not_equals( _mediaKeySession.sessionId, undefined, "SessionId should be defined" );
+ _sessionId = _mediaKeySession.sessionId;
+ })).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > ( config.duration || 1 ) && !_startedReleaseSequence) {
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ _video.pause();
+ _video.removeAttribute('src');
+ _video.load();
+
+ _startedReleaseSequence = true;
+ _mediaKeySession.closed.then(onClosed);
+ _mediaKeySession.remove().catch(onFailure);
+ }
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ function onClosed() {
+ // Try and reload and check this fails
+ var mediaKeySession = _mediaKeys.createSession( 'persistent-license' );
+ mediaKeySession.load(_sessionId).then( test.step_func(function(success) {
+ assert_false( success, "Load of removed session shouold fail" );
+ test.done();
+ })).catch(onFailure);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ _mediaKeySession = _mediaKeys.createSession('persistent-license');
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js
new file mode 100644
index 0000000000..2d99f679f4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license-events.js
@@ -0,0 +1,158 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-license, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, check events';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] };
+
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _receivedTimeupdateEvent = false,
+ _startedReleaseSequence = false,
+ _events = [ ];
+
+ function recordEventFunc(eventType) {
+ return function() { _events.push(eventType); };
+ }
+
+ function recordEventFuncAndCheckExpirationForNaN(eventType) {
+ return function() {
+ _events.push(eventType);
+ assert_equals(_mediaKeySession.expiration, NaN);
+ };
+ }
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals( event.target, _mediaKeySession );
+ assert_true( event instanceof window.MediaKeyMessageEvent );
+ assert_equals( event.type, 'message');
+
+ if (!_startedReleaseSequence) {
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+ } else {
+ assert_equals(event.messageType, 'license-release');
+ }
+
+ if (event.messageType !== 'individualization-request') {
+ _events.push(event.messageType);
+ }
+
+ config.messagehandler(event.messageType, event.message ).then(function(response) {
+ _events.push(event.messageType + '-response');
+ return _mediaKeySession.update(response);
+ }).then(test.step_func(function() {
+ _events.push(event.messageType + '-response-resolved');
+ if (event.messageType === 'license-release') {
+ test.step_timeout(function() {
+ checkEventSequence(_events, [
+ 'generaterequest',
+ [ // potentially repeating
+ 'license-request',
+ 'license-request-response',
+ 'license-request-response-resolved'
+ ],
+ 'keystatuseschange-usablekey',
+ 'playing',
+ 'remove-resolved',
+ 'keystatuseschange-allkeysreleased',
+ 'license-release',
+ 'license-release-response',
+ 'closed-attribute-resolved',
+ 'license-release-response-resolved',
+ 'keystatuseschange-empty'
+ ]);
+ test.done();
+ }, 100);
+ }
+ })).catch(onFailure);
+ }
+
+ function onKeyStatusesChange(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.Event);
+ assert_equals(event.type, 'keystatuseschange');
+ var hasKeys = false,
+ usableKey = false; // true if any key usable.
+ _mediaKeySession.keyStatuses.forEach(function(value, keyid) {
+ assert_in_array(value, ['usable', 'released']);
+ hasKeys = true;
+ usableKey = usableKey || (value === 'usable');
+ });
+
+ if (!hasKeys) {
+ _events.push('keystatuseschange-empty');
+ } else if (usableKey) {
+ _events.push('keystatuseschange-usablekey');
+ } else {
+ _events.push('keystatuseschange-allkeysreleased');
+ }
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData ).then(recordEventFunc('generaterequest')
+ ).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if ( _video.currentTime > ( config.duration || 1 ) && !_receivedTimeupdateEvent ) {
+ _receivedTimeupdateEvent = true;
+ _video.pause();
+ _video.removeAttribute('src');
+ _video.load();
+
+ _startedReleaseSequence = true;
+ _mediaKeySession.remove()
+ .then(recordEventFuncAndCheckExpirationForNaN('remove-resolved'))
+ .catch(onFailure);
+ }
+ }
+
+ function onPlaying(event) {
+ _events.push( 'playing' );
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-license' );
+ waitForEventAndRunStep('keystatuseschange', _mediaKeySession, onKeyStatusesChange, test);
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.closed
+ .then(recordEventFuncAndCheckExpirationForNaN('closed-attribute-resolved'))
+ .catch(onFailure);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js
new file mode 100644
index 0000000000..c7e56e3aea
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-license.js
@@ -0,0 +1,77 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-license, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + 'playback';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] };
+
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals( event.target, _mediaKeySession );
+ assert_true( event instanceof window.MediaKeyMessageEvent );
+ assert_equals( event.type, 'message');
+
+ assert_in_array( event.messageType, [ 'license-request', 'individualization-request' ] );
+
+ config.messagehandler(event.messageType, event.message).then( function( response ) {
+ return _mediaKeySession.update(response)
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData ).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1)) {
+ _video.pause();
+ test.done();
+ }
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-license' );
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js
new file mode 100644
index 0000000000..e8e1e54790
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record-events.js
@@ -0,0 +1,109 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-usage-record, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, check events';
+
+ var configuration = { initDataTypes: [config.initDataType ],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['persistent-usage-record']};
+
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _sessionId,
+ _timeupdateEvent = false,
+ _events = [ ];
+
+ function recordEventFunc(eventType) {
+ return function() { _events.push(eventType); };
+ }
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ if (event.messageType !== 'individualization-request') {
+ _events.push(event.messageType);
+ }
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ _events.push(event.messageType + '-response');
+ return _mediaKeySession.update(response);
+ }).then(test.step_func(function() {
+ _events.push('update-resolved');
+ if (event.messageType === 'license-release') {
+ checkEventSequence( _events,
+ ['encrypted','generaterequest-done',
+ ['license-request', 'license-request-response', 'update-resolved'], // potentially repeating
+ 'keystatuseschange',
+ 'playing',
+ 'remove-resolved',
+ 'keystatuseschange',
+ 'license-release',
+ 'license-release-response',
+ 'closed-attribute-resolved',
+ 'update-resolved' ]);
+ test.done();
+ }
+
+ if ( event.messageType === 'license-request' ) {
+ _video.setMediaKeys(_mediaKeys);
+ }
+ })).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ _events.push(event.type);
+ _mediaKeySession.generateRequest( config.initDataType || event.initDataType,
+ config.initData || event.initData ).then( function() {
+ _events.push( 'generaterequest-done' );
+ _sessionId = _mediaKeySession.sessionId;
+ }).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1) && !_timeupdateEvent) {
+ _timeupdateEvent = true;
+ _video.pause();
+ _mediaKeySession.remove().then(recordEventFunc('remove-resolved')).catch(onFailure);
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, recordEventFunc('playing'), test);
+
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' );
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ waitForEventAndRunStep('keystatuseschange', _mediaKeySession, recordEventFunc('keystatuseschange'), test);
+ _mediaKeySession.closed.then(recordEventFunc('closed-attribute-resolved'));
+ return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true;
+ }).then(function( success ) {
+ return testmediasource(config);
+ }).then(function(source) {
+ _video.src = URL.createObjectURL(source);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js
new file mode 100644
index 0000000000..1772b4bd5f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-persistent-usage-record.js
@@ -0,0 +1,104 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-usage-record, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + 'playback';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-usage-record' ] };
+
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _releaseSequence = false;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ // event instance verification failing on CastTV
+ // assert_true( event instanceof window.MediaKeyMessageEvent );
+ assert_equals(event.type, 'message');
+
+ if (!_releaseSequence)
+ {
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+ }
+ else
+ {
+ assert_equals(event.messageType, 'license-release');
+ }
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).then(function() {
+ if(event.messageType === 'license-request') {
+ return _video.setMediaKeys(_mediaKeys);
+ } else if(event.messageType === 'license-release') {
+ test.done();
+ }
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData )
+ .catch(onFailure);
+ }
+
+ function onClosed(event) {
+ _video.src = "";
+ _video.setMediaKeys( null );
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > ( config.duration || 1) && !_releaseSequence) {
+ _video.removeEventListener('timeupdate', onTimeupdate );
+ _video.pause();
+ _releaseSequence = true;
+
+ _mediaKeySession.closed.then(test.step_func(onClosed));
+ _mediaKeySession.remove().catch(onFailure);
+
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ }
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [ configuration ]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ _mediaKeySession = _mediaKeys.createSession('persistent-usage-record');
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true;
+ }).then(function(success) {
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js
new file mode 100644
index 0000000000..83cba34028
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-license.js
@@ -0,0 +1,115 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-license, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', ' + config.testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-license' ] };
+
+
+ async_test( function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _sessionId;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData ).then( function() {
+ _sessionId = _mediaKeySession.sessionId;
+ }).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1)) {
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ _video.pause();
+ _video.removeAttribute('src');
+ _video.load();
+
+ _mediaKeySession.closed
+ .then(test.step_func(onClosed))
+ .catch(onFailure);
+ _mediaKeySession.close()
+ .catch(onFailure);
+ }
+ }
+
+ function onClosed() {
+ // Open a new window in which we will attempt to play with the persisted license
+ var win = window.open(config.windowscript);
+ assert_not_equals(win, null, "Popup windows not allowed?");
+
+ // Lisen for an event from the new window containing its test assertions
+ window.addEventListener('message', test.step_func(function(messageEvent) {
+ if (messageEvent.data.testResult) {
+ messageEvent.data.testResult.forEach(test.step_func(function(assertion) {
+ assert_equals(assertion.actual, assertion.expected, assertion.message);
+ }));
+
+ win.close();
+ test.done();
+ }
+ }));
+
+ // Delete things which can't be cloned and posted over to the new window
+ delete config.video;
+ delete config.messagehandler;
+
+ // Post the config and session id to the new window when it is ready
+ win.onload = function() {
+ win.postMessage({config: config, sessionId: _sessionId}, '*');
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys( mediaKeys );
+ }).then(function() {
+ _mediaKeySession = _mediaKeys.createSession('persistent-license');
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js
new file mode 100644
index 0000000000..a04f97d2ca
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js
@@ -0,0 +1,114 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', persistent-usage-record, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, retrieve in new window';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'persistent-usage-record' ] };
+
+
+ async_test( function( test ) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _sessionId,
+ _isClosing = false;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initDataType || event.initDataType,
+ config.initData || event.initData ).then( function() {
+ _sessionId = _mediaKeySession.sessionId;
+ }).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array( event.messageType,['license-request', 'individualization-request']);
+
+ config.messagehandler( event.messageType, event.message ).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).then(function() {
+ return _video.setMediaKeys(_mediaKeys);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ function onTimeupdate(event) {
+ if (!_isClosing && _video.currentTime > (config.duration || 1)) {
+ _isClosing = true;
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ _video.pause();
+ _mediaKeySession.closed.then( test.step_func(onClosed));
+ _mediaKeySession.close();
+ }
+ }
+
+ function onClosed(event) {
+ _video.src = "";
+ _video.setMediaKeys( null );
+
+ var win = window.open(config.windowscript);
+ assert_not_equals(win, null, "Popup windows not allowed?");
+
+ window.addEventListener('message', test.step_func(function(event) {
+ if (event.data.testResult) {
+ event.data.testResult.forEach(test.step_func(function(assertion) {
+ assert_equals(assertion.actual, assertion.expected, assertion.message);
+ }));
+
+ win.close();
+ test.done();
+ }
+ }));
+
+ delete config.video;
+ delete config.messagehandler;
+
+ win.onload = function() {
+ win.postMessage({ config: config, sessionId: _sessionId }, '*');
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(mediaKeys);
+ }).then(function(){
+ _mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' );
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return config.servercertificate ? _mediaKeys.setServerCertificate(config.servercertificate) : true;
+ }).then(function(success) {
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-segmented-sources.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-segmented-sources.js
new file mode 100644
index 0000000000..8f5af2cd6b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-segmented-sources.js
@@ -0,0 +1,109 @@
+function runTest(configEncrypted,configClear,qualifier) {
+
+ var testname = testnamePrefix(qualifier, configEncrypted.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(configEncrypted.videoType)[1]
+ + ', playback, encrypted and clear sources in separate segments';
+
+ var configuration = { initDataTypes: [ configEncrypted.initDataType ],
+ audioCapabilities: [ { contentType: configEncrypted.audioType } ],
+ videoCapabilities: [ { contentType: configEncrypted.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var didAppendEncrypted = false,
+ _video = configEncrypted.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _sourceBuffer;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onVideoError(event) {
+ var message = (_video.error || {}).message || 'Got unknown error from <video>';
+ forceTestFailureFromPromise(test, new Error(message));
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ configEncrypted.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ var initDataType = configEncrypted.initDataType || event.initDataType;
+ var initData = configEncrypted.initData || event.initData;
+
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest(initDataType, initData).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (configEncrypted.duration || 1) + (configClear.duration || 1)) {
+ _video.pause();
+ test.done();
+ }
+ if (_video.currentTime > 1 && !didAppendEncrypted) {
+ didAppendEncrypted = true;
+ _sourceBuffer.timestampOffset = configClear.duration;
+ fetchAndAppend(configEncrypted.videoPath).then(function() {
+ _mediaSource.endOfStream();
+ }).catch(onFailure);
+ }
+ }
+
+ function fetchAndAppend(path) {
+ return fetch(path).then(function(response) {
+ if (!response.ok) throw new Error('Resource fetch failed');
+ return response.arrayBuffer();
+ }).then(function(data) {
+ return new Promise(function(resolve, reject) {
+ _sourceBuffer.appendBuffer(data);
+ _sourceBuffer.addEventListener('updateend', resolve);
+ _sourceBuffer.addEventListener('error', reject);
+ });
+ });
+ }
+
+ _video.addEventListener('error', onVideoError);
+ navigator.requestMediaKeySystemAccess(configEncrypted.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+
+ return new Promise(function(resolve, reject) {
+ _mediaSource = new MediaSource();
+ _mediaSource.addEventListener('sourceopen', resolve);
+ _video.src = URL.createObjectURL(_mediaSource);
+ });
+ }).then(function() {
+ _sourceBuffer = _mediaSource.addSourceBuffer(configEncrypted.videoType);
+ return fetchAndAppend(configClear.videoPath);
+ }).then(function() {
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js
new file mode 100644
index 0000000000..41ea183f2e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js
@@ -0,0 +1,109 @@
+function runTest(configEncrypted,configClear,qualifier) {
+
+ var testname = testnamePrefix(qualifier, configEncrypted.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(configEncrypted.videoType)[1]
+ + ', playback, encrypted and clear sources';
+
+ var configuration = { initDataTypes: [ configEncrypted.initDataType ],
+ audioCapabilities: [ { contentType: configEncrypted.audioType } ],
+ videoCapabilities: [ { contentType: configEncrypted.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var playbackCount = 0,
+ _video = configEncrypted.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ configEncrypted.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update( response );
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest(configEncrypted.initData ? configEncrypted.initDataType : event.initDataType,
+ configEncrypted.initData || event.initData).then(function(){
+ return _video.setMediaKeys(_mediaKeys);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event)
+ {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeUpdate, true);
+ }
+
+ function onTimeUpdate(event) {
+ if (_video.currentTime < (configEncrypted.duration || 0.5)) {
+ return;
+ }
+
+ _video.removeEventListener('timeupdate', onTimeUpdate, true);
+
+ resetSrc().then(function(){
+ if (playbackCount >= 2) {
+ test.done();
+ } else {
+ playbackCount++;
+ startPlayback();
+ }
+ }).catch(onFailure);
+ }
+
+ function resetSrc() {
+ _video.pause();
+ _video.removeAttribute('src');
+ _video.load();
+ return _video.setMediaKeys(null);
+ }
+
+ function startPlayback() {
+ // Alternate between encrypted and unencrypted files.
+ if (playbackCount % 2) {
+ // Unencrypted files don't require MediaKeys
+ testmediasource( configClear ).then(function( source ) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ _video.play();
+ }).catch(onFailure);
+ } else {
+ navigator.requestMediaKeySystemAccess(configEncrypted.keysystem, [ configuration ]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ _mediaKeySession = _mediaKeys.createSession( 'temporary' );
+ }).then(function() {
+ return testmediasource(configEncrypted);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }
+ }
+
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ startPlayback();
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js
new file mode 100644
index 0000000000..28f45222cf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-events.js
@@ -0,0 +1,131 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, check events';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource,
+ _timeupdateEvent = false,
+ _events = [ ];
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array( event.messageType, ['license-request', 'individualization-request']);
+
+ if (event.messageType !== 'individualization-request') {
+ _events.push(event.messageType);
+ }
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ _events.push('license-request-response');
+ waitForEventAndRunStep('keystatuseschange', _mediaKeySession, onKeyStatusesChange, test);
+ return _mediaKeySession.update( response );
+ }).then(function() {
+ _events.push('update-resolved');
+ }).catch(onFailure);
+ }
+
+ function onKeyStatusesChange(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.Event);
+ assert_equals(event.type, 'keystatuseschange');
+ var hasKeys = false, pendingKeys = false;
+ _mediaKeySession.keyStatuses.forEach(function(value, keyid) {
+ assert_in_array(value, ['status-pending', 'usable']);
+ hasKeys = true;
+ pendingKeys = pendingKeys || (value === 'status-pending');
+ });
+
+ if (!hasKeys) {
+ _events.push('emptykeyslist');
+ } else if (!pendingKeys ) {
+ _events.push('allkeysusable');
+ _video.setMediaKeys(_mediaKeys).catch(onFailure);
+ } else {
+ assert_unreached('unexpected ' + event.type + ' event');
+ }
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData ).then(function() {
+ _events.push('generaterequest');
+ }).catch(onFailure);
+ }
+
+ function onClosed(event) {
+ _events.push('closed-attribute-resolved');
+ setTimeout(test.step_func(function() {
+ checkEventSequence( _events,
+ ['generaterequest',
+ ['license-request', 'license-request-response', 'update-resolved'], // potentially repeating
+ 'allkeysusable',
+ 'playing',
+ 'closed-attribute-resolved',
+ 'close-promise-resolved',
+ 'emptykeyslist']);
+ test.done();
+ } ), 0);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1) && !_timeupdateEvent) {
+ _timeupdateEvent = true;
+ _video.pause();
+
+ _mediaKeySession.closed.then(test.step_func(onClosed));
+ _mediaKeySession.close().then(function() {
+ _events.push('close-promise-resolved');
+ }).catch(onFailure);
+ }
+ }
+
+ function onPlaying(event) {
+ _events.push('playing');
+
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ }).then(function() {
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js
new file mode 100644
index 0000000000..3d1bd9591d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-expired.js
@@ -0,0 +1,95 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', expired license';
+
+ var configuration = { initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['temporary'] };
+
+ async_test(function(test) {
+
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ // Only create the session for the first encrypted event
+ if (_mediaKeySession !== undefined) return;
+
+ var initDataType = config.initData ? config.initDataType : event.initDataType;
+ var initData = config.initData || event.initData;
+
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest(initDataType, initData).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ // Generate a license that expires 1 second from now.
+ var expiration = Date.now().valueOf() + 1000;
+ config.messagehandler(event.messageType, event.message, { expiration: expiration }).then(function(response) {
+ // Wait 2 seconds before calling update() to ensure that the
+ // license has really expired. This is to avoid problems
+ // where the browser starts buffering frames as soon as a
+ // valid license is received.
+ test.step_timeout(function() {
+ event.target.update(response).then(function() {
+ // License server may only have second granularity, so check
+ // that session expiration time is close to the desired value.
+ assert_approx_equals(event.target.expiration, expiration, 3000,
+ "expiration attribute should equal provided expiration time");
+ assert_greater_than(Date.now().valueOf(), expiration, "Starting play before license expired");
+ _video.play();
+ // Wait 2 seconds to ensure that the video does not play.
+ test.step_timeout(function() { test.done(); }, 2000);
+ }).catch(onFailure);
+ }, 2000);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', test.step_func(onTimeupdate), true);
+ }
+
+ function onTimeupdate(event) {
+ _video.pause();
+ assert_unreached("Playback should not start with expired license");
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js
new file mode 100644
index 0000000000..597e8f9b0c
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multikey-sequential.js
@@ -0,0 +1,122 @@
+function runTest(config,qualifier) {
+
+ // config.initData contains a list of keys. We expect those to be needed in order and get
+ // one waitingforkey event for each one.
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', successful playback, temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', multiple keys, sequential'
+ + (config.checkReadyState ? ', readyState' : '');
+
+ var configuration = { initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['temporary'] };
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySessions = [],
+ _mediaSource,
+ _waitingForKey = false,
+ _playingCount = 0,
+ _canplayCount = 0,
+ _timeupdateWhileWaitingCount = 0;
+
+ function startNewSession() {
+ assert_less_than(_mediaKeySessions.length, config.initData.length);
+ var mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', mediaKeySession, onMessage, test);
+ _mediaKeySessions.push(mediaKeySession);
+ mediaKeySession.variantId = config.variantIds ? config.variantIds[_mediaKeySessions.length - 1] : undefined;
+ mediaKeySession.generateRequest(config.initDataType, config.initData[_mediaKeySessions.length - 1]).catch(onFailure);
+ }
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ var firstMessage = !_video.src;
+ config.messagehandler(event.messageType, event.message, {variantId: event.target.variantId}).then(function(response) {
+ return event.target.update(response);
+ }).then(function(){
+ if (firstMessage) {
+ _video.src = URL.createObjectURL(_mediaSource);
+ return _mediaSource.done;
+ } else if (event.target.keyStatuses.size > 0){
+ _waitingForKey = false;
+ return Promise.resolve();
+ }
+ }).then(function(){
+ if (firstMessage) {
+ _video.play();
+ }
+ }).catch(onFailure);
+ }
+
+ function onWaitingForKey(event) {
+ _waitingForKey = true;
+ if (config.checkReadyState) {
+ // This test does not start playing until the first license has been provided,
+ // so this event should occur when transitioning between keys.
+ // Thus, the frame at the current playback position is available and readyState
+ // should be HAVE_CURRENT_DATA.
+ assert_equals(_video.readyState, _video.HAVE_CURRENT_DATA, "Video readyState should be HAVE_CURRENT_DATA on watingforkey event");
+ }
+ startNewSession();
+ }
+
+ function onPlaying(event) {
+ _playingCount++;
+ assert_equals(_mediaKeySessions.length, _playingCount, "Should get one 'playing' event per key / session added");
+ assert_less_than_equal(_playingCount, 2, "Should not get more than two 'playing' events.");
+ }
+
+ function onCanPlay(event) {
+ _canplayCount++;
+ assert_equals(_mediaKeySessions.length, _canplayCount, "Should get one 'canplay' event per key / session added");
+ assert_less_than_equal(_canplayCount, 2, "Should not get more than two 'canplay' events.");
+ }
+
+ function onTimeupdate(event) {
+ // We should not receive 'timeupdate' events due to playing while waiting for a key, except
+ // when we first start waiting for key we should change the readyState to HAVE_CURRENT_DATA
+ // which will trigger the "If the previous ready state was HAVE_FUTURE_DATA or more, and
+ // the new ready state is HAVE_CURRENT_DATA or less" case of the readyState change
+ // algorithm which requires a "timeupdate" event be fired.
+ if (_waitingForKey) {
+ assert_equals(++_timeupdateWhileWaitingCount, 1, "Should only receive one timeupdate while waiting for key");
+ assert_equals(_video.readyState, _video.HAVE_CURRENT_DATA, "Video readyState should be HAVE_CURRENT_DATA while wating for key");
+ }
+
+ if (_video.currentTime > config.duration) {
+ assert_equals(_mediaKeySessions.length, config.initData.length, "It should require all keys to reach end of content");
+ assert_equals(_timeupdateWhileWaitingCount, 1, "Should have only received exactly one timeupdate while waiting for key");
+ _video.pause();
+ test.done();
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', test.step_func(onTimeupdate), true);
+
+ waitForEventAndRunStep('waitingforkey', _video, onWaitingForKey, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ waitForEventAndRunStep('canplay', _video, onCanPlay, test);
+
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ startNewSession();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js
new file mode 100644
index 0000000000..d23bd1097e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-multisession.js
@@ -0,0 +1,76 @@
+function runTest(config,qualifier) {
+
+ // This test assumes one session is required for each provided initData
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback with multiple sessions, '
+ + config.testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySessions = [],
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_any(assert_equals, event.target, _mediaKeySessions);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message, {variantId: event.target._variantId}).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1)) {
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ _video.pause();
+ test.done();
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+
+ config.initData.forEach(function(initData,i) {
+ var mediaKeySession = _mediaKeys.createSession( 'temporary' );
+ mediaKeySession._variantId = config.variantIds ? config.variantIds[i] : undefined;
+ waitForEventAndRunStep('message', mediaKeySession, onMessage, test);
+ _mediaKeySessions.push(mediaKeySession);
+ mediaKeySession.generateRequest(config.initDataType, initData).catch(onFailure);
+ } );
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration-keystatus.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration-keystatus.js
new file mode 100644
index 0000000000..e21b8f8f2a
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration-keystatus.js
@@ -0,0 +1,78 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback with limited playduration, check keystatus, ' + config.testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ // Only create the session for the first encrypted event
+ if (_mediaKeySession !== undefined) return;
+
+ var initDataType = config.initData ? config.initDataType : event.initDataType;
+ var initData = config.initData || event.initData;
+
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( initDataType, initData ).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message, {playDuration: config.playduration}).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ waitForEventAndRunStep('keystatuseschange', _mediaKeySession, onKeystatuseschange, test);
+ }
+
+ function onKeystatuseschange(event) {
+ for (var status of event.target.keyStatuses.values()) {
+ assert_equals(status, "expired", "All keys should have keyStatus expired");
+ }
+ test.done();
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration.js
new file mode 100644
index 0000000000..6ce6157529
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-playduration.js
@@ -0,0 +1,80 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback with limited playduration, ' + config.testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ // Only create the session for the first encrypted event
+ if (_mediaKeySession !== undefined) return;
+
+ var initDataType = config.initData ? config.initDataType : event.initDataType;
+ var initData = config.initData || event.initData;
+
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( initDataType, initData ).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message, {playDuration: config.playduration}).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', test.step_func(onTimeupdate), true);
+ test.step_timeout(function(){
+ test.done();
+ },config.playduration * 2);
+ }
+
+ function onTimeupdate(event) {
+ assert_less_than(_video.currentTime * 1000, config.playduration, "Video should not play for more than playDuration from licence");
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js
new file mode 100644
index 0000000000..fddcf56774
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-setMediaKeys.js
@@ -0,0 +1,105 @@
+SETMEDIAKEYS_IMMEDIATELY = 0;
+SETMEDIAKEYS_AFTER_SRC = 1;
+SETMEDIAKEYS_ONENCRYPTED = 2;
+SETMEDIAKEYS_AFTER_UPDATE = 3;
+
+function runTest(config,qualifier) {
+
+ var testcase = (config.testcase === SETMEDIAKEYS_IMMEDIATELY) ? 'setMediaKeys first'
+ : (config.testcase === SETMEDIAKEYS_AFTER_SRC) ? 'setMediaKeys after setting video.src'
+ : (config.testcase === SETMEDIAKEYS_ONENCRYPTED) ? 'setMediaKeys in encrypted event'
+ : (config.testcase === SETMEDIAKEYS_AFTER_UPDATE) ? 'setMediaKeys after updating session'
+ : 'unknown';
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, ' + testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array( event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update( response );
+ }).then(function() {
+ if (config.testcase === SETMEDIAKEYS_AFTER_UPDATE) {
+ return _video.setMediaKeys(_mediaKeys);
+ }
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ var promise = ( config.testcase === SETMEDIAKEYS_ONENCRYPTED )
+ ? _video.setMediaKeys(_mediaKeys)
+ : Promise.resolve();
+
+ promise.then( function() {
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ return _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData );
+ }).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1)) {
+ _video.pause();
+ test.done();
+ }
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(test.step_func(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ if ( config.testcase === SETMEDIAKEYS_IMMEDIATELY ) {
+ return _video.setMediaKeys( _mediaKeys );
+ }
+ })).then(function(){
+ _mediaKeySession = _mediaKeys.createSession( 'temporary' );
+
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+
+ if (config.testcase === SETMEDIAKEYS_AFTER_SRC) {
+ return _video.setMediaKeys(_mediaKeys);
+ }
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js
new file mode 100644
index 0000000000..b17168d113
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-two-videos.js
@@ -0,0 +1,83 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback two videos';
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ promise_test(function(test)
+ {
+ var promises = config.video.map(function(video) { return play_video_as_promise(test,video); });
+ return Promise.all(promises);
+
+ }, testname);
+
+ function play_video_as_promise(test, _video) {
+ var _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array( event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return _mediaKeySession.update(response);
+ }).catch(onFailure);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+
+ _mediaKeySession.generateRequest(config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData).catch(onFailure);
+ }
+
+ function wait_for_timeupdate_message(video)
+ {
+ return new Promise(function(resolve) {
+ video.addEventListener('timeupdate', function listener(event) {
+ if (event.target.currentTime > (config.duration || 1))
+ {
+ video.removeEventListener('timeupdate', listener);
+ resolve(event);
+ }
+ });
+ });
+ };
+
+ return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ return wait_for_timeupdate_message(_video);
+ }).catch(onFailure);
+ }
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js
new file mode 100644
index 0000000000..daa9f3b169
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary-waitingforkey.js
@@ -0,0 +1,71 @@
+function runTest(config,qualifier) {
+
+ // config.initData contains a list of keys. We expect those to be needed in order and get
+ // one waitingforkey event for each one.
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', successful playback, temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', waitingforkey event, '
+ + config.initData.length + ' key' + (config.initData.length > 1 ? 's' : '');
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySessions = [],
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ config.messagehandler( event.messageType, event.message ).then( function( response ) {
+ return event.target.update( response );
+ }).catch(onFailure);
+ }
+
+ function onWaitingForKey(event) {
+ // Expect one waitingforkey event for each initData we were given
+ assert_less_than(_mediaKeySessions.length, config.initData.length);
+ var mediaKeySession = _mediaKeys.createSession( 'temporary' );
+ waitForEventAndRunStep('message', mediaKeySession, onMessage, test);
+ _mediaKeySessions.push(mediaKeySession);
+ mediaKeySession.generateRequest(config.initDataType, config.initData[_mediaKeySessions.length - 1]).catch(onFailure);
+ }
+
+ function onTimeupdate(event) {
+ if (_video.currentTime > (config.duration || 1)) {
+ assert_equals(_mediaKeySessions.length, config.initData.length);
+ _video.removeEventListener('timeupdate', onTimeupdate);
+ _video.pause();
+ test.done();
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('waitingforkey', _video, onWaitingForKey, test);
+
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js
new file mode 100644
index 0000000000..2f79824ec7
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/playback-temporary.js
@@ -0,0 +1,82 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', temporary, '
+ + /video\/([^;]*)/.exec(config.videoType)[1]
+ + ', playback, ' + config.testcase;
+
+ var configuration = { initDataTypes: [ config.initDataType ],
+ audioCapabilities: [ { contentType: config.audioType } ],
+ videoCapabilities: [ { contentType: config.videoType } ],
+ sessionTypes: [ 'temporary' ] };
+
+ async_test(function(test) {
+
+ var _video = config.video,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onEncrypted(event) {
+ assert_equals(event.target, _video);
+ assert_true(event instanceof window.MediaEncryptedEvent);
+ assert_equals(event.type, 'encrypted');
+
+ // Only create the session for the firs encrypted event
+ if (_mediaKeySession !== undefined) return;
+
+ var initDataType = config.initData ? config.initDataType : event.initDataType;
+ var initData = config.initData || event.initData;
+
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( initDataType, initData ).catch(onFailure);
+ }
+
+ function onMessage(event) {
+ assert_equals(event.target, _mediaKeySession);
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.type, 'message');
+
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ return event.target.update(response);
+ }).catch(onFailure);
+ }
+
+ function onPlaying(event) {
+ // Not using waitForEventAndRunStep() to avoid too many
+ // EVENT(onTimeUpdate) logs.
+ _video.addEventListener('timeupdate', onTimeupdate, true);
+ }
+
+ function onTimeupdate(event) {
+ if ( _video.currentTime > (config.duration || 1)) {
+ _video.pause();
+ test.done();
+ }
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ _mediaKeys = mediaKeys;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(){
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ waitForEventAndRunStep('playing', _video, onPlaying, test);
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ _video.src = URL.createObjectURL(_mediaSource);
+ return source.done;
+ }).then(function(){
+ _video.play();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js b/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js
new file mode 100644
index 0000000000..a60d4a1e76
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/requestmediakeysystemaccess.js
@@ -0,0 +1,341 @@
+function runTest(config, qualifier) {
+
+ var prefix = testnamePrefix(qualifier, config.keysystem) + ', requestMediaKeySystemAccess: ';
+
+ function expect_error(keySystem, configurations, expectedError, testname) {
+
+ var audioCapabilities = configurations.length ? configurations[0].audioCapabilities : undefined,
+ videoCapabilities = configurations.length ? configurations[0].videoCapabilities : undefined,
+ audiocontenttypes = audioCapabilities ? audioCapabilities.map( function(ac) { return "'" + ac.contentType + "'"; } ).join(',') : '',
+ videocontenttypes = videoCapabilities ? videoCapabilities.map( function(ac) { return "'" + ac.contentType + "'"; } ).join(',') : '',
+ modifiedtestname = testname.replace( '%audiocontenttype', audiocontenttypes ).replace( '%videocontenttype', videocontenttypes );
+
+ promise_test(function(test) {
+ var p = navigator.requestMediaKeySystemAccess(keySystem, configurations);
+ // expectedError is a string name for the error. We can differentiate
+ // JS Errors from DOMExceptions by checking whether
+ // window[expectedError] exists. If it does, expectedError is the name
+ // of a JS Error subclass and window[expectedError] is the constructor
+ // for that subclass. Otherwise it's a name for a DOMException.
+ if (window[expectedError]) {
+ return promise_rejects_js(test, window[expectedError], p);
+ } else {
+ return promise_rejects_dom(test, expectedError, p);
+ }
+ }, prefix + modifiedtestname + ' should result in ' + expectedError );
+ }
+
+ function assert_subset(actual, expected, path) {
+ if (typeof expected == 'string') {
+ assert_equals(actual, expected, path);
+ } else {
+ if (expected.hasOwnProperty('length')) {
+ assert_equals(actual.length, expected.length, path + '.length');
+ }
+ for (property in expected) {
+ assert_subset(actual[property], expected[property], path + '.' + property);
+ }
+ }
+ }
+
+ function expect_config(keySystem, configurations, expectedConfiguration, testname) {
+ promise_test(function(test) {
+ return navigator.requestMediaKeySystemAccess(keySystem, configurations).then(function(a) {
+ assert_subset(a.getConfiguration(), expectedConfiguration, testname + ': ');
+ });
+ }, testname);
+ }
+
+ // Tests for Key System.
+ expect_error('', [{}], 'TypeError', 'Empty Key System');
+ expect_error('com.example.unsupported', [{}], 'NotSupportedError', 'Unsupported Key System');
+ expect_error(config.keysystem + '.', [{}], 'NotSupportedError', 'Key System ending in "."');
+ expect_error(config.keysystem.toUpperCase(), [{}], 'NotSupportedError', 'Capitalized Key System');
+ expect_error(config.keysystem + '\u028F', [{}], 'NotSupportedError', 'Non-ASCII Key System');
+
+ // Parent of Clear Key not supported.
+ expect_error(config.keysystem.match(/^(.*?)\./)[1], [{}], 'NotSupportedError', 'Root domain of Key System alone');
+ expect_error(config.keysystem.match(/^(.*?)\./)[0], [{}], 'NotSupportedError', 'Root domain of Key System, with dot');
+ expect_error(config.keysystem.match(/^(.*?\..*?)\./)[1], [{}], 'NotSupportedError', 'Domain of Key System along');
+ expect_error(config.keysystem.match(/^(.*?\..*?)\./)[0], [{}], 'NotSupportedError', 'Domain of Key System, with dot');
+
+ // Child of Clear Key not supported.
+ expect_error(config.keysystem+'.foo', [{}], 'NotSupportedError', 'Child of Key System');
+
+ // Prefixed Clear Key not supported.
+ expect_error('webkit-'+config.keysystem, [{}], 'NotSupportedError', 'Prefixed Key System');
+
+ // Incomplete names.
+ expect_error(config.keysystem.substr(0,7)+config.keysystem.substr(8), [{}], 'NotSupportedError', 'Missing characters in middle of Key System name');
+ expect_error(config.keysystem.substr(0,config.keysystem.length-1), [{}], 'NotSupportedError', 'Missing characters at end of Key System name');
+
+ // Spaces in key system name not supported.
+ expect_error(' '+config.keysystem, [{}], 'NotSupportedError', 'Leading space in Key System name');
+ expect_error(config.keysystem.substr(0,6) + ' ' + config.keysystem.substr(6), [{}], 'NotSupportedError', 'Extra space in Key System name');
+ expect_error(config.keysystem + ' ', [{}], 'NotSupportedError', 'Trailing space in Key System name');
+
+ // Extra dots in key systems names not supported.
+ expect_error('.' + config.keysystem, [{}], 'NotSupportedError', 'Leading dot in Key System name');
+ expect_error(config.keysystem.substr(0,6) + '.' + config.keysystem.substr(6), [{}], 'NotSupportedError', 'Extra dot in middle of Key System name');
+ expect_error(config.keysystem + '.', [{}], 'NotSupportedError', 'Trailing dot in Key System name');
+
+ // Key system name is case sensitive.
+ if (config.keysystem !== config.keysystem.toUpperCase()) {
+ expect_error(config.keysystem.toUpperCase(), [{}], 'NotSupportedError', 'Key System name is case sensitive');
+ }
+
+ if (config.keysystem !== config.keysystem.toLowerCase()) {
+ expect_error(config.keysystem.toLowerCase(), [{}], 'NotSupportedError', 'Key System name is case sensitive');
+ }
+
+ // Tests for trivial configurations.
+ expect_error(config.keysystem, [], 'TypeError', 'Empty supportedConfigurations');
+ expect_error(config.keysystem, [{}], 'NotSupportedError', 'Empty configuration');
+
+ // Various combinations of supportedConfigurations.
+ expect_config(config.keysystem, [{
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ label: 'abcd',
+ }], {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ label: 'abcd',
+ }, 'Basic supported configuration');
+
+ expect_config(config.keysystem, [{
+ initDataTypes: ['fakeidt', config.initDataType],
+ audioCapabilities: [{contentType: 'audio/fake'}, {contentType: config.audioType}],
+ videoCapabilities: [{contentType: 'video/fake'}, {contentType: config.videoType}],
+ }], {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ }, 'Partially supported configuration');
+
+ expect_config(config.keysystem, [{
+ audioCapabilities: [{contentType: config.audioType}],
+ }], {
+ audioCapabilities: [{contentType: config.audioType}],
+ }, 'Supported audio codec');
+
+ expect_config(config.keysystem, [{
+ audioCapabilities: [{contentType: config.audioType.replace(/^(.*?);(.*)/, "$1; $2")}],
+ }], {
+ audioCapabilities: [{contentType: config.audioType.replace(/^(.*?);(.*)/, "$1; $2")}],
+ }, 'ContentType formatting must be preserved');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [{contentType: 'audio/webm; codecs=fake'}],
+ }], 'NotSupportedError', 'Unsupported audio codec (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [{contentType: 'video/webm; codecs=fake'}],
+ }], 'NotSupportedError', 'Unsupported video codec (%videocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/webm; codecs=mp4a'},
+ {contentType: 'audio/webm; codecs=mp4a.40.2'}
+ ],
+ }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [{contentType: config.videoType}],
+ }], 'NotSupportedError', 'Video codec specified in audio field (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: config.audioType}],
+ }], 'NotSupportedError', 'Audio codec specified in video field (%videocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/webm; codecs=avc1'},
+ {contentType: 'audio/webm; codecs=avc1.42e01e'}
+ ],
+ }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/mp4; codecs=vorbis'}
+ ],
+ }], 'NotSupportedError', 'Mismatched audio container/codec (%audiocontenttype)');
+
+ expect_config(config.keysystem, [{
+ initDataTypes: ['fakeidt'],
+ videoCapabilities: [{contentType: config.videoType}]
+ }, {
+ initDataTypes: [config.initDataType],
+ videoCapabilities: [{contentType: config.videoType}]
+ }
+ ], {
+ initDataTypes: [config.initDataType],
+ videoCapabilities: [{contentType: config.videoType}]
+ }, 'Two configurations, one supported');
+
+ expect_config(config.keysystem, [{
+ initDataTypes: [config.initDataType],
+ videoCapabilities: [{contentType: config.videoType}]
+ }, {
+ videoCapabilities: [{contentType: config.videoType}]
+ }
+ ], {
+ initDataTypes: [config.initDataType],
+ videoCapabilities: [{contentType: config.videoType}]
+ }, 'Two configurations, both supported');
+
+ // Audio MIME type does not support video codecs.
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/webm; codecs="vp8,vorbis"'},
+ {contentType: 'audio/webm; codecs="vorbis, vp8"'},
+ {contentType: 'audio/webm; codecs="vp8"'}
+ ],
+ }], 'NotSupportedError', 'Audio MIME type does not support video codecs (webm) (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/mp4; codecs="avc1"'},
+ {contentType: 'audio/mp4; codecs="avc1.4d401e"'},
+ ],
+ }], 'NotSupportedError', 'Audio MIME type does not support video codecs (mp4) (%audiocontenttype)');
+
+ // Video MIME type does not support audio codecs.
+ expect_error(config.keysystem, [{
+ videoCapabilities: [
+ {contentType: 'video/webm; codecs="vp8,vorbis"'},
+ {contentType: 'video/webm; codecs="vorbis, vp8"'},
+ {contentType: 'video/webm; codecs="vorbis"'}
+ ],
+ }], 'NotSupportedError', 'Video MIME type does not support audio codecs (webm) (%videocontenttype)');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [
+ {contentType: 'video/mp4; codecs="mp4a"'},
+ {contentType: 'video/mp4; codecs="mp4a.40.2"'}
+ ],
+ }], 'NotSupportedError', 'Video MIME type does not support audio codecs (mp4) (%videocontenttype)');
+
+ // WebM does not support AVC1/AAC.
+ expect_error(config.keysystem, [{
+ audioCapabilities: [
+ {contentType: 'audio/webm; codecs="aac"'},
+ {contentType: 'audio/webm; codecs="avc1"'},
+ {contentType: 'audio/webm; codecs="vp8,aac"'}
+ ],
+ }], 'NotSupportedError', 'WebM audio does not support AVC1/AAC (%audiocontenttype)');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [
+ {contentType: 'video/webm; codecs="aac"'},
+ {contentType: 'video/webm; codecs="avc1"'},
+ {contentType: 'video/webm; codecs="vp8,aac"'}
+ ],
+ }], 'NotSupportedError', 'WebM video does not support AVC1/AAC (%videocontenttype)');
+
+ // Extra space is allowed in contentType.
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: ' ' + config.videoType}],
+ }], {
+ videoCapabilities: [{contentType: ' ' + config.videoType}],
+ }, 'Leading space in contentType');
+
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?);(.*)/, "$1 ;$2")}],
+ }], {
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?);(.*)/, "$1 ;$2")}],
+ }, 'Space before ; in contentType');
+
+
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType + ' '}],
+ }], {
+ videoCapabilities: [{contentType: config.videoType + ' '}],
+ }, 'Trailing space in contentType');
+
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\")(.*)/, "$1 $2")}],
+ }], {
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\")(.*)/, "$1 $2")}],
+ }, 'Space at start of codecs parameter');
+
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\".*)\"/, "$1 \"")}],
+ }], {
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?codecs=\".*)\"/, "$1 \"")}],
+ }, 'Space at end of codecs parameter');
+
+ // contentType is not case sensitive (except the codec names).
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: 'V' + config.videoType.substr(1)}],
+ }], {
+ videoCapabilities: [{contentType: 'V' + config.videoType.substr(1)}],
+ }, 'Video/' );
+
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?)c(odecs.*)/, "$1C$2")}],
+ }], {
+ videoCapabilities: [{contentType: config.videoType.replace( /^(.*?)c(odecs.*)/, "$1C$2")}],
+ }, 'Codecs=');
+
+ var t = config.videoType.match(/(.*?)(;.*)/);
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: t[1].toUpperCase() + t[2]}],
+ }], {
+ videoCapabilities: [{contentType: t[1].toUpperCase() + t[2]}],
+ }, 'Upper case MIME type');
+
+ t = config.videoType.match(/(.*?)codecs(.*)/);
+ expect_config(config.keysystem, [{
+ videoCapabilities: [{contentType: t[1] + 'CODECS' + t[2]}],
+ }], {
+ videoCapabilities: [{contentType: t[1] + 'CODECS' + t[2]}],
+ }, 'CODECS=');
+
+ // Unrecognized attributes are not allowed.
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: 'video/webm; foo="bar"'}],
+ }], 'NotSupportedError', 'Unrecognized foo with webm (%videocontenttype)');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: 'video/mp4; foo="bar"'}],
+ }], 'NotSupportedError', 'Unrecognized foo with mp4 (%videocontenttype)');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: config.videoType + '; foo="bar"'}],
+ }], 'NotSupportedError', 'Unrecognized foo with codecs (%videocontenttype)');
+
+ // Invalid contentTypes.
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: 'fake'}],
+ }], 'NotSupportedError', 'contentType: %videocontenttype');
+
+ expect_error(config.keysystem, [{
+ audioCapabilities: [{contentType: 'audio/fake'}],
+ }], 'NotSupportedError', 'contentType: %audiocontenttype');
+
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: 'video/fake'}],
+ }], 'NotSupportedError', 'contentType: %videocontenttype');
+
+ // The actual codec names are case sensitive.
+ t = config.videoType.match( /(.*?codecs=\")(.*?\")(.*)/ );
+ if (t[2] !== t[2].toUpperCase()) {
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: t[1] + t[2].toUpperCase() + t[3] }],
+ }], 'NotSupportedError', 'contentType: %videocontenttype');
+ }
+
+ if (t[2] !== t[2].toLowerCase()) {
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: t[1] + t[2].toLowerCase() + t[3] }],
+ }], 'NotSupportedError', 'contentType: %videocontenttype');
+ }
+
+ // Extra comma is not allowed in codecs.
+ expect_error(config.keysystem, [{
+ videoCapabilities: [{contentType: t[1] + ',' + t[2] + t[3] }],
+ }], 'NotSupportedError', 'contentType: %videocontenttype');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js
new file mode 100644
index 0000000000..0ccce3275e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/reset-src-after-setmediakeys.js
@@ -0,0 +1,61 @@
+function runTest(config)
+{
+ async_test(function(test) {
+ var mediaKeys;
+ var mediaSource;
+ var encryptedEventIndex = 0;
+ var video = config.video;
+ var keysystem = config.keysystem;
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{
+ contentType: config.audioType
+ }],
+ videoCapabilities: [{
+ contentType: config.videoType
+ }],
+ sessionTypes: ['temporary']
+ };
+
+ assert_not_equals(video, null);
+
+ var onEncrypted = function(event) {
+ ++encryptedEventIndex;
+ assert_equals(video.mediaKeys, mediaKeys);
+
+ // This event is fired once for the audio stream and once
+ // for the video stream each time .src is set.
+ if (encryptedEventIndex === 2) {
+ // Finished first video; Create new media source and wait for two more encrypted events
+ return testmediasource(config).then(function (source) {
+ video.src = URL.createObjectURL(source);
+ }).catch(function (error) {
+ forceTestFailureFromPromise(test, error)
+ });
+ } else if (encryptedEventIndex === 4) {
+ // Finished second video.
+ test.done();
+ }
+ };
+
+ // Create a MediaKeys object and assign it to video.
+ navigator.requestMediaKeySystemAccess(keysystem, [configuration]).then(test.step_func(function (access) {
+ assert_equals(access.keySystem, keysystem);
+ return access.createMediaKeys();
+ })).then(test.step_func(function (result) {
+ mediaKeys = result;
+ assert_not_equals(mediaKeys, null);
+ return video.setMediaKeys(mediaKeys);
+ })).then(test.step_func(function () {
+ assert_equals(video.mediaKeys, mediaKeys);
+ return testmediasource(config);
+ })).then(function (source) {
+ waitForEventAndRunStep('encrypted', video, onEncrypted, test);
+ mediaSource = source;
+ video.src = URL.createObjectURL(mediaSource);
+ }).catch(function (error) {
+ forceTestFailureFromPromise(test, error);
+ });
+
+ }, 'Reset src after setMediaKeys().');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js
new file mode 100644
index 0000000000..772bfcaa87
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-playback.js
@@ -0,0 +1,79 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', setmediakeys again after playback';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test) {
+ var _video = config.video,
+ _access,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ config.messagehandler(event.messageType, event.message).then( function(response) {
+ _mediaKeySession.update(response).catch(onFailure).then(function() {
+ _video.play();
+ });
+ });
+ }
+
+ function onEncrypted(event) {
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData )
+ .catch(onFailure);
+ }
+
+ function playVideo()
+ {
+ return new Promise(function(resolve) {
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ _video.src = URL.createObjectURL(_mediaSource);
+ resolve('success');
+ });
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ _access = access;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true;
+ }).then(function( success ) {
+ return testmediasource(config);
+ }).then(function(source) {
+ _mediaSource = source;
+ return playVideo();
+ }).then(function(results) {
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ return waitForEvent('playing', _video);
+ }).then(test.step_func(function(result) {
+ assert_false(_video.ended);
+ return _video.setMediaKeys(_mediaKeys);
+ })).then(function() {
+ // Able to change MediaKeys while playing.
+ // This is not required to fail.
+ _video.src='';
+ test.done();
+ }, test.step_func(function(error) {
+ assert_in_array(error.name, ['InvalidStateError','NotSupportedError']);
+ _video.src='';
+ test.done();
+ })).catch(onFailure);
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js
new file mode 100644
index 0000000000..a870600982
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-again-after-resetting-src.js
@@ -0,0 +1,79 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', setmediakeys again after resetting src';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test) {
+ var _video = config.video,
+ _access,
+ _mediaKeys,
+ _mediaKeySession,
+ _mediaSource;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function onMessage(event) {
+ config.messagehandler(event.messageType, event.message).then(function(response) {
+ _mediaKeySession.update(response).catch(onFailure).then(function() {
+ _video.play();
+ });
+ });
+ }
+
+ function onEncrypted(event) {
+ waitForEventAndRunStep('message', _mediaKeySession, onMessage, test);
+ _mediaKeySession.generateRequest( config.initData ? config.initDataType : event.initDataType,
+ config.initData || event.initData )
+ .catch(onFailure);
+ }
+
+ function playVideoAndWaitForTimeupdate()
+ {
+ return new Promise(function(resolve) {
+ testmediasource(config).then(function(source) {
+ _mediaKeySession = _mediaKeys.createSession('temporary');
+ _video.src = URL.createObjectURL(source);
+ });
+ _video.addEventListener('timeupdate', function listener(event) {
+ if (event.target.currentTime < (config.duration || 1))
+ return;
+ _video.removeEventListener('timeupdate', listener);
+ resolve('success');
+ });
+ });
+ }
+
+ waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ _access = access;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true;
+ }).then(function( success ) {
+ return playVideoAndWaitForTimeupdate();
+ }).then(function(results) {
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ _video.src = '';
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ return config.servercertificate ? _mediaKeys.setServerCertificate( config.servercertificate ) : true;
+ }).then(function( success ) {
+ return playVideoAndWaitForTimeupdate();
+ }).then(function() {
+ _video.src = '';
+ test.done();
+ }).catch(onFailure);
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js
new file mode 100644
index 0000000000..6d67d95b1f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-at-same-time.js
@@ -0,0 +1,59 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', setmediakeys at same time';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ async_test(function(test) {
+ var _video = config.video,
+ _access,
+ _mediaKeys1,
+ _mediaKeys2,
+ _mediaKeys3,
+ _mediaKeys4,
+ _mediaKeys5;
+
+ // Test MediaKeys assignment.
+ assert_equals(_video.mediaKeys, null);
+ assert_equals(typeof _video.setMediaKeys, 'function');
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function setMediaKeys(mediaKeys) {
+ return _video.setMediaKeys(mediaKeys)
+ .then(function() {return 1}, function() {return 0})
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ _access = access;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys1 = result;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys2 = result;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys3 = result;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys4 = result;
+ return _access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys5 = result;
+ return Promise.all([
+ setMediaKeys(_mediaKeys1),
+ setMediaKeys(_mediaKeys2),
+ setMediaKeys(_mediaKeys3),
+ setMediaKeys(_mediaKeys4),
+ setMediaKeys(_mediaKeys5)
+ ]);
+ }).then(function(results) {
+ var sum = results.reduce((a, b) => a + b, 0);
+ assert_in_array(sum,[1,5]);
+ test.done();
+ }).catch(onFailure);
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js
new file mode 100644
index 0000000000..ef44477b16
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-different-mediakeys.js
@@ -0,0 +1,98 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix( qualifier, config.keysystem )
+ + ', setmediakeys multiple times with different mediakeys';
+
+ var configuration = getSimpleConfigurationForContent( config.content );
+
+ async_test (function (test) {
+ var _video = config.video,
+ _access,
+ _mediaKeys1,
+ _mediaKeys2,
+ _usingMediaKeys2 = false;;
+
+ // Test MediaKeys assignment.
+ assert_equals(_video.mediaKeys, null);
+ assert_equals(typeof _video.setMediaKeys, 'function');
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ _access = access;
+ return _access.createMediaKeys();
+ }).then(test.step_func(function(result) {
+ _mediaKeys1 = result;
+ assert_not_equals(_mediaKeys1, null);
+ // Create a second mediaKeys.
+ return _access.createMediaKeys();
+ })).then(test.step_func(function(result) {
+ _mediaKeys2 = result;
+ assert_not_equals(_mediaKeys2, null);
+ // Set _mediaKeys1 on video.
+ return _video.setMediaKeys(_mediaKeys1);
+ })).then(test.step_func(function() {
+ assert_equals(_video.mediaKeys, _mediaKeys1);
+ // Set _mediaKeys2 on video (switching MediaKeys).
+ return _video.setMediaKeys(_mediaKeys2);
+ })).then(test.step_func(function() {
+ assert_equals(_video.mediaKeys, _mediaKeys2);
+ // Clear mediaKeys from video.
+ return _video.setMediaKeys(null);
+ })).then(test.step_func(function() {
+ assert_equals(_video.mediaKeys, null);
+ // Set _mediaKeys1 on video again.
+ return _video.setMediaKeys(_mediaKeys1);
+ })).then(test.step_func(function() {
+ assert_equals(_video.mediaKeys, _mediaKeys1);
+ return testmediasource(config);
+ })).then(function(source) {
+ // Set src attribute on Video Element
+ _video.src = URL.createObjectURL(source);
+ // According to the specification, support for changing the Media Keys object after
+ // the src attribute on the video element has been set is optional. The following operation
+ // may therefore either succeed or fail. We handle both cases.
+ return _video.setMediaKeys(_mediaKeys2);
+ }).then(test.step_func(function() {
+ // Changing the Media Keys object succeeded
+ _usingMediaKeys2 = true;
+ assert_equals(_video.mediaKeys, _mediaKeys2);
+ // Return something so the promise resolves properly.
+ return Promise.resolve();
+ }), test.step_func(function(error) {
+ // Changing the Media Keys object failed
+ _usingMediaKeys2 = false;
+ assert_equals(_video.mediaKeys, _mediaKeys1);
+ // The specification allows either NotSupportedError or InvalidStateError depending on
+ // whether the failure was because changing Media Keys object is not supported
+ // or just not allowed at this time, respectively.
+ assert_in_array(error.name, ['InvalidStateError','NotSupportedError']);
+ assert_not_equals(error.message, '');
+ // Return something so the promise resolves properly.
+ return Promise.resolve();
+ })).then(function() {
+ // According to the specification, support for clearing the Media Keys object associated
+ // with the video element is optional. The following operation
+ // may therefore either succeed or fail. We handle both cases.
+ return _video.setMediaKeys(null);
+ }).then(test.step_func(function() {
+ // Clearing the media keys succeeded
+ assert_equals(_video.mediaKeys, null);
+ test.done();
+ }), test.step_func(function(error) {
+ // Clearing the media keys failed
+ if(!_usingMediaKeys2) {
+ assert_equals(_video.mediaKeys, _mediaKeys1);
+ } else {
+ assert_equals(_video.mediaKeys, _mediaKeys2);
+ }
+ // The specification allows either NotSupportedError or InvalidStateError depending on
+ // whether the failure was because changing Media Keys object is not supported
+ // or just not allowed at this time, respectively.
+ assert_in_array(error.name, ['InvalidStateError','NotSupportedError']);
+ assert_not_equals(error.message, '');
+ test.done();
+ })).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js
new file mode 100644
index 0000000000..f6af8267f2
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-multiple-times-with-the-same-mediakeys.js
@@ -0,0 +1,46 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix( qualifier, config.keysystem )
+ + ', setmediakeys multiple times with the same mediakeys';
+
+ var configuration = getSimpleConfigurationForContent( config.content );
+
+ if ( config.initDataType && config.initData ) {
+ configuration.initDataTypes = [ config.initDataType ];
+ }
+
+ async_test (function (test) {
+ var _video = config.video,
+ _mediaKeys;
+
+ // Test MediaKeys assignment.
+ assert_equals(_video.mediaKeys, null);
+ assert_equals(typeof _video.setMediaKeys, 'function');
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ return access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ // Set mediaKeys for first time on video should work.
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(result) {
+ assert_equals(_video.mediaKeys, _mediaKeys);
+ // Set mediaKeys on video again should return a resolved promise.
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function (result) {
+ assert_equals(_video.mediaKeys, _mediaKeys);
+ return testmediasource(config);
+ }).then(function(source) {
+ // Set src attribute on Video Element
+ _video.src = URL.createObjectURL(source);
+ // Set mediaKeys again on video should still return a resolved promise.
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function() {
+ assert_equals(_video.mediaKeys, _mediaKeys);
+ test.done();
+ }).catch(onFailure);
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js
new file mode 100644
index 0000000000..4c7faef69d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys-to-multiple-video-elements.js
@@ -0,0 +1,54 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix(qualifier, config.keysystem)
+ + ', setMediaKeys to multiple video elements';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if ( config.initDataType && config.initData ) {
+ configuration.initDataTypes = [ config.initDataType ];
+ }
+
+ async_test (function (test) {
+ var _video1 = config.video1,
+ _video2 = config.video2,
+ _mediaKeys;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ assert_equals(access.keySystem, config.keysystem)
+ return access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ assert_not_equals(_mediaKeys, null);
+ assert_equals(typeof _mediaKeys.createSession, 'function');
+ return _video1.setMediaKeys(_mediaKeys);
+ }).then(function(result) {
+ assert_not_equals(_video1.mediaKeys, null);
+ assert_equals(_video1.mediaKeys, _mediaKeys);
+ // The specification allows this to fail, but it is not required to fail.
+ return _video2.setMediaKeys(_mediaKeys);
+ }).then(function(result) {
+ // Second setMediaKeys is not required to fail.
+ assert_equals(_video2.mediaKeys, _mediaKeys);
+ return Promise.resolve();
+ }, function(error) {
+ assert_equals(error.name, 'QuotaExceededError');
+ assert_not_equals(error.message, '');
+ // Return something so the promise resolves properly.
+ return Promise.resolve();
+ }).then(function() {
+ // Now clear it from video1.
+ return _video1.setMediaKeys(null);
+ }).then(function() {
+ // Should be assignable to video2.
+ return _video2.setMediaKeys(_mediaKeys);
+ }).then(function(result) {
+ assert_not_equals(_video2.mediaKeys, null);
+ assert_equals(_video2.mediaKeys, _mediaKeys);
+ test.done();
+ }).catch(onFailure);
+ }, testname);
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js
new file mode 100644
index 0000000000..a85adeaeaf
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/setmediakeys.js
@@ -0,0 +1,50 @@
+function runTest(config, qualifier) {
+ var testname = testnamePrefix( qualifier, config.keysystem )
+ + ', setMediaKeys';
+
+ var configuration = getSimpleConfigurationForContent( config.content );
+
+ if ( config.initDataType && config.initData ) {
+ configuration.initDataTypes = [ config.initDataType ];
+ }
+
+ async_test (function (test) {
+ var _video = config.video,
+ _mediaKeys;
+
+ // Test MediaKeys assignment.
+ assert_equals(_video.mediaKeys, null);
+ assert_equals(typeof _video.setMediaKeys, 'function');
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ // Try setting mediaKeys to null.
+ _video.setMediaKeys(null).then(function(result) {
+ assert_equals(_video.mediaKeys, null);
+
+ // setMediaKeys should fail when setting to the wrong type of object - Date.
+ return _video.setMediaKeys(new Date());
+ }).then(function (result) {
+ assert_unreached('setMediaKeys should fail when setting to wrong kind of object (Date)');
+ }, function(error) {
+ // The error should be TypeError.
+ assert_throws_js(TypeError, () => { throw error; },
+ 'setMediaKeys should return a TypeError when setting to wrong kind of object (Date)');
+ return navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]);
+ }).then(function(access) {
+ assert_equals(access.keySystem, config.keysystem)
+ return access.createMediaKeys();
+ }).then(function(result) {
+ _mediaKeys = result;
+ assert_not_equals(_mediaKeys, null);
+ assert_equals(typeof _mediaKeys.createSession, 'function');
+ return _video.setMediaKeys(_mediaKeys);
+ }).then(function(result) {
+ assert_not_equals(_video.mediaKeys, null);
+ assert_equals(_video.mediaKeys, _mediaKeys);
+ test.done();
+ }).catch(onFailure);
+ }, testname);
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js
new file mode 100644
index 0000000000..4ec6551e8f
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeys.js
@@ -0,0 +1,184 @@
+function runTest(config) {
+ var keysystem = config.keysystem;
+ var testname = testnamePrefix(null, config.keysystem);
+ var initDataType = config.initDataType;
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['temporary']
+ };
+
+ function createMediaKeysAttributeTest() {
+ return new Promise(function (resolve, reject) {
+ var access;
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function');
+ assert_true(isTypeSupported, "initDataType should be supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (result) {
+ access = result;
+ assert_equals(access.keySystem, keysystem);
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ assert_not_equals(mediaKeys, null);
+ assert_equals(typeof mediaKeys, 'object');
+ assert_equals(typeof mediaKeys.createSession, 'function');
+ assert_equals(typeof mediaKeys.setServerCertificate, 'function');
+
+ // Test creation of a second MediaKeys.
+ // The extra parameter is ignored.
+ return access.createMediaKeys('extra');
+ }).then(function (mediaKeys) {
+ assert_not_equals(mediaKeys, null);
+ assert_equals(typeof mediaKeys, 'object');
+ assert_equals(typeof mediaKeys.createSession, 'function');
+ assert_equals(typeof mediaKeys.setServerCertificate, 'function');
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+
+ promise_test(function() {
+ return createMediaKeysAttributeTest();
+ }, testname + ' test MediaKeys attribute syntax');
+
+ var kSetServerCertificateExceptionsTestCases = [
+ // Too few parameters.
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate();
+ }
+ },
+ // Invalid parameters.
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate('');
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate(null);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate(undefined);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate(1);
+ }
+ },
+ // Empty array.
+ {
+ exception: 'TypeError',
+ func: function (mk) {
+ return mk.setServerCertificate(new Uint8Array(0));
+ }
+ }
+ ];
+
+
+ function setServerCertificateTestExceptions() {
+ return new Promise(function(resolve, reject) {
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function');
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var promises = kSetServerCertificateExceptionsTestCases.map(function (testCase) {
+ return test_exception(testCase, mediaKeys);
+ });
+ assert_not_equals(promises.length, 0);
+ return Promise.all(promises);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return setServerCertificateTestExceptions();
+ }, testname + ' test MediaKeys setServerCertificate() exceptions.');
+
+ // All calls to |func| in this group resolve. setServerCertificate with these cert may either resolve with true
+ // for clearkey or throw a DOMException.
+ var kSetServerCertificateTestCases = [
+ {
+ // Pass in ArrayBufferView
+ func: function (mk) {
+ var cert = new Uint8Array(200);
+ assert_true(ArrayBuffer.isView(cert));
+
+ return new Promise(function (resolve, reject) {
+ mk.setServerCertificate(cert).then(function (value) {
+ resolve(value);
+ }).catch(function (error) {
+ if (Object.prototype.toString.call(error) === "[object DOMException]") {
+ resolve(false);
+ }
+ });
+ })
+ },
+ expected: false
+ },
+ {
+ // Pass in ArrayBuffer.
+ func: function (mk) {
+ var cert = new ArrayBuffer(200);
+ assert_false(ArrayBuffer.isView(cert));
+ return new Promise(function (resolve) {
+ mk.setServerCertificate(cert).then(function (resolveValue) {
+ resolve(resolveValue);
+ }).catch(function (error) {
+ if (Object.prototype.toString.call(error) === "[object DOMException]") {
+ resolve(false);
+ }
+ });
+ })
+ },
+ expected: false
+ }
+ ];
+ function setServerCertificateTest(){
+ return new Promise(function(resolve, reject){
+ var expected_result;
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function');
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var promises = kSetServerCertificateTestCases.map(function (testCase) {
+ return testCase.func.call(null, mediaKeys);
+ });
+ expected_result = kSetServerCertificateTestCases.map(function (testCase) {
+ return testCase.expected;
+ });
+ assert_not_equals(promises.length, 0);
+ return Promise.all(promises);
+ }).then(function (result) {
+ assert_array_equals(result, expected_result);
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return setServerCertificateTest();
+ }, testname + ' test MediaKeys setServerCertificate() syntax with non-empty certificate.');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js
new file mode 100644
index 0000000000..fac31cbb3e
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysession.js
@@ -0,0 +1,452 @@
+function runTest(config) {
+ var keysystem = config.keysystem;
+ var testname = testnamePrefix(null, config.keysystem);
+ var initDataType = config.initDataType;
+ var initData = config.initData;
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['temporary']
+ };
+
+ var kTypeSpecificGenerateRequestExceptionsTestCases = [
+ // Tests in this set use a shortened parameter name due to
+ // format_value() only returning the first 60 characters as the
+ // result. With a longer name the first 60 characters is not
+ // enough to determine which test failed. Even with the
+ // shortened name, the error message for the last couple of
+ // tests is the same.
+
+ // Too few parameters.
+ {
+ exception: 'TypeError',
+ func: function (mk1, type) {
+ return mk1.createSession().generateRequest(type);
+ }
+ },
+ // Invalid parameters.
+ {
+ exception: 'TypeError',
+ func: function (mk2, type) {
+ return mk2.createSession().generateRequest(type, '');
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk3, type) {
+ return mk3.createSession().generateRequest(type, null);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk4, type) {
+ return mk4.createSession().generateRequest(type, undefined);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk5, type) {
+ return mk5.createSession().generateRequest(type, 1);
+ }
+ },
+ // (new Uint8Array(0)) returns empty array. So 'TypeError' should
+ // be returned.
+ {
+ exception: 'TypeError',
+ func: function (mk6, type) {
+ return mk6.createSession().generateRequest(type, new Uint8Array(0));
+ }
+ },
+ // Using an empty type should return a 'TypeError'.
+ {
+ exception: 'TypeError',
+ func: function (mk7, type) {
+ return mk7.createSession().generateRequest('', initData);
+ }
+ },
+ ];
+ function generateRequestTestExceptions(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var mp4SessionPromises = kTypeSpecificGenerateRequestExceptionsTestCases.map(function (testCase) {
+ return test_exception(testCase, mediaKeys, initDataType, initData);
+ });
+ assert_not_equals(mp4SessionPromises.length, 0);
+ return Promise.all(mp4SessionPromises);
+ }).then(function (result) {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return generateRequestTestExceptions();
+ }, testname + ' test MediaKeySession generateRequest() exceptions.');
+
+ var kLoadExceptionsTestCases = [
+ // Too few parameters.
+ {
+ exception: 'TypeError',
+ func: function (mk1) {
+ return mk1.createSession('temporary').load();
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk3) {
+ return mk3.createSession('temporary').load('');
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk4) {
+ return mk4.createSession('temporary').load(1);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk5) {
+ return mk5.createSession('temporary').load('!@#$%^&*()');
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (mk6) {
+ return mk6.createSession('temporary').load('1234');
+ }
+ }
+ ];
+ function loadTestExceptions(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var sessionPromises = kLoadExceptionsTestCases.map(function (testCase) {
+ return test_exception(testCase, mediaKeys);
+ });
+ assert_not_equals(sessionPromises.length, 0);
+ return Promise.all(sessionPromises);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return loadTestExceptions();
+ }, testname + ' test MediaKeySession load() exceptions.');
+
+ // All calls to |func| in this group are supposed to succeed.
+ // However, the spec notes that some things are optional for
+ // Clear Key. In particular, support for persistent sessions
+ // is optional. Since some implementations won't support some
+ // features, a NotSupportedError is treated as a success
+ // if |isNotSupportedAllowed| is true.
+ var kCreateSessionTestCases = [
+ // Use the default sessionType.
+ {
+ func: function(mk) { return mk.createSession(); },
+ isNotSupportedAllowed: false
+ },
+ // Try variations of sessionType.
+ {
+ func: function(mk) { return mk.createSession('temporary'); },
+ isNotSupportedAllowed: false
+ },
+ {
+ func: function(mk) { return mk.createSession(undefined); },
+ isNotSupportedAllowed: false
+ },
+ {
+ // Since this is optional, some Clear Key implementations
+ // will succeed, others will return a "NotSupportedError".
+ // Both are allowed results.
+ func: function(mk) { return mk.createSession('persistent-license'); },
+ isNotSupportedAllowed: true
+ },
+ // Try additional parameter, which should be ignored.
+ {
+ func: function(mk) { return mk.createSession('temporary', 'extra'); },
+ isNotSupportedAllowed: false
+ }
+ ];
+ // This function checks that calling generateRequest() works for
+ // various sessions. |testCase.func| creates a MediaKeySession
+ // object, and then generateRequest() is called on that object. It
+ // allows for an NotSupportedError to be generated and treated as a
+ // success, if allowed. See comment above kCreateSessionTestCases.
+ function test_generateRequest(testCase, mediaKeys, type, initData) {
+ var mediaKeySession;
+ try {
+ mediaKeySession = testCase.func.call(null, mediaKeys);
+ } catch (e) {
+ assert_true(testCase.isNotSupportedAllowed);
+ assert_equals(e.name, 'NotSupportedError');
+ return Promise.resolve('not supported');
+ }
+ return mediaKeySession.generateRequest(type, initData);
+ }
+ function generateRequestForVariousSessions(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType should be supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var mp4SessionPromises = kCreateSessionTestCases.map(function (testCase) {
+ return test_generateRequest(testCase, mediaKeys, initDataType, initData);
+ });
+ assert_not_equals(mp4SessionPromises.length, 0);
+ return Promise.all(mp4SessionPromises);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return generateRequestForVariousSessions();
+ }, testname + ' test if MediaKeySession generateRequest() resolves for various sessions');
+
+ var kUpdateSessionExceptionsTestCases = [
+ // Tests in this set use a shortened parameter name due to
+ // format_value() only returning the first 60 characters as the
+ // result. With a longer name (mediaKeySession) the first 60
+ // characters is not enough to determine which test failed.
+
+ // Too few parameters.
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update();
+ }
+ },
+ // Invalid parameters.
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update('');
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update(null);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update(undefined);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update(1);
+ }
+ },
+ // (new Uint8Array(0)) returns empty array. So 'TypeError' should
+ // be returned.
+ {
+ exception: 'TypeError',
+ func: function (s) {
+ return s.update(new Uint8Array(0));
+ }
+ }
+ ];
+
+ function updateTestExceptions(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ var mp4SessionPromises = kUpdateSessionExceptionsTestCases.map(function (testCase) {
+ var mediaKeySession = mediaKeys.createSession();
+ return mediaKeySession.generateRequest(initDataType, initData).then(function (result) {
+ return test_exception(testCase, mediaKeySession);
+ });
+ });
+ assert_not_equals(mp4SessionPromises.length, 0);
+ return Promise.all(mp4SessionPromises);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return updateTestExceptions();
+ }, testname + ' test MediaKeySession update() exceptions.');
+
+ function create_close_exception_test(mediaKeys) {
+ var mediaKeySession = mediaKeys.createSession();
+ return mediaKeySession.close().then(function (result) {
+ assert_unreached('close() should not succeed if session uninitialized');
+ }).catch(function (error) {
+ assert_equals(error.name, 'InvalidStateError');
+ // Return something so the promise resolves.
+ return Promise.resolve();
+ });
+ }
+ function closeTestExceptions(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ return create_close_exception_test(mediaKeys);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ promise_test(function() {
+ return closeTestExceptions();
+ }, testname + ' test MediaKeySession close() exceptions.');
+
+ function create_remove_exception_test(mediaKeys, type, initData) {
+ // remove() on an uninitialized session should fail.
+ var mediaKeySession = mediaKeys.createSession('temporary');
+ return mediaKeySession.remove().then(function (result) {
+ assert_unreached('remove() should not succeed if session uninitialized');
+ }, function (error) {
+ assert_equals(error.name, 'InvalidStateError');
+ });
+ }
+ function removeTestException(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ return create_remove_exception_test(mediaKeys, initDataType, initData);
+ }).then(function () {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ });
+ }
+ promise_test(function() {
+ return removeTestException();
+ }, testname + ' test MediaKeySession remove() exceptions.');
+
+ // All calls to |func| in this group are supposed to succeed.
+ // However, the spec notes that some things are optional for
+ // Clear Key. In particular, support for persistent sessions
+ // is optional. Since some implementations won't support some
+ // features, a NotSupportedError is treated as a success
+ // if |isNotSupportedAllowed| is true.
+ var kCreateSessionTestCases = [
+ // Use the default sessionType.
+ {
+ func: function (mk) {
+ return mk.createSession();
+ },
+ isNotSupportedAllowed: false
+ },
+ // Try variations of sessionType.
+ {
+ func: function (mk) {
+ return mk.createSession('temporary');
+ },
+ isNotSupportedAllowed: false
+ },
+ {
+ func: function (mk) {
+ return mk.createSession(undefined);
+ },
+ isNotSupportedAllowed: false
+ },
+ {
+ // Since this is optional, some Clear Key implementations
+ // will succeed, others will return a "NotSupportedError".
+ // Both are allowed results.
+ func: function (mk) {
+ return mk.createSession('persistent-license');
+ },
+ isNotSupportedAllowed: true
+ },
+ // Try additional parameter, which should be ignored.
+ {
+ func: function (mk) {
+ return mk.createSession('temporary', 'extra');
+ },
+ isNotSupportedAllowed: false
+ }
+ ];
+
+ // This function checks that calling |testCase.func| creates a
+ // MediaKeySession object with some default values. It also
+ // allows for an NotSupportedError to be generated and treated as a
+ // success, if allowed. See comment above kCreateSessionTestCases.
+ function test_createSession(testCase, mediaKeys) {
+ var mediaKeySession;
+ try {
+ mediaKeySession = testCase.func.call(null, mediaKeys);
+ } catch (e) {
+ assert_true(testCase.isNotSupportedAllowed);
+ return;
+ }
+ assert_equals(typeof mediaKeySession, 'object');
+ assert_equals(typeof mediaKeySession.addEventListener, 'function');
+ assert_equals(typeof mediaKeySession.sessionId, 'string');
+ assert_equals(typeof mediaKeySession.expiration, 'number');
+ assert_equals(typeof mediaKeySession.closed, 'object');
+ assert_equals(typeof mediaKeySession.keyStatuses, 'object');
+ assert_equals(typeof mediaKeySession.onkeystatuseschange, 'object');
+ assert_equals(typeof mediaKeySession.onmessage, 'object');
+ assert_equals(typeof mediaKeySession.generateRequest, 'function');
+ assert_equals(typeof mediaKeySession.load, 'function');
+ assert_equals(typeof mediaKeySession.update, 'function');
+ assert_equals(typeof mediaKeySession.close, 'function');
+ assert_equals(typeof mediaKeySession.remove, 'function');
+ assert_equals(mediaKeySession.sessionId, '');
+ }
+ function createSessionTest(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ kCreateSessionTestCases.map(function (testCase) {
+ test_createSession(testCase, mediaKeys);
+ });
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return createSessionTest();
+ }, testname + ' test MediaKeySession attribute syntax.');
+
+
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js
new file mode 100644
index 0000000000..bbc7b6700b
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/syntax-mediakeysystemaccess.js
@@ -0,0 +1,147 @@
+function runTest(config) {
+ var keysystem = config.keysystem;
+ var testname = testnamePrefix(null, config.keysystem);
+ var initDataType = config.initDataType;
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{contentType: config.audioType}],
+ videoCapabilities: [{contentType: config.videoType}],
+ sessionTypes: ['temporary']
+ };
+
+ var kRequestMediaKeySystemAccessExceptionsTestCases = [
+ // Too few parameters.
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess();
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem);
+ }
+ },
+ // Invalid key systems. Note that JavaScript converts all these
+ // values into strings by calling toString(), so they fail due
+ // to the key system not being supported, not due to the type.
+ {
+ exception: 'NotSupportedError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(null, [{}]);
+ }
+ },
+ {
+ exception: 'NotSupportedError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(undefined, [{}]);
+ }
+ },
+ {
+ exception: 'NotSupportedError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(1, [{}]);
+ }
+ },
+ {
+ exception: 'NotSupportedError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess('unsupported', [{}]);
+ }
+ },
+ // Empty keysystem string should be rejected with TypeError.
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess('', [{}]);
+ }
+ },
+ // (new Uint8Array(0)).toString() should return ''. So this case should be the same
+ // as the above.
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(new Uint8Array(0), [{}]);
+ }
+ },
+ // Non-ASCII names.
+ {
+ exception: 'NotSupportedError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem + '\u263A', [{}]);
+ }
+ },
+ // Empty sequence of MediaKeySystemConfiguration.
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem, []);
+ }
+ },
+ // Things that don't convert to valid sequences of MediaKeySystemConfigurations.
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem, {});
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem, "invalid");
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem, [{}, 6]);
+ }
+ },
+ {
+ exception: 'TypeError',
+ func: function () {
+ return navigator.requestMediaKeySystemAccess(keysystem, ["invalid", "upsupported"]);
+ }
+ }
+ ];
+
+ function requestMediaKeySystemAccessTestExceptions(){
+ return new Promise(function(resolve, reject){
+ var createPromises = kRequestMediaKeySystemAccessExceptionsTestCases.map(function (testCase) {
+ return test_exception(testCase);
+ });
+ Promise.all(createPromises).then(function (result) {
+ resolve();
+ }).catch(function (error) {
+ reject(error);
+ });
+ })
+ }
+ promise_test(function() {
+ return requestMediaKeySystemAccessTestExceptions();
+ }, testname + ' test requestMediaKeySystemAccess() exceptions.');
+
+ function requestMediaKeySystemAccessTestAttributes(){
+ return new Promise(function(resolve, reject){
+ isInitDataTypeSupported(keysystem, initDataType).then(function (isTypeSupported) {
+ assert_equals(typeof navigator.requestMediaKeySystemAccess, 'function');
+ assert_true(isTypeSupported, "initDataType not supported");
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]);
+ }).then(function (access) {
+ assert_not_equals(access, null);
+ assert_equals(typeof access, 'object');
+ assert_equals(access.keySystem, keysystem);
+ assert_equals(typeof access.getConfiguration, 'function');
+ assert_equals(typeof access.createMediaKeys, 'function');
+ resolve();
+ }).catch(function(error){
+ reject(error);
+ })
+ })
+ }
+ promise_test(function() {
+ return requestMediaKeySystemAccessTestAttributes();
+ }, testname + ' test MediaKeySystemAccess attribute syntax.');
+
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js b/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js
new file mode 100644
index 0000000000..44c9f15808
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/temporary-license-type.js
@@ -0,0 +1,61 @@
+function runTest(config,qualifier) {
+
+ var testname = testnamePrefix(qualifier, config.keysystem) + ', cannot load persistent license into temporary session';
+
+ var configuration = getSimpleConfigurationForContent(config.content);
+
+ if (config.initDataType && config.initData) {
+ configuration.initDataTypes = [config.initDataType];
+ }
+
+ async_test(function(test)
+ {
+ var initDataType;
+ var initData;
+ var mediaKeySession;
+
+ function onFailure(error) {
+ forceTestFailureFromPromise(test, error);
+ }
+
+ function processMessage(event)
+ {
+ assert_true(event instanceof window.MediaKeyMessageEvent);
+ assert_equals(event.target, mediaKeySession);
+ assert_equals(event.type, 'message');
+ assert_in_array(event.messageType, ['license-request', 'individualization-request']);
+
+ config.messagehandler(event.messageType, event.message).then( function(response) {
+ mediaKeySession.update(response).then( test.step_func( function() {
+ if ( event.messageType !== 'license-request' ) {
+ return;
+ }
+ assert_unreached( "Update with incorrect license type should fail" )
+ } ) ).catch( test.step_func( function( error ) {
+ if ( event.messageType !== 'license-request' ) {
+ forceTestFailureFromPromise(test, error);
+ return;
+ }
+
+ assert_throws_js(TypeError, () => { throw error; });
+ test.done();
+ } ) );
+ }).catch(onFailure);
+ }
+
+ navigator.requestMediaKeySystemAccess(config.keysystem, [configuration]).then(function(access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+ if (config.initDataType && config.initData) {
+ initData = config.initData;
+ } else {
+ initData = getInitData(config.content, initDataType);
+ }
+ return access.createMediaKeys();
+ }).then(test.step_func(function(mediaKeys) {
+ mediaKeySession = mediaKeys.createSession('temporary');
+ waitForEventAndRunStep('message', mediaKeySession, test.step_func(processMessage), test);
+ return mediaKeySession.generateRequest(initDataType, initData);
+ })).catch(onFailure);
+ }, testname );
+
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js b/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js
new file mode 100644
index 0000000000..015ea9d4e9
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/unique-origin.js
@@ -0,0 +1,64 @@
+function runTest(config) {
+ // When the sandbox attribute is present on an iframe, it will
+ // treat the content as being from a unique origin. So try to
+ // call createMediaKeys() inside an iframe and it should fail.
+
+ function load_iframe(src, sandbox) {
+ return new Promise(function (resolve) {
+ var iframe = document.createElement('iframe');
+ iframe.onload = function () {
+ resolve(iframe);
+ };
+ iframe.sandbox = sandbox;
+ iframe.srcdoc = 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 =
+ '<script>' +
+ ' window.onmessage = function(e) {' +
+ ' navigator.requestMediaKeySystemAccess("' + config.keysystem + '", [{' +
+ ' initDataTypes: [\"' + config.initDataType + '\"],' +
+ ' audioCapabilities: [' +
+ ' { contentType:\'' + config.audioType + '\'},' +
+ ' ]' +
+ ' }]).then(function(access) {' +
+ ' return access.createMediaKeys();' +
+ ' }).then(function(mediaKeys) {' +
+ ' window.parent.postMessage({result: \'allowed\'}, \'*\');' +
+ ' }, function(error) {' +
+ ' window.parent.postMessage({result: \'failed\'}, \'*\');' +
+ ' });' +
+ ' };' +
+ '<\/script>';
+
+ // Verify that this page can create a MediaKeys first.
+ return navigator.requestMediaKeySystemAccess(config.keysystem, [{
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [
+ {contentType: config.audioType},
+ ]
+ }]).then(function (access) {
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ // Success, so now create the iframe and try there.
+ return load_iframe(script, 'allow-scripts allow-secure-context');
+ }).then(function (iframe) {
+ iframe.contentWindow.postMessage({}, '*');
+ return wait_for_message();
+ }).then(function (message) {
+ assert_equals(message.result, 'failed');
+ });
+ }, 'Unique origin is unable to create MediaKeys');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js b/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js
new file mode 100644
index 0000000000..2a30ad38d4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/update-disallowed-input.js
@@ -0,0 +1,43 @@
+function runTest(config)
+{
+ // This test passes |response| to update() as a JSON Web Key Set.
+ // CDMs other than Clear Key won't expect |response| in this format.
+ promise_test(function(test) {
+ var initDataType;
+ var initData;
+ var keySystem = config.keysystem;
+ var mediaKeySession;
+
+ function createReallyLongJWKSet()
+ {
+ // This is just a standard JWKSet with a lot of
+ // extra items added to the end. Key ID and key
+ // doesn't really matter.
+ var jwkSet = '{"keys":[{'
+ + '"kty":"oct",'
+ + '"k":"MDEyMzQ1Njc4OTAxMjM0NQ",'
+ + '"kid":"MDEyMzQ1Njc4OTAxMjM0NQ"'
+ + '}]';
+ return jwkSet + ',"test":"unknown"'.repeat(4000) + '}';
+ }
+
+ var p = navigator.requestMediaKeySystemAccess(keySystem, getSimpleConfiguration()).then(function(access) {
+ initDataType = access.getConfiguration().initDataTypes[0];
+ initData = getInitData(initDataType);
+ return access.createMediaKeys();
+ }).then(function(mediaKeys) {
+ mediaKeySession = mediaKeys.createSession();
+ var eventWatcher = new EventWatcher(test, mediaKeySession, ['message']);
+ var promise = eventWatcher.wait_for('message');
+ mediaKeySession.generateRequest(initDataType, initData);
+ return promise;
+ }).then(function () {
+ var jwkSet = createReallyLongJWKSet();
+ assert_greater_than(jwkSet.length, 65536);
+ var jwkSetArray = stringToUint8Array(jwkSet);
+ return mediaKeySession.update(jwkSetArray);
+ });
+
+ return promise_rejects_js(test, TypeError, p);
+ }, 'update() with invalid response (longer than 64Kb characters) should fail.');
+}
diff --git a/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js b/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js
new file mode 100644
index 0000000000..fdfb855677
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/scripts/waiting-for-a-key.js
@@ -0,0 +1,166 @@
+function runTest(config)
+{
+ // For debugging timeouts, keep track of the number of the
+ // various events received.
+ var debugEncryptedEventFired = false;
+ var debugWaitingForKeyEventFired = false;
+ var debugTimeUpdateEventCount = 0;
+ var debugMessage = '';
+
+ // Set global option explicit_timeout to true and control
+ // the timeout in the promise test below.
+ setup({
+ explicit_timeout: true
+ });
+
+ promise_test(function (test) {
+ var video = config.video;
+ var keysystem = config.keysystem;
+ var configuration = {
+ initDataTypes: [config.initDataType],
+ audioCapabilities: [{
+ contentType: config.audioType
+ }],
+ videoCapabilities: [{
+ contentType: config.videoType
+ }],
+ sessionTypes: ['temporary']
+ };
+ var initData;
+ var initDataType;
+ var mediaKeySession;
+ // As this code doesn't wait for the 'message' event for clearkey to avoid
+ // race conditions with 'waitingforkey', specify the key ID and
+ // key used by the encrypted content.
+ var keyId = new Uint8Array(config.content.keys[0].kid);
+ var rawKey = new Uint8Array(config.content.keys[0].key);
+ // Use the message handler for non clearkey drm
+ var handler = config.messageHandler || null;
+
+ // Override timeout() to use custom message instead of default
+ // message "Test timed out"
+ test.timeout = function () {
+ var message = 'timeout. message = ' + debugMessage
+ + ', encrypted: ' + debugEncryptedEventFired
+ + ', waitingforkey: ' + debugWaitingForKeyEventFired
+ + ', timeupdate count: ' + debugTimeUpdateEventCount;
+
+ this.timeout_id = null;
+ this.set_status(this.TIMEOUT, message);
+ this.phase = this.phases.HAS_RESULT;
+ this.done();
+ };
+
+ return navigator.requestMediaKeySystemAccess(keysystem, [configuration]).then(function (access) {
+ debugMessage = 'createMediaKeys()';
+ return access.createMediaKeys();
+ }).then(function (mediaKeys) {
+ debugMessage = 'setMediaKeys()';
+ return video.setMediaKeys(mediaKeys);
+ }).then(function () {
+ return testmediasource(config);
+ }).then(function (source) {
+ debugMessage = 'wait_for_encrypted_event()';
+ mediaSource = source;
+ video.src = URL.createObjectURL(mediaSource);
+ video.play();
+ return wait_for_encrypted_event(video);
+ }).then(function (e) {
+ // Received the 'encrypted' event(s), so keep a copy of
+ // the initdata for use when creating the session later.
+ initDataType = config.initData ? config.initDataType : e.initDataType;
+ initData = config.initData || e.initData;
+ // Wait until the video indicates that it needs a key to
+ // continue.
+ debugMessage = 'wait_for_waitingforkey_event()';
+ return wait_for_waitingforkey_event(video);
+ }).then(function () {
+ // Make sure the video is NOT paused and not progressing
+ // before a key is provided. This requires the video
+ // to NOT have a clear lead.
+ assert_false(video.paused);
+ assert_less_than(video.currentTime, 0.2);
+ // Create a session.
+ mediaKeySession = video.mediaKeys.createSession('temporary');
+ debugMessage = 'generateRequest()';
+ return mediaKeySession.generateRequest(initDataType, initData);
+ }).then(function () {
+ // generateRequest() will cause a 'message' event to
+ // occur specifying the keyId that is needed
+ // Add the key needed to decrypt.
+ return wait_for_message_event(mediaKeySession, handler);
+ }).then(function () {
+ // Video should start playing now that it can decrypt the
+ // streams, so wait until a little bit of the video has
+ // played.
+ debugMessage = 'wait_for_timeupdate_event()';
+ return wait_for_timeupdate_event(video);
+ }).catch(function (error) {
+ assert_unreached('Error: ' + error.name);
+ });
+
+ // Typical test duration is 6 seconds on release builds
+ // (12 seconds on debug).
+ }, 'Waiting for a key.');
+
+ // Wait for an 'encrypted' event
+ function wait_for_encrypted_event(video)
+ {
+ return new Promise(function (resolve) {
+ video.addEventListener('encrypted', function listener(e) {
+ assert_equals(e.target, video);
+ assert_true(e instanceof window.MediaEncryptedEvent);
+ assert_equals(e.type, 'encrypted');
+ debugEncryptedEventFired = true;
+ video.removeEventListener('encrypted', listener);
+ resolve(e);
+ });
+ });
+ };
+
+ // Wait for a 'waitingforkey' event. Promise resolved when the
+ // event is received.
+ function wait_for_waitingforkey_event(video)
+ {
+ return new Promise(function (resolve) {
+ video.addEventListener('waitingforkey', function listener(e) {
+ assert_equals(e.target, video);
+ assert_equals(e.type, 'waitingforkey');
+ debugWaitingForKeyEventFired = true;
+ video.removeEventListener('waitingforkey', listener);
+ resolve(e);
+ });
+ });
+ };
+
+ // Wait for a 'timeupdate' event. Promise resolved if |video| has
+ // played for more than 0.2 seconds.
+ function wait_for_timeupdate_event(video)
+ {
+ return new Promise(function (resolve) {
+ video.addEventListener('timeupdate', function listener(e) {
+ assert_equals(e.target, video);
+ ++debugTimeUpdateEventCount;
+ if (video.currentTime < 0.2)
+ return;
+ video.removeEventListener('timeupdate', listener);
+ resolve(e);
+ });
+ });
+ };
+
+ // We need to wait for the message even if for non clearkey DRMs.
+ function wait_for_message_event(mediaKeySession, handler)
+ {
+ return new Promise(function (resolve, reject) {
+ mediaKeySession.addEventListener('message', function listener(e) {
+ assert_equals(e.target, mediaKeySession);
+ assert_equals(e.type, 'message');
+ video.removeEventListener('message', listener);
+ return handler(e.messageType, e.message).then(function (response) {
+ return e.target.update(response)
+ }).then(resolve, reject);
+ });
+ });
+ }
+}
diff --git a/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js b/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js
new file mode 100644
index 0000000000..c91a57f6d4
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/util/clearkey-messagehandler.js
@@ -0,0 +1,64 @@
+// Expect utf8decoder and utf8decoder to be TextEncoder('utf-8') and TextDecoder('utf-8') respectively
+
+function MessageHandler( keysystem, content ) {
+ this._keysystem = keysystem;
+ this._content = content;
+ this.messagehandler = MessageHandler.prototype.messagehandler.bind( this );
+ this.servercertificate = undefined;
+}
+
+MessageHandler.prototype.messagehandler = function messagehandler( messageType, message )
+{
+ if ( messageType === 'license-request' )
+ {
+ var request = fromUtf8( message );
+
+ var keys = request.kids.map( function( kid ) {
+
+ var key;
+ for( var i=0; i < this._content.keys.length; ++i )
+ {
+ if ( base64urlEncode( this._content.keys[ i ].kid ) === kid )
+ {
+ key = base64urlEncode( this._content.keys[ i ].key );
+ break;
+ }
+ }
+
+ return { kty: 'oct', kid: kid, k: key };
+
+ }.bind( this ) );
+
+ return Promise.resolve( toUtf8( { keys: keys } ) );
+ }
+ else if ( messageType === 'license-release' )
+ {
+ var release = fromUtf8( message );
+
+ // TODO: Check the license release message here
+
+ return Promise.resolve( toUtf8( { kids: release.kids } ) );
+ }
+
+ throw new TypeError( 'Unsupported message type for ClearKey' );
+};
+
+MessageHandler.prototype.createJWKSet = function createJWKSet(keyId, key) {
+ var jwkSet = '{"keys":[';
+ for (var i = 0; i < arguments.length; i++) {
+ if (i != 0)
+ jwkSet += ',';
+ jwkSet += arguments[i];
+ }
+ jwkSet += ']}';
+ return jwkSet;
+};
+
+MessageHandler.prototype.createJWK = function createJWK(keyId, key) {
+ var jwk = '{"kty":"oct","alg":"A128KW","kid":"';
+ jwk += base64urlEncode(keyId);
+ jwk += '","k":"';
+ jwk += base64urlEncode(key);
+ jwk += '"}';
+ return jwk;
+}; \ No newline at end of file
diff --git a/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js b/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js
new file mode 100644
index 0000000000..5c5577c6d6
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/util/drm-messagehandler.js
@@ -0,0 +1,265 @@
+(function(){
+// Expect utf8decoder and utf8decoder to be TextEncoder('utf-8') and TextDecoder('utf-8') respectively
+//
+// drmconfig format:
+// { <keysystem> : { "serverURL" : <the url for the server>,
+// "httpRequestHeaders" : <map of HTTP request headers>,
+// "servertype" : "microsoft" | "drmtoday", // affects how request parameters are formed
+// "certificate" : <base64 encoded server certificate> } }
+//
+
+drmtodaysecret = Uint8Array.from( [144, 34, 109, 76, 134, 7, 97, 107, 98, 251, 140, 28, 98, 79, 153, 222, 231, 245, 154, 226, 193, 1, 213, 207, 152, 204, 144, 15, 13, 2, 37, 236] );
+
+drmconfig = {
+ "com.widevine.alpha": [ {
+ "serverURL": "https://lic.staging.drmtoday.com/license-proxy-widevine/cenc/",
+ "servertype" : "drmtoday",
+ "merchant" : "w3c-eme-test",
+ "secret" : drmtodaysecret
+ } ],
+ "com.microsoft.playready": [ {
+ "serverURL": "http://playready-testserver.azurewebsites.net/rightsmanager.asmx",
+ "servertype": "microsoft",
+ "sessionTypes" : [ "persistent-usage-record" ],
+ "certificate" : "Q0hBSQAAAAEAAAUEAAAAAAAAAAJDRVJUAAAAAQAAAfQAAAFkAAEAAQAAAFjt9G6KdSncCkrjbTQPN+/2AAAAAAAAAAAAAAAJIPbrW9dj0qydQFIomYFHOwbhGZVGP2ZsPwcvjh+NFkP/////AAAAAAAAAAAAAAAAAAAAAAABAAoAAABYxw6TjIuUUmvdCcl00t4RBAAAADpodHRwOi8vcGxheXJlYWR5LmRpcmVjdHRhcHMubmV0L3ByL3N2Yy9yaWdodHNtYW5hZ2VyLmFzbXgAAAAAAQAFAAAADAAAAAAAAQAGAAAAXAAAAAEAAQIAAAAAADBRmRRpqV4cfRLcWz9WoXIGZ5qzD9xxJe0CSI2mXJQdPHEFZltrTkZtdmurwVaEI2etJY0OesCeOCzCqmEtTkcAAAABAAAAAgAAAAcAAAA8AAAAAAAAAAVEVEFQAAAAAAAAABVNZXRlcmluZyBDZXJ0aWZpY2F0ZQAAAAAAAAABAAAAAAABAAgAAACQAAEAQGHic/IPbmLCKXxc/MH20X/RtjhXH4jfowBWsQE1QWgUUBPFId7HH65YuQJ5fxbQJCT6Hw0iHqKzaTkefrhIpOoAAAIAW+uRUsdaChtq/AMUI4qPlK2Bi4bwOyjJcSQWz16LAFfwibn5yHVDEgNA4cQ9lt3kS4drx7pCC+FR/YLlHBAV7ENFUlQAAAABAAAC/AAAAmwAAQABAAAAWMk5Z0ovo2X0b2C9K5PbFX8AAAAAAAAAAAAAAARTYd1EkpFovPAZUjOj2doDLnHiRSfYc89Fs7gosBfar/////8AAAAAAAAAAAAAAAAAAAAAAAEABQAAAAwAAAAAAAEABgAAAGAAAAABAAECAAAAAABb65FSx1oKG2r8AxQjio+UrYGLhvA7KMlxJBbPXosAV/CJufnIdUMSA0DhxD2W3eRLh2vHukIL4VH9guUcEBXsAAAAAgAAAAEAAAAMAAAABwAAAZgAAAAAAAAAgE1pY3Jvc29mdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFBsYXlSZWFkeSBTTDAgTWV0ZXJpbmcgUm9vdCBDQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDEuMC4wLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEACAAAAJAAAQBArAKJsEIDWNG5ulOgLvSUb8I2zZ0c5lZGYvpIO56Z0UNk/uC4Mq3jwXQUUN6m/48V5J/vuLDhWu740aRQc1dDDAAAAgCGTWHP8iVuQixWizwoABz7PhUnZYWEugUht5sYKNk23h2Cao/D5uf6epDVyilG8fZKLvufXc/+fkNOtEKT+sWr"
+ },
+ {
+ "serverURL": "http://playready.directtaps.net/pr/svc/rightsmanager.asmx",
+ "servertype": "microsoft",
+ "sessionTypes" : [ "persistent-usage-record" ],
+ "certificate" : "Q0hBSQAAAAEAAAUEAAAAAAAAAAJDRVJUAAAAAQAAAfQAAAFkAAEAAQAAAFjt9G6KdSncCkrjbTQPN+/2AAAAAAAAAAAAAAAJIPbrW9dj0qydQFIomYFHOwbhGZVGP2ZsPwcvjh+NFkP/////AAAAAAAAAAAAAAAAAAAAAAABAAoAAABYxw6TjIuUUmvdCcl00t4RBAAAADpodHRwOi8vcGxheXJlYWR5LmRpcmVjdHRhcHMubmV0L3ByL3N2Yy9yaWdodHNtYW5hZ2VyLmFzbXgAAAAAAQAFAAAADAAAAAAAAQAGAAAAXAAAAAEAAQIAAAAAADBRmRRpqV4cfRLcWz9WoXIGZ5qzD9xxJe0CSI2mXJQdPHEFZltrTkZtdmurwVaEI2etJY0OesCeOCzCqmEtTkcAAAABAAAAAgAAAAcAAAA8AAAAAAAAAAVEVEFQAAAAAAAAABVNZXRlcmluZyBDZXJ0aWZpY2F0ZQAAAAAAAAABAAAAAAABAAgAAACQAAEAQGHic/IPbmLCKXxc/MH20X/RtjhXH4jfowBWsQE1QWgUUBPFId7HH65YuQJ5fxbQJCT6Hw0iHqKzaTkefrhIpOoAAAIAW+uRUsdaChtq/AMUI4qPlK2Bi4bwOyjJcSQWz16LAFfwibn5yHVDEgNA4cQ9lt3kS4drx7pCC+FR/YLlHBAV7ENFUlQAAAABAAAC/AAAAmwAAQABAAAAWMk5Z0ovo2X0b2C9K5PbFX8AAAAAAAAAAAAAAARTYd1EkpFovPAZUjOj2doDLnHiRSfYc89Fs7gosBfar/////8AAAAAAAAAAAAAAAAAAAAAAAEABQAAAAwAAAAAAAEABgAAAGAAAAABAAECAAAAAABb65FSx1oKG2r8AxQjio+UrYGLhvA7KMlxJBbPXosAV/CJufnIdUMSA0DhxD2W3eRLh2vHukIL4VH9guUcEBXsAAAAAgAAAAEAAAAMAAAABwAAAZgAAAAAAAAAgE1pY3Jvc29mdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFBsYXlSZWFkeSBTTDAgTWV0ZXJpbmcgUm9vdCBDQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDEuMC4wLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEACAAAAJAAAQBArAKJsEIDWNG5ulOgLvSUb8I2zZ0c5lZGYvpIO56Z0UNk/uC4Mq3jwXQUUN6m/48V5J/vuLDhWu740aRQc1dDDAAAAgCGTWHP8iVuQixWizwoABz7PhUnZYWEugUht5sYKNk23h2Cao/D5uf6epDVyilG8fZKLvufXc/+fkNOtEKT+sWr"
+ },
+ {
+ "serverURL": "https://lic.staging.drmtoday.com/license-proxy-headerauth/drmtoday/RightsManager.asmx",
+ "servertype" : "drmtoday",
+ "sessionTypes" : [ "temporary", "persistent-usage-record", "persistent-license" ],
+ "merchant" : "w3c-eme-test",
+ "secret" : drmtodaysecret
+ } ]
+};
+
+
+var keySystemWrappers = {
+ // Key System wrappers map messages and pass to a handler, then map the response and return to caller
+ //
+ // function wrapper(handler, messageType, message, params)
+ //
+ // where:
+ // Promise<response> handler(messageType, message, responseType, headers, params);
+ //
+
+ 'com.widevine.alpha': function(handler, messageType, message, params) {
+ return handler.call(this, messageType, new Uint8Array(message), 'json', null, params).then(function(response){
+ return base64DecodeToUnit8Array(response.license);
+ });
+ },
+
+ 'com.microsoft.playready': function(handler, messageType, message, params) {
+ var msg, xmlDoc;
+ var licenseRequest = null;
+ var headers = {};
+ var parser = new DOMParser();
+ var dataview = new Uint16Array(message);
+
+ msg = String.fromCharCode.apply(null, dataview);
+ xmlDoc = parser.parseFromString(msg, 'application/xml');
+
+ if (xmlDoc.getElementsByTagName('Challenge')[0]) {
+ var challenge = xmlDoc.getElementsByTagName('Challenge')[0].childNodes[0].nodeValue;
+ if (challenge) {
+ licenseRequest = atob(challenge);
+ }
+ }
+
+ var headerNameList = xmlDoc.getElementsByTagName('name');
+ var headerValueList = xmlDoc.getElementsByTagName('value');
+ for (var i = 0; i < headerNameList.length; i++) {
+ headers[headerNameList[i].childNodes[0].nodeValue] = headerValueList[i].childNodes[0].nodeValue;
+ }
+ // some versions of the PlayReady CDM return 'Content' instead of 'Content-Type',
+ // but the license server expects 'Content-Type', so we fix it up here.
+ if (headers.hasOwnProperty('Content')) {
+ headers['Content-Type'] = headers.Content;
+ delete headers.Content;
+ }
+
+ return handler.call(this, messageType, licenseRequest, 'arraybuffer', headers, params).catch(function(response){
+ return response.text().then( function( error ) { throw error; } );
+ });
+ }
+};
+
+const requestConstructors = {
+ // Server request construction functions
+ //
+ // Promise<request> constructRequest(config, sessionType, content, messageType, message, params)
+ //
+ // request = { url: ..., headers: ..., body: ... }
+ //
+ // content = { assetId: ..., variantId: ..., key: ... }
+ // params = { expiration: ... }
+
+ 'drmtoday': function(config, sessionType, content, messageType, message, headers, params) {
+ var optData = JSON.stringify({merchant: config.merchant, userId:"12345", sessionId:""});
+ var crt = {};
+ if (messageType === 'license-request') {
+ crt = {assetId: content.assetId,
+ outputProtection: {digital : false, analogue: false, enforce: false},
+ storeLicense: (sessionType === 'persistent-license')};
+
+ if (!params || (params.expiration === undefined && params.playDuration === undefined)) {
+ crt.profile = {purchase: {}};
+ } else {
+ var expiration = params.expiration || (Date.now().valueOf() + 3600000),
+ playDuration = params.playDuration || 3600000;
+
+ crt.profile = {rental: {absoluteExpiration: (new Date(expiration)).toISOString(),
+ playDuration: playDuration } };
+ }
+
+ if (content.variantId !== undefined) {
+ crt.variantId = content.variantId;
+ }
+ }
+
+ return JWT.encode("HS256", {optData: optData, crt: JSON.stringify([crt])}, config.secret).then(function(jwt){
+ headers = headers || {};
+ headers['x-dt-auth-token'] = jwt;
+ return {url: config.serverURL, headers: headers, body: message};
+ });
+ },
+
+ 'microsoft': function(config, sessionType, content, messageType, message, headers, params) {
+ var url = config.serverURL;
+ if (messageType === 'license-request') {
+ url += "?";
+ if (sessionType === 'temporary' || sessionType === 'persistent-usage-record') {
+ url += "UseSimpleNonPersistentLicense=1&";
+ }
+ if (sessionType === 'persistent-usage-record') {
+ url += "SecureStop=1&";
+ }
+ url += "PlayEnablers=B621D91F-EDCC-4035-8D4B-DC71760D43E9&"; // disable output protection
+ url += "ContentKey=" + btoa(String.fromCharCode.apply(null, content.key));
+ return url;
+ }
+
+ // TODO: Include expiration time in URL
+ return Promise.resolve({url: url, headers: headers, body: message});
+ }
+};
+
+MessageHandler = function(keysystem, content, sessionType) {
+ sessionType = sessionType || "temporary";
+
+ this._keysystem = keysystem;
+ this._content = content;
+ this._sessionType = sessionType;
+ try {
+ this._drmconfig = drmconfig[this._keysystem].filter(function(drmconfig) {
+ return drmconfig.sessionTypes === undefined || (drmconfig.sessionTypes.indexOf(sessionType) !== -1);
+ })[0];
+ this._requestConstructor = requestConstructors[this._drmconfig.servertype];
+
+ this.messagehandler = keySystemWrappers[keysystem].bind(this, MessageHandler.prototype.messagehandler);
+
+ if (this._drmconfig && this._drmconfig.certificate) {
+ this.servercertificate = stringToUint8Array(atob(this._drmconfig.certificate));
+ }
+ } catch(e) {
+ return null;
+ }
+}
+
+MessageHandler.prototype.messagehandler = function messagehandler(messageType, message, responseType, headers, params) {
+
+ var variantId = params ? params.variantId : undefined;
+ var key;
+ if( variantId ) {
+ var keys = this._content.keys.filter(function(k){return k.variantId === variantId;});
+ if (keys[0]) key = keys[0].key;
+ }
+ if (!key) {
+ key = this._content.keys[0].key;
+ }
+
+ var content = {assetId: this._content.assetId,
+ variantId: variantId,
+ key: key};
+
+ return this._requestConstructor(this._drmconfig, this._sessionType, content, messageType, message, headers, params).then(function(request){
+ return fetch(request.url, {
+ method: 'POST',
+ headers: request.headers,
+ body: request.body });
+ }).then(function(fetchresponse){
+ if(fetchresponse.status !== 200) {
+ throw fetchresponse;
+ }
+
+ if(responseType === 'json') {
+ return fetchresponse.json();
+ } else if(responseType === 'arraybuffer') {
+ return fetchresponse.arrayBuffer();
+ }
+ });
+}
+
+})();
+
+(function() {
+
+ var subtlecrypto = window.crypto.subtle;
+
+ // Encoding / decoding utilities
+ function b64pad(b64) { return b64+"==".substr(0,(b64.length%4)?(4-b64.length%4):0); }
+ function str2b64url(str) { return btoa(str).replace(/=+$/g, '').replace(/\+/g, "-").replace(/\//g, "_"); }
+ function b64url2str(b64) { return atob(b64pad(b64.replace(/\-/g, "+").replace(/\_/g, "/"))); }
+ function str2ab(str) { return Uint8Array.from( str.split(''), function(s){return s.charCodeAt(0)} ); }
+ function ab2str(ab) { return String.fromCharCode.apply(null, new Uint8Array(ab)); }
+
+ function jwt2webcrypto(alg) {
+ if (alg === "HS256") return {name: "HMAC", hash: "SHA-256", length: 256};
+ else if (alg === "HS384") return { name: "HMAC", hash: "SHA-384", length: 384};
+ else if (alg === "HS512") return { name: "HMAC", hash: "SHA-512", length: 512};
+ else throw new Error("Unrecognized JWT algorithm: " + alg);
+ }
+
+ JWT = {
+ encode: function encode(alg, claims, secret) {
+ var algorithm = jwt2webcrypto(alg);
+ if (secret.byteLength !== algorithm.length / 8) throw new Error("Unexpected secret length: " + secret.byteLength);
+
+ if (!claims.iat) claims.iat = ((Date.now() / 1000) | 0) - 60;
+ if (!claims.jti) {
+ var nonce = new Uint8Array(16);
+ window.crypto.getRandomValues(nonce);
+ claims.jti = str2b64url( ab2str(nonce) );
+ }
+
+ var header = {typ: "JWT", alg: alg};
+ var plaintext = str2b64url(JSON.stringify(header)) + '.' + str2b64url(JSON.stringify(claims));
+ return subtlecrypto.importKey("raw", secret, algorithm, false, [ "sign" ]).then( function(key) {
+ return subtlecrypto.sign(algorithm, key, str2ab(plaintext));
+ }).then(function(hmac){
+ return plaintext + '.' + str2b64url(ab2str(hmac));
+ });
+ },
+
+ decode: function decode(jwt, secret) {
+ var jwtparts = jwt.split('.');
+ var header = JSON.parse( b64url2str(jwtparts[0]));
+ var claims = JSON.parse( b64url2str(jwtparts[1]));
+ var hmac = str2ab(b64url2str(jwtparts[2]));
+ var algorithm = jwt2webcrypto(header.alg);
+ if (secret.byteLength !== algorithm.length / 8) throw new Error("Unexpected secret length: " + secret.byteLength);
+
+ return subtlecrypto.importKey("raw", secret, algorithm, false, ["sign", "verify"]).then(function(key) {
+ return subtlecrypto.verify(algorithm, key, hmac, str2ab(jwtparts[0] + '.' + jwtparts[1]));
+ }).then(function(success){
+ if (!success) throw new Error("Invalid signature");
+ return claims;
+ });
+ }
+ };
+})();
diff --git a/testing/web-platform/tests/encrypted-media/util/testmediasource.js b/testing/web-platform/tests/encrypted-media/util/testmediasource.js
new file mode 100644
index 0000000000..47cfeb4512
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/util/testmediasource.js
@@ -0,0 +1,49 @@
+function testmediasource(config) {
+
+ return new Promise(function(resolve, reject) {
+ // Fetch the media resources
+ var fetches = [config.audioPath, config.videoPath].map(function(path) {
+ return fetch(path).then(function(response) {
+ if (!response.ok) throw new Error('Resource fetch failed');
+ return response.arrayBuffer();
+ });
+ });
+
+ Promise.all(fetches).then(function(resources) {
+ config.audioMedia = resources[0];
+ config.videoMedia = resources[1];
+
+ // Create media source
+ var source = new MediaSource();
+ source.done = new Promise(function(resolvesource,rejectsource){
+
+ // Create and fill source buffers when the media source is opened
+ source.addEventListener('sourceopen', onSourceOpen);
+ resolve(source);
+
+ function onSourceOpen(event) {
+ var audioSourceBuffer = source.addSourceBuffer(config.audioType),
+ videoSourceBuffer = source.addSourceBuffer(config.videoType);
+
+ audioSourceBuffer.addEventListener('updateend',onUpdateEnd);
+ videoSourceBuffer.addEventListener('updateend',onUpdateEnd);
+
+ audioSourceBuffer.appendBuffer(config.audioMedia);
+ videoSourceBuffer.appendBuffer(config.videoMedia);
+
+ function onUpdateEnd(event){
+ event.target.removeEventListener('updateend', onUpdateEnd);
+ if (!audioSourceBuffer.updating && !videoSourceBuffer.updating) {
+ if (source.readyState !== 'open') {
+ rejectsource(new Error("Media source error"));
+ } else {
+ source.endOfStream();
+ resolvesource();
+ }
+ }
+ }
+ }
+ });
+ });
+ });
+}
diff --git a/testing/web-platform/tests/encrypted-media/util/utf8.js b/testing/web-platform/tests/encrypted-media/util/utf8.js
new file mode 100644
index 0000000000..aea5ad7626
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/util/utf8.js
@@ -0,0 +1,2 @@
+toUtf8 = function( o ) { return new TextEncoder().encode( JSON.stringify( o ) ); }
+fromUtf8 = function( t ) { return JSON.parse( new TextDecoder().decode( t ) ); }
diff --git a/testing/web-platform/tests/encrypted-media/util/utils.js b/testing/web-platform/tests/encrypted-media/util/utils.js
new file mode 100644
index 0000000000..79f8c7ea6d
--- /dev/null
+++ b/testing/web-platform/tests/encrypted-media/util/utils.js
@@ -0,0 +1,293 @@
+function testnamePrefix( qualifier, keysystem ) {
+ return ( qualifier || '' ) + ( keysystem === 'org.w3.clearkey' ? keysystem : 'drm' );
+}
+
+function getInitData(initDataType) {
+
+ // FIXME: This is messed up, because here we are hard coding the key ids for the different content
+ // that we use for clearkey testing: webm and mp4. For keyids we return the mp4 one
+ //
+ // The content used with the DRM today servers has a different key id altogether
+
+ if (initDataType == 'webm') {
+ return new Uint8Array([
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ ]);
+ }
+
+ if (initDataType == 'cenc') {
+ return new Uint8Array([
+ 0x00, 0x00, 0x00, 0x34, // size
+ 0x70, 0x73, 0x73, 0x68, // 'pssh'
+ 0x01, // version = 1
+ 0x00, 0x00, 0x00, // flags
+ 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
+ 0x00, 0x00, 0x00, 0x01, // key count
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0xd2, 0xfc, 0x41, // key id
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 // datasize
+ ]);
+ }
+ if (initDataType == 'keyids') {
+ var keyId = new Uint8Array([
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0xd2, 0xfc, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ ]);
+ return stringToUint8Array(createKeyIDs(keyId));
+ }
+ throw 'initDataType ' + initDataType + ' not supported.';
+}
+
+function stringToUint8Array(str)
+{
+ var result = new Uint8Array(str.length);
+ for(var i = 0; i < str.length; i++) {
+ result[i] = str.charCodeAt(i);
+ }
+ return result;
+}
+// Encodes |data| into base64url string. There is no '=' padding, and the
+// characters '-' and '_' must be used instead of '+' and '/', respectively.
+function base64urlEncode(data) {
+ var result = btoa(String.fromCharCode.apply(null, data));
+ return result.replace(/=+$/g, '').replace(/\+/g, "-").replace(/\//g, "_");
+}
+// Decode |encoded| using base64url decoding.
+function base64urlDecode(encoded) {
+ return atob(encoded.replace(/\-/g, "+").replace(/\_/g, "/"));
+}
+// Decode |encoded| using base64 to a Uint8Array
+function base64DecodeToUnit8Array(encoded) {
+ return new Uint8Array( atob( encoded ).split('').map( function(c){return c.charCodeAt(0);} ) );
+}
+// Clear Key can also support Key IDs Initialization Data.
+// ref: http://w3c.github.io/encrypted-media/keyids-format.html
+// Each parameter is expected to be a key id in an Uint8Array.
+function createKeyIDs() {
+ var keyIds = '{"kids":["';
+ for (var i = 0; i < arguments.length; i++) {
+ if (i != 0) keyIds += '","';
+ keyIds += base64urlEncode(arguments[i]);
+ }
+ keyIds += '"]}';
+ return keyIds;
+}
+
+function getSupportedKeySystem() {
+ var userAgent = navigator.userAgent.toLowerCase();
+ var keysystem = undefined;
+ if (userAgent.indexOf('edge') > -1 ) {
+ keysystem = 'com.microsoft.playready';
+ } else if ( userAgent.indexOf('chrome') > -1 || userAgent.indexOf('firefox') > -1 ) {
+ keysystem = 'com.widevine.alpha';
+ }
+ return keysystem;
+}
+
+function waitForEventAndRunStep(eventName, element, func, stepTest)
+{
+ var eventCallback = function(event) {
+ if (func)
+ func(event);
+ }
+
+ element.addEventListener(eventName, stepTest.step_func(eventCallback), true);
+}
+
+function waitForEvent(eventName, element) {
+ return new Promise(function(resolve) {
+ element.addEventListener(eventName, resolve, true);
+ })
+}
+
+var consoleDiv = null;
+
+function consoleWrite(text)
+{
+ if (!consoleDiv && document.body) {
+ consoleDiv = document.createElement('div');
+ document.body.appendChild(consoleDiv);
+ }
+ var span = document.createElement('span');
+ span.appendChild(document.createTextNode(text));
+ span.appendChild(document.createElement('br'));
+ consoleDiv.appendChild(span);
+}
+
+function forceTestFailureFromPromise(test, error, message)
+{
+ test.step_func(assert_unreached)(message ? message + ': ' + error.message : error);
+}
+
+// Returns an array of audioCapabilities that includes entries for a set of
+// codecs that should cover all user agents.
+function getPossibleAudioCapabilities()
+{
+ return [
+ { contentType: 'audio/mp4; codecs="mp4a.40.2"' },
+ { contentType: 'audio/webm; codecs="opus"' },
+ ];
+}
+
+// Returns a trivial MediaKeySystemConfiguration that should be accepted,
+// possibly as a subset of the specified capabilities, by all user agents.
+function getSimpleConfiguration()
+{
+ return [ {
+ initDataTypes : [ 'webm', 'cenc', 'keyids' ],
+ audioCapabilities: getPossibleAudioCapabilities()
+ } ];
+}
+
+// Returns a MediaKeySystemConfiguration for |initDataType| that should be
+// accepted, possibly as a subset of the specified capabilities, by all
+// user agents.
+function getSimpleConfigurationForInitDataType(initDataType)
+{
+ return [ {
+ initDataTypes: [ initDataType ],
+ audioCapabilities: getPossibleAudioCapabilities()
+ } ];
+}
+
+// Returns a promise that is fulfilled with true if |initDataType| is supported,
+// by keysystem or false if not.
+function isInitDataTypeSupported(keysystem,initDataType)
+{
+ return navigator.requestMediaKeySystemAccess(
+ keysystem, getSimpleConfigurationForInitDataType(initDataType))
+ .then(function() { return true; }, function() { return false; });
+}
+
+function getSupportedInitDataTypes( keysystem )
+{
+ return [ 'cenc', 'keyids', 'webm' ].filter( isInitDataTypeSupported.bind( null, keysystem ) );
+}
+
+function arrayBufferAsString(buffer)
+{
+ var array = [];
+ Array.prototype.push.apply( array, new Uint8Array( buffer ) );
+ return '0x' + array.map( function( x ) { return x < 16 ? '0'+x.toString(16) : x.toString(16); } ).join('');
+}
+
+function dumpKeyStatuses(keyStatuses,short)
+{
+ var userAgent = navigator.userAgent.toLowerCase();
+ if (userAgent.indexOf('edge') === -1) {
+ if (!short) { consoleWrite("for (var entry of keyStatuses)"); }
+ for (var entry of keyStatuses) {
+ consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]);
+ }
+ if (!short) {
+ consoleWrite("for (var keyId of keyStatuses.keys())");
+ for (var keyId of keyStatuses.keys()) {
+ consoleWrite(arrayBufferAsString(keyId));
+ }
+ consoleWrite("for (var status of keyStatuses.values())");
+ for (var status of keyStatuses.values()) {
+ consoleWrite(status);
+ }
+ consoleWrite("for (var entry of keyStatuses.entries())");
+ for (var entry of keyStatuses.entries()) {
+ consoleWrite(arrayBufferAsString(entry[0]) + ": " + entry[1]);
+ }
+ consoleWrite("keyStatuses.forEach()");
+ keyStatuses.forEach(function(status, keyId) {
+ consoleWrite(arrayBufferAsString(keyId) + ": " + status);
+ });
+ }
+ } else {
+ if (!short) { consoleWrite("keyStatuses.forEach()"); }
+ keyStatuses.forEach(function(keyId, status) {
+ consoleWrite(arrayBufferAsString(keyId) + ": " + status);
+ });
+ }
+}
+
+// Verify that |keyStatuses| contains just the keys in |keys.expected|
+// and none of the keys in |keys.unexpected|. All keys should have status
+// 'usable'. Example call: verifyKeyStatuses(mediaKeySession.keyStatuses,
+// { expected: [key1], unexpected: [key2] });
+function verifyKeyStatuses(keyStatuses, keys)
+{
+ var expected = keys.expected || [];
+ var unexpected = keys.unexpected || [];
+
+ // |keyStatuses| should have same size as number of |keys.expected|.
+ assert_equals(keyStatuses.size, expected.length, "keystatuses should have expected size");
+
+ // All |keys.expected| should be found.
+ expected.map(function(key) {
+ assert_true(keyStatuses.has(key), "keystatuses should have the expected keys");
+ assert_equals(keyStatuses.get(key), 'usable', "keystatus value should be 'usable'");
+ });
+
+ // All |keys.unexpected| should not be found.
+ unexpected.map(function(key) {
+ assert_false(keyStatuses.has(key), "keystatuses should not have unexpected keys");
+ assert_equals(keyStatuses.get(key), undefined, "keystatus for unexpected key should be undefined");
+ });
+}
+
+// This function checks that calling |testCase.func| returns a
+// rejected Promise with the error.name equal to
+// |testCase.exception|.
+function test_exception(testCase /*...*/) {
+ var func = testCase.func;
+ var exception = testCase.exception;
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ // This should really be rewritten in terms of the promise_rejects_*
+ // testharness utility functions, but that needs the async test involved
+ // passed in, and we don't have that here.
+ return func.apply(null, args).then(
+ function (result) {
+ assert_unreached(format_value(func));
+ },
+ function (error) {
+ assert_not_equals(error.message, "", format_value(func));
+ // `exception` is a string name for the error. We can differentiate
+ // JS Errors from DOMExceptions by checking whether
+ // window[exception] exists. If it does, expectedError is the name
+ // of a JS Error subclass and window[exception] is the constructor
+ // for that subclass. Otherwise it's a name for a DOMException.
+ if (window[exception]) {
+ assert_throws_js(window[exception],
+ () => { throw error; },
+ format_value(func));
+ } else {
+ assert_throws_dom(exception,
+ () => { throw error; },
+ format_value(func));
+ }
+ }
+ );
+}
+
+// Check that the events sequence (array of strings) matches the pattern (array of either strings, or
+// arrays of strings, with the latter representing a possibly repeating sub-sequence)
+function checkEventSequence(events,pattern) {
+ function th(i) { return i + (i < 4 ? ["th", "st", "nd", "rd"][i] : "th"); }
+ var i = 0, j=0, k=0;
+ while(i < events.length && j < pattern.length) {
+ if (!Array.isArray(pattern[j])) {
+ assert_equals(events[i], pattern[j], "Expected " + th(i+1) + " event to be '" + pattern[j] + "'");
+ ++i;
+ ++j;
+ } else {
+ assert_equals(events[i], pattern[j][k], "Expected " + th(i+1) + " event to be '" + pattern[j][k] + "'");
+ ++i;
+ k = (k+1)%pattern[j].length;
+ if (k === 0 && events[i] !== pattern[j][0]) {
+ ++j;
+ }
+ }
+ }
+ assert_equals(i,events.length,"Received more events than expected");
+ assert_equals(j,pattern.length,"Expected more events than received");
+}
+
+