tor-browser

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

setSinkId-manual.https.html (6724B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <title>Test setSinkId behavior with permissions / device changes</title>
      5 <link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
      6 <link rel="help" href="https://www.w3.org/TR/audio-output/#dom-htmlmediaelement-setsinkid">
      7 <meta name="timeout" content="long">
      8 
      9 </head>
     10 <body>
     11 <h1 class="instructions">Description</h1>
     12 <p class="instructions">This test checks that <code>setSinkId</code> follows the algorithm, this includes manually checking the proper rendering on new output devices.</p>
     13 <p class="instructions">When prompted to access microphones, please accept as this is the only current way to get permissions for associated output devices.</p>
     14 <p class="instructions">For each authorized output device, check that selecting it makes the audio beat rendered on the corresponding device.</p>
     15 <p>Available but unauthorized devices (only those for which we can gain permission can be selected):</p>
     16 <ul id="available"></ul>
     17 <p>Authorized  devices:</p>
     18 <ul id="authorized"></ul>
     19 <audio controls id="beat" src="/media/sound_5.mp3" loop></audio>
     20 
     21 <div id='log'></div>
     22 <script src=/resources/testharness.js></script>
     23 <script src=/resources/testharnessreport.js></script>
     24 <script>
     25 "use strict";
     26 
     27 const is_output = d => d.kind === "audiooutput";
     28 const by_id = (id) => d => d.groupId === id;
     29 const is_input = d => d.kind === "audioinput";
     30 const audio = document.getElementById("beat");
     31 const available = document.getElementById("available");
     32 const authorized = document.getElementById("authorized");
     33 
     34 let outputList;
     35 
     36 const selectDeviceTester = (t) => (e) => {
     37    const groupId = e.target.dataset["groupid"];
     38    const device = outputList.find(by_id(groupId));
     39    if (audio.paused) audio.play();
     40    promise_test(pt => audio.setSinkId(device.deviceId).then(() => {
     41        assert_equals(device.deviceId, audio.sinkId);
     42 
     43        const pass = document.createElement("button");
     44        const fail = document.createElement("button");
     45 
     46        const result = (bool) => () => {
     47            assert_true(bool, "Sound rendered on right device");
     48            fail.remove();
     49            pass.remove();
     50            audio.pause();
     51            e.target.checked = false;
     52            e.target.disabled = true;
     53            t.done();
     54        };
     55 
     56        pass.style.backgroundColor = "#0f0";
     57        pass.textContent = "\u2713 Sound plays on " + device.label;
     58        pass.addEventListener("click", result(true));
     59 
     60        fail.style.backgroundColor = "#f00";
     61        fail.textContent = "\u274C Sound doesn't play on " + device.label;
     62        fail.addEventListener("click", result(true));
     63 
     64        const container = e.target.parentNode.parentNode;
     65        container.appendChild(pass);
     66        container.appendChild(fail);
     67    }), "setSinkId for " + device.label + " resolves");
     68 };
     69 
     70 const addAuthorizedDevice = (groupId) => {
     71    const device = outputList.find(by_id(groupId));
     72    const async_t = async_test("Selecting output device " + device.label + " makes the audio rendered on the proper device");
     73    const li = document.createElement("li");
     74    const label = document.createElement("label");
     75    const input = document.createElement("input");
     76    input.type = "radio";
     77    input.name = "device";
     78    input.dataset["groupid"] = device.groupId;
     79    input.addEventListener("change", selectDeviceTester(async_t));
     80    const span = document.createElement("span");
     81    span.textContent = device.label;
     82    label.appendChild(input);
     83    label.appendChild(span);
     84    li.appendChild(label);
     85    authorized.appendChild(li);
     86 };
     87 
     88 const authorizeDeviceTester = (t) => (e) => {
     89    const groupId = e.target.dataset["groupid"];
     90    navigator.mediaDevices.getUserMedia({audio: {groupId}})
     91        .then( () => {
     92            addAuthorizedDevice(groupId);
     93            t.done();
     94        });
     95 };
     96 
     97 promise_test(gum =>
     98             navigator.mediaDevices.getUserMedia({audio: true}).then(
     99                 () => {
    100                     promise_test(t =>
    101                                  navigator.mediaDevices.enumerateDevices().then(list => {
    102                                      assert_not_equals(list.find(is_output), undefined, "media device list includes at least one audio output device");
    103                                      outputList = list.filter(is_output);
    104                                      outputList.forEach(d => {
    105                                          const li = document.createElement("li");
    106                                          assert_not_equals(d.label, "", "Audio Output Device Labels are available after permission grant");
    107                                          li.textContent = d.label;
    108                                          // Check permission
    109                                          promise_test(perm => navigator.permissions.query({name: "speaker", deviceId: d.deviceId}).then(({state}) => {
    110                                              if (state === "granted") {
    111                                                  addAuthorizedDevice(d.groupId);
    112                                              } else if (state === "prompt") {
    113                                                  const inp = list.find(inp => inp.kind === "audioinput" && inp.groupId === d.groupId);
    114                                                  if (inp || true) {
    115                                                      const async_t = async_test("Authorizing output devices via permission requests for microphones works");
    116                                                      const button = document.createElement("button");
    117                                                      button.textContent = "Authorize access";
    118                                                      button.dataset["groupid"] = d.groupId;
    119                                                      button.addEventListener("click", async_t.step_func_done(authorizeDeviceTester(async_t)));
    120                                                      li.appendChild(button);
    121                                                  }
    122                                                  available.appendChild(li);
    123                                              }
    124                                          }, () => {
    125                                                           // if we can't query the permission, we assume it's granted :/
    126                                                           addAuthorizedDevice(d.groupId);
    127                                                       })
    128                                                       , "Query permission to use " + d.label);
    129                                      });
    130                                  }), "List media devices");
    131                 }), "Authorize mike access");
    132 </script>