Source code

Revision control

Other Tools

Test Info: Warnings

  • This test gets skipped with pattern: (os == "win" && processor == "aarch64") os == 'win' && os_version == '10.0' && webrender os == 'android'
<!DOCTYPE HTML>
<html>
<!--
-->
<head>
<title>Test for MediaRecorder Reaction to Principal Change</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<div>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1018299">Test for MediaRecorder Principal Handling</a>
</div>
<pre id="test">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
let throwOutside = e => setTimeout(() => { throw e; });
// Loading data from a resource that changes origins while streaming should
// be detected by the media cache and result in a null principal so that the
// MediaRecorder usages below fail.
// This test relies on midflight-redirect.sjs returning the the first quarter of
// the resource as a byte range response, and then hanging up, and when Firefox
// requests the remainder midflight-redirect.sjs serves a redirect to another origin.
async function testPrincipals(resource) {
if (!resource) {
todo(false, "No types supported");
return;
}
await testPrincipals1(resource);
await testPrincipals2(resource);
}
function makeVideo() {
let video = document.createElement("video");
video.preload = "metadata";
video.controls = true;
document.body.appendChild(video);
return video;
}
// First test: Load file from same-origin first, then get redirected to
// another origin before attempting to record stream.
async function testPrincipals1(resource) {
let video = makeVideo();
video.src =
"?resource=" + resource.name + "&type=" + resource.type;
let errorBarrier = once(video, "error");
// Wait for the video to load to metadata. We can then start capturing.
// Must also handle the download bursting and hitting the error before we
// reach loadedmetadata. Normally we reach loadedmetadata first, but
// rarely we hit the redirect first.
await Promise.race([once(video, "loadedmetadata"), errorBarrier]);
let rec = new MediaRecorder(video.mozCaptureStreamUntilEnded());
video.play();
// Wait until we hit a playback error. This means our download has hit the redirect.
await errorBarrier;
// Try to record, it should be blocked with a security error.
try {
rec.start();
ok(false, "mediaRecorder.start() must throw SecurityError, but didn't throw at all");
} catch (ex) {
is(ex.name, "SecurityError", "mediaRecorder.start() must throw SecurityError");
}
removeNodeAndSource(video);
}
// Second test: Load file from same-origin first, but record ASAP, before
// getting redirected to another origin.
async function testPrincipals2(resource) {
let video = makeVideo();
video.src =
"?resource=" + resource.name + "&type=" + resource.type;
// Wait for the video to load to metadata. We can then start capturing.
// Must also handle the download bursting and hitting the error before we
// reach loadedmetadata. Normally we reach loadedmetadata first, but
// rarely we hit the redirect first.
await Promise.race([once(video, "loadedmetadata"), once(video, "error")]);
let ended = false;
once(video, "ended", () => ended = true);
// Start capturing. It should work.
let rec;
let errorBarrier;
try {
rec = new MediaRecorder(video.mozCaptureStreamUntilEnded());
errorBarrier = nextEvent(rec, "error");
rec.start();
ok(true, "mediaRecorder.start() should not throw here, and didn't");
} catch (ex) {
ok(false, "mediaRecorder.start() unexpectedly threw " + ex.name + " (" + ex.message + ")");
}
// Play the video, this should result in a SecurityError on the recorder.
let hasStopped = once(rec, "stop");
video.play();
let error = (await errorBarrier).error;
is(error.name, "SecurityError", "mediaRecorder.onerror must fire SecurityError");
ok(error.stack.includes('test_mediarecorder_principals.html'),
'Events fired from onerror should include an error with a stack trace indicating ' +
'an error in this test');
is(ended, false, "Playback should not have reached end");
await hasStopped;
is(ended, false, "Playback should definitely not have reached end");
removeNodeAndSource(video);
}
testPrincipals({ name:"pixel_aspect_ratio.mp4", type:"video/mp4", duration:28 })
.catch(e => throwOutside(e))
.then(() => SimpleTest.finish());
</script>
</pre>
</body>
</html>