DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
<!DOCTYPE HTML>
<html>
<head>
  <script src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "Run enumerateDevices code", bug: "1046245" });
/**
  Tests covering enumerateDevices API and deviceId constraint. Exercise code.
*/

async function mustSucceed(msg, f) {
  try {
    await f();
    ok(true, msg + " must succeed");
  } catch (e) {
    is(e.name, null, msg + " must succeed: " + e.message);
  }
}

async function mustFailWith(msg, reason, constraint, f) {
  try {
    await f();
    ok(false, msg + " must fail");
  } catch(e) {
    is(e.name, reason, msg + " must fail: " + e.message);
    if (constraint) {
      is(e.constraint, constraint, msg + " must fail w/correct constraint.");
    }
  }
}

var gUM = c => navigator.mediaDevices.getUserMedia(c);

var validateDevice = ({kind, label, deviceId, groupId}) => {
  ok(kind == "videoinput" || kind == "audioinput", "Known device kind");
  is(deviceId.length, 44, "deviceId length id as expected for Firefox");
  ok(label.length !== undefined, "Device label: " + label);
  isnot(groupId, "", "groupId must be present.");
}

runTest(async () => {
  await pushPrefs(["media.navigator.streams.fake", true]);

  // Validate enumerated devices.

  let devices = await navigator.mediaDevices.enumerateDevices();
  ok(devices.length > 0, "At least one device found");
  let jsoned = JSON.parse(JSON.stringify(devices));
  is(jsoned[0].kind, devices[0].kind, "kind survived serializer");
  is(jsoned[0].deviceId, devices[0].deviceId, "deviceId survived serializer");
  for (let device of devices) {
    validateDevice(device);
    // Test deviceId constraint
    let deviceId = device.deviceId;
    let constraints = (device.kind == "videoinput") ? { video: { deviceId } }
                                                    : { audio: { deviceId } };
    for (let track of (await gUM(constraints)).getTracks()) {
      is(typeof(track.label), "string", "Track label is a string");
      is(track.label, device.label, "Track label is the device label");
      track.stop();
    }
  }

  const unknownId = "unknown9qHr8B0JIbcHlbl9xR+jMbZZ8WyoPfpCXPfc=";

  // Check deviceId failure paths for video.

  await mustSucceed("unknown plain deviceId on video",
                    () => gUM({ video: { deviceId: unknownId } }));
  await mustSucceed("unknown plain deviceId on audio",
                    () => gUM({ audio: { deviceId: unknownId } }));
  await mustFailWith("unknown exact deviceId on video",
                     "OverconstrainedError", "deviceId",
                     () => gUM({ video: { deviceId: { exact: unknownId } } }));
  await mustFailWith("unknown exact deviceId on audio",
                     "OverconstrainedError", "deviceId",
                     () => gUM({ audio: { deviceId: { exact: unknownId } } }));

  // Check that deviceIds are stable for same origin and differ across origins.

  const path = "/tests/dom/media/tests/mochitest/test_enumerateDevices_iframe.html";
  const origins = ["https://example.com", "https://test1.example.com"];
  info(window.location);

  let haveDevicesMap = new Promise(resolve => {
    let map = new Map();
    window.addEventListener("message", ({origin, data}) => {
      ok(origins.includes(origin), "Got message from expected origin");
      map.set(origin, JSON.parse(data));
      if (map.size < origins.length) return;
      resolve(map);
    });
  });

  await Promise.all(origins.map(origin => {
    let iframe = document.createElement("iframe");
    iframe.src = origin + path;
    info(iframe.src);
    document.documentElement.appendChild(iframe);
    return new Promise(resolve => iframe.onload = resolve);
  }));
  let devicesMap = await haveDevicesMap;
  let [sameOriginDevices, differentOriginDevices] = origins.map(o => devicesMap.get(o));

  is(sameOriginDevices.length, devices.length);
  is(differentOriginDevices.length, devices.length);
  [...sameOriginDevices, ...differentOriginDevices].forEach(d => validateDevice(d));

  for (let device of sameOriginDevices) {
    ok(devices.find(d => d.deviceId == device.deviceId),
       "Same origin deviceId for " + device.label + " must match");
  }
  for (let device of differentOriginDevices) {
    ok(!devices.find(d => d.deviceId == device.deviceId),
         "Different origin deviceId for " + device.label + " must be different");
  }

  // Check the special case of no devices found.
  await pushPrefs(["media.navigator.streams.fake", false],
                  ["media.audio_loopback_dev", "none"],
                  ["media.video_loopback_dev", "none"]);
  devices = await navigator.mediaDevices.enumerateDevices();
  ok(devices.length === 0, "No devices found");
});
</script>
</pre>
</body>
</html>