зеркало из https://github.com/mozilla/gecko-dev.git
120 строки
4.8 KiB
HTML
120 строки
4.8 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=489415
|
|
-->
|
|
<head>
|
|
<title>Test for MediaRecorder Reaction to Principal Change</title>
|
|
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
|
|
<script type="application/javascript" 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>
|
|
|
|
<video id="v1" preload="auto"></video>
|
|
<video id="v2" preload="auto"></video>
|
|
|
|
<pre id="test">
|
|
<script type="text/javascript">
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
var pushPrefs = (...p) => new Promise(r => SpecialPowers.pushPrefEnv({set: p}, r));
|
|
var throwOutside = e => setTimeout(() => { throw e; });
|
|
|
|
// Generate a random key. The first load with that key will return
|
|
// data, the second and subsequent loads with that key will return a redirect
|
|
// to a different origin ('localhost:8888' will be redirected to 'example.org',
|
|
// and 'example.org' will be redirected to 'localhost:8888'). We rely on the
|
|
// fact that Ogg will do a seek to the end of the resource, triggering a new
|
|
// load with the same key which will return a same-origin resource.
|
|
// Loading data from two different origins should be detected by the media
|
|
// cache and result in a null principal so that the MediaRecorder usages below
|
|
// fail.
|
|
let key = Math.floor(Math.random()*100000000);
|
|
let interval;
|
|
|
|
function testPrincipals(resource) {
|
|
if (!resource) {
|
|
todo(false, "No types supported");
|
|
return;
|
|
}
|
|
// Reduce cache size and cache-ahead to make HTMLMediaElement do partial requests.
|
|
return pushPrefs(['media.cache_readahead_limit', 2],
|
|
['media.cache_size', 192])
|
|
.then(() => {
|
|
// 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;
|
|
video.load();
|
|
// To limit readahead, avoid racing with playback and "catching up" mode.
|
|
return new Promise(resolve => video.oncanplaythrough = resolve).then(() => {
|
|
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 / 2))
|
|
// Test failure of the next step only, so "catch-bypass" any errors above.
|
|
.then(() => Promise.resolve()
|
|
.then(() => new MediaRecorder(video.mozCaptureStreamUntilEnded()).start())
|
|
.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;
|
|
video.load();
|
|
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());
|
|
rec.ondataavailable = e => data.push(e.data);
|
|
rec.start();
|
|
hasStopped = new Promise(resolve => rec.onstop = resolve);
|
|
video.play();
|
|
})
|
|
.then(() => ok(true, msgNoThrow), e => is(e.name, null, msgNoThrow))
|
|
.then(() => Promise.race([
|
|
new Promise((_, reject) => rec.onerror = e => reject(new DOMException("", e.name))),
|
|
hasEnded
|
|
]))
|
|
.then(() => ok(false, msgSecErr), e => is(e.name, "SecurityError", msgSecErr))
|
|
.then(() => Promise.race([hasStopped, hasEnded.then(() => Promise.reject())]))
|
|
.then(() => ok(true, msgOnStop), e => ok(false, msgOnStop))
|
|
.then(() => clearInterval(interval));
|
|
});
|
|
}
|
|
|
|
testPrincipals(getPlayableVideo(gSeekTests))
|
|
.catch(e => throwOutside(e))
|
|
.then(() => SimpleTest.finish())
|
|
.catch(e => throwOutside(e));
|
|
|
|
var stop = stream => stream.getTracks().forEach(track => track.stop());
|
|
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
var waitUntil = f => new Promise(resolve => {
|
|
var ival = setInterval(() => f() && resolve(clearInterval(ival)), 100);
|
|
});
|
|
|
|
</script>
|
|
</pre>
|
|
|
|
</body>
|
|
</html>
|