diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/hr-time | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/hr-time')
25 files changed, 646 insertions, 0 deletions
diff --git a/testing/web-platform/tests/hr-time/META.yml b/testing/web-platform/tests/hr-time/META.yml new file mode 100644 index 0000000000..779d5b4af0 --- /dev/null +++ b/testing/web-platform/tests/hr-time/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/hr-time/ +suggested_reviewers: + - plehegar + - igrigorik diff --git a/testing/web-platform/tests/hr-time/basic.any.js b/testing/web-platform/tests/hr-time/basic.any.js new file mode 100644 index 0000000000..4cd6e42dfc --- /dev/null +++ b/testing/web-platform/tests/hr-time/basic.any.js @@ -0,0 +1,37 @@ +test(function() { + assert_true((self.performance !== undefined), "self.performance exists"); + assert_equals(typeof self.performance, "object", "self.performance is an object"); + assert_equals((typeof self.performance.now), "function", "self.performance.now() is a function"); + assert_equals(typeof self.performance.now(), "number", "self.performance.now() returns a number"); +}, "self.performance.now() is a function that returns a number"); + +test(function() { + assert_true(self.performance.now() > 0); +}, "self.performance.now() returns a positive number"); + +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0); + }, "self.performance.now() difference is not negative"); + +async_test(function() { + // Check whether the performance.now() method is close to Date() within 30ms (due to inaccuracies) + var initial_hrt = self.performance.now(); + var initial_date = Date.now(); + this.step_timeout(function() { + var final_hrt = self.performance.now(); + var final_date = Date.now(); + assert_approx_equals(final_hrt - initial_hrt, final_date - initial_date, 30, 'High resolution time value increased by approximately the same amount as time from date object'); + this.done(); + }, 2000); +}, 'High resolution time has approximately the right relative magnitude'); + +test(function() { + var didHandle = false; + self.performance.addEventListener("testEvent", function() { + didHandle = true; + }, { once: true} ); + self.performance.dispatchEvent(new Event("testEvent")); + assert_true(didHandle, "Performance extends EventTarget, so event dispatching should work."); +}, "Performance interface extends EventTarget."); diff --git a/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html b/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html new file mode 100644 index 0000000000..ce30698b77 --- /dev/null +++ b/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html @@ -0,0 +1,14 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/clamped-time-origin.js"></script> +</head> +<body> +<script> +// Isolated contexts should be clamped to 5 microseconds. +run_test(/*isolated=*/true); +</script> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html.headers b/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html.headers new file mode 100644 index 0000000000..5f8621ef83 --- /dev/null +++ b/testing/web-platform/tests/hr-time/clamped-time-origin-isolated.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/hr-time/clamped-time-origin.html b/testing/web-platform/tests/hr-time/clamped-time-origin.html new file mode 100644 index 0000000000..1f438e9fef --- /dev/null +++ b/testing/web-platform/tests/hr-time/clamped-time-origin.html @@ -0,0 +1,14 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/clamped-time-origin.js"></script> +</head> +<body> +<script> +// Non-isolated contexts should be clamped to 100 microseconds. +run_test(/*isolated=*/false); +</script> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html b/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html new file mode 100644 index 0000000000..88848740a9 --- /dev/null +++ b/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>window.performance.now should not enable timing attacks</title> +<link rel="author" title="W3C" href="http://www.w3.org/" /> +<link rel="help" href="http://w3c.github.io/hr-time/#privacy-security"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/timing-attack.js"></script> +<script> +run_test(/*isolated=*/true); +</script> +</head> +<body> +<h1>Description</h1> +<p>The recommended minimum resolution of the Performance interface should be set to 5 microseconds.</p> + +<div id="log"></div> + +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html.headers b/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html.headers new file mode 100644 index 0000000000..5f8621ef83 --- /dev/null +++ b/testing/web-platform/tests/hr-time/cross-origin-isolated-timing-attack.https.html.headers @@ -0,0 +1,2 @@ +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Opener-Policy: same-origin diff --git a/testing/web-platform/tests/hr-time/idlharness-shadowrealm.window.js b/testing/web-platform/tests/hr-time/idlharness-shadowrealm.window.js new file mode 100644 index 0000000000..3209db5f41 --- /dev/null +++ b/testing/web-platform/tests/hr-time/idlharness-shadowrealm.window.js @@ -0,0 +1,2 @@ +// META: script=/resources/idlharness-shadowrealm.js +idl_test_shadowrealm(["hr-time"], ["html", "dom"]); diff --git a/testing/web-platform/tests/hr-time/idlharness.any.js b/testing/web-platform/tests/hr-time/idlharness.any.js new file mode 100644 index 0000000000..6676b001a8 --- /dev/null +++ b/testing/web-platform/tests/hr-time/idlharness.any.js @@ -0,0 +1,23 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +// https://w3c.github.io/hr-time/ + +idl_test( + ['hr-time'], + ['html', 'dom'], + async idl_array => { + if (self.GLOBAL.isWorker()) { + idl_array.add_objects({ WorkerGlobalScope: ['self'] }); + } else { + idl_array.add_objects({ Window: ['self'] }); + } + idl_array.add_objects({ + Performance: ['performance'], + }); + } +); diff --git a/testing/web-platform/tests/hr-time/monotonic-clock.any.js b/testing/web-platform/tests/hr-time/monotonic-clock.any.js new file mode 100644 index 0000000000..c53b04d844 --- /dev/null +++ b/testing/web-platform/tests/hr-time/monotonic-clock.any.js @@ -0,0 +1,13 @@ +// The time values returned when calling the now method MUST be monotonically increasing and not subject to system clock adjustments or system clock skew. +test(function() { + assert_true(self.performance.now() > 0, "self.performance.now() returns positive numbers"); +}, "self.performance.now() returns a positive number"); + +// The difference between any two chronologically recorded time values returned from the now method MUST never be negative. +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0, "self.performance.now() difference is not negative"); + }, + "self.performance.now() difference is not negative" +); diff --git a/testing/web-platform/tests/hr-time/navigation-start-post-before-unload.html b/testing/web-platform/tests/hr-time/navigation-start-post-before-unload.html new file mode 100644 index 0000000000..88ee5db77e --- /dev/null +++ b/testing/web-platform/tests/hr-time/navigation-start-post-before-unload.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + function busyWait(millis) { + const start = performance.now(); + while (performance.now() < start + millis) {} + } + promise_test(async t => { + const delay = 3000; + const iframe = document.createElement('iframe'); + iframe.src = './resources/now_frame.html'; + document.body.appendChild(iframe); + await new Promise(resolve => iframe.addEventListener('load', resolve)); + iframe.contentWindow.addEventListener('beforeunload', () => { + busyWait(delay); + }); + iframe.src = './resources/post.html'; + await new Promise(resolve => this.addEventListener('message', ({data}) => { + if (data === 'done') + resolve(); + })); + + const entry = iframe.contentWindow.performance.getEntriesByType('navigation')[0]; + assert_less_than(entry.fetchStart, delay); + }, 'timeOrigin should be set after beforeunload'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/performance-tojson.html b/testing/web-platform/tests/hr-time/performance-tojson.html new file mode 100644 index 0000000000..fd8049cb9a --- /dev/null +++ b/testing/web-platform/tests/hr-time/performance-tojson.html @@ -0,0 +1,76 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +test(() => { + // Check Performance attributes. + assert_equals(typeof(performance.toJSON), 'function'); + const json = performance.toJSON(); + assert_equals(typeof(json), 'object'); + assert_equals(json.timeOrigin, performance.timeOrigin, + 'performance.toJSON().timeOrigin should match performance.timeOrigin'); + + // Check PerformanceTiming toJSON. + const jsonTiming = json.timing; + const timing = performance.timing; + assert_equals(typeof(timing.toJSON), 'function'); + const timingJSON = timing.toJSON(); + assert_equals(typeof(timingJSON), 'object'); + // Check PerformanceTiming attributes, from both: + // 1) |jsonTiming| from Performance. + // 2) |timingJSON| from PerformanceTiming. + const performanceTimingKeys = [ + 'navigationStart', + 'unloadEventStart', + 'unloadEventEnd', + 'redirectStart', + 'redirectEnd', + 'fetchStart', + 'domainLookupStart', + 'domainLookupEnd', + 'connectStart', + 'connectEnd', + 'secureConnectionStart', + 'requestStart', + 'responseStart', + 'responseEnd', + 'domLoading', + 'domInteractive', + 'domContentLoadedEventStart', + 'domContentLoadedEventEnd', + 'domComplete', + 'loadEventStart', + 'loadEventEnd' + ]; + for (const key of performanceTimingKeys) { + assert_equals(jsonTiming[key], timing[key], + `performance.toJSON().timing.${key} should match performance.timing.${key}`); + assert_equals(timingJSON[key], timing[key], + `performance.timing.toJSON().${key} should match performance.timing.${key}`); + } + + // Check PerformanceNavigation toJSON. + const jsonNavigation = json.navigation; + const navigation = performance.navigation; + assert_equals(typeof(navigation.toJSON), 'function'); + const navigationJSON = navigation.toJSON(); + assert_equals(typeof(navigationJSON), 'object'); + // Check PerformanceNavigation attributes, from both: + // 1) |jsonNavigation| from Performance. + // 2) |navigationJSON| from PerformanceNavigation. + let performanceNavigationKeys = ['type', 'redirectCount']; + for (const key of performanceNavigationKeys) { + assert_equals(jsonNavigation[key], navigation[key], + `performance.toJSON().navigation.${key} should match performance.navigation.${key}`); + assert_equals(navigationJSON[key], navigation[key], + `performance.navigation.toJSON().${key} should match performance.navigation.${key}`); + } +}, 'Test performance.toJSON()'); +</script> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/hr-time/resources/clamped-time-origin.js b/testing/web-platform/tests/hr-time/resources/clamped-time-origin.js new file mode 100644 index 0000000000..09967ed6d1 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/clamped-time-origin.js @@ -0,0 +1,30 @@ +const run_test = isolated => { + // Multiplier to convert the clamped timestamps to microseconds. + const multiplier = 1000; + const windowOrigin = performance.timeOrigin; + // Clamp to at least 5 microseconds in isolated contexts and at least 100 in + // non-isolated ones. + const resolution = isolated ? 5 : 100; + + const create_worker = () => { + return new Promise(resolve => { + const workerScript = 'postMessage({timeOrigin: performance.timeOrigin})'; + const blob = new Blob([workerScript]); + const worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', event => { + resolve(event.data.timeOrigin); + }); + }); + }; + promise_test(async t => { + assert_equals(self.crossOriginIsolated, isolated, + "crossOriginIsolated is properly set"); + let prev = windowOrigin; + let current; + for (let i = 1; i < 100; ++i) { + current = await create_worker(); + assert_true(current === prev || current - prev > resolution / 1000); + prev = current; + } + }, 'timeOrigins are clamped.'); +}; diff --git a/testing/web-platform/tests/hr-time/resources/now_frame.html b/testing/web-platform/tests/hr-time/resources/now_frame.html new file mode 100644 index 0000000000..5bec688af9 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/now_frame.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML> +<html> + <head> + <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> + <title>window.performance.now frame</title> + <link rel="author" title="Google" href="http://www.google.com/" /> + </head> + <body></body> +</html> diff --git a/testing/web-platform/tests/hr-time/resources/post.html b/testing/web-platform/tests/hr-time/resources/post.html new file mode 100644 index 0000000000..b8541016dd --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/post.html @@ -0,0 +1,4 @@ +<!DOCTYPE HTML> +<script> + window.parent.postMessage('done'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/hr-time/resources/timing-attack.js b/testing/web-platform/tests/hr-time/resources/timing-attack.js new file mode 100644 index 0000000000..f1fc786903 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/timing-attack.js @@ -0,0 +1,42 @@ +function run_test(isolated) { + let resolution = 100; + if (isolated) { + resolution = 5; + } + test(function() { + function check_resolutions(times, length) { + const end = length - 2; + + // we compare each value with the following ones + for (let i = 0; i < end; i++) { + const h1 = times[i]; + for (let j = i+1; j < end; j++) { + const h2 = times[j]; + const diff = h2 - h1; + assert_true((diff === 0) || ((diff * 1000) >= resolution), + "Differences smaller than ' + resolution + ' microseconds: " + diff); + } + } + return true; + } + + const times = new Array(10); + let index = 0; + let hrt1, hrt2, hrt; + assert_equals(self.crossOriginIsolated, isolated, "Document cross-origin isolated value matches"); + + // rapid firing of performance.now + hrt1 = performance.now(); + hrt2 = performance.now(); + times[index++] = hrt1; + times[index++] = hrt2; + + // ensure that we get performance.now() to return a different value + do { + hrt = performance.now(); + times[index++] = hrt; + } while ((hrt - hrt1) === 0); + + assert_true(check_resolutions(times, index), 'Difference should be at least ' + resolution + ' microseconds.'); + }, 'The recommended minimum resolution of the Performance interface has been set to ' + resolution + ' microseconds for cross-origin isolated contexts.'); +} diff --git a/testing/web-platform/tests/hr-time/resources/unload-a.html b/testing/web-platform/tests/hr-time/resources/unload-a.html new file mode 100644 index 0000000000..40c1d06183 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/unload-a.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> + <title>Helper page for ../unload-manual.html</title> +</head> +<body> + <script src="./unload.js"></script> + <script> + setupListeners("a", "./unload-b.html"); + </script> + <button id="proceed">Click me!</button> +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/resources/unload-b.html b/testing/web-platform/tests/hr-time/resources/unload-b.html new file mode 100644 index 0000000000..7c2d90df27 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/unload-b.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> + <title>Helper page for ../unload-manual.html</title> +</head> +<body> + <script src="./unload.js"></script> + <script> + setupListeners("b", "./unload-c.html"); + </script> + <button id="proceed">Click me again!</button> +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/resources/unload-c.html b/testing/web-platform/tests/hr-time/resources/unload-c.html new file mode 100644 index 0000000000..731da9db75 --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/unload-c.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> + <title>Helper page for ../unload-manual.html</title> +</head> +<body> + <script src="./unload.js"></script> + <script> + setupListeners("c", null); + </script> + <button id="proceed">Click me, one last time!</button> +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/resources/unload.js b/testing/web-platform/tests/hr-time/resources/unload.js new file mode 100644 index 0000000000..ab6b121c2b --- /dev/null +++ b/testing/web-platform/tests/hr-time/resources/unload.js @@ -0,0 +1,51 @@ +const syncDelay = ms => { + const start = performance.now(); + let elapsedTime; + do { + elapsedTime = performance.now() - start; + } while (elapsedTime < ms); +}; + +const markTime = (docName, lifecycleEventName) => { + // Calculating these values before the below `mark` invocation ensures that delays in + // reaching across to the other window object doesn't interfere with the correctness + // of the test. + const dateNow = Date.now(); + const performanceNow = performance.now(); + + window.opener.mark({ + docName, + lifecycleEventName, + performanceNow: performanceNow, + dateNow: dateNow + }); +}; + +const setupUnloadPrompt = (docName, msg) => { + window.addEventListener("beforeunload", ev => { + markTime(docName, "beforeunload"); + return ev.returnValue = msg || "Click OK to continue test." + }); +}; + +const setupListeners = (docName, nextDocument) => { + window.addEventListener("load", () => { + markTime(docName, "load"); + document.getElementById("proceed").addEventListener("click", ev => { + ev.preventDefault(); + if (nextDocument) { + document.location = nextDocument; + } else { + window.close(); + } + }) + }); + + setupUnloadPrompt(docName); + + window.addEventListener("unload", () => { + markTime(docName, "unload"); + if (docName !== "c") { syncDelay(1000); } + }); +}; + diff --git a/testing/web-platform/tests/hr-time/test_cross_frame_start.html b/testing/web-platform/tests/hr-time/test_cross_frame_start.html new file mode 100644 index 0000000000..30e804bd73 --- /dev/null +++ b/testing/web-platform/tests/hr-time/test_cross_frame_start.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" > + <title>window.performance.now across frames</title> + <link rel="author" title="Google" href="http://www.google.com/"> + <link rel="help" href="http://www.w3.org/TR/hr-time/#sec-extenstions-performance-interface"> + + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + + <script type="text/javascript"> + setup({explicit_done: true}); + + var setup_frame = async_test("Setup the frame"); + + function start_test() { + setup_frame.step_timeout(function () { + var iframe = document.createElement('iframe'); + iframe.id = 'frameContext'; + iframe.onload = finish_test; + iframe.src = "resources/now_frame.html"; + document.body.appendChild(iframe); + setup_frame.done(); + }, 1000); + } + + function finish_test() { + var childWindow = document.getElementById('frameContext').contentWindow; + + // Verify a positive number is returned for both the frame and parent. + test(function() { assert_true(window.performance.now() > 0); }, 'parent performance.now() > 0'); + test(function() { assert_true(childWindow.performance.now() > 0); }, 'child performance.now() > 0'); + + // Verify that the test properly created the child at least a second after the parent. + test(function () { assert_true(childWindow.performance.timing.navigationStart > (window.performance.timing.navigationStart + 1000)); }, + 'Child created at least 1 second after parent'); + + test(function () { + var parentNow = window.performance.now(); + var childNow = childWindow.performance.now(); + var childParentSkew = Math.abs(childNow - parentNow); + assert_true(childParentSkew > 1000, 'Child and parent\'s now()s have different bases (skewed more than 1 second)'); + + var childLoadTime = childWindow.performance.timing.loadEventStart - childWindow.performance.timing.navigationStart; + assert_true(1000 > (childNow - childLoadTime), 'Child\'s now() is based on its document\'s navigationStart'); + }, 'Child and parent time bases are correct'); + + done(); + } + </script> + + </head> + <body onload="start_test()"> + <h1>Description</h1> + <p>This test validates the values of the window.performance.now() are based on the current document's navigationStart.</p> + <div id="log"></div> + </body> +</html> diff --git a/testing/web-platform/tests/hr-time/timeOrigin.html b/testing/web-platform/tests/hr-time/timeOrigin.html new file mode 100644 index 0000000000..20aea75084 --- /dev/null +++ b/testing/web-platform/tests/hr-time/timeOrigin.html @@ -0,0 +1,45 @@ +<!doctype html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +const windowOrigin = performance.timeOrigin; + +test(() => { + // Use a 30ms cushion when comparing with Date() to account for inaccuracy. + const startTime = Date.now(); + assert_greater_than_equal(startTime + 30, windowOrigin, 'Date.now() should be at least as large as the window timeOrigin.'); + const startNow = performance.now(); + assert_less_than_equal(startTime, windowOrigin + startNow + 30, 'Date.now() should be close to window timeOrigin.'); +}, 'Window timeOrigin is close to Date.now() when there is no system clock adjustment.'); + +const workerScript = 'postMessage({timeOrigin: performance.timeOrigin})'; +const blob = new Blob([workerScript]); + +async_test(function(t) { + const beforeWorkerCreation = performance.now(); + const worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', t.step_func_done(function(event) { + const workerOrigin = event.data.timeOrigin; + assert_greater_than_equal(workerOrigin, windowOrigin + beforeWorkerCreation, 'Worker timeOrigin should be greater than the window timeOrigin.'); + const afterWorkerCreation = performance.now(); + assert_less_than_equal(workerOrigin - windowOrigin, afterWorkerCreation, 'Window and worker timeOrigins should be close.'); + })); +}, 'Window and worker timeOrigins are close when created one after another.'); + +async_test(function(t) { + this.step_timeout(function() { + const workerCreation = performance.now(); + const worker = new Worker(URL.createObjectURL(blob)); + worker.addEventListener('message', t.step_func_done(function(event) { + const workerOrigin = event.data.timeOrigin; + assert_greater_than_equal(workerOrigin - windowOrigin, 200, 'We waited 200ms to spawn the second worker, so its timeOrigin should be greater than that of the window.'); + })); + }, 200); +}, 'Window and worker timeOrigins differ when worker is created after a delay.'); +</script> +</body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/hr-time/timing-attack.html b/testing/web-platform/tests/hr-time/timing-attack.html new file mode 100644 index 0000000000..6352b4dbe3 --- /dev/null +++ b/testing/web-platform/tests/hr-time/timing-attack.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>window.performance.now should not enable timing attacks</title> +<link rel="author" title="W3C" href="http://www.w3.org/" /> +<link rel="help" href="http://w3c.github.io/hr-time/#privacy-security"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/timing-attack.js"></script> +<script> +run_test(/*isolated=*/false); +</script> +</head> +<body> +<h1>Description</h1> +<p>The recommended minimum resolution of the Performance interface should be set to 100 microseconds for non-isolated contexts.</p> + +<div id="log"></div> + +</body> +</html> diff --git a/testing/web-platform/tests/hr-time/unload-manual.html b/testing/web-platform/tests/hr-time/unload-manual.html new file mode 100644 index 0000000000..18c4e0dc32 --- /dev/null +++ b/testing/web-platform/tests/hr-time/unload-manual.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> +<head> + <title>time origin value manual test</title> + <link rel="help" href="https://w3c.github.io/hr-time/#time-origin-1"> + <link rel="prefetch" href="./resources/unload-a.html"> + <link rel="prefetch" href="./resources/unload-b.html"> + <link rel="prefetch" href="./resources/unload-c.html"> +</head> +<body> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + setup({ explicit_timeout: true }); + + const ACCEPTABLE_VARIANCE = 400; // ms + + const isRoughlyEqual = (a, b) => Math.abs(a - b) < ACCEPTABLE_VARIANCE; + + const timings = { a: {}, b: {}, c: {} }; + const t = async_test("hr-time time origin"); + + window.mark = msg => { + timings[msg.docName][msg.lifecycleEventName] = { + performanceNow: msg.performanceNow, + dateNow: msg.dateNow + }; + + if (msg.docName === "c" && msg.lifecycleEventName === "unload") { + setTimeout(makeAssertions, 0); + } + }; + + function makeAssertions () { + t.step(() => { + const loadTimeBetweenAandB = timings.b.load.dateNow - timings.a.unload.dateNow; + const loadTimeBetweenBandC = timings.c.load.dateNow - timings.b.unload.dateNow; + + assert_true( + isRoughlyEqual(loadTimeBetweenAandB, timings.b.load.performanceNow), + "Document in reused window's time origin should be time of close of pop-up box." + ); + assert_true( + isRoughlyEqual(loadTimeBetweenBandC, timings.c.load.performanceNow), + "Document in reused window's time origin should be time of close of pop-up box." + ); + assert_true( + !isRoughlyEqual(timings.a.unload.performanceNow, 0), + "Time origin during unload event should match that of rest of document." + ); + assert_true( + !isRoughlyEqual(timings.b.unload.performanceNow, 0), + "Time origin during unload event should match that of rest of document." + ); + assert_true( + !isRoughlyEqual(timings.c.unload.performanceNow, 0), + "Time origin during unload event should match that of rest of document." + ); + }); + t.done(); + } + </script> + + <h2>Description</h2> + <p>This test validates the behavior of <code>performance.now()</code> with respect to its time origin.</p> + <div id="log"> + <h2>Manual Test Steps</h2> + <ol> + <li><a href="resources/unload-a.html" target="_blank">Click here</a> + </ol> + </div> +</body> +<html> diff --git a/testing/web-platform/tests/hr-time/window-worker-timeOrigin.window.js b/testing/web-platform/tests/hr-time/window-worker-timeOrigin.window.js new file mode 100644 index 0000000000..1e5ef1cdff --- /dev/null +++ b/testing/web-platform/tests/hr-time/window-worker-timeOrigin.window.js @@ -0,0 +1,30 @@ +"use strict" +// https://w3c.github.io/hr-time/#time-origin + +async_test(function(test) { + // Cache global time before starting worker + const globalTimeOrigin = performance.timeOrigin; + const globalNowBeforeWorkerStart = performance.now(); + + // Start worker and retrieve time + const workerScript = "postMessage({timeOrigin: performance.timeOrigin, now: performance.now()})"; + const blob = new Blob([workerScript]); + let worker = new Worker(URL.createObjectURL(blob)); + + worker.addEventListener("message", test.step_func_done(function(event) { + const workerTimeOrigin = event.data.timeOrigin; + const workerNow = event.data.now; + + assert_not_equals(workerTimeOrigin, 0, "worker timeOrigin must not be 0"); + assert_not_equals(performance.timeOrigin, 0, "Document timeOrigin must not be 0"); + + assert_equals(globalTimeOrigin, performance.timeOrigin, "timeOrigin should not be changed in same document mode"); + assert_less_than(globalTimeOrigin, workerTimeOrigin, "Document timeOrigin must be earlier than worker timeOrigin"); + + // Document and worker's now() start from their respective timeOrigins. + const timeDiff = workerTimeOrigin - globalTimeOrigin; // convert worker's time to Document time. + assert_less_than(globalTimeOrigin + globalNowBeforeWorkerStart, globalTimeOrigin + timeDiff + workerNow, "Document old now is earlier than worker now."); + + // Comparing timing between Document and worker threads could be delicate as it relies on the thread implementation and could be subject to race conditions. + })); +}, 'timeOrigin and now() should be correctly ordered between window and worker'); |