Bug 1443942 - Switch over to midflight redirect for all redirect media tests. r?jya
We have two SJS files; midflight-redirect.sjs and dynamic_redirect.sjs,
which are very similar, but dynamic_redirect.sjs is buggy, so we should
just use midflight-redirect.sjs.
dynamic_redirect.sjs is buggy because it relies on the client doing multiple
HTTP requests to it in order to redirect, but we can't actually guarantee
this. Previously users of it would try things like setting a small MediaCache
size, or only using Ogg for which we expect a seek to the end to calculate
the duration, but I have observed the entire resource being downloaded in
one hit before the media element has finished loading metadata, meaning the
seek (in the Ogg case) can happen without another HTTP request. This is even
with a small MediaCache.
midfligh-redirect.sjs solves this problem by explicitly only returning a
partial response, so the client is forced to make another HTTP request,
which we will serve a redirect to.
MozReview-Commit-ID: 39imyayhnBG
deleted file mode 100644
--- a/dom/media/test/dynamic_redirect.sjs
+++ /dev/null
@@ -1,69 +0,0 @@
-function parseQuery(query, key) {
- for (let p of query.split('&')) {
- if (p == key) {
- return true;
- }
- if (p.startsWith(key + "=")) {
- return p.substring(key.length + 1);
- }
- }
-}
-
-// Return seek.ogv file content for the first request with a given key.
-// All subsequent requests return a redirect to a different-origin resource.
-function handleRequest(request, response)
-{
- var query = request.queryString;
- var key = parseQuery(query, "key");
- var type = parseQuery(query, "type") || "application/octet-stream";
- var resource = parseQuery(query, "res");
- var nested = parseQuery(query, "nested") || false;
-
- dump("Received request for key = "+ key +"\n");
- if (!nested) {
- if (getState(key) == "redirect") {
- var origin = request.host == "mochi.test" ? "example.org" : "mochi.test:8888";
- response.setStatusLine(request.httpVersion, 303, "See Other");
- let url = "http://" + origin +
- "/tests/dom/media/test/dynamic_redirect.sjs?nested&" + query;
- dump("Redirecting to "+ url + "\n");
- response.setHeader("Location", url);
- response.setHeader("Content-Type", "text/html");
- return;
- }
- setState(key, "redirect");
- }
- var file = Components.classes["@mozilla.org/file/directory_service;1"].
- getService(Components.interfaces.nsIProperties).
- get("CurWorkD", Components.interfaces.nsIFile);
- var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
- createInstance(Components.interfaces.nsIFileInputStream);
- var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
- createInstance(Components.interfaces.nsIBinaryInputStream);
- var paths = "tests/dom/media/test/" + resource;
- var split = paths.split("/");
- for (var i = 0; i < split.length; ++i) {
- file.append(split[i]);
- }
- fis.init(file, -1, -1, false);
-
- bis.setInputStream(fis);
- var bytes = bis.readBytes(bis.available());
- let [from, to] = request.getHeader("range").split("=")[1].split("-").map(s => parseInt(s));
- to = to || Math.max(from, bytes.length - 1);
- byterange = bytes.substring(from, to + 1);
-
- let contentRange = "bytes "+ from +"-"+ to +"/"+ bytes.length;
- let contentLength = (to - from + 1).toString();
- dump("Response Content-Range = "+ contentRange +"\n");
- dump("Response Content-Length = "+ contentLength +"\n");
-
- response.setStatusLine(request.httpVersion, 206, "Partial Content");
- response.setHeader("Content-Range", contentRange);
- response.setHeader("Content-Length", contentLength, false);
- response.setHeader("Content-Type", type, false);
- response.setHeader("Accept-Ranges", "bytes", false);
- response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
- response.write(byterange, byterange.length);
- bis.close();
-}
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -429,17 +429,16 @@ support-files =
detodos-short.webm
detodos-short.webm^headers^
detodos-recorder-test.opus
detodos-recorder-test.opus^headers^
detodos-short.opus
detodos-short.opus^headers^
dirac.ogg
dirac.ogg^headers^
- dynamic_redirect.sjs
dynamic_resource.sjs
eme.js
file_access_controls.html
file_autoplay_policy_unmute_pauses.html
file_autoplay_policy_activation_window.html
file_autoplay_policy_activation_frame.html
flac-s24.flac
flac-s24.flac^headers^
--- a/dom/media/test/test_mediarecorder_principals.html
+++ b/dom/media/test/test_mediarecorder_principals.html
@@ -41,18 +41,18 @@ function testPrincipals(resource) {
if (!resource) {
todo(false, "No types supported");
return;
}
// First test: Load file from same-origin first, then get redirected to
// another origin before attempting to record stream.
let video = document.getElementById("v1");
video.src =
- "http://mochi.test:8888/tests/dom/media/test/dynamic_redirect.sjs?key=v1_" +
- key + "&res=" + resource.name + "&type=" + resource.type;
+ "http://mochi.test:8888/tests/dom/media/test/midflight-redirect.sjs?key=v1_" +
+ key + "&resource=" + resource.name + "&type=" + resource.type;
return new Promise(resolve => video.onloadedmetadata = resolve).then(() => {
video.load();
video.play();
interval = setInterval(() => info("video.currentTime = "+ video.currentTime), 1000);
let msg = "mediaRecorder.start() must throw SecurityError";
return new Promise(resolve => video.onplaying = resolve)
.then(() => waitUntil(() => video.currentTime > resource.duration / 5))
@@ -62,18 +62,18 @@ function testPrincipals(resource) {
.then(() => ok(false, msg), e => is(e.name, "SecurityError", msg)), 0)
.then(() => clearInterval(interval));
})
.then(() => {
// Second test: Load file from same-origin first, but record ASAP, before
// getting redirected to another origin.
let video = document.getElementById("v2");
video.src =
- "http://mochi.test:8888/tests/dom/media/test/dynamic_redirect.sjs?key=v2_" +
- key + "&res=" + resource.name + "&type=" + resource.type;
+ "http://mochi.test:8888/tests/dom/media/test/midflight-redirect.sjs?key=v2_" +
+ key + "&resource=" + resource.name + "&type=" + resource.type;
let rec, hasStopped, hasEnded = new Promise(r => video.onended = r);
let data = [];
let msgNoThrow = "mediaRecorder.start() should not throw here";
let msgSecErr = "mediaRecorder.onerror must fire SecurityError";
let msgOnStop = "mediaRecorder.onstop must also have fired";
return new Promise(resolve => video.onloadedmetadata = resolve).then(() => {
rec = new MediaRecorder(video.mozCaptureStreamUntilEnded());
--- a/dom/media/test/test_mixed_principals.html
+++ b/dom/media/test/test_mixed_principals.html
@@ -42,18 +42,18 @@ https://bugzilla.mozilla.org/show_bug.cg
function runTest(origin, shouldReadBackOnLoad) {
return new Promise(function (resolve, reject) {
// Load will redirect mid-flight, which will be detected and should error,
// and we should no longer be able to readback.
var noise = Math.floor(Math.random() * 100000000);
var video = document.createElement("video");
video.preload = "metadata";
video.controls = true;
- var url = "http://" + origin + "/tests/dom/media/test/dynamic_redirect.sjs?key="
- + noise + "&res=pixel_aspect_ratio.mp4"
+ var url = "http://" + origin + "/tests/dom/media/test/midflight-redirect.sjs?key="
+ + noise + "&resource=pixel_aspect_ratio.mp4"
+ "&type=video/mp4";
SimpleTest.info("Loading from " + url);
video.src = url;
document.body.appendChild(video);
once(video, "loadeddata", () => {
is(canReadBack(video), shouldReadBackOnLoad, "Should be able to readback");
video.play();