Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!--
Any copyright is dedicated to the Public Domain.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for Permissions API</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test"></pre>
<script type="application/javascript">
"use strict";
const {
UNKNOWN_ACTION,
PROMPT_ACTION,
ALLOW_ACTION,
DENY_ACTION,
} = SpecialPowers.Ci.nsIPermissionManager;
SimpleTest.waitForExplicitFinish();
const PERMISSIONS = [{
name: "geolocation",
type: "geo",
}, {
name: "notifications",
type: "desktop-notification",
}, {
name: "push",
type: "desktop-notification",
}, {
name: "persistent-storage",
type: "persistent-storage",
}, {
name: "midi",
type: "midi",
} ];
const UNSUPPORTED_PERMISSIONS = [
"foobarbaz", // Not in spec, for testing only.
];
// Create a closure, so that tests are run on the correct window object.
function createPermissionTester(aWindow) {
return {
setPermissions(allow) {
const permissions = PERMISSIONS.map(({ type }) => {
return {
type,
allow,
"context": aWindow.document,
};
});
return new Promise((resolve) => {
SpecialPowers.popPermissions(() => {
SpecialPowers.pushPermissions(permissions, resolve);
});
});
},
checkPermissions(state) {
const promisesToQuery = PERMISSIONS.map(({ name }) => {
return aWindow.navigator.permissions
.query({ name })
.then(
() => is(state, state, `correct state for '${name}'`),
() => ok(false, `query should not have rejected for '${name}'`)
);
});
return Promise.all(promisesToQuery);
},
checkUnsupportedPermissions() {
const promisesToQuery = UNSUPPORTED_PERMISSIONS.map(({ name }) => {
return aWindow.navigator.permissions
.query({ name })
.then(
() => ok(false, `query should not have resolved for '${name}'`),
error => {
is(error.name, "TypeError",
`query should have thrown TypeError for '${name}'`);
}
);
});
return Promise.all(promisesToQuery);
},
promiseStateChanged(name, state) {
return aWindow.navigator.permissions
.query({ name })
.then(status => {
return new Promise( resolve => {
status.onchange = () => {
status.onchange = null;
is(status.state, state, `state changed for '${name}'`);
resolve();
};
});
},
() => ok(false, `query should not have rejected for '${name}'`));
},
testStatusOnChange() {
return new Promise((resolve) => {
SpecialPowers.popPermissions(() => {
const permission = "geolocation";
const promiseGranted = this.promiseStateChanged(permission, "granted");
this.setPermissions(ALLOW_ACTION);
promiseGranted.then(async () => {
const promisePrompt = this.promiseStateChanged(permission, "prompt");
await SpecialPowers.popPermissions();
return promisePrompt;
}).then(resolve);
});
});
},
testInvalidQuery() {
return aWindow.navigator.permissions
.query({ name: "invalid" })
.then(
() => ok(false, "invalid query should not have resolved"),
() => ok(true, "invalid query should have rejected")
);
},
};
}
function enablePrefs() {
const ops = {
"set": [
["privacy.firstparty.isolate", true],
],
};
return SpecialPowers.pushPrefEnv(ops);
}
function createIframe() {
return new Promise((resolve) => {
const iframe = document.createElement("iframe");
iframe.src = "file_empty.html";
iframe.onload = () => resolve(iframe.contentWindow);
document.body.appendChild(iframe);
});
}
window.onload = () => {
enablePrefs()
.then(createIframe)
.then(createPermissionTester)
.then((tester) => {
return tester
.checkUnsupportedPermissions()
.then(() => tester.setPermissions(UNKNOWN_ACTION))
.then(() => tester.checkPermissions("prompt"))
.then(() => tester.setPermissions(PROMPT_ACTION))
.then(() => tester.checkPermissions("prompt"))
.then(() => tester.setPermissions(ALLOW_ACTION))
.then(() => tester.checkPermissions("granted"))
.then(() => tester.setPermissions(DENY_ACTION))
.then(() => tester.checkPermissions("denied"))
.then(() => tester.testStatusOnChange())
.then(() => tester.testInvalidQuery())
})
.then(SimpleTest.finish)
.catch((e) => {
ok(false, `Unexpected error ${e}`);
SimpleTest.finish();
});
};
</script>
</body>
</html>