diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal')
68 files changed, 2386 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-1.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-1.html new file mode 100644 index 0000000000..cadcf126f5 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-1.html @@ -0,0 +1,11 @@ +<!doctype html> +001-1 +<script> +addEventListener("pageshow", + function(e) { + parent.events.push(e); + if (parent.events.length == 2) { + parent.do_test(); + } + }, false); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-2.html new file mode 100644 index 0000000000..6387bc89c8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001-2.html @@ -0,0 +1,5 @@ +<!doctype html> +001-2 +<script> +onload = function() {setTimeout(function() {history.go(-1)}, 500)} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001.html new file mode 100644 index 0000000000..336ede4cb6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/001.html @@ -0,0 +1,35 @@ +<!doctype html> +<title>pageshow event from traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe src="001-1.html"></iframe> +<script> +var t = async_test(); +var events = []; +var iframe = document.getElementsByTagName("iframe")[0]; + +onload = t.step_func(function() { + setTimeout(t.step_func( + function() { + assert_equals(iframe.contentDocument.readyState, "complete") + iframe.src = "001-2.html"; + }), 500); + onload = null; +}) + +do_test = t.step_func(function() { + assert_equals(events.length, 2); + events.forEach(function(e, i) { + phase = i ? "after" : "before"; + assert_equals(e.type, "pageshow", "type " + phase + " navigation"); + + // https://github.com/whatwg/html/issues/6794 + assert_equals(e.bubbles, true, "bubbles " + phase + " navigation"); + assert_equals(e.cancelable, true, "cancelable " + phase + " navigation"); + + assert_equals(e.persisted, i == 0 ? false : true, "persisted " + phase + " navigation"); + t.done(); + }); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html new file mode 100644 index 0000000000..9ee7576249 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html @@ -0,0 +1,47 @@ +<!doctype html> +<meta charset=utf-8> +<title>Synthetic popstate events</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + assert_throws_js( + TypeError, + () => PopStateEvent(''), + "Calling PopStateEvent constructor without 'new' must throw" + ); +}, "PopStateEvent constructor called as normal function"); + +test(function () { + assert_false('initPopStateEvent' in PopStateEvent.prototype, + 'There should be no PopStateEvent#initPopStateEvent'); +}, 'initPopStateEvent'); + +test(function () { + var popStateEvent = new PopStateEvent("popstate"); + assert_equals(popStateEvent.state, null, "the PopStateEvent.state"); +}, "Initial value of PopStateEvent.state must be null"); + +test(function () { + var popStateEvent = new PopStateEvent("popstate"); + assert_false(popStateEvent.hasUAVisualTransition, "the PopStateEvent.hasUAVisualTransition"); +}, "Initial value of PopStateEvent.hasUAVisualTransition must be false"); + +test(function () { + var state = history.state; + var data; + var hasUAVisualTransition = false; + window.addEventListener('popstate', function (e) { + data = e.state; + hasUAVisualTransition = e.hasUAVisualTransition; + }); + window.dispatchEvent(new PopStateEvent('popstate', { + 'state': {testdata:true}, + 'hasUAVisualTransition': true + })); + assert_true(data.testdata,'state data was corrupted'); + assert_equals(history.state, state, "history.state was NOT set by dispatching the event"); + assert_true(hasUAVisualTransition, 'hasUAVisualTransition not set correctly'); +}, 'Dispatching a synthetic PopStateEvent'); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/api-availability.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/api-availability.html new file mode 100644 index 0000000000..2f7d3fafdf --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/api-availability.html @@ -0,0 +1,22 @@ +<!doctype html> +<title>API availability following history traversal</title> +<meta charset=utf-8> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<p>Test requires popup blocker disabled</p> +<div id=log></div> +<script> +var t = async_test(); +var hasNavigated = false; +var child; +t.step(function() { + child = window.open("resources/api-availability-1.html"); + t.add_cleanup(function() { + child.close(); + }); +}); +navigate = t.step_func(function() { + hasNavigated = true; + child.location = child.location.href.replace("api-availability-1.html", "api-availability-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html new file mode 100644 index 0000000000..5cbab71a5e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html @@ -0,0 +1,35 @@ +<iframe id="test"></iframe> +<script> +var opener = window.opener; +var t = opener.t; +var f = document.getElementById("test"); +var l = opener.document.getElementById("step_log"); + +log = function(t) {l.textContent += ("\n" + t)} +var navigated = false; +var steps = [ + () => f.src = "browsing_context_name-1.html", + () => { + navigated = true; + opener.assert_equals(f.contentWindow.name, "test", "Initial load"); + f.src = "browsing_context_name-2.html" + }, + () => { + opener.assert_equals(f.contentWindow.name, "test1"); + opener.assert_equals(history.length, 2); + history.back() + }, + () => { + opener.assert_equals(f.contentWindow.name, "test1", "After navigation"); + t.done(); + } +].map((x, i) => t.step_func(() => {log("Step " + (i+1)); x()})); + +next = () => steps.shift()(); + +onload = () => { + log("page load"); + f.onload = () => {log("iframe onload"); next()}; + setTimeout(next, 0); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-1.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-1.html new file mode 100644 index 0000000000..85748a2ebc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-1.html @@ -0,0 +1,6 @@ +document 1 +<script> +if (!parent.navigated) { + window.name = "test"; +} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-2.html new file mode 100644 index 0000000000..b0c869046b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-2.html @@ -0,0 +1,4 @@ +document 2 +<script> +window.name = "test1"; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-3.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-3.html new file mode 100644 index 0000000000..e0c239744f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-3.html @@ -0,0 +1,6 @@ +document 3 +<script> +if (!parent.navigated) { + window.name = "test3"; +} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-4.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-4.html new file mode 100644 index 0000000000..5d2dfa6bb8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name-4.html @@ -0,0 +1,6 @@ +document 4 +<script> +if (!parent.navigated) { + window.name = "test4"; +} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name.html new file mode 100644 index 0000000000..60a8acb098 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name.html @@ -0,0 +1,13 @@ +<!doctype html> +<title>Retaining window.name on history traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<pre id="step_log"></pre> + +<script> +var t = async_test(); +t.step(() => { + win = window.open("browsing_context_name-0.html"); + t.add_cleanup(() => win.close()); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin-0.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin-0.html new file mode 100644 index 0000000000..9e91722714 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin-0.html @@ -0,0 +1,34 @@ +<iframe id="test"></iframe> +<script> +var t = opener.t; +var f = document.getElementById("test"); +var l = opener.document.getElementById("step_log"); + +var log = function(t) {l.textContent += ("\n" + t)} +var navigated = false; +var steps = [ + () => f.src = "browsing_context_name-1.html", + () => { + navigated = true; + opener.assert_equals(f.contentWindow.name, "test", "Initial load"); + f.src = f.src.replace("http://", "http://www.").replace("browsing_context_name-1", "browsing_context_name-2"); + }, + () => { + // Can't test .name easily here because it's cross-origin + opener.assert_equals(history.length, 2); + history.back() + }, + () => { + opener.assert_equals(f.contentWindow.name, "test", "After navigation"); + t.done(); + } +].map((x, i) => t.step_func(() => {log("Step " + (i+1)); x()})); + +next = () => steps.shift()(); + +onload = () => { + log("page load"); + f.onload = () => {log("iframe onload"); next()}; + setTimeout(next, 0); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin.html new file mode 100644 index 0000000000..caa0bce3eb --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin.html @@ -0,0 +1,13 @@ +<!doctype html> +<title>Restoring window.name on cross-origin history traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<pre id="step_log"></pre> + +<script> +var t = async_test(); +t.step(() => { + var win = window.open("browsing_context_name_cross_origin-0.html"); + t.add_cleanup(() => win.close()); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_2.html new file mode 100644 index 0000000000..8202a892a3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_2.html @@ -0,0 +1,43 @@ +<!doctype html> +<title>Restoring window.name on cross-origin history traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<pre id="step_log"></pre> +<iframe id="test"></iframe> +<script> +var t = async_test(); +var f = document.getElementById("test"); +var l = document.getElementById("step_log"); + +log = function(t) {l.textContent += ("\n" + t)} + +var steps = [ + function() {f.src = "browsing_context_name-1.html"}, + function() { + assert_equals(f.contentWindow.name, "test", "Initial load"); + setTimeout(next, 0); + }, + function() {f.src = "browsing_context_name-3.html"}, + function() { + assert_equals(f.contentWindow.name, "test3", "After navigation 1"); + setTimeout(next, 0); + }, + function() {f.src = f.src.replace("http://", "http://www.").replace("browsing_context_name-3", "browsing_context_name-2");}, + function() { + setTimeout(next, 0); + }, + function() {history.go(-2); setTimeout(next, 500)}, + function() { + assert_equals(f.contentWindow.name, "test3", "After navigation 2"); + t.done(); + } +].map(function(x) {return t.step_func(function() {log("Step " + step + " " + f.contentWindow.location); x()})}); + +var step = 0; +next = t.step_func(function() {steps[step++]()}); + +f.onload=next; + +onload = function() { setTimeout(next, 0); }; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3.html new file mode 100644 index 0000000000..b6a35680dd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/browsing_context_name_cross_origin_3.html @@ -0,0 +1,44 @@ +<!doctype html> +<title>Restoring window.name on cross-origin history traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<pre id="step_log"></pre> +<iframe id="test"></iframe> +<script> +var t = async_test(); +var f = document.getElementById("test"); +var l = document.getElementById("step_log"); + +log = function(t) {l.textContent += ("\n" + t)} + +var steps = [ + function() {f.src = "browsing_context_name-1.html"}, + function() { + assert_equals(f.contentWindow.name, "test", "Initial load"); + setTimeout(next, 0); + }, + function() {f.src = "browsing_context_name-3.html"}, + function() { + assert_equals(f.contentWindow.name, "test3", "After navigation 1"); + setTimeout(next, 0); + }, + function() {f.src = f.src.replace("http://", "http://www.").replace("browsing_context_name-1", "browsing_context_name-2");}, + function() {f.src = f.src.replace("http://www.", "http://").replace("browsing_context_name-2", "browsing_context_name-4");}, + function() { + assert_equals(f.contentWindow.name, "test3", "After navigation 2"); + history.go(-3); setTimeout(next, 500) + }, + function() { + assert_equals(f.contentWindow.name, "test3", "After navigation 3"); + t.done(); + } +].map(function(x) {return t.step_func(function() {log("Step " + step + " " + f.contentWindow.location); x()})}); + +var step = 0; +next = t.step_func(function() {steps[step++]()}); + +f.onload=next; + +onload = function() { setTimeout(next, 0); }; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/document-state.https.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/document-state.https.html new file mode 100644 index 0000000000..f03efc3b65 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/document-state.https.html @@ -0,0 +1,133 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test the properties of a session history entry's document state</title> +<link rel="help" href="https://html.spec.whatwg.org/#document-state"> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +// In this test, we create an auxiliary window with a session history A -> B, +// where the document on site B is the current active document. Bf-cache is +// disabled via `Cache-Control: no-store` headers. We then `history.back()` to +// site A, and perform `location.replace(B)`. This makes the first document in +// the session history now same-origin/site with the URL in the subsequent +// session history entry's document state. +// +// We then perform `history.forward()` in the first document, which loads the +// second document (from network). We confirm that the resulting navigation +// request was made with the expected state, stored on the history entry's +// document state. The consequences of this are: +// - The navigation is made with the `Sec-Fetch-Site: cross-site` header, +// indicating that the *original* document state's initiator origin was +// preserved +// - The navigation is made with a cross-origin `Referer` header, indicating +// that the *original* document state's referrer was preserved +// - The resulting document has a cross-origin `document.referrer`, indicating +// the same as above +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + const A = await rcHelper.addWindow(); + + // Create B on a new origin (with bf-cache disabled). + const B = await A.navigateToNew({ + origin: 'HTTPS_NOTSAMESITE_ORIGIN', + headers: [['Cache-Control', 'no-store']], + }); + + // This is the origin we're going to navigate A to, so that it becomes + // same-origin with B. + const originB = new URL(await B.executeScript(() => location.href)).origin; + await B.historyBack(); + + // Make A navigate to the same document but in origin B: + const urlA = await A.executeScript(() => location.href); + const originA = new URL(urlA).origin; + assert_not_equals(originA, originB, 'Contexts A and B are cross-origin'); + + // Load A's current document but on origin B. + const newUrlOnOriginB = urlA.replace(originA, originB); + await A.navigate((url) => { + location.replace(url); + }, [newUrlOnOriginB]); + + // Assert that A and B are now same-origin: + const newUrlA = await A.executeScript(() => { + return location.href; + }); + + // Now the session history looks like: + // B -> B (initiator origin: A) + assert_equals(new URL(newUrlA).origin, originB); + + // This means that when we navigate forward, we should request the second + // document with the history entry's document state, which mostly preserves + // parameters from the original initiator (a cross-site document), despite a + // now-same-origin document initiating this navigation via history. + await A.historyForward(); + + const requestHeaders = await B.getRequestHeaders(); + const documentReferrer = await B.executeScript(() => document.referrer); + + assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' + + 'header'); + assert_equals(requestHeaders.get('referer'), originA + '/', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site ends up with the Referer header that is the ' + + 'original cross-site initiator'); + assert_equals(documentReferrer, originA + '/', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site ends up with document.referrer that is the ' + + 'original cross-site initiator'); +}, "A navigation's initiator origin and referrer are stored in the document " + + "state and used in the document repopulation case"); + +// This test is similar to the above, but instead of testing for the true +// history entry -> document state -> document repopulation case, we stay on [B] +// (the document who was navigated to from [A]) and run `location.reload()` to +// confirm that the initiator information from the [A] -> [B] navigation is used +// when reloading [B], not [B]'s own same-origin information. +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + const A = await rcHelper.addWindow(); + + const originA = new URL(await A.executeScript(() => location.href)).origin; + + // Create B on a new origin. + const B = await A.navigateToNew({ + origin: 'HTTPS_NOTSAMESITE_ORIGIN', + }); + + const originB = new URL(await B.executeScript(() => location.href)).origin; + assert_not_equals(originA, originB, 'Contexts A and B are cross-origin'); + + // Reload B. + await B.navigate(() => { + location.reload(); + }, []); + + const requestHeaders = await B.getRequestHeaders(); + const documentReferrer = await B.executeScript(() => document.referrer); + + assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' + + 'header'); + assert_equals(requestHeaders.get('referer'), originA + '/', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site ends up with the Referer header that is the ' + + 'original cross-site initiator'); + assert_equals(documentReferrer, originA + '/', + 'Same-origin forward history navigation to a document whose original ' + + 'initiator was cross-site ends up with document.referrer that is the ' + + 'original cross-site initiator'); +}, "A navigation's initiator origin and referrer are stored in the document " + + "state and used on location.reload()"); +</script> +</body> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash-twice.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash-twice.html new file mode 100644 index 0000000000..75889ef517 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash-twice.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + // 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement. + window.addEventListener("load", () => t.step_timeout(() => { + assert_array_equals(window.eventOrder, ["load"]); + + window.addEventListener("hashchange", t.step_func(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "popstate", "hashchange"]); + + window.addEventListener("hashchange", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "popstate", "hashchange", "hashchange"]); + })); + }), { once: true }); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["load", "popstate"]); + location.hash = "#2"; + assert_array_equals(window.eventOrder, ["load", "popstate", "popstate"]); + }, 0)); +}, "when changing hash, after the load event"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash.html new file mode 100644 index 0000000000..f74d716d91 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-hash.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + // 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement. + window.addEventListener("load", () => t.step_timeout(() => { + assert_array_equals(window.eventOrder, ["load"]); + + window.addEventListener("hashchange", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]); + })); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["load", "popstate"]); + }, 0)); +}, "when changing hash, after the load event"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-pushState.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-pushState.html new file mode 100644 index 0000000000..4f9f3dad47 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-pushState.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + // 0 timeout is necessary because if we do pushState before load is finished firing it counts as a replacement. + window.addEventListener("load", () => t.step_timeout(() => { + assert_array_equals(window.eventOrder, ["load"]); + + t.step_timeout(t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load"]); + }), 100); + + history.pushState({ state: "new state" }, ""); + }, 0)); +}, "when pushing state, after the load event"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-replaceState.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-replaceState.html new file mode 100644 index 0000000000..28148ff7b2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/after-load-replaceState.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + window.addEventListener("load", t.step_func(() => { + assert_array_equals(window.eventOrder, ["load"]); + + t.step_timeout(t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load"]); + }), 100); + + history.replaceState({ state: "new state" }, ""); + })); +}, "when replacing state, after the load event"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html new file mode 100644 index 0000000000..7c8df11843 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + window.addEventListener("load", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["popstate", "popstate", "hashchange", "hashchange", "load"]); + })); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["popstate"]); + location.hash = "#2"; + assert_array_equals(window.eventOrder, ["popstate", "popstate"]); +}, "when changing hash twice, before load"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html new file mode 100644 index 0000000000..97c4636fad --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + window.addEventListener("load", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["popstate", "hashchange", "load"]); + })); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["popstate"]); +}, "when changing hash, before load"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-pushState.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-pushState.html new file mode 100644 index 0000000000..a08afa474f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-pushState.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + window.addEventListener("load", t.step_func(() => { + t.step_timeout(t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load"]); + }), 100); + })); + + history.pushState({ state: "new state" }, ""); +}, "when pushing state, before load"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-replaceState.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-replaceState.html new file mode 100644 index 0000000000..10d30038fb --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/before-load-replaceState.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + t.step_timeout(t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load"]); + }), 100); + + history.replaceState({ state: "new state" }, ""); +}, "when replacing state, before load"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/pushState-inside-popstate.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/pushState-inside-popstate.html new file mode 100644 index 0000000000..35ada116ed --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/pushState-inside-popstate.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let popstate_called = false; + window.onpopstate = t.step_func(e => { + popstate_called = true; + history.pushState(2, null, "#2"); + assert_not_equals(history.state, e.state); + }); + location.hash = "#1"; + assert_true(popstate_called); +}, "pushState inside popstate") +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-immediate.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-immediate.html new file mode 100644 index 0000000000..51ea20b289 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-immediate.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + // 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement. + window.addEventListener("load", () => t.step_timeout(() => { + assert_array_equals(window.eventOrder, ["load"]); + + window.addEventListener("hashchange", t.step_func(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]); + + window.addEventListener("hashchange", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange", "popstate", "hashchange"]); + })); + }), { once: true }); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["load", "popstate"]); + history.back(); + assert_array_equals(window.eventOrder, ["load", "popstate"]); + }, 0)); +}, "when traversing back, before hashchange"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-wait.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-wait.html new file mode 100644 index 0000000000..39bc760ff7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/event-order/same-document-traverse-wait.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Popstate/hashchange/load event ordering</title> + +<script> +// Set these up super-early before we hit the network for the test harness, just in case. +window.eventOrder = []; +window.onhashchange = () => window.eventOrder.push("hashchange"); +window.onpopstate = () => window.eventOrder.push("popstate"); +window.onload = () => window.eventOrder.push("load"); +</script> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + assert_array_equals(window.eventOrder, []); + + // 0 timeout is necessary because if we do location.hash assignment before load is finished firing it counts as a replacement. + window.addEventListener("load", () => t.step_timeout(() => { + assert_array_equals(window.eventOrder, ["load"]); + + window.addEventListener("hashchange", t.step_func(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]); + + window.addEventListener("hashchange", t.step_func_done(() => { + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange", "popstate", "hashchange"]); + })); + + history.back(); + assert_array_equals(window.eventOrder, ["load", "popstate", "hashchange"]); + }), { once: true }); + + location.hash = "#1"; + assert_array_equals(window.eventOrder, ["load", "popstate"]); + }, 0)); +}, "when traversing back, after hashchange"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/events.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/events.html new file mode 100644 index 0000000000..d5ff83fac0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/events.html @@ -0,0 +1,151 @@ +<!doctype html> +<title> PageTransitionEffect Event </title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var e = new PageTransitionEvent("pageshow", {persisted:false, cancelable:false, bubbles:false}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); + assert_false(e.persisted, "persisted"); +}, "Constructing pageshow event"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {persisted:false, cancelable:false, bubbles:false}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {persisted:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_true(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, persisted true"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {persisted:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_true(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, persisted true"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, empty options"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, empty options"); + +test(function() { + var e = new PageTransitionEvent("pageshow"); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, missing options"); + +test(function() { + var e = new PageTransitionEvent("pagehide"); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, missing options"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {persisted:null}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, persisted:null"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {persisted:null}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, persisted:null"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {persisted:undefined}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, persisted:undefined"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {persisted:undefined}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, persisted:undefined"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {bubbles:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_true(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pageshow event, bubbles:true"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {bubbles:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_true(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); +}, "Constructing pagehide event, bubbles:true"); + +test(function() { + var e = new PageTransitionEvent("pageshow", {cancelable:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pageshow"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_true(e.cancelable, "cancelable"); +}, "Constructing pageshow event, cancelable:true"); + +test(function() { + var e = new PageTransitionEvent("pagehide", {cancelable:true}); + assert_true(e instanceof PageTransitionEvent); + assert_equals(e.type, "pagehide"); + assert_false(e.persisted, "persisted"); + assert_false(e.bubbles, "bubbles"); + assert_true(e.cancelable, "cancelable"); +}, "Constructing pagehide event, cancelable:true"); + +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html new file mode 100644 index 0000000000..b7111255f8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html @@ -0,0 +1,49 @@ +<!doctype html> +<title>Queue a task to fire hashchange event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +t = async_test(); +window.onload = t.step_func(function () { + if (location.href.toString().indexOf("#") > -1) { + location.href = location.href.replace(/#.*$/,''); + return; + } + var root = location.href; + var oldURLs = []; + var newURLs = []; + + var timer = null; + + location.hash = 'foo'; + window.onhashchange = t.step_func(function (e) { + assert_true(e.isTrusted, "isTrusted"); + assert_equals(e.target, window, "target"); + assert_equals(e.type, "hashchange", "type"); + assert_true(e instanceof HashChangeEvent, "is HashChangeEvent"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); + oldURLs.push(e.oldURL); + newURLs.push(e.newURL); + if (newURLs.length === 2) { + check_result(); + } else if (timer === null) { + timer = setTimeout(function() {check_result()}, 500); + } + }) + + check_result = t.step_func(function() { + clearTimeout(timer); + try { + assert_array_equals([root, root+"#foo"], oldURLs, "e.newURL"); + assert_array_equals([root+"#foo", root+"#bar"], newURLs, "e.newURL"); + t.done(); + } finally { + location.hash = ""; + } + }); + + location.hash = 'bar'; +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html new file mode 100644 index 0000000000..2b70375a14 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigate-parent-while-child-loading.html @@ -0,0 +1,30 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i"></iframe> +<body> +<script> +async_test(t => { + let starting_history_length = history.length; + let iframe_url = (new URL("/common/blank.html", location.href)).href; + i.src = iframe_url; + + history.pushState("a", "", "#a"); + assert_equals(history.length, starting_history_length + 1, "First history length"); + + i.onload = t.step_func(() => { + assert_equals(history.length, starting_history_length + 1, "Second history length"); + assert_equals(i.contentWindow.location.href, iframe_url); + assert_equals(location.hash, "#a"); + history.back(); + // Wait a while for a back navigation. Since all of the possible outcomes + // are either same-document or navigating to about:blank, this doesn't need + // to wait terribly long. + t.step_timeout(t.step_func_done(() => { + assert_equals(location.hash, "", "top frame should have navigated back"); + assert_equals(i.contentWindow.location.href, iframe_url, "iframe should not have navigated"); + }), 100); + }); +}, "pushState() in parent while child is doing initial navigation, then go back"); +</script> +</body> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigates-multiple-frames.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigates-multiple-frames.html new file mode 100644 index 0000000000..4f2429fbfd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/history-traversal-navigates-multiple-frames.html @@ -0,0 +1,29 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +async_test(t => { + window.onload = () => t.step_timeout(t.step_func(() => { + let starting_history_length = history.length; + location.hash = "#a"; + assert_equals(starting_history_length + 1, history.length); + i.contentWindow.location.hash = "#b"; + assert_equals(starting_history_length + 2, history.length); + + let popstateCount = 0; + const popstateCalled = t.step_func(() => { + popstateCount++; + if (popstateCount < 2) + return; + assert_equals(location.hash, ""); + assert_equals(i.contentWindow.location.hash, ""); + t.done(); + }); + + window.onpopstate = popstateCalled; + i.contentWindow.onpopstate = popstateCalled; + history.go(-2); + }), 0); +}, "A history traversal should be able to navigate a parent and child simultaneously"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-bfcache-restore.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-bfcache-restore.html new file mode 100644 index 0000000000..f453c80a2a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-bfcache-restore.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on restoration from BFCache</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document"> +<link rel="author" href="mailto:bokan@chromium.org"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/html/browsers/browsing-the-web/back-forward-cache/resources/helper.sub.js"></script> +<script> +// runBfcacheTest opens a popup to pageA which navigates to pageB and then +// back, ensuring pageA is stored in the BFCache. +runBfcacheTest({ + funcBeforeNavigation: async () => { + // This function executes in pageA + + // Wait for an animation frame to ensure the the initial-load + // `pagereveal` has already been fired so it doesn't get recorded + // below. + const raf = new Promise(resolve => requestAnimationFrame(resolve)); + await raf; + + window.event_log = []; + let restored = false; + + function recordRafs() { + requestAnimationFrame( () => { + // Avoid recording animation frames until the page is restored from + // BFCache since it's currently uncached. This test is interested only + // in the behavior during restoration. + if (restored) + window.event_log.push('rAF'); + + recordRafs(); + }); + } + + recordRafs(); + + addEventListener('pageshow', (e) => { + window.event_log.push('pageshow' + (e.persisted ? '.persisted' : '')); + if (e.persisted) + restored = true; + }); + + addEventListener('pagereveal', () => { + window.event_log.push('pagereveal'); + }); + }, + funcAfterAssertion: async (pageA, pageB, t) => { + let event_log = await pageA.execute_script(async () => { + // Ensure at least one animation frame is produced to ensure + // pagereveal must have fired. + await new Promise(requestAnimationFrame); + return window.event_log; + }); + + // Expect that the events seen are: + // pageshow.persisted, pagereveal, rAF, rAF, rAF, ... + assert_equals(event_log.slice(0, 3).toString(), + 'pageshow.persisted,pagereveal,rAF'); + for (let i = 3; i < event_log.length; ++i) { + assert_equals(event_log[i], 'rAF', + 'All events following pagereveal should be animation frames'); + } + }, + targetOrigin: originSameOrigin, +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-new-document-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-new-document-navigation.html new file mode 100644 index 0000000000..d2c44511d3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-new-document-navigation.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on new-document navigation</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering"> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +const event_log = []; + +addEventListener('pageshow', () => event_log.push('pageshow')); +addEventListener('pagereveal', () => event_log.push('pagereveal')); +requestAnimationFrame(() => event_log.push('rAF')); + +promise_test(async () => { + await new Promise(resolve => requestAnimationFrame(resolve)); + assert_equals(event_log.toString(),'pageshow,pagereveal,rAF'); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-prerender-activation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-prerender-activation.html new file mode 100644 index 0000000000..b281b2b088 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/order-in-prerender-activation.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on prerender activation</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering"> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/speculation-rules/resources/utils.js"></script> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<script> +setup(() => assertSpeculationRulesIsSupported()); + +const uid = token(); +const initiator_url = `resources/order-in-prerender-activation-popup.html?uid=${uid}`; + +// This test opens a popup to an initiator page. That page then prerenders a +// "prerendering" version of itself (by adding a `prerendering` query param) +// and navigates itself to activate the prerender. The results are recorded and +// sent back to this test harness. +promise_test(async () => { + const channel = new PrerenderChannel('result', uid); + const test_done = new Promise(resolve => { + channel.addEventListener('message', e => resolve(e.data), { once: true }); + }); + + window.open(initiator_url, '_blank', 'noopener'); + + const result = await test_done; + + if (result.hasOwnProperty('fail')) { + assert_unreached(result.fail); + } + + // The test records relevant event occurrences up to the second animation + // frame. Ensure their order and apparance is as expected. + const events_in_order = result.events.join(','); + assert_equals(events_in_order, + 'pageshow,prerenderingchange,pagereveal,raf'); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/resources/order-in-prerender-activation-popup.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/resources/order-in-prerender-activation-popup.html new file mode 100644 index 0000000000..78989adc17 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/pagereveal/resources/order-in-prerender-activation-popup.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<title>pagereveal event fires and in correct order on prerender activation (popup)</title> +<link rel="author" href="mailto:bokan@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<script> +const params = new URLSearchParams(location.search); +const uid = params.get('uid'); +const is_prerender_step = params.has('prerendering'); + +const ready_channel = new PrerenderChannel('ready-to-activate', uid); + +function finish(result) { + const result_channel = new PrerenderChannel('result', uid); + result_channel.postMessage(result); + result_channel.close(); + window.close(); +} + +// testharness.js assertions don't work inside this popup so this small helper +// sends a failure signal back to the test page which will cause test failure. +function assert(cond, desc) { + if (!cond) { + finish({fail: desc}); + } +} + +// The first load of this page should be without 'prerendering' and is used +// to setup the prerender and then activate it when it's ready. +if (!is_prerender_step) { + assert(!document.prerendering, 'initiator page must not be prerendered'); + + const ready_to_activate = new Promise(resolve => { + ready_channel.addEventListener('message', resolve, {once: true}); + }); + + const prerendering_url = location.href + '&prerendering'; + startPrerendering(prerendering_url); + + ready_to_activate.then(() => { + location.replace(prerendering_url); + }); +} else { + assert(document.prerendering, 'prerendering step must be initially prerendered'); + + const result = { + events: [] + }; + + document.addEventListener('prerenderingchange', () => { + result.events.push('prerenderingchange'); + }); + + addEventListener('pageshow', () => { + result.events.push('pageshow'); + }); + + // A second rAF will end the test. + requestAnimationFrame(() => { + result.events.push('raf'); + requestAnimationFrame(() => finish(result)); + }); + + addEventListener('pagereveal', () => { + result.events.push('pagereveal'); + }); + + addEventListener('load', () => { + ready_channel.postMessage('unused-readyToActivateMessage'); + ready_channel.close(); + }); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html new file mode 100644 index 0000000000..6b4df1ef2f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<style> +body { + height: 2000px; + width: 2000px; +} +</style> +<body> Blank 1 </body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html new file mode 100644 index 0000000000..def2139667 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<style> +body { + height: 2000px; + width: 2000px; +} +</style> +<body> Blank 2 </body> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html new file mode 100644 index 0000000000..11737661d0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<style> +body { + height: 2000px; + width: 2000px; +} +#fragment { + position: absolute; + top: 800px; + background-color: #faa; + display: block; + height: 100px; + width: 100px; +} + +</style> +<body> +Page with fragment + <a id="fragment" name="fragment" class='box'></a> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html new file mode 100644 index 0000000000..1e9b10d1ee --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html @@ -0,0 +1,7 @@ +<!doctype html> +<script> +addEventListener('load', _ => { + let params = new URLSearchParams(window.location.search); + window.opener.postMessage(params.get('name'), '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html new file mode 100644 index 0000000000..77602b2d42 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html @@ -0,0 +1,146 @@ +<!doctype html> +<title>Verify history.back() on a persisted page resumes timers</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + +function make_post_back_url(name) { + return new URL('resources/post_name_on_load.html?name=' + name, + window.location).href; +} + +function wait_for_message(name) { + return new Promise(resolve => { + addEventListener('message', function onMsg(evt) { + if (evt.data !== name) { + return; + } + removeEventListener('message', onMsg); + resolve(); + }); + }); +} + +function with_window_by_name(name) { + let win = window.open(make_post_back_url(name)); + return wait_for_message(name).then(_ => { + return win; + }); +} + +function with_nested_frame(win, url) { + return new Promise(resolve => { + let frame = win.document.createElement('iframe'); + frame.addEventListener('load', function onLoad(evt) { + removeEventListener('load', onLoad); + resolve(frame); + }); + frame.src = url; + win.document.body.appendChild(frame); + }); +} + +function delay(win, delay) { + return new Promise(resolve => { + win.setTimeout(_ => { + resolve(win); + }, delay); + }); +} + +function navigate_by_name(win, name) { + win.location = make_post_back_url(name); + return wait_for_message(name).then(_ => { + return win; + }); +} + +function go_back(win) { + return new Promise(resolve => { + win.onpagehide = e => resolve(win); + win.history.back(); + }); +} + +let DELAY = 500; + +promise_test(t => { + // Create a new window so we can navigate it later. + return with_window_by_name('foo').then(win => { + // Schedule a timer within the new window. Our intent is + // to navigate the window before the timer fires. + let delayFired = false; + let innerDelay = delay(win, DELAY); + innerDelay.then(_ => { + delayFired = true; + }); + + return navigate_by_name(win, 'bar').then(_ => { + // Since the window has navigated the timer should not + // fire. We set a timer on our current test window + // to verify the other timer is not received. + assert_false(delayFired); + return delay(window, DELAY * 2); + }).then(_ => { + // The navigated window's timer should not have fired. + assert_false(delayFired); + // Now go back to the document that set the timer. + return go_back(win); + }).then(_ => { + // We wait for one of two conditions here. For browsers + // with a bfcache the original suspended timer will fire. + // Alternatively, if the browser reloads the page the original + // message will be sent again. Wait for either of these + // two events. + return Promise.race([wait_for_message('foo'), innerDelay]); + }).then(_ => { + win.close(); + }); + }); +}, 'history.back() handles top level page timer correctly'); + +promise_test(t => { + let win; + // Create a new window so we can navigate it later. + return with_window_by_name('foo').then(w => { + win = w; + + // Create a nested frame so we check if navigation and history.back() + // properly handle child window state. + return with_nested_frame(win, 'about:blank'); + + }).then(frame => { + // Schedule a timer within the nested frame contained by the new window. + // Our intent is to navigate the window before the timer fires. + let delayFired = false; + let innerDelay = delay(frame.contentWindow, DELAY); + innerDelay.then(_ => { + delayFired = true; + }); + + return navigate_by_name(win, 'bar').then(_ => { + // Since the window has navigated the timer should not + // fire. We set a timer on our current test window + // to verify the other timer is not received. + assert_false(delayFired); + return delay(window, DELAY * 2); + }).then(_ => { + // The navigated window's timer should not have fired. + assert_false(delayFired); + // Now go back to the document containing the frame that set the timer. + return go_back(win); + }).then(_ => { + // We wait for one of two conditions here. For browsers + // with a bfcache the original suspended timer will fire. + // Alternatively, if the browser reloads the page the original + // message will be sent again. Wait for either of these + // two events. + return Promise.race([wait_for_message('foo'), innerDelay]); + }).then(_ => { + win.close(); + }); + }); +}, 'history.back() handles nested iframe timer correctly'); + +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html new file mode 100644 index 0000000000..e47cd9c383 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html @@ -0,0 +1,34 @@ +<!doctype html> +<title>Verify existence and basic read/write function of history.scrollRestoration</title> + +<style> + body { + height: 2000px; + width: 2000px; + } +</style> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + test(function() { + assert_equals(history.scrollRestoration, 'auto'); + }, 'Default value is "auto"'); + + test(function() { + history.scrollRestoration = 'manual'; + assert_equals(history.scrollRestoration, 'manual', 'should be able to set "manual"'); + history.scrollRestoration = 'auto'; + assert_equals(history.scrollRestoration, 'auto', 'should be able to set "auto"'); + }, 'It is writable'); + + test(function() { + history.scrollRestoration = 'auto'; + for (var v of [3.1415, {}, 'bogus']) { + history.scrollRestoration = v; + assert_equals(history.scrollRestoration, 'auto', `setting to invalid value (${v}) should be ignored`); + } + }, 'Invalid values are ignored'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html new file mode 100644 index 0000000000..fec801e94b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<meta name=timeout content=long> +<title>Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<style> + iframe { + height: 300px; + width: 300px; + } +</style> +<div id="log"></div> +<script> + 'use strict'; + + var next; + function frameOnload() { + if (next) { + next(); + } else { + // The test does the following navigation steps for iframe + // 1. load page-with-fragment.html#fragment + // 2. load blank1 + // 3. go back to page-with-fragment.html + async_test(function(t) { + var iframe = document.querySelector('iframe'); + var hostInfo = get_host_info(); + var basePath = location.pathname.substring(0, location.pathname.lastIndexOf('/')); + var localURL = hostInfo.HTTP_ORIGIN + basePath + '/resources/page-with-fragment.html#fragment'; + var remoteURL = hostInfo.HTTP_REMOTE_ORIGIN + basePath + "/resources/blank1.html" + + var steps = [ + function() { + assert_equals(iframe.contentWindow.location.href, localURL, 'should be on page-with-fragment page'); + // wait one animation frame to ensure layout is run and fragment scrolling is complete + iframe.contentWindow.requestAnimationFrame(function() { + assert_approx_equals(iframe.contentWindow.scrollY, 800, 5, 'should scroll to fragment'); + + iframe.contentWindow.history.scrollRestoration = 'manual'; + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual'); + setTimeout(next, 0); + }); + }, function() { + // navigate to a new page from a different origin + iframe.src = remoteURL; + }, function() { + // going back causes the iframe to traverse back + history.back(); + }, function() { + // coming back from history, scrollRestoration should be set to manual and respected + assert_equals(iframe.contentWindow.location.href, localURL, 'should be back on page-with-fragment page'); + iframe.contentWindow.requestAnimationFrame(t.step_func_done(function() { + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value'); + assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment'); + assert_equals(iframe.contentWindow.scrollY, 0, 'should not scroll to fragment'); + })); + } + ]; + + var stepCount = 0; + next = t.step_func(function() { + steps[stepCount++](); + }); + next(); + }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation'); + } + } +</script> +<iframe src="resources/page-with-fragment.html#fragment" onload="frameOnload()"></iframe> + diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html new file mode 100644 index 0000000000..073e0f6e06 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<style> + body { + height: 2000px; + width: 2000px; + } + + #fragment { + position: absolute; + top: 800px; + background-color: #faa; + display: block; + height: 100px; + width: 100px; + } +</style> + +<body> + <a id="fragment" name="fragment" class='box'></a> +</body> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + async_test(function(t) { + history.scrollRestoration = 'manual'; + assert_equals(history.scrollRestoration, 'manual'); + + location.hash = '#fragment'; + assert_equals(window.scrollY, 800, 'new navigations should scroll to fragment'); + + // create a new entry and reset the scroll before verification + history.pushState(null, null, '#done'); + window.scrollTo(0, 0); + assert_equals(window.scrollY, 0, 'should reset scroll before verification'); + + setTimeout(function() { + // setup verification + window.addEventListener('hashchange', t.step_func(function() { + assert_equals(location.hash, '#fragment'); + assert_equals(history.scrollRestoration, 'manual'); + // navigating back should give precedent to history restoration which is 'manual' + assert_equals(window.scrollX, 0, 'should not scroll to fragment'); + assert_equals(window.scrollY, 0, 'should not scroll to fragment'); + t.done(); + })); + // kick off verification + window.history.back(); + }, 0); + + }, 'Manual scroll restoration should take precedent over scrolling to fragment in cross doc navigation'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html new file mode 100644 index 0000000000..87a337b2da --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<meta name=timeout content=long> +<title>Correct behaviour of scroll restoration mode is cross origin history traversal</title> + +<style> + iframe { + height: 300px; + width: 300px; + } +</style> + +<body> + <iframe></iframe> +</body> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + // The test does the following navigation steps for iframe + // 1. load blank1 + // 2. load blank2 + // 3. go back to blank1 + async_test(function(t) { + var iframe = document.querySelector('iframe'); + var baseURL = location.href.substring(0, location.href.lastIndexOf('/')); + + var steps = [ + function() { + iframe.src = 'resources/blank1.html'; + }, + function() { + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be on first blank page'); + iframe.contentWindow.history.scrollRestoration = 'manual'; + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual'); + iframe.contentWindow.scrollTo(500, 500); + assert_equals(iframe.contentWindow.scrollX, 500, 'scripted scrolling should take effect'); + assert_equals(iframe.contentWindow.scrollY, 500, 'scripted scrolling should take effect'); + setTimeout(next, 0); + }, + function() { + // navigate to new page + iframe.src = 'resources/blank2.html'; + }, + function() { + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank2.html', 'should be on second blank page'); + assert_equals(iframe.contentWindow.history.scrollRestoration, 'auto', 'new page loads should set scrollRestoration to "auto"'); + setTimeout(next, 0); + }, function() { + iframe.contentWindow.history.back(); + }, function() { + // coming back scrollRestoration should be restored to 'manual' and respected + assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/blank1.html', 'should be back on first blank page'); + assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value'); + assert_equals(iframe.contentWindow.scrollX, 0, 'horizontal scroll offset should not be restored'); + assert_equals(iframe.contentWindow.scrollY, 0, 'vertical scroll offset should not be restored'); + t.done(); + } + ]; + + var stepCount = 0; + var next = t.step_func(function() { + steps[stepCount++](); + }); + + iframe.onload = next; + next(); + }, 'Navigating to new page should reset to "auto" and navigating back should restore and respect scroll restoration mode'); + +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html new file mode 100644 index 0000000000..46d40eedc6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<title>Correct behaviour of scroll restoration mode in same document history traversals</title> + +<style> + body { + height: 10000px; + width: 10000px; + } +</style> + +<body></body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="text/javascript"> + 'use strict'; + + async_test(function(t) { + history.scrollRestoration = 'auto'; + window.scrollTo(0, 0); + + // create history entries and then verify the impact of scrollRestoration + // when they are popped + var entries = { + /* For scroll restoration mode 'auto', the spec does not require scroll + position to be restored at any particular value. */ + '#1': {type: 'push', expectedScroll: null, scrollRestoration: 'auto'}, + '#2': {type: 'replace', expectedScroll: null, scrollRestoration: 'auto'}, + /* For scroll restoration mode 'manual', the spec requires scroll position + not to be restored. So we expect [555,555] which is the latest position + before navigation. */ + '#3': {type: 'push', expectedScroll: [555, 555], scrollRestoration: 'manual'}, + '#4': {type: 'replace', expectedScroll: [555, 555], scrollRestoration: 'manual'} + }; + + // setup entries + for (var key in entries) { + var entry = entries[key], + beforeValue = history.scrollRestoration, + newValue = entry.scrollRestoration; + + var args = [{key: key}, '', key]; + if (entry.type == 'push') { + history.pushState.apply(history, args); + } else { + history.pushState(null, '', key); + history.replaceState.apply(history, args); + } + assert_equals(history.scrollRestoration, beforeValue, `history.scrollRestoration value is retained after pushing new state`); + history.scrollRestoration = newValue; + assert_equals(history.scrollRestoration, newValue, `Setting scrollRestoration to ${newValue} works as expected`); + window.scrollBy(50, 100); + } + + // setup verification + window.addEventListener('hashchange', t.step_func(function() { + var key = location.hash, + entry = entries[key]; + + if (key === '') { + t.done(); + return; + } + assert_equals(history.state.key, key, `state should have key: ${key}`); + assert_equals(history.scrollRestoration, entry.scrollRestoration, 'scrollRestoration is updated correctly'); + if (entry.expectedScroll) { + assert_equals(window.scrollX, entry.expectedScroll[0], `scrollX is correct for ${key}`); + assert_equals(window.scrollY, entry.expectedScroll[1], `scrollY is correct for ${key}`); + } + + window.history.back(); + })); + + // reset the scroll and kick off the verification + setTimeout(function() { + history.pushState(null, null, '#done'); + window.scrollTo(555, 555); + window.history.back(); + }, 0); + + }, 'history.{push,replace}State retain scroll restoration mode and navigation in the same document respects it'); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/popstate_event.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/popstate_event.html new file mode 100644 index 0000000000..05b1dbf4b7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/popstate_event.html @@ -0,0 +1,48 @@ +<!doctype html> +<title>Queue a task to fire popstate event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +t = async_test(); +window.onload = t.step_func(function () { + var states = []; + + var timer = null; + + history.pushState("a", "State a", "/a"); + history.pushState("b", "State b", "/b"); + + history.back(); + window.onpopstate = t.step_func(function (e) { + assert_true(e.isTrusted, "isTrusted"); + assert_equals(e.target, window, "target"); + assert_equals(e.type, "popstate", "type"); + assert_true(e instanceof PopStateEvent, "is PopStateEvent"); + assert_false(e.bubbles, "bubbles"); + assert_false(e.cancelable, "cancelable"); + assert_not_equals(e.hasUAVisualTransition, undefined); + + states.push(e.state); + + if (states.length === 2) { + check_result(); + } else if (timer === null) { + timer = setTimeout(function() {check_result()}, 500); + } + }) + + check_result = t.step_func(function() { + clearTimeout(timer); + try { + assert_array_equals(states, ["a", null]); + t.done(); + } finally { + location.hash = ""; + } + }); + + setTimeout(function() {history.back()}, 0); + +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/a.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/a.html new file mode 100644 index 0000000000..55b73e1153 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/a.html @@ -0,0 +1 @@ +Welcome to A.
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-1.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-1.html new file mode 100644 index 0000000000..2c31168750 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-1.html @@ -0,0 +1,31 @@ +<!doctype html> +<title>API availability following history traversal - 1</title> +<script> +var controller = opener; +var t = controller.t; +var assert_not_equals = controller.assert_not_equals; + +t.step(function() { + // If this document is discarded as a result of navigation, then this script + // will be executed a second time. The semantics this test intends to verify + // cannot be observed under these conditions, the discarding is not itself a + // violation. Silently pass the test in that case. + if (controller.hasNavigated) { + t.done(); + return; + } + + t.step_timeout(function() { + assert_not_equals(window.history, null, 'history'); + assert_not_equals(window.localStorage, null, 'localStorage'); + assert_not_equals(window.location, null, 'location'); + assert_not_equals(window.navigator, null, 'navigator'); + assert_not_equals(window.opener, null, 'opener'); + assert_not_equals(window.sessionStorage, null, 'sessionStorage'); + + t.done(); + }, 1000); + + controller.navigate(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-2.html new file mode 100644 index 0000000000..420e5092bc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/api-availability-2.html @@ -0,0 +1,3 @@ +<!doctype html> +<title>API availability following history traversal - 2</title> +<body onload="history.back()"></body> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/b.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/b.html new file mode 100644 index 0000000000..8f2fc900dd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/b.html @@ -0,0 +1 @@ +Welcome to B.
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/c.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/c.html new file mode 100644 index 0000000000..db494e878e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/c.html @@ -0,0 +1 @@ +Welcome to C.
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name-1.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name-1.sub.html new file mode 100644 index 0000000000..97918a1f99 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name-1.sub.html @@ -0,0 +1,45 @@ +<!doctype html> +<!-- test must be run in a top level browsing context --> +<title>window.name test helper</title> +<script> +const search = window.location.search.replace("?", ""); +const steps = search.split("|"); + +async function proceedTest() { + while (steps.length) { + const step = steps.shift(); + + if (step.startsWith("report=")) { + const id = step.split("=")[1]; + const stashURL = new URL("unset_context_name_stash.py", location); + stashURL.searchParams.set('id', id); + stashURL.searchParams.set('value', window.name); + + await fetch(stashURL, { method: "POST" }); + continue; + } + + if (step === "close") { + window.close(); + break; + } + + if (step === "navigate") { + const url = new URL(window.location); + url.host = "{{hosts[][www]}}:{{ports[http][0]}}"; + url.search = "?" + steps.join("|"); + window.location = url.href; + break; + } + + if (step.startsWith("set=")) { + window.name = step.split("=")[1]; + continue; + } + + throw new Error("Unsupported step!"); + } +} + +proceedTest(); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name_stash.py b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name_stash.py new file mode 100644 index 0000000000..411a4587bc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/resources/unset_context_name_stash.py @@ -0,0 +1,13 @@ +def main(request, response): + key = request.GET.first(b"id") + if request.method == "POST": + value = request.GET.first(b"value") + request.server.stash.take(key) + request.server.stash.put(key, value) + return b"OK" + else: + value = request.server.stash.take(key) + if value is not None: + return value + else: + return b"NONE" diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/same-url.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/same-url.html new file mode 100644 index 0000000000..bcca5ed90c --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/same-url.html @@ -0,0 +1,50 @@ +<title>Test same-URL navigation and its effects on history</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<iframe src=resources/a.html></iframe> +<script> +async_test((t) => { + let state = "begin" + self[0].frameElement.onload = t.step_func(() => { + if(state === "b first") { + assert_equals(history.length, 2) + + state = "c first" + navigateFrameAfterDelay(t, "resources/c.html") + } else if (state === "c first") { + assert_equals(history.length, 3) + + state = "a second" + history.back(2) + } else if (state === "a second") { + assert_equals(history.length, 3) + + state = "a third" + navigateFrameAfterDelay(t, "resources/a.html") + } else if (state === "a third") { + assert_equals(history.length, 3) + t.done() + } + }) + onload = t.step_func(() => { + assert_equals(state, "begin") + assert_equals(history.length, 1) + + state = "b first" + + navigateFrameAfterDelay(t, "resources/b.html") + }) +}) + +function navigateFrameAfterDelay(t, url) { + // Delay to avoid triggering the "replace" behavior which occurs if + // the page isn't yet completely loaded, which only occurs after the + // load event handlers have finished: + // https://html.spec.whatwg.org/#location-object-navigate + // https://html.spec.whatwg.org/#the-end:completely-finish-loading + t.step_timeout(() => { + self[0].location = url + }, 0) +} +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/scroll-restoration-order.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/scroll-restoration-order.html new file mode 100644 index 0000000000..8fe7d9f977 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/scroll-restoration-order.html @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>History restoration order test</title> +<meta name="assert" content="https://html.spec.whatwg.org/multipage/browsing-the-web.html#history-traversal"> +<meta name="assert" content="Traversing history should restore scroll position after dispatching popstate and before dispatching hashchange"> + +<style> + body { + height: 200vh; + width: 200vw; + } +</style> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + 'use strict'; + async_test(function(t) { + window.addEventListener('load', t.step_func(function() { + // Allow 1px epsilon for fractional scrolling. + assert_array_approx_equals(scrollPosition(), [0, 0], 1); + + history.pushState('#1', '', '#1'); + window.scrollTo(50, 100); + assert_array_approx_equals(scrollPosition(), [50, 100], 1); + + history.pushState('#2', '', '#2'); + window.scrollTo(100, 200); + assert_array_approx_equals(scrollPosition(), [100, 200], 1); + + setTimeout(t.step_func(function(){ + history.pushState(null, null, '#done'); + window.scrollTo(555, 555); + assert_array_approx_equals(scrollPosition(), [555, 555], 1); + // Kick off the verification. + window.history.back(); + }), 0); + })); + + window.addEventListener('popstate', t.step_func(function() { + // Verify that scroll position is *not* restored before popstate. + const key = location.hash; + const expected_scroll_position = expectedScrollPositionForKey(key); + assert_not_equals(scrollPosition()[0], expected_scroll_position[0], `scroll is restored before popstate for ${key}`); + assert_not_equals(scrollPosition()[1], expected_scroll_position[1], `scroll is restored before popstate for ${key}`); + + if (key == '') + t.done(); + else + setTimeout(t.step_func(function(){ window.history.back(); }), 0); + })); + + window.addEventListener('hashchange', t.step_func(function() { + // Verify that scroll position is restored before hashchange. + var key = location.hash; + const expected_scroll_position = expectedScrollPositionForKey(key); + assert_array_approx_equals(scrollPosition(), expected_scroll_position, 1, `scroll is restored before hashchange for ${key}`); + })); + + function scrollPosition() { + return [window.pageXOffset, window.pageYOffset]; + } + + function expectedScrollPositionForKey(key) { + switch (key) { + case '#2': return [100, 200]; + case '#1': return [50, 100]; + case '' : return [0, 0]; + default: assert_unreached(); + } + } + + }, 'Traversing history should restore scroll position after dispatching popstate and before dispatching hashchange'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/consecutive-srcdoc.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/consecutive-srcdoc.html new file mode 100644 index 0000000000..9aab36b986 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/consecutive-srcdoc.html @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>changing srcdoc to a different srcdoc</title> +<link rel="help" href="https://github.com/whatwg/html/issues/6809#issuecomment-905677979"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../resources/helpers.js"></script> + +<script> +"use strict"; + +// Note: bfcache won't mess with any windows with openers, so it doesn't +// interfere with these tests. + +promise_test(async t => { + // Set up a window whose iframe contains [normal page, srcdoc] entries. + const w = await openWindow("../../resources/has-iframe.html", t); + const iframe = w.document.querySelector("iframe"); + + await waitToAvoidReplace(t); + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc1"); + await waitForMessage(iframe.contentWindow); + + assert_equals(w.history.length, 2); + + // Now navigate to a different srcdoc + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc2"); + + // Test that it's a replace. + await waitForMessage(iframe.contentWindow); + assert_equals(w.history.length, 2, + "history.length must not change since it was a replace"); + assert_equals( + iframe.contentDocument.querySelector("p").textContent, + "srcdoc2", + "Sanity check: the srcdoc document did indeed update" + ); +}, "changing srcdoc does a replace navigation since the URL is still " + + "about:srcdoc"); + +promise_test(async t => { + // Set up a window whose iframe contains [normal page, srcdoc] entries. + const w = await openWindow("../../resources/has-iframe.html", t); + const iframe = w.document.querySelector("iframe"); + + await waitToAvoidReplace(t); + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc1"); + await waitForMessage(iframe.contentWindow); + + assert_equals(w.history.length, 2); + + // Now navigate to about:srcdoc#yo + iframe.contentWindow.location.href = "about:srcdoc#yo"; + assert_equals(iframe.contentWindow.location.href, "about:srcdoc#yo"); + assert_equals(w.history.length, 3); + + // Now navigate to a different srcdoc + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc2"); + + // Test that it's a push back to about:srcdoc. + await waitForMessage(iframe.contentWindow); + assert_equals( + w.history.length, + 4, + "history.length must increase since it was a push" + ); + assert_equals(iframe.contentWindow.location.href, "about:srcdoc"); + assert_equals( + iframe.contentDocument.querySelector("p").textContent, + "srcdoc2", + "Sanity check: the srcdoc document did indeed update" + ); + + // Test that we can go back to about:srcdoc#yo. + w.history.back(); + await waitForMessage(iframe.contentWindow); + assert_equals(iframe.contentWindow.location.href, "about:srcdoc#yo"); + assert_equals( + iframe.contentDocument.querySelector("p").textContent, + "srcdoc1", + "srcdoc content must be restored from history" + ); +}, "changing srcdoc to about:srcdoc#yo then another srcdoc does two push " + + "navigations and we can navigate back"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/srcdoc-history-entries.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/srcdoc-history-entries.html new file mode 100644 index 0000000000..09f4094c5f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/srcdoc/srcdoc-history-entries.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>srcdoc history entries</title> +<link rel="help" href="https://github.com/whatwg/html/issues/6809"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../resources/helpers.js"></script> + +<script> +"use strict"; + +// Note: bfcache won't mess with any windows with openers, so it doesn't +// interfere with these tests. + +promise_test(async t => { + // Set up a window whose iframe contains + // [normal page, srcdoc, normal page, srcdoc] entries. + const w = await openWindow("/common/blank.html", t); + const iframe = await addIframe("/common/blank.html?iframe", w.document); + + assert_equals(w.history.length, 1); + + await waitToAvoidReplace(t); + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc1"); + assert_equals(w.history.length, 1, "srcdoc navigation must not be sync"); + + await waitForMessage(iframe.contentWindow); + assert_equals(w.history.length, 2); + + await waitToAvoidReplace(t); + const middleURL = (new URL( + "../../resources/post-top-opener-on-load.html", location.href)).href; + iframe.contentWindow.location.href = middleURL; + + await waitForMessage(iframe.contentWindow); + assert_equals(w.history.length, 3); + + await waitToAvoidReplace(t); + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc2"); + assert_equals(w.history.length, 3, "srcdoc navigation must not be sync"); + + await waitForMessage(iframe.contentWindow); + assert_equals(w.history.length, 4); + + // Now test traversal. + w.history.back(); + await waitForMessage(iframe.contentWindow); + assert_equals(iframe.contentWindow.location.href, middleURL); + + await waitToAvoidReplace(t); + + w.history.back(); + await waitForMessage(iframe.contentWindow); + assert_equals(iframe.contentWindow.location.href, "about:srcdoc"); + assert_equals( + iframe.contentDocument.querySelector("p").textContent, + "srcdoc1", + "srcdoc contents must be restored from history, not from the current " + + "value ('srcdoc2') of the content attribute" + ); +}, "srcdoc history entries: the iframe itself navigates"); + +promise_test(async t => { + // Set up a window whose iframe contains [normal page, srcdoc] entries. + const w = await openWindow("../../resources/has-iframe.html", t); + const iframe = w.document.querySelector("iframe"); + + assert_equals(w.history.length, 1); + + await waitToAvoidReplace(t); + iframe.srcdoc = srcdocThatPostsParentOpener("srcdoc1"); + assert_equals(w.history.length, 1, "srcdoc navigation must not be sync"); + + await waitForMessage(iframe.contentWindow); + assert_equals(w.history.length, 2); + + // Now navigate the window itself. + w.location.href = "../../resources/post-top-opener-on-load.html"; + await waitForMessage(w); + assert_equals(w.history.length, 3); + + // Now test traversal. + w.history.back(); + await waitForMessage(w); + const iframeAgain = w.document.querySelector("iframe"); + + assert_equals(iframeAgain.contentWindow.location.href, "about:srcdoc"); + assert_equals( + iframeAgain.contentDocument?.querySelector("p")?.textContent, + "srcdoc1", + "srcdoc contents must be restored from history, not from the current " + + "value of the (not-existing) content attribute" + ); +}, "srcdoc history entries: the container window navigates"); +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-cross-origin-main-frame-navigation-popup.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-cross-origin-main-frame-navigation-popup.sub.html new file mode 100644 index 0000000000..e13d191658 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-cross-origin-main-frame-navigation-popup.sub.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML> +<html> +<head> +</head> +<body> + <script> + document.location = "window-name-navigation.sub.html?hostname={{domains[www1]}}&shouldhavename=false&sendmessage=true"; + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-same-origin-main-frame-navigation-1.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-same-origin-main-frame-navigation-1.sub.html new file mode 100644 index 0000000000..4b7824b488 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-after-same-origin-main-frame-navigation-1.sub.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<script> + window.location = "window-name-navigation.sub.html?hostname={{host}}&shouldhavename=true&sendmessage=true"; +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-navigation.sub.html new file mode 100644 index 0000000000..285469a148 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-navigation.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <script> + var url = new URL(window.location.href); + url.hostname = "{{GET[hostname]}}"; + url.pathname = "/html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html"; + url.search = "shouldhavename={{GET[shouldhavename]}}&sendmessage={{GET[sendmessage]}}"; + window.name = "test"; + window.location = url.href; + </script> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html new file mode 100644 index 0000000000..460db2e979 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/support/window-name-test.sub.html @@ -0,0 +1,23 @@ +<script> + function process_test_result(passed, test_name) { + if ({{GET[sendmessage]}}) { + if (window.opener) { + window.opener.postMessage(passed, "*"); + } else { + parent.postMessage(passed, "*"); + } + } else { + let host = window.opener || parent; + host.test(function(t) { + host.assert_equals(passed, true); + }, test_name); + host.done(); + } + } + + if ({{GET[shouldhavename]}}) { + process_test_result(window.name == "test", "Test that window name is present"); + } else { + process_test_result(window.name == "", "Test that window name is not present"); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/unset_context_name.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/unset_context_name.html new file mode 100644 index 0000000000..285f6d7428 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/unset_context_name.html @@ -0,0 +1,32 @@ +<!doctype html> +<title>window.name is reset after navigating to a different origin</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script> + +async function pollResultAndCheck(t, id, expected) { + const stashURL = new URL("resources/unset_context_name_stash.py", location); + stashURL.searchParams.set('id', id); + + let res = "NONE"; + while (res == "NONE") { + await new Promise(resolve => { t.step_timeout(resolve, 100); }); + + const response = await fetch(stashURL); + res = await response.text(); + } + if (res !== expected) { + assert_unreached('Stash result does not equal expected result.') + } +} + +promise_test(async t => { + const id = token(); + + window.open(`resources/unset_context_name-1.sub.html?set=${id}|navigate|report=${id}|close`, "_blank", "noopener"); + await pollResultAndCheck(t, id, ""); +}, "Window.name is reset after navigating to a different origin"); + +</script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html new file mode 100644 index 0000000000..6bc64c6373 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-aux-frame-navigation.sub.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <!-- window.name should equal "test" after a cross-origin auxiliary frame navigation. --> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + t = async_test("Test that the window name is correct"); + window.addEventListener("message", t.step_func_done(function(e) { + assert_equals(e.data, true); + })); + window.open("support/window-name-navigation.sub.html?hostname={{domains[www1]}}&shouldhavename=true&sendmessage=true"); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html new file mode 100644 index 0000000000..fb0bb1883f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-main-frame-navigation.sub.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <button id="button" onclick="popup();">open popup</button> + <script> + function popup() { + window.popupWin = window.open('support/window-name-after-cross-origin-main-frame-navigation-popup.sub.html', '_blank'); + } + async_test(t => { + t.add_cleanup(() => { + popupWin.close(); + }) + document.getElementById('button').click(); + onmessage = t.step_func(e => { + assert_true(e.data); + }); + }, 'window.name should equal "" after a cross-origin main frame navigation'); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html new file mode 100644 index 0000000000..a309be6d80 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-cross-origin-sub-frame-navigation.sub.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <!-- window.name should equal "test" after a cross-origin sub frame navigation. --> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + t = async_test("Test that the window name is correct"); + window.addEventListener("message", t.step_func_done(function(e) { + assert_equals(e.data, true); + })); + </script> + <iframe src="support/window-name-navigation.sub.html?hostname={{domains[www1]}}&shouldhavename=true&sendmessage=true"; + </iframe> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html new file mode 100644 index 0000000000..8e0a95d8c0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-aux-frame-navigation.sub.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> +<head> + <!-- window.name should equal "test" after a same-origin auxiliary frame navigation. --> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + t = async_test("Test that the window name is correct"); + window.addEventListener("message", t.step_func_done(function(e) { + assert_equals(e.data, true); + })); + window.open("support/window-name-navigation.sub.html?hostname={{host}}&shouldhavename=true&sendmessage=true"); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.html new file mode 100644 index 0000000000..ef11d9971a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-main-frame-navigation.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML> +<title>window.name after a same-origin main frame navigation</title> +<script src='/resources/testharness.js'></script> +<script src='/resources/testharnessreport.js'></script> +<body> + <script> + var win; + async_test(function(t) { + win = window.open("support/window-name-after-same-origin-main-frame-navigation-1.sub.html") + addEventListener("message", t.step_func_done(e => assert_true(e.data))); + }).add_cleanup(() => {if (win) {win.close()}}); + </script> diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html new file mode 100644 index 0000000000..48a6e247b0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/window-name-after-same-origin-sub-frame-navigation.sub.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> +<head> + <!-- window.name should equal "test" after a same-origin sub frame navigation. --> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + t = async_test("Test that the window name is correct"); + window.addEventListener("message", t.step_func_done(function(e) { + assert_equals(e.data, true); + })); + </script> + <iframe src="support/window-name-navigation.sub.html?hostname={{host}}&shouldhavename=true&sendmessage=true"; + </iframe> +</body> +</html> |