diff options
Diffstat (limited to 'testing/web-platform/tests/permissions')
11 files changed, 409 insertions, 0 deletions
diff --git a/testing/web-platform/tests/permissions/META.yml b/testing/web-platform/tests/permissions/META.yml new file mode 100644 index 0000000000..6a05abee46 --- /dev/null +++ b/testing/web-platform/tests/permissions/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/permissions/ +suggested_reviewers: + - miketaylr + - marcoscaceres diff --git a/testing/web-platform/tests/permissions/all-permissions.html b/testing/web-platform/tests/permissions/all-permissions.html new file mode 100644 index 0000000000..9ad014bc6e --- /dev/null +++ b/testing/web-platform/tests/permissions/all-permissions.html @@ -0,0 +1,43 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test all known permissions support</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id="log"></div> + +<script> + // These are marked "at risk" in the spec... + const atRisk = [ + "accelerometer", + "ambient-light-sensor", + "background-fetch", + "background-sync", + "bluetooth", + "gyroscope", + "magnetometer", + "midi", + "nfc", + "screen-wake-lock", + "camera", + "display-capture", + "microphone", + "speaker-selection", + "xr-spatial-tracking", + ]; + + // These are known to be supported by multiple engines... + const permissions = [ + "geolocation", + "notifications", + "persistent-storage", + "push", + ] + + for (const name of [...permissions, ...atRisk]) { + promise_test(async (test) => { + const status = await navigator.permissions.query({ name }); + assert_true(status instanceof PermissionStatus); + //assert_equals(status.name, name, `permission's name should be "${name}"`); + }, `Query "${name}" permission`); + } +</script> diff --git a/testing/web-platform/tests/permissions/feature-policy-permissions-query.html b/testing/web-platform/tests/permissions/feature-policy-permissions-query.html new file mode 100644 index 0000000000..bd152e973e --- /dev/null +++ b/testing/web-platform/tests/permissions/feature-policy-permissions-query.html @@ -0,0 +1,11 @@ +<script> +'use strict'; + +Promise.resolve().then(() => navigator.permissions.query({name:'geolocation'})) + .then(permissionStatus => { + window.parent.postMessage({ state: permissionStatus.state }, '*'); +}, error => { + window.parent.postMessage({ state: null }, '*'); +}); +</script> + diff --git a/testing/web-platform/tests/permissions/idlharness.any.js b/testing/web-platform/tests/permissions/idlharness.any.js new file mode 100644 index 0000000000..ff0a969bad --- /dev/null +++ b/testing/web-platform/tests/permissions/idlharness.any.js @@ -0,0 +1,27 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/permissions/#idl-index + +"use strict"; + +idl_test( + ['permissions'], + ['html', 'dom'], + async idl_array => { + try { + self.permissionStatus = await navigator.permissions.query({ name: "geolocation" }); + } catch (e) {} + + if (self.GLOBAL.isWorker()) { + idl_array.add_objects({ WorkerNavigator: ['navigator'] }); + } else { + idl_array.add_objects({ Navigator: ['navigator'] }); + } + + idl_array.add_objects({ + Permissions: ['navigator.permissions'], + PermissionStatus: ['permissionStatus'] + }); + } +); diff --git a/testing/web-platform/tests/permissions/midi-permission.html b/testing/web-platform/tests/permissions/midi-permission.html new file mode 100644 index 0000000000..1d75e1c883 --- /dev/null +++ b/testing/web-platform/tests/permissions/midi-permission.html @@ -0,0 +1,35 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test WebIDL conversion when querying the "midi" permission</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id="log"></div> + +<script> + promise_test(async (test) => { + let calledCount = 0; + const status = await navigator.permissions.query({ + get name() { + calledCount++; + return "midi"; + }, + }); + assert_true(status instanceof PermissionStatus); + assert_equals(status.name, "midi", `permission's name should be "midi"`); + // + // First call should be from: + // + // Let rootDesc be the object permissionDesc refers to, converted to an + // IDL value of type PermissionDescriptor. + // + // Second from: + // + // Let typedDescriptor be the object permissionDesc refers to, + // converted to an IDL value of rootDesc's name's permission descriptor + // type. + // + // See: https://w3c.github.io/permissions/#query-method + // + assert_equals(calledCount, 2, "midi permission should be converted twice"); + }, `querying the "midi" permission requires two WebIDL conversions`); +</script> diff --git a/testing/web-platform/tests/permissions/non-fully-active.https.html b/testing/web-platform/tests/permissions/non-fully-active.https.html new file mode 100644 index 0000000000..1c11afa3d9 --- /dev/null +++ b/testing/web-platform/tests/permissions/non-fully-active.https.html @@ -0,0 +1,108 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Geolocation Test: non-fully active document</title> +<link rel="help" href="https://github.com/w3c/permissions/pull/365" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body></body> +<script> + // Creates the iframe, wait for it to load... + async function attachIframe() { + const iframe = document.createElement("iframe"); + await new Promise((resolve) => { + iframe.src = "resources/empty.html"; + iframe.addEventListener("load", resolve, { once: true }); + document.body.appendChild(iframe); + }); + return iframe; + } + + promise_test(async (t) => { + const iframe = await attachIframe(); + + // Steal the needed references + const { permissions } = iframe.contentWindow.navigator; + const TypeErrorCtor = iframe.contentWindow.TypeError; + const DOMExceptionCtor = iframe.contentWindow.DOMException; + + // Let's check that ordering is correct. + await promise_rejects_js( + t, + TypeErrorCtor, + permissions.query({ name: "xxxxx-not-supported" }), + "query() should reject if the feature is not supported" + ); + + // no longer fully active, let's try that again... + iframe.remove(); + + // Now, let's try with Geolocation as it's supported by all browsers. + await promise_rejects_dom( + t, + "InvalidStateError", + DOMExceptionCtor, + permissions.query({ name: "whatever" }), + "must reject in the right global when the document is not fully active" + ); + + // Re-attach, and go back to fully active. + document.body.appendChild(iframe); + await new Promise((resolve) => + iframe.addEventListener("load", resolve, { once: true }) + ); + + // And we are back to fully active, so this should not reject. + const status = await iframe.contentWindow.navigator.permissions.query({ + name: "geolocation", + }); + assert_equals(status.name, "geolocation"); + iframe.remove(); + }, "Trying to query() a non-fully active document rejects with a InvalidStateError"); + + promise_test(async (t) => { + // Create the iframe, wait for it to load... + const iframe = await attachIframe(); + + // Get the status + const initialStatus = + await iframe.contentWindow.navigator.permissions.query({ + name: "geolocation", + }); + + assert_true("onchange" in initialStatus, "onchange is supported"); + + // Let's check events are firing... + await new Promise(async (resolve) => { + const newState = initialStatus.state === "prompt" ? "denied" : "granted"; + initialStatus.addEventListener("change", resolve, { once: true }); + await test_driver.set_permission({ name: "geolocation" }, newState); + }); + + // No longer fully active... + iframe.remove(); + + await new Promise(async (resolve, reject) => { + // Gets dropped on the floor. + initialStatus.addEventListener("change", reject, { once: true }); + await test_driver.set_permission({ name: "geolocation" }, "prompt"); + // Try to force it synthetically. This would trigger the event synchronously. + initialStatus.dispatchEvent(new Event("change")); + resolve(); + }); + + // Re-attach, and go back to fully active. + document.body.appendChild(iframe); + await new Promise((resolve) => + iframe.addEventListener("load", resolve, { once: true }) + ); + + // Finally, let's recheck that permission state. + const finalStatus = await iframe.contentWindow.navigator.permissions.query({ + name: "geolocation", + }); + assert_equals(finalStatus.state, "prompt", "expected prompt state"); + iframe.remove(); + }, "Permission change events shouldn't fire on non-fully active document"); +</script> diff --git a/testing/web-platform/tests/permissions/permissions-cg.https.html b/testing/web-platform/tests/permissions/permissions-cg.https.html new file mode 100644 index 0000000000..7a2d8dcbb4 --- /dev/null +++ b/testing/web-platform/tests/permissions/permissions-cg.https.html @@ -0,0 +1,36 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test PermissionStatus's name attribute.</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/common/gc.js"></script> + +<script> +promise_test(async () => { + const { state: initialState } = await navigator.permissions.query({ + name: "geolocation", + }); + + const pass = new Promise(async (resolve) => { + let status = await navigator.permissions.query({ + name: "geolocation", + }); + status.addEventListener("change", resolve, { once: true }); + + status = null; + await garbageCollect(); + + // Will cause change event to be dispatched. + await test_driver.set_permission({ name: "geolocation" }, "granted"); + }); + + // Wait for the change event to be dispatched. + await pass; + + // Reset the permission to its default value. + await test_driver.set_permission({ name: "geolocation" }, initialState); +}, "status is not garbage collected when it goes out of scope"); + +</script> diff --git a/testing/web-platform/tests/permissions/permissions-garbage-collect.https.html b/testing/web-platform/tests/permissions/permissions-garbage-collect.https.html new file mode 100644 index 0000000000..cd650dc8f2 --- /dev/null +++ b/testing/web-platform/tests/permissions/permissions-garbage-collect.https.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Test Permission garbage collection persistance.</title> +<link rel="help" href="https://github.com/w3c/permissions/pull/256" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body> + <script> + async function createABunchOfGarbage() { + const promises = []; + for (let i = 0; i < 25; i++) { + const promise = new Promise((r) => { + const iframe = document.createElement("iframe"); + iframe.onload = () => r(iframe); + iframe.src = "about:blank"; + document.body.appendChild(iframe); + }); + promises.push(promise); + } + const iframes = await Promise.all(promises); + iframes.forEach((iframe) => iframe.remove()); + } + + promise_test(async (t) => { + t.add_cleanup(() => { + return test_driver.set_permission({ name: "geolocation" }, "prompt"); + }); + + const eventPromise = new Promise( + async (r) => { + // we create the status here, but it goes out of scope + // at the end of the function. Thus, we assume it will be + // garbage collected. + const status = await navigator.permissions.query({ + name: "geolocation", + }); + status.addEventListener("change", r); + }, + { once: true } + ); + + // Maybe got garbage collected. + await createABunchOfGarbage(); + + // Causes event to fire. + await test_driver.set_permission({ name: "geolocation" }, "granted"); + await eventPromise; + }, "Events fire even if the status object is garbage collected"); + </script> +</body> diff --git a/testing/web-platform/tests/permissions/permissions-query-feature-policy-attribute.https.sub.html b/testing/web-platform/tests/permissions/permissions-query-feature-policy-attribute.https.sub.html new file mode 100644 index 0000000000..1d7333d9b5 --- /dev/null +++ b/testing/web-platform/tests/permissions/permissions-query-feature-policy-attribute.https.sub.html @@ -0,0 +1,75 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test permissions query againts feature policy allow attribute</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id="log"></div> + +<script> + "use strict"; + + function test_permissions_query( + feature_description, test, src, expect_state, allow_attribute) { + let frame = document.createElement('iframe'); + frame.src = src; + + if (typeof allow_attribute !== 'undefined') { + frame.allow = allow_attribute; + } + + window.addEventListener('message', test.step_func(function handler(evt) { + if (evt.source === frame.contentWindow) { + assert_equals(evt.data.state, expect_state, feature_description); + document.body.removeChild(frame); + window.removeEventListener('message', handler); + test.done(); + } + })); + + document.body.appendChild(frame); + } + + const same_origin_src = + "/permissions/feature-policy-permissions-query.html"; + const cross_origin_src = + "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; + + async_test(t => { + test_permissions_query( + 'navigator.permissions.query("geolocation")', + t, + same_origin_src, + "prompt", + "geolocation" + ); + }, 'Permissions.state is "prompt" with allow="geolocation" in same-origin iframes.'); + + async_test(t => { + test_permissions_query( + 'navigator.permissions.query("geolocation")', + t, + cross_origin_src, + "prompt", + "geolocation" + ); + }, 'Permissions.state is "prompt" with allow="geolocation" in cross-origin iframes.'); + + async_test(t => { + test_permissions_query( + 'navigator.permissions.query("geolocation")', + t, + same_origin_src, + "prompt" + ); + }, 'Permission.state is "prompt" in same-origin iframes.'); + + async_test(t => { + test_permissions_query( + 'navigator.permissions.query("geolocation")', + t, + cross_origin_src, + "denied" + ); + }, 'Permission.state is "denied" in cross-origin iframes.'); + +</script> diff --git a/testing/web-platform/tests/permissions/permissionsstatus-name.html b/testing/web-platform/tests/permissions/permissionsstatus-name.html new file mode 100644 index 0000000000..db1d1bb83e --- /dev/null +++ b/testing/web-platform/tests/permissions/permissionsstatus-name.html @@ -0,0 +1,15 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test PermissionStatus's name attribute.</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id="log"></div> + +<script> +promise_test(async () => { + const result = await navigator.permissions.query({ + name: "geolocation", + }); + assert_equals(result.name, "geolocation", "Name was geolocation"); +}); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/permissions/resources/empty.html b/testing/web-platform/tests/permissions/resources/empty.html new file mode 100644 index 0000000000..b0653f8c0c --- /dev/null +++ b/testing/web-platform/tests/permissions/resources/empty.html @@ -0,0 +1,3 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Just a support file</title> |