181 lines
6.6 KiB
HTML
181 lines
6.6 KiB
HTML
<html>
|
|
<head>
|
|
<title>WebMIDI Listener Test</title>
|
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
<script type="application/javascript" src="MIDITestUtils.js"></script>
|
|
</head>
|
|
|
|
<body onload="runTests()">
|
|
<iframe id="subdomain"></iframe>
|
|
<iframe id="localhost"></iframe>
|
|
<script class="testbody" type="application/javascript">
|
|
SimpleTest.waitForExplicitFinish();
|
|
const filePath = "/tests/dom/midi/tests/file_midi_permission_gated.html";
|
|
// Generally this runs on example.com but with --enable-xorigin-tests it runs
|
|
// on example.org.
|
|
let subdomainURL = "https://test1." + location.host + filePath;
|
|
$("subdomain").src = subdomainURL;
|
|
// For some reason the mochitest server returns "Bad request" with localhost,
|
|
// but permits the loopback address. That's good enough for testing purposes.
|
|
$("localhost").src = "http://127.0.0.1:8888" + filePath;
|
|
|
|
function waitForMessage() {
|
|
return new Promise((resolve) => {
|
|
window.addEventListener("message", (e) => resolve(e.data), {once: true});
|
|
});
|
|
}
|
|
|
|
async function runTests() {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["dom.webmidi.enabled", true],
|
|
["midi.testing", true],
|
|
],
|
|
});
|
|
ok(
|
|
await SpecialPowers.testPermission(
|
|
"midi-sysex",
|
|
SpecialPowers.Services.perms.UNKNOWN_ACTION,
|
|
document
|
|
),
|
|
"midi-sysex value should have UNKNOWN permission"
|
|
);
|
|
ok(
|
|
await SpecialPowers.testPermission(
|
|
"midi-sysex",
|
|
SpecialPowers.Services.perms.UNKNOWN_ACTION,
|
|
subdomainURL
|
|
),
|
|
"permission should also not be set for subdomain"
|
|
);
|
|
|
|
let onChangeCalled = 0;
|
|
let onChangeCalledWithSysex = 0;
|
|
// We expect the same states with and without sysex support.
|
|
const expectedChangedStates = ["denied", "granted", "prompt"];
|
|
|
|
const results = [];
|
|
for (let sysex of [false, true]) {
|
|
let result = await navigator.permissions.query({ name: "midi", sysex });
|
|
is(result?.state, "prompt", "expected 'prompt' permission status");
|
|
// Register two unique listeners that should be invoked every time we
|
|
// change permissions in the rest of this test case: one with sysex
|
|
// support, and the other one without.
|
|
if (sysex) {
|
|
result.onchange = () => {
|
|
is(
|
|
result.state,
|
|
expectedChangedStates[onChangeCalledWithSysex++],
|
|
"expected change event with sysex support"
|
|
);
|
|
};
|
|
results.push(result);
|
|
} else {
|
|
result.onchange = () => {
|
|
is(
|
|
result.state,
|
|
expectedChangedStates[onChangeCalled++],
|
|
"expected change event"
|
|
);
|
|
};
|
|
results.push(result);
|
|
}
|
|
}
|
|
|
|
// Explicitly set the permission as blocked, and expect the
|
|
// `requestMIDIAccess` call to be automatically rejected (not having any
|
|
// permission set would trigger the synthetic addon install provided by
|
|
// AddonManager and SitePermsAddonProvider).
|
|
await SpecialPowers.addPermission(
|
|
"midi-sysex",
|
|
SpecialPowers.Services.perms.DENY_ACTION,
|
|
document
|
|
);
|
|
await SpecialPowers.addPermission(
|
|
"midi",
|
|
SpecialPowers.Services.perms.DENY_ACTION,
|
|
document
|
|
);
|
|
for (let sysex of [false, true]) {
|
|
try {
|
|
await navigator.requestMIDIAccess({ sysex });
|
|
ok(false, "MIDI Access Request gate allowed but expected to be denied");
|
|
} catch (ex) {
|
|
ok(true, "MIDI Access Request denied by default");
|
|
}
|
|
|
|
let result = await navigator.permissions.query({ name: "midi", sysex });
|
|
// We expect "denied" because that's what has been set above (with
|
|
// `SpecialPowers.addPermission()`). In practice, this state should
|
|
// never be returned since explicit rejection is handled at the add-on
|
|
// installation level.
|
|
is(result?.state, "denied", "expected 'denied' permission status");
|
|
}
|
|
|
|
// Gated permission should prompt for localhost.
|
|
//
|
|
// Note: We don't appear to have good test machinery anymore for
|
|
// navigating prompts from a plain mochitest. If you uncomment the lines
|
|
// below and run the test interactively, it should pass. Given that this
|
|
// is a niche feature that's unlikely to break, it doesn't seem worth
|
|
// investing in complicated test infrastructure to check it in automation.
|
|
// for (let sysex of [false, true]) {
|
|
// $("localhost").contentWindow.postMessage(sysex, "*");
|
|
// let response = await waitForMessage();
|
|
// is(response, "succeeded", "MIDI Access Request allowed for localhost");
|
|
// }
|
|
|
|
// When an addon is installed, the permission is inserted. Test
|
|
// that the request succeeds after we insert the permission.
|
|
await SpecialPowers.addPermission(
|
|
"midi-sysex",
|
|
SpecialPowers.Services.perms.ALLOW_ACTION,
|
|
document
|
|
);
|
|
await SpecialPowers.addPermission(
|
|
"midi",
|
|
SpecialPowers.Services.perms.ALLOW_ACTION,
|
|
document
|
|
);
|
|
// Gated permission should allow access after addon inserted permission.
|
|
for (let sysex of [false, true]) {
|
|
try {
|
|
await navigator.requestMIDIAccess({ sysex });
|
|
ok(true, "MIDI Access Request allowed");
|
|
} catch (ex) {
|
|
ok(false, "MIDI Access Request failed");
|
|
}
|
|
|
|
let result = await navigator.permissions.query({ name: "midi", sysex });
|
|
is(result?.state, "granted", "expected 'granted' permission status");
|
|
}
|
|
|
|
// Gated permission should also apply to subdomains.
|
|
for (let sysex of [false, true]) {
|
|
$("subdomain").contentWindow.postMessage(sysex, "*");
|
|
let response = await waitForMessage();
|
|
is(response, "succeeded", "MIDI Access Request allowed for subdomain");
|
|
}
|
|
|
|
is(
|
|
onChangeCalled,
|
|
expectedChangedStates.length - 1,
|
|
`expected onchange listener to have been called ${expectedChangedStates.length - 1} times`
|
|
);
|
|
is(
|
|
onChangeCalledWithSysex,
|
|
expectedChangedStates.length - 1,
|
|
`expected onchange listener to have been called ${expectedChangedStates.length - 1} times (sysex)`
|
|
);
|
|
|
|
// Remove the permission.
|
|
await SpecialPowers.removePermission("midi-sysex", document);
|
|
await SpecialPowers.removePermission("midi", document);
|
|
|
|
results.forEach(result => result.onchange = null);
|
|
|
|
SimpleTest.finish();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|