tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaDevices-enumerateDevices-per-origin-ids.sub.https.html (4671B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <title>enumerateDevices rotates deviceId across origins and after cookies get cleared</title>
      5 <script src=/resources/testharness.js></script>
      6 <script src=/resources/testharnessreport.js></script>
      7 <script src=/resources/testdriver.js></script>
      8 <script src=/resources/testdriver-vendor.js></script>
      9 <script src=permission-helper.js></script>
     10 </head>
     11 <body>
     12  <iframe allow="camera 'src';microphone 'src';speaker-selection 'src'" id=same src="/mediacapture-streams/iframe-enumerate.html"></iframe>
     13 <iframe allow="camera 'src';microphone 'src';speaker-selection 'src'" id=cross src="https://{{hosts[][www1]}}:{{ports[https][0]}}/mediacapture-streams/iframe-enumerate.html"></iframe>
     14 <script>
     15 
     16  let deviceList;
     17 
     18  promise_test(async t => {
     19    await setMediaPermission();
     20    const stream = await navigator.mediaDevices.getUserMedia({audio : true, video: true});
     21    stream.getTracks().forEach(t => t.stop());
     22    deviceList = await navigator.mediaDevices.enumerateDevices();
     23    const msgWatcher = new EventWatcher(t, window, ['message']);
     24    frames[0].postMessage('run', '*')
     25    const e = await msgWatcher.wait_for('message');
     26    const iframeDevices = e.data.devices;
     27    assert_equals(deviceList.length, iframeDevices.length, "Same number of devices detected same-origin");
     28    for (const device of deviceList) {
     29      // Look for the same device in the iframe based on deviceId
     30      // "default" can be used across several kinds, so it needs an additional check
     31      // but we limit that check to "default" to detect re-use of deviceId across kinds
     32      const sameDevice = iframeDevices.find(d => d.deviceId === device.deviceId && (device.deviceId !== "default" || d.kind === device.kind));
     33      assert_true(!!sameDevice, "deviceIds stay the same when loaded in same origin");
     34      assert_equals(sameDevice.label, device.label, "labels matches when deviceId matches");
     35      assert_equals(sameDevice.kind, device.kind, "kind matches when deviceId matches");
     36      // The group identifier MUST be uniquely generated for each document.
     37      assert_not_equals(sameDevice.groupId, device.groupId, "groupId is specific to a document");
     38    }
     39    // setting a cookie as a way to detect if cookie clearing gets done
     40    document.cookie = "test=true";
     41    window.localStorage.touched = true;
     42  }, "enumerateDevices has stable deviceIds across same-origin iframe");
     43 
     44  promise_test(async t => {
     45    const msgWatcher = new EventWatcher(t, window, ['message']);
     46    frames[1].postMessage('run', '*')
     47    const e = await msgWatcher.wait_for('message');
     48    const iframeDevices = e.data.devices;
     49    assert_equals(deviceList.length, iframeDevices.length, "Same number of devices detected cross-origin");
     50    for (const device of deviceList) {
     51      // An identifier can be reused across origins as long as
     52      // it is not tied to the user and can be guessed by other means
     53      // In practice, "default" is what is used today, so we hardcode it
     54      // to be able to detect the general case of non-shared deviceIds
     55      if (device.deviceId !== "default") {
     56        const sameDevice = iframeDevices.find(d => d.deviceId === device.deviceId);
     57        assert_false(!!sameDevice, "deviceIds are not shared across origin");
     58      }
     59      assert_false(!!iframeDevices.find(d => d.groupId === device.groupId), "groupId is specific to a document");
     60    }
     61  }, "enumerateDevices rotates deviceId across different-origin iframe");
     62 
     63  promise_test(async t => {
     64    const iframe = document.createElement("iframe");
     65    iframe.setAttribute("allow", "camera 'src';microphone 'src'");
     66    iframe.src = "/mediacapture-streams/iframe-enumerate-cleared.html";
     67    document.body.appendChild(iframe);
     68    const loadWatcher = new EventWatcher(t, iframe, ['load']);
     69    await loadWatcher.wait_for('load');
     70    assert_implements_optional(document.cookie === "", "Clear-Site-Data not enabled, can't test clearing deviceId");
     71 
     72    const msgWatcher = new EventWatcher(t, window, ['message']);
     73    frames[2].postMessage('run', '*')
     74    const e = await msgWatcher.wait_for('message');
     75    const iframeDevices = e.data.devices;
     76    assert_equals(deviceList.length, iframeDevices.length, "Same number of devices detected after clearing cookies");
     77    for (const device of deviceList) {
     78      const sameDevice = iframeDevices.find(d => d.deviceId === device.deviceId);
     79      assert_false(!!sameDevice, "deviceIds are not kept after clearing site data");
     80      assert_false(!!iframeDevices.find(d => d.groupId === device.groupId), "groupId is specific to a document");
     81    }
     82 
     83  }, "enumerateDevices rotates deviceId after clearing site data");
     84 
     85 </script>
     86 </body>
     87 </html>