tor-browser

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

MediaDevices-after-discard.https.html (2914B)


      1 <!doctype html>
      2 <title>Test promises from MediaDevices methods in a discarded browsing
      3  context</title>
      4 <script src=/resources/testharness.js></script>
      5 <script src=/resources/testharnessreport.js></script>
      6 <script src=/resources/testdriver.js></script>
      7 <script src=/resources/testdriver-vendor.js></script>
      8 <script src=permission-helper.js></script>
      9 <body></body>
     10 <script>
     11 let devices;
     12 let child_DOMException;
     13 setup(() => {
     14  const frame = document.createElement('iframe');
     15  document.body.appendChild(frame);
     16  devices = frame.contentWindow.navigator.mediaDevices;
     17  child_DOMException = frame.contentWindow.DOMException;
     18  frame.remove();
     19 });
     20 
     21 // https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia
     22 // If the current settings object's responsible document is NOT fully active,
     23 // return a promise rejected with a DOMException object whose name attribute
     24 // has the value "InvalidStateError".
     25 promise_test(async () => {
     26  await setMediaPermission("granted", ["microphone"]);
     27  // `catch()` is used rather than static Promise methods because microtasks
     28  // for `PromiseResolve()` do not run when Promises in inactive Documents are
     29  // involved.  Whether microtasks for `catch()` run depends on the realm of
     30  // the handler rather than the realm of the Promise.
     31  // See https://github.com/whatwg/html/issues/5319.
     32  let promise_already_rejected = false;
     33  let rejected_reason;
     34  devices.getUserMedia({audio:true}).catch(reason => {
     35    promise_already_rejected = true;
     36    rejected_reason = reason;
     37  });
     38  // Race a settled promise to check that the returned promise is already
     39  // rejected.
     40  await Promise.reject().catch(() => {
     41    assert_true(promise_already_rejected,
     42                'should have returned an already-rejected promise.');
     43    assert_throws_dom('InvalidStateError', child_DOMException,
     44                      () => { throw rejected_reason });
     45  });
     46 }, 'getUserMedia() in a discarded browsing context');
     47 
     48 // https://w3c.github.io/mediacapture-main/#dom-mediadevices-enumeratedevices
     49 // https://w3c.github.io/mediacapture-main/#device-enumeration-can-proceed
     50 // Device enumeration can proceed steps return false when device enumeration
     51 // can be exposed is true and the document is not fully active.
     52 promise_test(async () => {
     53  let promise_state = 'pending';
     54  // `then()` is used to avoid methods that apply `PromiseResolve()` to
     55  // Promises from inactive realms, which would lead to microtasks that don't
     56  // run.
     57  devices.enumerateDevices().then(() => promise_state = 'resolved',
     58                                  () => promise_state = 'rejected');
     59  // Enumerate in the parent document to provide enough time to check that the
     60  // Promise from the inactive document does not settle.
     61  await navigator.mediaDevices.enumerateDevices();
     62  assert_equals(promise_state, 'pending', 'Promise state');
     63 }, 'enumerateDevices() in a discarded browsing context');
     64 </script>