diff options
Diffstat (limited to 'dom/permission/tests')
-rw-r--r-- | dom/permission/tests/file_empty.html | 2 | ||||
-rw-r--r-- | dom/permission/tests/file_storage_access_notification_helper.html | 30 | ||||
-rw-r--r-- | dom/permission/tests/mochitest.toml | 18 | ||||
-rw-r--r-- | dom/permission/tests/test_cross_origin_iframe.html | 308 | ||||
-rw-r--r-- | dom/permission/tests/test_permissions_api.html | 254 | ||||
-rw-r--r-- | dom/permission/tests/test_storage_access_notification.html | 50 |
6 files changed, 662 insertions, 0 deletions
diff --git a/dom/permission/tests/file_empty.html b/dom/permission/tests/file_empty.html new file mode 100644 index 0000000000..15648ec5aa --- /dev/null +++ b/dom/permission/tests/file_empty.html @@ -0,0 +1,2 @@ +<h1>I'm just a support file</h1> +<p>I get loaded to do permission testing.</p> diff --git a/dom/permission/tests/file_storage_access_notification_helper.html b/dom/permission/tests/file_storage_access_notification_helper.html new file mode 100644 index 0000000000..0a8b978517 --- /dev/null +++ b/dom/permission/tests/file_storage_access_notification_helper.html @@ -0,0 +1,30 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<!DOCTYPE HTML> +<html> + +<head> + <meta charset="utf-8"> + <title>Helper for Permissions API Test</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> + <script> + 'use strict'; + async function helper() { + let status = await navigator.permissions + .query({ name: "storage-access" }); + status.onchange = () => { + status.onchange = null; + parent.postMessage(status.state, "*") + }; + parent.postMessage("ready", "*"); + } + + </script> +</head> + +<body onload="helper()"> +</body> +</html> diff --git a/dom/permission/tests/mochitest.toml b/dom/permission/tests/mochitest.toml new file mode 100644 index 0000000000..148bd6aba9 --- /dev/null +++ b/dom/permission/tests/mochitest.toml @@ -0,0 +1,18 @@ +[DEFAULT] +support-files = [ + "file_empty.html", + "file_storage_access_notification_helper.html", +] +prefs = [ + "dom.security.featurePolicy.header.enabled=true", + "dom.security.featurePolicy.webidl.enabled=true", +] + +["test_cross_origin_iframe.html"] +fail-if = ["xorigin"] + +["test_permissions_api.html"] +skip-if = ["xorigin"] # Hangs + +["test_storage_access_notification.html"] +skip-if = ["xorigin"] # Hangs diff --git a/dom/permission/tests/test_cross_origin_iframe.html b/dom/permission/tests/test_cross_origin_iframe.html new file mode 100644 index 0000000000..43ef9f0868 --- /dev/null +++ b/dom/permission/tests/test_cross_origin_iframe.html @@ -0,0 +1,308 @@ +<!-- + 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'; + + function setPermission(type, allow) { + return new Promise(resolve => { + SpecialPowers.popPermissions(() => { + SpecialPowers.pushPermissions( + [{ type, allow, context: document }], + resolve + ); + }); + }); + } + + function checkPermission(aIFrame, aExpectedState, aName) { + return SpecialPowers.spawn( + aIFrame, + [{name: aName, expectedState: aExpectedState}], + async aInput => { + try { + let result = await content.navigator + .permissions + .query({ name: aInput.name }); + is( + SpecialPowers.wrap(result).state, + aInput.expectedState, + `correct state for '${aInput.name}'` + ); + } catch (e) { + ok(false, `query should not have rejected for '${aInput.name}'`) + } + } + ); + } + + function createIframe(aId, aAllow) { + return new Promise((resolve) => { + const iframe = document.createElement('iframe'); + iframe.id = aId; + iframe.src = 'https://example.org/tests/dom/permission/tests/file_empty.html'; + if (aAllow) { + iframe.allow = aAllow; + } + iframe.onload = () => resolve(iframe); + document.body.appendChild(iframe); + }); + } + + function removeIframe(aId) { + return new Promise((resolve) => { + document.body.removeChild(document.getElementById(aId)); + resolve(); + }); + } + + const { + UNKNOWN_ACTION, + PROMPT_ACTION, + ALLOW_ACTION, + DENY_ACTION + } = SpecialPowers.Ci.nsIPermissionManager; + + const tests = [ + { + id: 'query navigation top unknown', + top: UNKNOWN_ACTION, + name: 'geolocation', + type: 'geo', + expected: 'denied', + }, + { + id: 'query notifications top unknown', + top: UNKNOWN_ACTION, + name: 'notifications', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query push top unknown', + top: UNKNOWN_ACTION, + name: 'push', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query persistent-storage unknown', + top: UNKNOWN_ACTION, + name: 'persistent-storage', + type: 'persistent-storage', + expected: 'denied', + }, + { + id: 'query storage-access unknown', + top: UNKNOWN_ACTION, + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query navigation top prompt', + top: PROMPT_ACTION, + name: 'geolocation', + type: 'geo', + expected: 'denied', + }, + { + id: 'query notifications top prompt', + top: PROMPT_ACTION, + name: 'notifications', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query push top prompt', + top: PROMPT_ACTION, + name: 'push', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query persistent-storage top prompt', + top: PROMPT_ACTION, + name: 'persistent-storage', + type: 'persistent-storage', + expected: 'denied', + }, + { + id: 'query storage-access top prompt', + top: PROMPT_ACTION, + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query navigation top denied', + top: DENY_ACTION, + name: 'geolocation', + type: 'geo', + expected: 'denied', + }, + { + id: 'query notifications top denied', + top: DENY_ACTION, + name: 'notifications', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query push top denied', + top: DENY_ACTION, + name: 'push', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query persistent-storage top denied', + top: DENY_ACTION, + name: 'persistent-storage', + type: 'persistent-storage', + expected: 'denied', + }, + { + id: 'query storage-access top denied', + top: DENY_ACTION, + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query navigation top granted', + top: ALLOW_ACTION, + name: 'geolocation', + type: 'geo', + expected: 'denied', + }, + { + id: 'query notifications top granted', + top: ALLOW_ACTION, + name: 'notifications', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query push top granted', + top: ALLOW_ACTION, + name: 'push', + type: 'desktop-notification', + expected: 'denied', + }, + { + id: 'query persistent-storage top granted', + top: ALLOW_ACTION, + name: 'persistent-storage', + type: 'persistent-storage', + expected: 'denied', + }, + { + id: 'query storage-access top granted', + top: ALLOW_ACTION, + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'granted', + }, + { + id: 'query navigation top denied, iframe has allow attribute', + top: DENY_ACTION, + allow: 'geolocation', + name: 'geolocation', + type: 'geo', + expected: 'denied', + }, + { + id: 'query navigation top granted, iframe has allow attribute', + top: ALLOW_ACTION, + allow: 'geolocation', + name: 'geolocation', + type: 'geo', + expected: 'granted', + }, + { + id: 'query navigation top prompt, iframe has allow attribute', + top: PROMPT_ACTION, + allow: 'geolocation', + name: 'geolocation', + type: 'geo', + expected: 'prompt', + }, + { + id: 'query navigation top unknown, iframe has allow attribute', + top: UNKNOWN_ACTION, + allow: 'geolocation', + name: 'geolocation', + type: 'geo', + expected: 'prompt', + }, + { + id: 'query storage-access top denied, iframe has allow none attribute', + top: DENY_ACTION, + allow: "storage-access 'none'", + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query storage-access top granted, iframe has allow none attribute', + top: ALLOW_ACTION, + allow: "storage-access 'none'", + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query storage-access top prompt, iframe has allow none attribute', + top: PROMPT_ACTION, + allow: "storage-access 'none'", + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + { + id: 'query storage-access top unknown, iframe has allow none attribute', + top: UNKNOWN_ACTION, + allow: "storage-access 'none'", + name: 'storage-access', + type: '3rdPartyFrameStorage^https://example.org', + expected: 'prompt', + }, + ]; + + SimpleTest.waitForExplicitFinish(); + + async function nextTest() { + if (!tests.length) { + SimpleTest.finish(); + return; + } + + let test = tests.shift(); + await setPermission(test.type, test.top) + .then(() => createIframe(test.id, test.allow)) + .then(iframe => checkPermission(iframe, test.expected, test.name)) + .then(() => removeIframe(test.id)); + + SimpleTest.executeSoon(nextTest); + } + + nextTest() + </script> +</body> + +</html> diff --git a/dom/permission/tests/test_permissions_api.html b/dom/permission/tests/test_permissions_api.html new file mode 100644 index 0000000000..57c45e9d58 --- /dev/null +++ b/dom/permission/tests/test_permissions_api.html @@ -0,0 +1,254 @@ +<!-- + 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' + }, { + 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(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); + }, + 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') + ); + }, + 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 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 = () => { + 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.testNotFullyActiveDoc()) + .then(() => tester.testNotFullyActiveChange()); + }) + .then(SimpleTest.finish) + .catch((e) => { + ok(false, `Unexpected error ${e}`); + SimpleTest.finish(); + }); + }; + </script> +</body> + +</html> diff --git a/dom/permission/tests/test_storage_access_notification.html b/dom/permission/tests/test_storage_access_notification.html new file mode 100644 index 0000000000..d8b5588554 --- /dev/null +++ b/dom/permission/tests/test_storage_access_notification.html @@ -0,0 +1,50 @@ +<!-- + 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"> + <script type="application/javascript"> + 'use strict'; + + SimpleTest.waitForExplicitFinish(); + + async function setPermission(type, allow) { + await SpecialPowers.popPermissions(); + await SpecialPowers.pushPermissions( + [{ type, allow, context: document }] + ); + } + + const { + UNKNOWN_ACTION, + PROMPT_ACTION, + ALLOW_ACTION, + DENY_ACTION + } = SpecialPowers.Ci.nsIPermissionManager; + + window.addEventListener( + "message", + (event) => { + if (event.data == "ready") { + setPermission("3rdPartyFrameStorage^https://example.org", ALLOW_ACTION); + } else { + is(event.data, "granted", "storage-access permission should change to granted after the permission is set"); + SimpleTest.finish(); + } + } + ); + </script> +</head> + +<body> + <iframe id="frame" src="https://example.org/tests/dom/permission/tests/file_storage_access_notification_helper.html"/> +</body> + +</html> |