Bug 1371741 - Test getUserMedia in sandboxed srcdoc, blob, data and regular iframes.
MozReview-Commit-ID: GUtY5bJy192
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -4,16 +4,18 @@ subsuite = media
support-files =
head.js
dataChannel.js
mediaStreamPlayback.js
network.js
nonTrickleIce.js
pc.js
templates.js
+ test_enumerateDevices_iframe.html
+ test_getUserMedia_permission_iframe.html
NetworkPreparationChromeScript.js
blacksilence.js
turnConfig.js
sdpUtils.js
addTurnsSelfsignedCert.js
!/dom/canvas/test/captureStream_common.js
!/dom/canvas/test/webgl-mochitest/webgl-util.js
!/dom/media/test/manifest.js
@@ -34,18 +36,16 @@ skip-if = android_version == '18' # andr
skip-if = toolkit == 'android' # Bug 1189784
[test_dataChannel_basicDataOnly.html]
[test_dataChannel_basicVideo.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_dataChannel_bug1013809.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_dataChannel_noOffer.html]
[test_enumerateDevices.html]
-[test_enumerateDevices_iframe.html]
-skip-if = true # needed by test_enumerateDevices.html on builders
[test_ondevicechange.html]
skip-if = os == 'android'
[test_getUserMedia_active_autoplay.html]
[test_getUserMedia_audioCapture.html]
skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator), android(Bug 1264333)
[test_getUserMedia_addTrackRemoveTrack.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_getUserMedia_addtrack_removetrack_events.html]
@@ -69,16 +69,17 @@ skip-if = toolkit == 'android' # no wind
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_getUserMedia_mediaElementCapture_tracks.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_getUserMedia_mediaElementCapture_video.html]
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
[test_getUserMedia_mediaStreamClone.html]
[test_getUserMedia_mediaStreamConstructors.html]
[test_getUserMedia_mediaStreamTrackClone.html]
+[test_getUserMedia_permission.html]
[test_getUserMedia_playAudioTwice.html]
[test_getUserMedia_playVideoAudioTwice.html]
[test_getUserMedia_playVideoTwice.html]
[test_getUserMedia_scarySources.html]
skip-if = toolkit == 'android' # no screenshare or windowshare on android
[test_getUserMedia_spinEventLoop.html]
[test_getUserMedia_stopAudioStream.html]
[test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_permission.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script src="mediaStreamPlayback.js"></script>
+</head>
+<body>
+<pre id="test">
+<iframe id="iframeSrcdoc" srcdoc="
+ <script type='application/javascript'>
+ var gUM = c => navigator.mediaDevices.getUserMedia(c);
+ (async () => {
+ let message;
+ try {
+ let stream = await gUM({ video: true });
+ message = 'success';
+ } catch(e) {
+ message = e.name;
+ }
+ parent.postMessage(message, 'http://mochi.test:8888');
+ })().catch(e => setTimeout(() => { throw e; }));
+ </script>">
+</iframe>
+<script type="application/javascript">
+createHTML({ title: "Test getUserMedia in iframes", bug: "1371741" });
+/**
+ Tests covering enumerateDevices API and deviceId constraint. Exercise code.
+*/
+
+let once = (t, msg) => new Promise(r => t.addEventListener(msg, r, { once: true }));
+
+// Call gUM in iframe.
+
+async function iframeGum(dict, iframe = document.createElement("iframe")) {
+ Object.assign(iframe, dict);
+ if (dict.src) {
+ info(`<iframe src="${dict.src}" sandbox="${dict.sandbox}">`);
+ } else {
+ info(`<iframe srcdoc sandbox="${dict.sandbox}">`);
+ }
+ document.documentElement.appendChild(iframe);
+
+ let haveMessage = once(window, "message");
+ await new Promise(resolve => iframe.onload = resolve);
+ return (await haveMessage).data;
+};
+
+runTest(async () => {
+ const path = "/tests/dom/media/tests/mochitest/test_getUserMedia_permission_iframe.html";
+
+ // Test gUM in sandboxed vs. regular iframe.
+
+ for (origin of ["http://mochi.test:8888", "http://test1.mochi.test:8888"]) {
+ let src = origin + path;
+ is(await iframeGum({ src, sandbox: "allow-scripts" }),
+ "SecurityError", "gUM fails in sandboxed iframe " + origin);
+ is(await iframeGum({ src, sandbox: "allow-scripts allow-same-origin " + origin }),
+ "success", "gUM works in regular iframe");
+ }
+
+ // Test gUM in sandboxed vs regular srcdoc iframe
+
+ is(await iframeGum({ sandbox: "allow-scripts" }, iframeSrcdoc),
+ "SecurityError", "gUM fails in sandboxed srcdoc iframe");
+ is(await iframeGum({ sandbox: "allow-scripts allow-same-origin" }, iframeSrcdoc),
+ "success", "gUM works in regular srcdoc iframe");
+
+ // Test gUM in sandboxed vs regular blob iframe
+
+ var blob = new Blob([iframeSrcdoc.srcdoc], {type : 'text/html'});
+ let src = URL.createObjectURL(blob);
+ is(await iframeGum({ src, sandbox: "allow-scripts" }),
+ "SecurityError", "gUM fails in sandboxed blob iframe");
+ is(await iframeGum({ src, sandbox: "allow-scripts allow-same-origin " + origin }),
+ "success", "gUM works in regular blob iframe");
+ URL.revokeObjectURL(src);
+
+ // Test gUM in sandboxed vs regular data iframe
+
+ src = `data:text/html;base64,ICA8c2NyaXB0IHR5cGU9J2FwcGxpY2F0aW9uL2phdmFzY3JpcHQnPg0KICB2YXIgZ1VNID0gYyA9PiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjKTsNCiAgKGFzeW5jICgpID0+IHsNCiAgICBsZXQgbWVzc2FnZTsNCiAgICB0cnkgew0KICAgICAgbGV0IHN0cmVhbSA9IGF3YWl0IGdVTSh7IHZpZGVvOiB0cnVlIH0pOw0KICAgICAgbWVzc2FnZSA9ICdzdWNjZXNzJzsNCiAgICB9IGNhdGNoKGUpIHsNCiAgICAgIG1lc3NhZ2UgPSBlLm5hbWU7DQogICAgfQ0KICAgIHBhcmVudC5wb3N0TWVzc2FnZShtZXNzYWdlLCAnaHR0cDovL21vY2hpLnRlc3Q6ODg4OCcpOw0KICB9KSgpLmNhdGNoKGUgPT4gc2V0VGltZW91dCgoKSA9PiB7IHRocm93IGU7IH0pKTsNCiAgPC9zY3JpcHQ+Ij4NCg==`;
+ is(await iframeGum({ src, sandbox: "allow-scripts" }),
+ "SecurityError", "gUM fails in sandboxed data iframe");
+ is(await iframeGum({ src, sandbox: "allow-scripts allow-same-origin " + origin }),
+ "success", "gUM works in regular data iframe");
+});
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_permission_iframe.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<pre id="test">
+<script type="application/javascript">
+/**
+ Runs inside iframe in test_getUserMedia_permission.html.
+*/
+
+var gUM = c => navigator.mediaDevices.getUserMedia(c);
+
+(async () => {
+ let message;
+ try {
+ let stream = await gUM({ video: true });
+ message = "success";
+ } catch(e) {
+ message = e.name;
+ }
+ parent.postMessage(message, "http://mochi.test:8888");
+})().catch(e => setTimeout(() => { throw e; }));
+</script>
+</pre>
+</body>
+</html>