Bug 1358399. P6 - rewrite SetupEME() using the new helper functions and fix its callers.
MozReview-Commit-ID: KUXhvPIuXry
--- a/dom/media/test/eme.js
+++ b/dom/media/test/eme.js
@@ -406,188 +406,39 @@ function CleanUpMedia(v) {
/*
* Close all sessions and clean up the |v| element.
*/
function CloseSessions(v, sessions) {
return Promise.all(sessions.map(s => s.close()))
.then(CleanUpMedia(v));
}
-function SetupEME(test, token, params)
-{
- var v = document.createElement("video");
- v.sessions = [];
-
- v.closeSessions = function() {
- return Promise.all(v.sessions.map(s => s.close().then(() => s.closed))).then(
- () => {
- v.setMediaKeys(null);
- if (v.parentNode) {
- v.remove();
- }
- v.onerror = null;
- v.src = null;
- });
- };
+/*
+ * Set up media keys and source buffers for the media element.
+ * Return a promise resolved when all key sessions are updated or rejected
+ * if any failure.
+ */
+function SetupEME(v, test, token, loadParams) {
+ let p = new EMEPromise;
- // Log events dispatched to make debugging easier...
- [ "canplay", "canplaythrough", "ended", "error", "loadeddata",
- "loadedmetadata", "loadstart", "pause", "play", "playing", "progress",
- "stalled", "suspend", "waiting", "waitingforkey",
- ].forEach(function (e) {
- v.addEventListener(e, function(event) {
- Log(token, "" + e);
- });
- });
-
- // Finish the test when error is encountered.
- v.onerror = bail(token + " got error event");
-
- var onSetKeysFail = (params && params.onSetKeysFail)
- ? params.onSetKeysFail
- : bail(token + " Failed to set MediaKeys on <video> element");
-
- // null: No session management in progress, just go ahead and update the session.
- // [...]: Session management in progress, add {initDataType, initData} to
- // this queue to get it processed when possible.
- var initDataQueue = [];
- function pushInitData(ev)
- {
- if (initDataQueue === null) {
- initDataQueue = [];
- }
- initDataQueue.push(ev);
- if (params && params.onInitDataQueued) {
- params.onInitDataQueued(ev, ev.initDataType, StringToHex(ArrayBufferToString(ev.initData)));
- }
+ v.onerror = function() {
+ p.reject(`${token} got an error event.`);
}
- function processInitDataQueue()
- {
- function maybeResolveInitDataPromise() {
- if (params && params.initDataPromise) {
- params.initDataPromise.resolve();
- }
- }
- if (initDataQueue === null) {
- maybeResolveInitDataPromise();
- return;
- }
- // If we're processed all our init data null the queue to indicate encrypted event handled.
- if (initDataQueue.length === 0) {
- initDataQueue = null;
- maybeResolveInitDataPromise();
- return;
- }
- var ev = initDataQueue.shift();
-
- var sessionType = (params && params.sessionType) ? params.sessionType : "temporary";
- Log(token, "createSession(" + sessionType + ") for (" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ")");
- var session = v.mediaKeys.createSession(sessionType);
- if (params && params.onsessioncreated) {
- params.onsessioncreated(session);
- }
- v.sessions.push(session);
-
- return new Promise(function (resolve, reject) {
- session.addEventListener("message", UpdateSessionFunc(test, token, sessionType, resolve, reject));
- Log(token, "session[" + session.sessionId + "].generateRequest(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ")");
- session.generateRequest(ev.initDataType, ev.initData).catch(function(reason) {
- // Reject the promise if generateRequest() failed. Otherwise it will
- // be resolve in UpdateSessionFunc().
- bail(token + ": session[" + session.sessionId + "].generateRequest(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ") failed")(reason);
- reject();
- });
- })
-
- .then(function(aSession) {
- Log(token, "session[" + session.sessionId + "].generateRequest(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ") succeeded");
- if (params && params.onsessionupdated) {
- params.onsessionupdated(aSession);
- }
- processInitDataQueue();
- });
- }
-
- function streamType(type) {
- var x = test.tracks.find(o => o.name == type);
- return x ? x.type : undefined;
- }
-
- // If sessions are to be delayed we won't peform any processing until the
- // callback the assigned here is called by the test.
- if (params && params.delaySessions) {
- params.ProcessSessions = processInitDataQueue;
- }
+ Promise.all([
+ LoadInitData(v, test, token),
+ CreateAndSetMediaKeys(v, test, token),
+ LoadTest(test, v, token, loadParams)])
+ .then(values => {
+ let initData = values[0];
+ return ProcessInitData(v, test, token, initData);
+ })
+ .then(p.resolve, p.reject);
- // Is this the first piece of init data we're processing?
- var firstInitData = true;
- v.addEventListener("encrypted", function(ev) {
- if (firstInitData) {
- Log(token, "got first encrypted(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + "), setup session");
- firstInitData = false;
- pushInitData(ev);
-
- function chain(promise, onReject) {
- return promise.then(function(value) {
- return Promise.resolve(value);
- }).catch(function(reason) {
- onReject(reason);
- return Promise.reject();
- })
- }
-
- var options = { initDataTypes: [ev.initDataType] };
- if (streamType("video")) {
- options.videoCapabilities = [{contentType: streamType("video")}];
- }
- if (streamType("audio")) {
- options.audioCapabilities = [{contentType: streamType("audio")}];
- }
-
- var p = navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, [options]);
- var r = bail(token + " Failed to request key system access.");
- chain(p, r)
- .then(function(keySystemAccess) {
- var p = keySystemAccess.createMediaKeys();
- var r = bail(token + " Failed to create MediaKeys object");
- return chain(p, r);
- })
-
- .then(function(mediaKeys) {
- Log(token, "created MediaKeys object ok");
- mediaKeys.sessions = [];
- var p = v.setMediaKeys(mediaKeys);
- return chain(p, onSetKeysFail);
- })
-
- .then(function() {
- Log(token, "set MediaKeys on <video> element ok");
- if (params && params.onMediaKeysSet) {
- params.onMediaKeysSet();
- }
- if (!(params && params.delaySessions)) {
- processInitDataQueue();
- }
- })
- } else {
- if (params && params.delaySessions) {
- Log(token, "got encrypted(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ") event, queue it in because we're delaying sessions");
- pushInitData(ev);
- } else if (initDataQueue !== null) {
- Log(token, "got encrypted(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ") event, queue it for later session update");
- pushInitData(ev);
- } else {
- Log(token, "got encrypted(" + ev.initDataType + ", " + StringToHex(ArrayBufferToString(ev.initData)) + ") event, update session now");
- pushInitData(ev);
- processInitDataQueue();
- }
- }
- });
- return v;
+ return p.promise;
}
function SetupEMEPref(callback) {
var prefs = [
[ "media.mediasource.enabled", true ],
[ "media.mediasource.webm.enabled", true ],
[ "media.eme.vp9-in-mp4.enabled", true ],
];
--- a/dom/media/test/test_eme_canvas_blocked.html
+++ b/dom/media/test/test_eme_canvas_blocked.html
@@ -11,21 +11,17 @@
<pre id="test">
<script class="testbody" type="text/javascript">
var manager = new MediaTestManager;
function startTest(test, token)
{
manager.started(token);
- var sessions = [];
- // Will be resolved when all initData are processed.
- let initDataPromise = new EMEPromise;
-
- var v = SetupEME(test, token, { initDataPromise: initDataPromise });
+ let v = document.createElement("video");
v.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
var p1 = new EMEPromise;
v.addEventListener("loadeddata", function(ev) {
var video = ev.target;
var canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
@@ -36,18 +32,24 @@ function startTest(test, token)
ctx.drawImage(video, 0, 0);
} catch (ex) {
threwError = true;
}
ok(threwError, TimeStamp(token) + " - Should throw an error when trying to draw EME video to canvas.");
p1.resolve();
});
- var p2 = LoadTest(test, v, token, { onlyLoadFirstFragments:2, noEndOfStream:false });
- EMEPromiseAll(v, token, [p1.promise, p2, initDataPromise.promise]);
+ let p2 = SetupEME(v, test, token, { noEndOfStream:false });
+
+ Promise.all([p1.promise, p2])
+ .catch(reason => ok(false, reason))
+ .then(() => {
+ CleanUpMedia(v);
+ manager.finished(token);
+ });
}
function beginTest() {
manager.runTests(gEMETests, startTest);
}
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
--- a/dom/media/test/test_eme_stream_capture_blocked_case2.html
+++ b/dom/media/test/test_eme_stream_capture_blocked_case2.html
@@ -17,32 +17,40 @@ function startTest(test, token)
// Three cases:
// 1. setting MediaKeys on an element captured by MediaElementSource should fail, and
// 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
// Case 2. creating a MediaElementSource on a media element with a MediaKeys should fail.
var p1 = new EMEPromise;
var case2token = token + "_case2";
- var v2 = SetupEME(test, case2token);
+ let v2 = document.createElement("video");
+
v2.addEventListener("loadeddata", function(ev) {
ok(true, case2token + " should reach loadeddata");
var threw = false;
try {
var context = new AudioContext();
var node = context.createMediaElementSource(v2);
} catch (e) {
threw = true;
}
ok(threw, "Should throw an error creating a MediaElementSource on an EME video.");
p1.resolve();
});
+
manager.started(case2token);
- var p2 = LoadTest(test, v2, case2token, { onlyLoadFirstFragments:2, noEndOfStream:false });
- EMEPromiseAll(v2, case2token, [p1.promise, p2]);
+ let p2 = SetupEME(v2, test, case2token, { noEndOfStream:false });
+
+ Promise.all([p1.promise, p2])
+ .catch(reason => ok(false, reason))
+ .then(() => {
+ CleanUpMedia(v2);
+ manager.finished(case2token);
+ });
}
function beginTest() {
manager.runTests(gEMETests, startTest);
}
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();
--- a/dom/media/test/test_eme_stream_capture_blocked_case3.html
+++ b/dom/media/test/test_eme_stream_capture_blocked_case3.html
@@ -17,31 +17,39 @@ function startTest(test, token)
// Three cases:
// 1. setting MediaKeys on an element captured by MediaElementSource should fail, and
// 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
// Case 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
var p1 = new EMEPromise;
var case3token = token + "_case3";
- var v3 = SetupEME(test, case3token);
+ let v3 = document.createElement("video");
+
v3.addEventListener("loadeddata", function(ev) {
ok(true, TimeStamp(case3token) + " should reach loadeddata");
var threw = false;
try {
var stream = v3.mozCaptureStreamUntilEnded();
} catch (e) {
threw = true;
}
ok(threw, TimeStamp(case3token) + " Should throw an error calling mozCaptureStreamUntilEnded an EME video.");
p1.resolve();
});
+
manager.started(case3token);
- var p2 = LoadTest(test, v3, case3token, { onlyLoadFirstFragments:2, noEndOfStream:false });
- EMEPromiseAll(v3, case3token, [p1.promise, p2]);
+ let p2 = SetupEME(v3, test, case3token, { noEndOfStream:false });
+
+ Promise.all([p1.promise, p2])
+ .catch(reason => ok(false, reason))
+ .then(() => {
+ CleanUpMedia(v3);
+ manager.finished(case3token);
+ });
}
function beginTest() {
manager.runTests(gEMETests, startTest);
}
if (!IsMacOSSnowLeopardOrEarlier()) {
SimpleTest.waitForExplicitFinish();