зеркало из https://github.com/mozilla/gecko-dev.git
297 строки
9.6 KiB
HTML
297 строки
9.6 KiB
HTML
<!--
|
|
Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/
|
|
-->
|
|
<!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">
|
|
/*globals SpecialPowers, SimpleTest, is, ok, */
|
|
'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'
|
|
}, ];
|
|
|
|
const UNSUPPORTED_PERMISSIONS = [
|
|
'foobarbaz', // Not in spec, for testing only.
|
|
'midi',
|
|
];
|
|
|
|
// Create a closure, so that tests are run on the correct window object.
|
|
function createPermissionTester(iframe) {
|
|
const iframeWindow = iframe.contentWindow;
|
|
return {
|
|
async setPermissions(allow, context = iframeWindow.document) {
|
|
const permissions = PERMISSIONS.map(({ type }) => {
|
|
return {
|
|
type,
|
|
allow,
|
|
context,
|
|
};
|
|
});
|
|
await SpecialPowers.popPermissions();
|
|
return SpecialPowers.pushPermissions(permissions);
|
|
},
|
|
revokePermissions() {
|
|
const promisesToRevoke = PERMISSIONS.map(({ name }) => {
|
|
return iframeWindow.navigator.permissions
|
|
.revoke({ name })
|
|
.then(
|
|
({ state }) => is(state, 'prompt', `correct state for '${name}'`),
|
|
() => ok(false, `revoke should not have rejected for '${name}'`)
|
|
);
|
|
});
|
|
return Promise.all(promisesToRevoke);
|
|
},
|
|
revokeUnsupportedPermissions() {
|
|
const promisesToRevoke = UNSUPPORTED_PERMISSIONS.map(({ name }) => {
|
|
return iframeWindow.navigator.permissions
|
|
.revoke({ name })
|
|
.then(
|
|
() => ok(false, `revoke should not have resolved for '${name}'`),
|
|
error => is(error.name, 'TypeError', `revoke should have thrown TypeError for '${name}'`)
|
|
);
|
|
});
|
|
return Promise.all(promisesToRevoke);
|
|
},
|
|
checkPermissions(expectedState) {
|
|
const promisesToQuery = PERMISSIONS.map(({ name: expectedName }) => {
|
|
return iframeWindow.navigator.permissions
|
|
.query({ name: expectedName })
|
|
.then(
|
|
({ state, name }) => {
|
|
is(state, expectedState, `correct state for '${expectedName}'`)
|
|
is(name, expectedName, `correct name for '${expectedName}'`)
|
|
},
|
|
() => ok(false, `query should not have rejected for '${name}'`)
|
|
);
|
|
});
|
|
return Promise.all(promisesToQuery);
|
|
},
|
|
checkUnsupportedPermissions() {
|
|
const promisesToQuery = UNSUPPORTED_PERMISSIONS.map(({ name }) => {
|
|
return iframeWindow.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 iframeWindow.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 iframeWindow.navigator.permissions
|
|
.query({ name: 'invalid' })
|
|
.then(
|
|
() => ok(false, 'invalid query should not have resolved'),
|
|
() => ok(true, 'invalid query should have rejected')
|
|
);
|
|
},
|
|
testInvalidRevoke() {
|
|
return iframeWindow.navigator.permissions
|
|
.revoke({ name: 'invalid' })
|
|
.then(
|
|
() => ok(false, 'invalid revoke should not have resolved'),
|
|
() => ok(true, 'invalid revoke should have rejected')
|
|
);
|
|
},
|
|
async testNotFullyActiveDoc() {
|
|
const iframe1 = await createIframe();
|
|
const expectedErrorClass = iframe1.contentWindow.DOMException;
|
|
const permAPI = iframe1.contentWindow.navigator.permissions;
|
|
// Document no longer fully active
|
|
iframe1.remove();
|
|
await new Promise((res) => {
|
|
permAPI.query({ name: "geolocation" }).catch((error) => {
|
|
ok(
|
|
error instanceof expectedErrorClass,
|
|
"DOMException from other realm"
|
|
);
|
|
is(
|
|
error.name,
|
|
"InvalidStateError",
|
|
"Must reject with a InvalidStateError"
|
|
);
|
|
iframe1.remove();
|
|
res();
|
|
});
|
|
});
|
|
},
|
|
async testNotFullyActiveChange() {
|
|
await SpecialPowers.popPermissions();
|
|
const iframe2 = await createIframe();
|
|
const initialStatus = await iframe2.contentWindow.navigator.permissions.query(
|
|
{ name: "geolocation" }
|
|
);
|
|
await SpecialPowers.pushPermissions([
|
|
{
|
|
type: "geo",
|
|
allow: PROMPT_ACTION,
|
|
context: iframe2.contentWindow.document,
|
|
},
|
|
]);
|
|
is(
|
|
initialStatus.state,
|
|
"prompt",
|
|
"Initially the iframe's permission is prompt"
|
|
);
|
|
|
|
// Document no longer fully active
|
|
const stolenDoc = iframe2.contentWindow.document;
|
|
iframe2.remove();
|
|
initialStatus.onchange = () => {
|
|
ok(false, "onchange must not fire when document is not fully active.");
|
|
};
|
|
// We set it to grant for this origin, but the PermissionStatus doesn't change.
|
|
await SpecialPowers.pushPermissions([
|
|
{
|
|
type: "geo",
|
|
allow: ALLOW_ACTION,
|
|
context: stolenDoc,
|
|
},
|
|
]);
|
|
is(
|
|
initialStatus.state,
|
|
"prompt",
|
|
"Inactive document's permission must not change"
|
|
);
|
|
|
|
// Re-attach the iframe
|
|
document.body.appendChild(iframe2);
|
|
await new Promise((res) => (iframe2.onload = res));
|
|
// Fully active again
|
|
const newStatus = await iframe2.contentWindow.navigator.permissions.query({
|
|
name: "geolocation",
|
|
});
|
|
is(newStatus.state, "granted", "Reflect that we are granted");
|
|
|
|
const newEventPromise = new Promise((res) => (newStatus.onchange = res));
|
|
await SpecialPowers.pushPermissions([
|
|
{
|
|
type: "geo",
|
|
allow: DENY_ACTION,
|
|
context: iframe2.contentWindow.document,
|
|
},
|
|
]);
|
|
// Event fires...
|
|
await newEventPromise;
|
|
is(initialStatus.state, "prompt", "Remains prompt, as it's actually dead.");
|
|
is(newStatus.state, "denied", "New status must be 'denied'.");
|
|
iframe2.remove();
|
|
},
|
|
};
|
|
}
|
|
|
|
function enablePrefs() {
|
|
const ops = {
|
|
'set': [
|
|
['dom.permissions.revoke.enable', 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);
|
|
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(() => tester.revokeUnsupportedPermissions())
|
|
.then(() => tester.revokePermissions())
|
|
.then(() => tester.checkPermissions('prompt'))
|
|
.then(() => tester.testInvalidRevoke())
|
|
.then(() => tester.testNotFullyActiveDoc())
|
|
.then(() => tester.testNotFullyActiveChange());
|
|
})
|
|
.then(SimpleTest.finish)
|
|
.catch((e) => {
|
|
ok(false, `Unexpected error ${e}`);
|
|
SimpleTest.finish();
|
|
});
|
|
};
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|