tor-browser

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

test_midi_permission_gated.html (6765B)


      1 <html>
      2  <head>
      3    <title>WebMIDI Listener Test</title>
      4    <script src="/tests/SimpleTest/SimpleTest.js"></script>
      5    <script type="application/javascript" src="MIDITestUtils.js"></script>
      6  </head>
      7 
      8  <body onload="runTests()">
      9    <iframe id="subdomain"></iframe>
     10    <iframe id="localhost"></iframe>
     11    <script class="testbody" type="application/javascript">
     12    SimpleTest.waitForExplicitFinish();
     13    const filePath = "/tests/dom/midi/tests/file_midi_permission_gated.html";
     14    // Generally this runs on example.com but with --enable-xorigin-tests it runs
     15    // on example.org.
     16    let subdomainURL = "https://test1." + location.host + filePath;
     17    $("subdomain").src = subdomainURL;
     18    // For some reason the mochitest server returns "Bad request" with localhost,
     19    // but permits the loopback address. That's good enough for testing purposes.
     20    $("localhost").src = "http://127.0.0.1:8888" + filePath;
     21 
     22    function waitForMessage() {
     23      return new Promise((resolve) => {
     24        window.addEventListener("message", (e) => resolve(e.data), {once: true});
     25      });
     26    }
     27 
     28    async function runTests() {
     29      await SpecialPowers.pushPrefEnv({
     30        set: [
     31          ["dom.webmidi.enabled", true],
     32          ["midi.testing", true],
     33        ],
     34      });
     35      ok(
     36        await SpecialPowers.testPermission(
     37          "midi-sysex",
     38          SpecialPowers.Services.perms.UNKNOWN_ACTION,
     39          document
     40        ),
     41        "midi-sysex value should have UNKNOWN permission"
     42      );
     43      ok(
     44        await SpecialPowers.testPermission(
     45          "midi-sysex",
     46          SpecialPowers.Services.perms.UNKNOWN_ACTION,
     47          subdomainURL
     48        ),
     49        "permission should also not be set for subdomain"
     50      );
     51 
     52      let onChangeCalled = 0;
     53      let onChangeCalledWithSysex = 0;
     54      // We expect the same states with and without sysex support.
     55      const expectedChangedStates = ["denied", "granted", "prompt"];
     56 
     57      const results = [];
     58      for (let sysex of [false, true]) {
     59        let result = await navigator.permissions.query({ name: "midi", sysex });
     60        is(result?.state, "prompt", "expected 'prompt' permission status");
     61        // Register two unique listeners that should be invoked every time we
     62        // change permissions in the rest of this test case: one with sysex
     63        // support, and the other one without.
     64        if (sysex) {
     65          result.onchange = () => {
     66            is(
     67              result.state,
     68              expectedChangedStates[onChangeCalledWithSysex++],
     69              "expected change event with sysex support"
     70            );
     71          };
     72          results.push(result);
     73        } else {
     74          result.onchange = () => {
     75            is(
     76              result.state,
     77              expectedChangedStates[onChangeCalled++],
     78              "expected change event"
     79            );
     80          };
     81          results.push(result);
     82        }
     83      }
     84 
     85      // Explicitly set the permission as blocked, and expect the
     86      // `requestMIDIAccess` call to be automatically rejected (not having any
     87      // permission set would trigger the synthetic addon install provided by
     88      // AddonManager and SitePermsAddonProvider).
     89      await SpecialPowers.addPermission(
     90        "midi-sysex",
     91        SpecialPowers.Services.perms.DENY_ACTION,
     92        document
     93      );
     94      await SpecialPowers.addPermission(
     95        "midi",
     96        SpecialPowers.Services.perms.DENY_ACTION,
     97        document
     98      );
     99      for (let sysex of [false, true]) {
    100        try {
    101          await navigator.requestMIDIAccess({ sysex });
    102          ok(false, "MIDI Access Request gate allowed but expected to be denied");
    103        } catch (ex) {
    104          ok(true, "MIDI Access Request denied by default");
    105        }
    106 
    107        let result = await navigator.permissions.query({ name: "midi", sysex });
    108        // We expect "denied" because that's what has been set above (with
    109        // `SpecialPowers.addPermission()`). In practice, this state should
    110        // never be returned since explicit rejection is handled at the add-on
    111        // installation level.
    112        is(result?.state, "denied", "expected 'denied' permission status");
    113      }
    114 
    115      // Gated permission should prompt for localhost.
    116      //
    117      // Note: We don't appear to have good test machinery anymore for
    118      // navigating prompts from a plain mochitest. If you uncomment the lines
    119      // below and run the test interactively, it should pass. Given that this
    120      // is a niche feature that's unlikely to break, it doesn't seem worth
    121      // investing in complicated test infrastructure to check it in automation.
    122      // for (let sysex of [false, true]) {
    123      //   $("localhost").contentWindow.postMessage(sysex, "*");
    124      //   let response = await waitForMessage();
    125      //   is(response, "succeeded", "MIDI Access Request allowed for localhost");
    126      // }
    127 
    128      // When an addon is installed, the permission is inserted.  Test
    129      // that the request succeeds after we insert the permission.
    130      await SpecialPowers.addPermission(
    131        "midi-sysex",
    132        SpecialPowers.Services.perms.ALLOW_ACTION,
    133        document
    134      );
    135      await SpecialPowers.addPermission(
    136        "midi",
    137        SpecialPowers.Services.perms.ALLOW_ACTION,
    138        document
    139      );
    140      // Gated permission should allow access after addon inserted permission.
    141      for (let sysex of [false, true]) {
    142        try {
    143          await navigator.requestMIDIAccess({ sysex });
    144          ok(true, "MIDI Access Request allowed");
    145        } catch (ex) {
    146          ok(false, "MIDI Access Request failed");
    147        }
    148 
    149        let result = await navigator.permissions.query({ name: "midi", sysex });
    150        is(result?.state, "granted", "expected 'granted' permission status");
    151      }
    152 
    153      // Gated permission should also apply to subdomains.
    154      for (let sysex of [false, true]) {
    155        $("subdomain").contentWindow.postMessage(sysex, "*");
    156        let response = await waitForMessage();
    157        is(response, "succeeded", "MIDI Access Request allowed for subdomain");
    158      }
    159 
    160      is(
    161        onChangeCalled,
    162        expectedChangedStates.length - 1,
    163        `expected onchange listener to have been called ${expectedChangedStates.length - 1} times`
    164      );
    165      is(
    166        onChangeCalledWithSysex,
    167        expectedChangedStates.length - 1,
    168        `expected onchange listener to have been called ${expectedChangedStates.length - 1} times (sysex)`
    169      );
    170 
    171      // Remove the permission.
    172      await SpecialPowers.removePermission("midi-sysex", document);
    173      await SpecialPowers.removePermission("midi", document);
    174 
    175      results.forEach(result => result.onchange = null);
    176 
    177      SimpleTest.finish();
    178    }
    179    </script>
    180  </body>
    181 </html>