summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html')
-rw-r--r--dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html112
1 files changed, 112 insertions, 0 deletions
diff --git a/dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html b/dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html
new file mode 100644
index 0000000000..7e9cd5a219
--- /dev/null
+++ b/dom/media/webrtc/tests/mochitests/test_fingerprinting_resistance.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="mediaStreamPlayback.js"></script>
+</head>
+<body>
+<script>
+/* global SimpleTest SpecialPowers */
+
+async function testEnumerateDevices(expectDevices) {
+ let devices = await navigator.mediaDevices.enumerateDevices();
+ if (!expectDevices) {
+ SimpleTest.is(devices.length, 0, "testEnumerateDevices: No devices");
+ return;
+ }
+ let cams = devices.filter((device) => device.kind == "videoinput");
+ let mics = devices.filter((device) => device.kind == "audioinput");
+ SimpleTest.ok((cams.length == 1) && (mics.length == 1),
+ "testEnumerateDevices: a microphone and a camera");
+}
+
+async function testGetUserMedia(expectDevices) {
+ const constraints = [
+ {audio: true},
+ {video: true},
+ {audio: true, video: true},
+ {video: {width: {min: 1e9}}}, // impossible
+ {audio: {channelCount: {exact: 1e3}}}, // impossible
+ ];
+ for (let constraint of constraints) {
+ let message = "getUserMedia(" + JSON.stringify(constraint) + ")";
+ try {
+ let stream = await navigator.mediaDevices.getUserMedia(constraint);
+ SimpleTest.ok(expectDevices, message + " resolved");
+ if (!expectDevices) {
+ continue;
+ }
+
+ // We only do testGetUserMedia(true) when privacy.resistFingerprinting
+ // is true, test if MediaStreamTrack.label is spoofed.
+ for (let track of stream.getTracks()) {
+ switch (track.kind) {
+ case "audio":
+ SimpleTest.is(track.label, "Internal Microphone", "AudioStreamTrack.label");
+ break;
+ case "video":
+ SimpleTest.is(track.label, "Internal Camera", "VideoStreamTrack.label");
+ break;
+ default:
+ SimpleTest.ok(false, "Unknown kind: " + track.kind);
+ break;
+ }
+ track.stop();
+ }
+ } catch (e) {
+ if (!expectDevices) {
+ SimpleTest.is(e.name, "NotAllowedError", message + " throws NotAllowedError");
+ } else {
+ SimpleTest.ok(false, message + " failed: " + e);
+ }
+ }
+ }
+}
+
+async function testDevices() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.resistFingerprinting", true],
+ ["media.navigator.streams.fake", true]
+ ]
+ });
+ await testEnumerateDevices(true); // should list a microphone and a camera
+ await testGetUserMedia(true); // should get audio and video streams
+}
+
+async function testNoDevices() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.resistFingerprinting", false],
+ ["media.navigator.permission.device", false],
+ ["media.navigator.streams.fake", false],
+ ["media.audio_loopback_dev", "foo"],
+ ["media.video_loopback_dev", "bar"]
+ ]
+ });
+ await testEnumerateDevices(false); // should list nothing
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["privacy.resistFingerprinting", true]
+ ]
+ });
+ await testEnumerateDevices(true); // should list a microphone and a camera
+ await testGetUserMedia(false); // should reject with NotAllowedError
+}
+
+createHTML({
+ title: "Neutralize the threat of fingerprinting of media devices API when 'privacy.resistFingerprinting' is true",
+ bug: "1372073"
+});
+
+runTest(async () => {
+ // Make sure enumerateDevices and getUserMedia work when
+ // privacy.resistFingerprinting is true.
+ await testDevices();
+
+ // Test that absence of devices can't be detected.
+ await testNoDevices();
+});
+</script>
+</body>
+</html>