[EME] Add layout test for clearKey CENC message event
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jan 2018 16:50:18 +0000 (16:50 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Jan 2018 16:50:18 +0000 (16:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180928

Patch by Yacine Bandou <yacine.bandou_ext@softathome.com> on 2018-01-09
Reviewed by Xabier Rodriguez-Calvar.

Tests the reception of clearKey message event after the encrypted event and checks its KeyID.
There are two tests: one with MSE playback and another with regular playback.

* media/encrypted-media/clearKey/clearKey-message-cenc-event-expected.txt: Added.
* media/encrypted-media/clearKey/clearKey-message-cenc-event-mse-expected.txt: Added.
* media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html: Added.
    Test with MSE playback.
* media/encrypted-media/clearKey/clearKey-message-cenc-event.html: Added.
    Test with regular playback.
* media/encrypted-media/clearKey/encrypted-media-clearKey-handler.js: Added.
    This JavaScript file provides a simple clearKey EME implementation, checks the EME support, handles the "encrypted", "message" and
    "keystatuseschange" events, and updates the CDM session with the right keys.
    This implementation allows to play an encrypted media (video or audio or both), it is used in this test by overloading the "onMessage" callback
    by an other function that checks the 'message' event and stops the test.
* media/encrypted-media/medias-enc.js:
    I take this opportunity to introduce some fixes:
    Rename "mimetype" field to "mimeType", this field is only used in "clearKey-encrypted-cenc-event-mse.html",
    thus it is easy to change it now.
    Change the KeyID of the encrypted video with the right value, it is used for first time in this test.
* media/media-source/media-source-loader-simple.js:
    Use "mimeType" instead of "mimetype" as it is modified in "medias-enc.js".
* platform/gtk/TestExpectations:
* platform/mac/TestExpectations:
* platform/wpe/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226639 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-expected.txt [new file with mode: 0644]
LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse-expected.txt [new file with mode: 0644]
LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html [new file with mode: 0644]
LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event.html [new file with mode: 0644]
LayoutTests/media/encrypted-media/clearKey/encrypted-media-clearKey-handler.js [new file with mode: 0644]
LayoutTests/media/encrypted-media/medias-enc.js
LayoutTests/media/media-source/media-source-loader-simple.js
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/mac/TestExpectations

index bce6808..17733ae 100644 (file)
@@ -1,3 +1,35 @@
+2018-01-09  Yacine Bandou  <yacine.bandou_ext@softathome.com>
+
+        [EME] Add layout test for clearKey CENC message event
+        https://bugs.webkit.org/show_bug.cgi?id=180928
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Tests the reception of clearKey message event after the encrypted event and checks its KeyID.
+        There are two tests: one with MSE playback and another with regular playback.
+
+        * media/encrypted-media/clearKey/clearKey-message-cenc-event-expected.txt: Added.
+        * media/encrypted-media/clearKey/clearKey-message-cenc-event-mse-expected.txt: Added.
+        * media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html: Added.
+            Test with MSE playback.
+        * media/encrypted-media/clearKey/clearKey-message-cenc-event.html: Added.
+            Test with regular playback.
+        * media/encrypted-media/clearKey/encrypted-media-clearKey-handler.js: Added.
+            This JavaScript file provides a simple clearKey EME implementation, checks the EME support, handles the "encrypted", "message" and 
+            "keystatuseschange" events, and updates the CDM session with the right keys.
+            This implementation allows to play an encrypted media (video or audio or both), it is used in this test by overloading the "onMessage" callback 
+            by an other function that checks the 'message' event and stops the test.
+        * media/encrypted-media/medias-enc.js:
+            I take this opportunity to introduce some fixes:
+            Rename "mimetype" field to "mimeType", this field is only used in "clearKey-encrypted-cenc-event-mse.html",
+            thus it is easy to change it now.
+            Change the KeyID of the encrypted video with the right value, it is used for first time in this test.
+        * media/media-source/media-source-loader-simple.js:
+            Use "mimeType" instead of "mimetype" as it is modified in "medias-enc.js".
+        * platform/gtk/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/wpe/TestExpectations:
+
 2018-01-09  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         Check Image::m_image is not null in ImageLoader::decode()
diff --git a/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-expected.txt b/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-expected.txt
new file mode 100644 (file)
index 0000000..1a75d55
--- /dev/null
@@ -0,0 +1,8 @@
+
+EME API is supported OK
+EVENT(encrypted)
+MediaKeys is created OK
+EVENT(message)
+Expected Kid OK
+END OF TEST
+
diff --git a/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse-expected.txt b/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse-expected.txt
new file mode 100644 (file)
index 0000000..ffc4205
--- /dev/null
@@ -0,0 +1,9 @@
+
+EME API is supported OK
+Media source is opened OK
+EVENT(encrypted)
+MediaKeys is created OK
+EVENT(message)
+Expected Kid OK
+END OF TEST
+
diff --git a/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html b/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html
new file mode 100644 (file)
index 0000000..c3d7003
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Message ClearKey CENC Event</title>
+    <script src="../medias-enc.js"></script>
+    <script src="../../video-test.js"></script>
+    <script src="../../media-source/media-source-loader-simple.js"></script>
+    <script src="encrypted-media-clearKey-handler.js"></script>
+    <script>
+
+    const videoConf = streamMedias["simpleClearKeyMSE"].video;
+
+    function runTest() {
+
+        findMediaElement();
+
+        let emeHandler = new EncryptedMediaHandler(video, videoConf);
+        if (!emeHandler)
+            endTest();
+
+        /* Overload the onMessage callback of EncryptedMediaHandler */
+        emeHandler.onMessage = function(event) {
+            let msgStr = String.fromCharCode.apply(String, new Uint8Array(event.message));
+            let msgJSON = JSON.parse(msgStr);
+            let kid = Base64ToHex(msgJSON.kids[0]).toLowerCase();
+            let key = videoConf.keys[kid];
+            if (key)
+                logResult(true, "Expected Kid");
+            endTest();
+        }
+
+        let ms = new MediaSourceLoaderSimple(video);
+        ms.onready = function() {
+            logResult(true, "Media source is opened");
+            ms.createSourceBuffer(videoConf, 1);
+        };
+    }
+    </script>
+</head>
+<body onload="runTest()">
+    <video></video>
+</body>
+</html>
diff --git a/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event.html b/LayoutTests/media/encrypted-media/clearKey/clearKey-message-cenc-event.html
new file mode 100644 (file)
index 0000000..becbf4d
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Message ClearKey CENC Event</title>
+    <script src="../medias-enc.js"></script>
+    <script src="../../video-test.js"></script>
+    <script src="encrypted-media-clearKey-handler.js"></script>
+    <script>
+
+    const videoConf = streamMedias["simpleClearKey"].video;
+
+    function runTest() {
+
+        findMediaElement();
+
+        let emeHandler = new EncryptedMediaHandler(video, videoConf);
+        if (!emeHandler)
+            endTest();
+
+        /* Overload the onMessage callback of EncryptedMediaHandler */
+        emeHandler.onMessage = function(event) {
+            let msgStr = String.fromCharCode.apply(String, new Uint8Array(event.message));
+            let msgJSON = JSON.parse(msgStr);
+            let kid = Base64ToHex(msgJSON.kids[0]).toLowerCase();
+            let key = videoConf.keys[kid];
+            if (key)
+                logResult(true, "Expected Kid");
+            endTest();
+        }
+
+        let source = document.createElement('source');
+        source.setAttribute("src", videoConf.path);
+        source.setAttribute("type", videoConf.mimeType);
+        video.appendChild(source);
+        video.play();
+    }
+    </script>
+</head>
+<body onload="runTest()">
+    <video></video>
+</body>
+</html>
diff --git a/LayoutTests/media/encrypted-media/clearKey/encrypted-media-clearKey-handler.js b/LayoutTests/media/encrypted-media/clearKey/encrypted-media-clearKey-handler.js
new file mode 100644 (file)
index 0000000..4278fc6
--- /dev/null
@@ -0,0 +1,134 @@
+function Base64ToHex(str)
+{
+    let bin = window.atob(str.replace(/-/g, "+").replace(/_/g, "/"));
+    let res = "";
+    for (let i = 0; i < bin.length; i++) {
+        res += ("0" + bin.charCodeAt(i).toString(16)).substr(-2);
+    }
+    return res;
+}
+
+function HexToBase64(hex)
+{
+    let bin = "";
+    for (let i = 0; i < hex.length; i += 2) {
+        bin += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
+    }
+    return window.btoa(bin).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
+}
+
+function stringToArray(s)
+{
+    let array = new Uint8Array(s.length);
+    for (let i = 0; i < s.length; i++) {
+        array[i] = s.charCodeAt(i);
+    }
+    return array;
+}
+
+function EncryptedMediaHandler(video, videoConf, audioConf)
+{
+    if (!navigator.requestMediaKeySystemAccess) {
+        logResult(false, "EME API is not supported");
+        return;
+    } else {
+        logResult(true, "EME API is supported");
+    }
+
+    this.video = video;
+    this.keys = videoConf.keys;
+    this.audioConf = null;
+    if (audioConf) {
+        for (let attrname in audioConf.keys) {
+            this.keys[attrname] =  audioConf.keys[attrname];
+        }
+        this.audioConf = audioConf;
+    }
+    this.videoConf = videoConf;
+    this.sessions = [];
+    this.setMediaKeyPromise;
+    waitForEventOn(video, "encrypted", this.onEncrypted.bind(this));
+    return this;
+};
+
+EncryptedMediaHandler.prototype = {
+
+    onEncrypted : function(event)
+    {
+        let self = this;
+        let initData = event.initData;
+        let initDataType = event.initDataType;
+        let eventVideo = event.target;
+
+        if (!this.setMediaKeyPromise) {
+            let options = [
+                {    initDataTypes: [self.videoConf.initDataType],
+                     videoCapabilities: [{contentType : self.videoConf.mimeType}] }
+            ];
+
+            if (self.audioConf) {
+                options.audioCapabilities = [{contentType : self.audioConf.mimeType}];
+            }
+
+            this.setMediaKeyPromise = navigator.requestMediaKeySystemAccess("org.w3.clearkey", options).then(function(keySystemAccess) {
+                return keySystemAccess.createMediaKeys();
+            }).then(function(mediaKeys) {
+                logResult(true, "MediaKeys is created");
+                return eventVideo.setMediaKeys(mediaKeys);
+            });
+        }
+
+        this.setMediaKeyPromise.then(function() {
+            let session = eventVideo.mediaKeys.createSession();
+            self.sessions.push(session);
+            waitForEventOn(session, "message", self.onMessage.bind(self));
+            waitForEventOn(session, "keystatuseschange", self.onKeyStatusChange.bind(self));
+            session.generateRequest(initDataType, initData);
+        });
+
+        this.setMediaKeyPromise.catch(function(error){
+            logResult(false, "setMediaKeys is failed");
+        });
+    },
+
+    onMessage : function(event)
+    {
+        let session = event.target;
+        let msgStr = String.fromCharCode.apply(String, new Uint8Array(event.message));
+        let msg = JSON.parse(msgStr);
+        let outKeys = [];
+        let keys = this.keys;
+
+        for (let i = 0; i < msg.kids.length; i++) {
+            let id64 = msg.kids[i];
+            let idHex = Base64ToHex(msg.kids[i]).toLowerCase();
+            let key = keys[idHex];
+            if (key) {
+                outKeys.push({
+                    "kty":"oct",
+                    "alg":"A128KW",
+                    "kid":id64,
+                    "k":HexToBase64(key)
+                });
+            }
+        }
+        let update = JSON.stringify({
+                        "keys" : outKeys,
+                        "type" : msg.type
+                     });
+
+        session.update(stringToArray(update).buffer);
+    },
+
+    onKeyStatusChange : function(event)
+    {
+        let session = event.target;
+        let keysStatus = session.keyStatuses;
+        for (let key of keysStatus.entries()) {
+            let keyId = key[0];
+            let status = key[1];
+            let base64KId = Base64ToHex(window.btoa(String.fromCharCode.apply(String,new Uint8Array(keyId))));
+            logResult(true,"Session:" + " keyId=" + base64KId + " status=" + status);
+        }
+    }
+};
index 6844ebe..a158c15 100644 (file)
@@ -1,16 +1,14 @@
-var streamMedias = {
+const streamMedias = {
     "simpleClearKeyMSE" : {    video : {    initDataType : "cenc",
-                                            mimetype     : 'video/mp4; codecs="avc1.64001F"',
+                                            mimeType     : 'video/mp4; codecs="avc1.64001F"',
                                             segments     : [ "../../content/encrypted/segments/VideoClearKeyCenc-seg-0.mp4" ],
-                                            keys         : {    KID : "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
-                                                                Key : "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" }
+                                            keys         : {    "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" : "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" }
                                        }
                           },
     "simpleClearKey"   :  {    video : {    initDataType : "cenc",
                                             mimeType     : 'video/mp4; codecs="avc1.64001F"',
                                             path         : "../../content/encrypted/VideoClearKeyCenc.mp4",
-                                            keys         : {    KID : "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf",
-                                                                Key : "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" }
+                                            keys         : {    "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" : "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" }
                                        }
                           }
                    };
index ecba458..043697a 100644 (file)
@@ -73,7 +73,7 @@ function MediaSourceLoaderSimple(video)
 MediaSourceLoaderSimple.prototype = {
     createSourceBuffer : function(media, maxSeg)
     {
-        var sb = this.ms.addSourceBuffer(media.mimetype);
+        let sb = this.ms.addSourceBuffer(media.mimeType);
         var sbBase = new SourceBufferLoaderSimple(sb, this.ms, media, maxSeg);
         sbBase.start();
     },
index f6f9f26..1e74b6d 100644 (file)
@@ -1404,6 +1404,9 @@ webkit.org/b/104809 media/encrypted-media/encrypted-media-not-loaded.html [ Fail
 webkit.org/b/104809 media/encrypted-media/encrypted-media-syntax.html [ Failure Timeout ]
 webkit.org/b/104809 media/track/track-cues-pause-on-exit.html [ Timeout Pass ]
 
+webkit.org/b/180928 media/encrypted-media/clearKey/clearKey-message-cenc-event.html [ Skip ]
+webkit.org/b/180928 media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html [ Skip ]
+
 # This test also crashes after the FTL merge
 webkit.org/b/106415 webkit.org/b/119255 fast/workers/worker-close-more.html [ Timeout Crash Pass ]
 
index fe77bbe..84d7544 100644 (file)
@@ -1349,6 +1349,9 @@ media/encrypted-media/mock-MediaKeySession-load.html [ Skip ]
 media/encrypted-media/mock-MediaKeySession-remove.html [ Skip ]
 media/encrypted-media/mock-MediaKeySession-update.html [ Skip ]
 
+webkit.org/b/180928 media/encrypted-media/clearKey/clearKey-message-cenc-event.html [ Skip ]
+webkit.org/b/180928 media/encrypted-media/clearKey/clearKey-message-cenc-event-mse.html [ Skip ]
+
 webkit.org/b/162507 http/tests/media/hls/hls-video-resize.html [ Pass Failure ]
 
 webkit.org/b/167642 imported/w3c/web-platform-tests/shadow-dom/slotchange.html [ Pass Failure ]