diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/idle-detection | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/idle-detection')
18 files changed, 958 insertions, 0 deletions
diff --git a/testing/web-platform/tests/idle-detection/META.yml b/testing/web-platform/tests/idle-detection/META.yml new file mode 100644 index 0000000000..adbdc7bd93 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/META.yml @@ -0,0 +1,5 @@ +spec: https://wicg.github.io/idle-detection/ +suggested_reviewers: + - goto + - jsbell + - reillyg
\ No newline at end of file diff --git a/testing/web-platform/tests/idle-detection/basics.tentative.https.window.js b/testing/web-platform/tests/idle-detection/basics.tentative.https.window.js new file mode 100644 index 0000000000..32cb6204b9 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/basics.tentative.https.window.js @@ -0,0 +1,98 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: title=Idle Detection API: Basics + +'use strict'; + +promise_setup(async t => { + await test_driver.set_permission({name: 'idle-detection'}, 'granted'); +}) + +promise_test(async t => { + let detector = new IdleDetector(); + let watcher = new EventWatcher(t, detector, ["change"]); + let initial_state = watcher.wait_for("change"); + + await detector.start(); + await initial_state; + + assert_true(['active', 'idle'].includes(detector.userState), + 'has a valid user state'); + assert_true(['locked', 'unlocked'].includes(detector.screenState), + 'has a valid screen state'); +}, 'start() basics'); + +promise_test(async t => { + let used = false; + + const detector = new IdleDetector(); + detector.start({ + get threshold() { + used = true; + return 60000; + } + }); + + assert_true(used, 'start() options "threshold" member was used'); +}, 'start() uses threshold property'); + +promise_test(async t => { + let used = false; + + const controller = new AbortController(); + const detector = new IdleDetector(); + detector.start({ + get signal() { + used = true; + return controller.signal; + } + }); + + assert_true(used, 'start() options "signal" member was used'); +}, 'start() uses signal property'); + + +promise_test(async t => { + const detector = new IdleDetector(); + await promise_rejects_js(t, TypeError, detector.start({threshold: 0})); +}, 'start() rejects with invalid threshold (0)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await promise_rejects_js(t, TypeError, detector.start({threshold: 59000})); +}, 'start() rejects with threshold below minimum (59000)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await detector.start({threshold: 60000}); +}, 'start() rejects threshold (60000)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await detector.start({threshold: 61000}); +}, 'start() allows threshold (61000)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await promise_rejects_js(t, TypeError, detector.start({threshold: null})); +}, 'start() rejects with invalid threshold (null)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await promise_rejects_js(t, TypeError, detector.start({threshold: -1})); +}, 'start() rejects with invalid threshold (-1)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await promise_rejects_js(t, TypeError, detector.start({threshold: NaN})); +}, 'start() rejects with invalid threshold (NaN)'); + +promise_test(async t => { + const detector = new IdleDetector(); + await detector.start(); +}, 'start() uses a default value for the threshold when none is passed'); + +promise_test(async t => { + const detector = new IdleDetector(); + await detector.start({threshold: undefined}); +}, 'start() uses a default value for the threshold'); diff --git a/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html new file mode 100644 index 0000000000..e419840ccd --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<body> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/permissions-policy/resources/permissions-policy.js></script> +<script> +'use strict'; + +const base_src = '/permissions-policy/resources/redirect-on-load.html#'; +const sub = 'https://{{domains[www]}}:{{ports[https][0]}}'; +const relative_path = + '/permissions-policy/resources/permissions-policy-idle-detection.html'; +const relative_worker_frame_path = + '/permissions-policy/resources/permissions-policy-idle-detection-worker.html'; +const same_origin_src = base_src + relative_path; +const same_origin_worker_frame_src = base_src + relative_worker_frame_path; +const cross_origin_src = base_src + sub + relative_path; +const cross_origin_worker_frame_src = base_src + sub + + relative_worker_frame_path; + +promise_setup(async () => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); +}); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame ' + + 'allows same-origin relocation.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame ' + + 'allows workers in same-origin relocation.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, + expect_feature_unavailable_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame ' + + 'disallows cross-origin relocation.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, + expect_feature_unavailable_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame ' + + 'disallows workers in cross-origin relocation.'); + +</script> +</body> diff --git a/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub.html b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub.html new file mode 100644 index 0000000000..e05772d9bc --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy-attribute.https.sub.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<body> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/permissions-policy/resources/permissions-policy.js></script> +<script> +'use strict'; + +const sub = 'https://{{domains[www]}}:{{ports[https][0]}}'; +const same_origin_src = + '/permissions-policy/resources/permissions-policy-idle-detection.html' +const same_origin_worker_frame_src = + '/permissions-policy/resources/permissions-policy-idle-detection-worker.html'; +const cross_origin_src = sub + same_origin_src; +const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; + +promise_setup(async () => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); +}); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + + 'in same-origin iframe using Permissions Policy "idle-detection".'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + + 'in a worker in same-origin iframe using Permissions Policy "idle-detection".'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + + 'in cross-origin iframe using Permissions Policy "idle-detection".'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, + expect_feature_available_default, 'idle-detection'); +}, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + + 'in a worker in cross-origin iframe using Permissions Policy "idle-detection".'); + +</script> +</body> diff --git a/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000..6fae367730 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<body> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/permissions-policy/resources/permissions-policy.js></script> +<script> +'use strict'; + +const sub = 'https://{{domains[www]}}:{{ports[https][0]}}'; +const same_origin_src = + '/permissions-policy/resources/permissions-policy-idle-detection.html' +const same_origin_worker_frame_src = + '/permissions-policy/resources/permissions-policy-idle-detection-worker.html'; +const cross_origin_src = sub + same_origin_src; +const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; + +promise_setup(async () => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); +}); + +promise_test(async t => { + await new IdleDetector().start(); +}, + 'Permissions-Policy idle-detection=* explicity set by top-level ' + + 'frame allows the top-level document.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_src, + expect_feature_available_default); +}, 'Permissions-Policy idle-detection=* explicity set by top-level ' + + 'frame allows same-origin iframes.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, + expect_feature_available_default); +}, 'Permissions-Policy idle-detection=* explicity set by top-level ' + + 'frame allows workers in same-origin iframes.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, + expect_feature_available_default); +}, 'Permissions-Policy idle-detection=* explicity set by top-level ' + + 'frame allows cross-origin iframes.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, + expect_feature_available_default); +}, 'Permissions-Policy idle-detection=* explicity set by top-level ' + + 'frame allows workers in cross-origin iframes.'); + +fetch_tests_from_worker(new Worker( + 'resources/idle-detection-allowed-by-permissions-policy-worker.js')) + +</script> +</body> diff --git a/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000..2bf18afe5f --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: idle-detection=* diff --git a/testing/web-platform/tests/idle-detection/idle-detection-default-permissions-policy.https.sub.html b/testing/web-platform/tests/idle-detection/idle-detection-default-permissions-policy.https.sub.html new file mode 100644 index 0000000000..90cb7f88d3 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-default-permissions-policy.https.sub.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<body> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/permissions-policy/resources/permissions-policy.js></script> +<script> +'use strict'; + +const same_origin_src = + '/permissions-policy/resources/permissions-policy-idle-detection.html' +const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' + + same_origin_src; + +promise_setup(async () => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); +}); + +promise_test(async t => { + await new IdleDetector().start() +}, + 'Default "idle-detection" permissions policy "self" ' + + 'allows the top-level document.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_src, + expect_feature_available_default); +}, 'Default "idle-detection" permissions policy "self" ' + + 'allows same-origin iframes.'); + +promise_test(async t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, + expect_feature_unavailable_default); +}, 'Default "idle-detection" permissions policy "self" ' + + 'disallows cross-origin iframes.'); + +</script> +</body> diff --git a/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html b/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000..90317dece7 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<body> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/permissions-policy/resources/permissions-policy.js></script> +<script> +'use strict'; + +const sub = 'https://{{domains[www]}}:{{ports[https][0]}}'; +const same_origin_src = + '/permissions-policy/resources/permissions-policy-idle-detection.html' +const same_origin_worker_frame_src = + '/permissions-policy/resources/permissions-policy-idle-detection-worker.html'; +const cross_origin_src = sub + same_origin_src; +const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; + +promise_test(async () => { + try { + let idleDetector = new IdleDetector(); + await idleDetector.start(); + assert_unreached('expected promise to reject with SecurityError'); + } catch (error) { + assert_equals(error.name, 'SecurityError'); + } +}, 'Permissions-Policy idle-detection=() explicitly set by top-level frame ' + + 'disallows query in the top-level document.'); + +async_test(t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_src, + expect_feature_unavailable_default); +}, 'Permissions-Policy idle-detection=() explicitly set by top-level frame ' + + 'disallows same-origin iframes.'); + +async_test(t => { + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, + expect_feature_unavailable_default); +}, 'Permissions-Policy idle-detection=() explicitly set by top-level frame ' + + 'disallows workers in same-origin iframes.'); + +async_test(t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, + expect_feature_unavailable_default); +}, 'Permissions-Policy idle-detection=() explicitly set by top-level frame ' + + 'disallows cross-origin iframes.'); + +async_test(t => { + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, + expect_feature_unavailable_default); +}, 'Permissions-Policy idle-detection=() explicitly set by top-level frame ' + + 'disallows workers in cross-origin iframes.'); + +fetch_tests_from_worker(new Worker( + 'resources/idle-detection-disabled-by-permissions-policy-worker.js')) + +</script> +</body> diff --git a/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html.headers b/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000..289463c30d --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-detection-disabled-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: idle-detection=() diff --git a/testing/web-platform/tests/idle-detection/idle-permission.tentative.https.window.js b/testing/web-platform/tests/idle-detection/idle-permission.tentative.https.window.js new file mode 100644 index 0000000000..524062f9f3 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idle-permission.tentative.https.window.js @@ -0,0 +1,34 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +'use strict'; + +promise_test(async t => { + await test_driver.set_permission({name: 'idle-detection'}, 'denied'); + + let detector = new IdleDetector(); + await promise_rejects_dom(t, 'NotAllowedError', detector.start()); +}, 'Denying idle-detection permission should block access.'); + +promise_test(async t => { + await test_driver.set_permission({name: 'idle-detection'}, 'granted'); + + let detector = new IdleDetector(); + await detector.start(); + + assert_true( + ['active', 'idle'].includes(detector.userState), + 'has a valid user state'); + assert_true( + ['locked', 'unlocked'].includes(detector.screenState), + 'has a valid screen state'); +}, 'Granting idle-detection permission should allow access.'); + +promise_test(async t => { + await test_driver.set_permission({name: 'idle-detection'}, 'prompt'); + + await promise_rejects_dom(t, 'NotAllowedError', IdleDetector.requestPermission()); + + await test_driver.bless('request permission'); + let state = await IdleDetector.requestPermission(); + assert_equals(state, 'prompt'); +}, 'The idle-detection permission cannot be requested without a user gesture'); diff --git a/testing/web-platform/tests/idle-detection/idlharness-worker.https.window.js b/testing/web-platform/tests/idle-detection/idlharness-worker.https.window.js new file mode 100644 index 0000000000..e8fcf9ede6 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idlharness-worker.https.window.js @@ -0,0 +1,10 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +'use strict'; + +promise_test(async t => { + await test_driver.set_permission({name: 'idle-detection'}, 'granted'); + + await fetch_tests_from_worker(new Worker('resources/idlharness-worker.js')); +}, 'Run idlharness tests in a worker.'); diff --git a/testing/web-platform/tests/idle-detection/idlharness.https.window.js b/testing/web-platform/tests/idle-detection/idlharness.https.window.js new file mode 100644 index 0000000000..2f1758098f --- /dev/null +++ b/testing/web-platform/tests/idle-detection/idlharness.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +// https://github.com/samuelgoto/idle-detection + +'use strict'; + +idl_test( + ['idle-detection'], + ['dom', 'html'], + async (idl_array, t) => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); + + self.idle = new IdleDetector(); + let watcher = new EventWatcher(t, self.idle, ["change"]); + let initial_state = watcher.wait_for("change"); + await self.idle.start(); + await initial_state; + + idl_array.add_objects({ + IdleDetector: ['idle'], + }); + } +); diff --git a/testing/web-platform/tests/idle-detection/interceptor.https.html b/testing/web-platform/tests/idle-detection/interceptor.https.html new file mode 100644 index 0000000000..e9350ce8ce --- /dev/null +++ b/testing/web-platform/tests/idle-detection/interceptor.https.html @@ -0,0 +1,378 @@ +<!DOCTYPE html> +<link rel="help" href="https://github.com/samuelgoto/idle-detection"> +<title>Tests the Idle Detection API</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/test-only-api.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="resources/idle-detection-helper.js"></script> +<script> +'use strict'; + +promise_setup(async t => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); + if (isChromiumBased) { + await loadChromiumResources(); + } +}) + +promise_test(async t => { + // Basic test that expects start() to call internally + // addMonitor, which in turn return an ACTIVE state. + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: true + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + await detector.start({ signal: controller.signal }); + await initial_state; + + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "locked"); + + controller.abort(); +}, 'start()'); + +promise_test(async t => { + // Verifies that an event is thrown when a change of state from IDLE to ACTIVE + // is detected. + expect(addMonitor).andReturn(async (monitorPtr) => { + const first = { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + + t.step_timeout(() => { + monitorPtr.update( + { + idleTime: { milliseconds: 0 }, + screenLocked: false + }, + /*is_overridden_by_devtools=*/true + ); + }, 0); + + return first; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + await detector.start({ signal: controller.signal }); + await initial_state; + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "unlocked"); + + // Wait for the first change in state. + await watcher.wait_for("change"); + + assert_equals(detector.userState, "idle"); + assert_equals(detector.screenState, "unlocked"); + + controller.abort(); +}, 'updates once'); + +promise_test(async t => { + // Simulates the user being active, going idle and then going back active + // again. + expect(addMonitor).andReturn(async (monitorPtr) => { + const first = { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + + // Updates the client once with the user idle. + t.step_timeout(() => { + monitorPtr.update( + { + idleTime: { milliseconds: 0 }, + screenLocked: false + }, + /*is_overridden_by_devtools=*/true + ); + }, 0); + + // Updates the client a second time with the user active. + t.step_timeout(() => { + monitorPtr.update( + { + idleTime: null, + screenLocked: false + }, + /*is_overridden_by_devtools=*/true + ); + }, 1); + + return first; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + await detector.start({ signal: controller.signal }); + await initial_state; + + // Waits for the first event. + await watcher.wait_for("change"); + assert_equals(detector.userState, "idle"); + + // Waits for the second event. + await watcher.wait_for("change"); + assert_equals(detector.userState, "active"); + + controller.abort(); +}, 'updates twice'); + +promise_test(async t => { + // Simulates a locked screen. + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: true + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + await detector.start({ signal: controller.signal }); + await initial_state; + + assert_equals(detector.screenState, "locked"); + + controller.abort(); +}, 'locked screen'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: true + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + + let event = new Promise((resolve, reject) => { + detector.onchange = resolve; + }); + + await detector.start({ signal: controller.signal }); + + // Waits for the first event. + await event; + + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "locked"); + + controller.abort(); +}, 'IdleDetector.onchange'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector({ signal: controller.signal }); + + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + // Only the first call to start() is allowed. + const start_promise = detector.start({ signal: controller.signal }); + await promise_rejects_dom(t, 'InvalidStateError', detector.start()); + await start_promise; + + await initial_state; + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "unlocked"); + + // Calling abort() multiple times is safe. + controller.abort(); + controller.abort(); + controller.abort(); + controller.abort(); +}, 'Calling start() and abort() multiple times'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + + controller.abort(); + + await promise_rejects_dom( + t, 'AbortError', detector.start({ signal: controller.signal })); +}, 'Calling abort() before start() makes it fail'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + const controller = new AbortController(); + const detector = new IdleDetector(); + + const promise = promise_rejects_dom( + t, 'AbortError', detector.start({ signal: controller.signal })) + controller.abort(); + + await promise; +}, 'Calling abort() after start() makes it fail'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + + let controller = new AbortController(); + const first_start = promise_rejects_dom( + t, 'AbortError', detector.start({ signal: controller.signal })) + controller.abort(); + + controller = new AbortController(); + const initial_state = watcher.wait_for("change"); + const second_start = detector.start({ signal: controller.signal }); + + await first_start; + await second_start; + await initial_state; + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "unlocked"); + + controller.abort(); +}, 'A start() that has been aborted can be retried'); + +promise_test(async t => { + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + let controller = new AbortController(); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + let initial_state = watcher.wait_for("change"); + + await detector.start({ signal: controller.signal }); + await initial_state; + assert_equals(detector.userState, "active"); + assert_equals(detector.screenState, "unlocked"); + + controller.abort(); + + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: { milliseconds: 0 }, + screenLocked: true + } + }; + }); + + // Restarting the monitor. + controller = new AbortController(); + + initial_state = watcher.wait_for("change"); + await detector.start({ signal: controller.signal }); + await initial_state; + assert_equals(detector.userState, "idle"); + assert_equals(detector.screenState, "locked"); + + // Abort in a new task and restart the monitor again. + const p = new Promise((resolve) => { + t.step_timeout(resolve, 1); + }); + await p; + controller.abort(); + + expect(addMonitor).andReturn(async (monitorPtr) => { + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: { milliseconds: 0 }, + screenLocked: false + } + }; + }); + + // Restarting the monitor. + controller = new AbortController(); + + initial_state = watcher.wait_for("change"); + await detector.start({ signal: controller.signal }); + await initial_state; + assert_equals(detector.userState, "idle"); + assert_equals(detector.screenState, "unlocked"); + + controller.abort(); +}, 'Calling start() after abort(): re-starting monitor.'); + +</script> diff --git a/testing/web-platform/tests/idle-detection/page-visibility.https.html b/testing/web-platform/tests/idle-detection/page-visibility.https.html new file mode 100644 index 0000000000..550683f704 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/page-visibility.https.html @@ -0,0 +1,79 @@ +<!DOCTYPE html> +<link rel="help" href="https://github.com/samuelgoto/idle-detection"> +<title>Tests the Idle Detection API</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/test-only-api.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/page-visibility/resources/window_state_context.js"></script> +<script src="resources/idle-detection-helper.js"></script> +<script> +'use strict'; + +promise_setup(async t => { + await test_driver.set_permission({ name: 'idle-detection' }, 'granted'); + if (isChromiumBased) { + await loadChromiumResources(); + } +}) + +promise_test(async t => { + let monitor; + + expect(addMonitor).andReturn(async (monitorPtr) => { + monitor = monitorPtr; + return { + error: IdleDetectorError.SUCCESS, + state: { + idleTime: null, + screenLocked: false + } + }; + }); + + const controller = new AbortController(); + t.add_cleanup(() => { + controller.abort(); + }); + const detector = new IdleDetector(); + const watcher = new EventWatcher(t, detector, ["change"]); + const initial_state = watcher.wait_for("change"); + + await detector.start({threshold: 60000, signal: controller.signal}); + await initial_state; + + assert_equals(detector.userState, "active"); + assert_false(document.hidden); + + const {minimize, restore} = window_state_context(t); + + await minimize(); + monitor.update( + { + idleTime: { milliseconds: 0 }, + screenLocked: false + }, + /*is_overridden_by_devtools=*/true + ); + + // Assert that the detector works while the page is not visible. + await watcher.wait_for("change"); + assert_equals(detector.userState, "idle"); + assert_true(document.hidden); + + await restore(); + monitor.update( + { + idleTime: null, + screenLocked: false + }, + /*is_overridden_by_devtools=*/true + ); + + await watcher.wait_for("change"); + assert_equals(detector.userState, "active"); + assert_false(document.hidden); +}, 'Page visibility.'); + +</script> diff --git a/testing/web-platform/tests/idle-detection/resources/idle-detection-allowed-by-permissions-policy-worker.js b/testing/web-platform/tests/idle-detection/resources/idle-detection-allowed-by-permissions-policy-worker.js new file mode 100644 index 0000000000..1fe410ed11 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/resources/idle-detection-allowed-by-permissions-policy-worker.js @@ -0,0 +1,16 @@ +'use strict'; + +importScripts('/resources/testharness.js'); + +let workerType; + +if (typeof postMessage === 'function') { + workerType = 'dedicated'; +} + +promise_test(async () => { + await new IdleDetector().start() +}, + `Inherited header permissions policy allows ${workerType} workers.`) + +done(); diff --git a/testing/web-platform/tests/idle-detection/resources/idle-detection-disabled-by-permissions-policy-worker.js b/testing/web-platform/tests/idle-detection/resources/idle-detection-disabled-by-permissions-policy-worker.js new file mode 100644 index 0000000000..c30f7c188e --- /dev/null +++ b/testing/web-platform/tests/idle-detection/resources/idle-detection-disabled-by-permissions-policy-worker.js @@ -0,0 +1,22 @@ +'use strict'; + +importScripts('/resources/testharness.js'); + +const header = 'Permissions-Policy header idle-detection=()'; +let workerType; + +if (typeof postMessage === 'function') { + workerType = 'dedicated'; +} + +promise_test(async () => { + try { + await new IdleDetector().start(); + assert_unreached('expected start() to throw with SecurityError'); + } catch (error) { + assert_equals(error.name, 'SecurityError'); + } +}, +`Inherited ${header} disallows ${workerType} workers.`); + +done(); diff --git a/testing/web-platform/tests/idle-detection/resources/idle-detection-helper.js b/testing/web-platform/tests/idle-detection/resources/idle-detection-helper.js new file mode 100644 index 0000000000..f053e635e0 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/resources/idle-detection-helper.js @@ -0,0 +1,14 @@ +'use strict'; + +// These tests rely on the User Agent providing an implementation of +// platform nfc backends. +// +// In Chromium-based browsers this implementation is provided by a polyfill +// in order to reduce the amount of test-only code shipped to users. To enable +// these tests the browser must be run with these options: +// +// --enable-blink-features=MojoJS,MojoJSTest + +async function loadChromiumResources() { + await import('/resources/chromium/mock-idle-detection.js'); +} diff --git a/testing/web-platform/tests/idle-detection/resources/idlharness-worker.js b/testing/web-platform/tests/idle-detection/resources/idlharness-worker.js new file mode 100644 index 0000000000..9733050284 --- /dev/null +++ b/testing/web-platform/tests/idle-detection/resources/idlharness-worker.js @@ -0,0 +1,22 @@ +'use strict'; + +importScripts("/resources/testharness.js"); +importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js"); + +idl_test( + ['idle-detection'], + ['dom', 'html'], + async (idl_array, t) => { + self.idle = new IdleDetector(); + let watcher = new EventWatcher(t, self.idle, ["change"]); + let initial_state = watcher.wait_for("change"); + await self.idle.start(); + await initial_state; + + idl_array.add_objects({ + IdleDetector: ['idle'], + }); + } +); + +done(); |