diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/html/browsers/history | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/browsers/history')
197 files changed, 5557 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child1.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child1.html new file mode 100644 index 0000000000..22bb0b2980 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child1.html @@ -0,0 +1,18 @@ +<body> + <a id="link" href="joint-session-history-child2.html">Child1</a>. + <iframe id="grandchild"></iframe> +</body> +<script> + window.onload = function() { + var link = document.getElementById("link"); + var grandchild = document.getElementById("grandchild"); + var timer = window.setInterval(poll, 100); + function poll() { + if (grandchild.getAttribute("data-grandchild-loaded")) { + window.clearInterval(timer); + link.click(); + } + } + grandchild.src="joint-session-history-grandchild1.html"; + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child2.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child2.html new file mode 100644 index 0000000000..24b4695166 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-child2.html @@ -0,0 +1,5 @@ +<body>Child 2.</body> +<script> + // Servo doesn't support postMessage yet, so we poll on attributes. + window.frameElement.setAttribute("data-child-loaded", true); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-filler.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-filler.html new file mode 100644 index 0000000000..b6d47c310b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-filler.html @@ -0,0 +1 @@ +<body>Filler</body> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild1.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild1.html new file mode 100644 index 0000000000..d05e152425 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild1.html @@ -0,0 +1,8 @@ +<body> + <a id="link" href="joint-session-history-grandchild2.html">Grandchild1</a>. +</body> +<script> + window.onload = function() { + document.getElementById("link").click(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild2.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild2.html new file mode 100644 index 0000000000..b5c81e1fca --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-grandchild2.html @@ -0,0 +1,5 @@ +<body>Grandchild2.</body> +<script> + // Servo doesn't support postMessage yet, so we poll on attributes. + window.frameElement.setAttribute("data-grandchild-loaded", true); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-iframe-state.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-iframe-state.html new file mode 100644 index 0000000000..ffa64c0b35 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-iframe-state.html @@ -0,0 +1,41 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Joint session history should not override parent's state.</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<iframe id="frame" src="about:blank"></iframe> +<script> +async_test(function(t) { + // Setup. + var initialState = {foo: 'bar'}; + var newStateFromChild = {foo: 'baz'}; + var child = document.getElementById("frame"); + + // Child's initial state should be a default empty state. + assert_equals(child.contentWindow.history.state, null); + + // Perform navigation in the top-level container to set the state. + window.history.pushState(initialState, 'title'); + + // Validate initial state was properly set. + assert_object_equals(window.history.state, initialState); + + child.onload = t.step_func_done(() => { + // Child's initial state should be `null`. + assert_equals(child.contentWindow.history.state, null); + + // Navigate in the child. + child.contentWindow.history.pushState(newStateFromChild, 'title'); + + // Child's state should now equal the new state. + assert_object_equals(child.contentWindow.history.state, newStateFromChild); + // Parent's state should still be preserved, having exactly the same state as it + // had before parent navigated. + assert_object_equals(window.history.state, initialState); + }) + child.src = "joint-session-history-filler.html"; +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-only-fully-active.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-only-fully-active.html new file mode 100644 index 0000000000..c42d160a21 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-only-fully-active.html @@ -0,0 +1,30 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Do only fully active documents count for session history?</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + <iframe id="child"></iframe> +</body> +<script> + async_test(function(t) { + var old_history_len = window.history.length; + var child = document.getElementById("child"); + var timer = window.setInterval(t.step_func(poll), 100); + function poll() { + if (child.getAttribute("data-child-loaded")) { + // Check to see how many entries have been added to the session history. + // The spec https://html.spec.whatwg.org/multipage/#joint-session-history + // says that only fully active documents are included in the joint session history. + // If only fully active documents count, then the only fully active document + // is the child, with session length 1, so the joint session length change will be 1. + // If all documents count, then the grandchild is reachable via the session history, + // and it has session length 1, so the joint session length change will be 2. + assert_equals(2, window.history.length - old_history_len); + window.clearInterval(timer); + t.done(); + } + } + child.src = "joint-session-history-child1.html"; + }); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html new file mode 100644 index 0000000000..ee7aa368af --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html @@ -0,0 +1,24 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Joint session history length does not include entries from a removed iframe.</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<iframe id="frame" src="about:blank"></iframe> +<script> +async_test(function(t) { + t.step_timeout(() => { + var child = document.getElementById("frame"); + var old_history_len = history.length; + child.onload = () => { + assert_equals(old_history_len + 1, history.length); + document.body.removeChild(document.getElementById("frame")); + assert_equals(old_history_len, history.length); + t.done(); + } + child.src = "joint-session-history-filler.html"; + }, 1000); +}); +</script> +</body> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/001.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/001.html new file mode 100644 index 0000000000..16cb834c78 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/001.html @@ -0,0 +1,339 @@ +<!doctype html> +<html> + <head> + <title>history.pushState tests</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> +//does not test for firing of popstate onload, because this was dropped from the specification on 25 March 2011 +//covers history.state after load, in accordance with the specification draft from 25 March 2011 +//history.state before load is tested in 006 and 007 +//does not test for structured cloning of FileList, File or Blob interfaces, as these require manual file selection + +//**This test assumes that assignments to location.hash will be synchronous - this is how all browsers implement it. +//The spec (as of 25 March 2011) disagrees.**// + +var histlength, atstep = 0, lasttimer; +setup({explicit_done:true}); //tests should take under 6 seconds + execution time + +window.onload = function () { + if( location.protocol == 'file:' ) { + document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.'; + return; + } else if( location.protocol == 'https:' ) { + document.getElementsByTagName('p')[0].innerHTML += '<br>WARNING: Browsers may intentionally fail to update history.length when pages are loaded over HTTPS, as a privacy restriction. If possible, load this page over HTTP.'; + } + //use a timeout, because some browsers intentionally do not add history entries for URL changes in the onload thread + setTimeout(testinit,100); +}; +function testinit() { + atstep = 1; + histlength = history.length; + iframe = document.getElementsByTagName('iframe')[0].src = 'blank2.html'; + //reportload will now be called by the onload handler for the iframe +} +function reportload() { + var iframe = document.getElementsByTagName('iframe')[0], hashchng = false; + var canvassup = false, cloneobj; + + function tests1() { + //Firefox may fail when reloading, because it recovers iframe state, and therefore does not see the need to alter history length + test(function () { assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); }, 'history.length should update when loading pages in an iframe'); + histlength = history.length; + iframe.contentWindow.location.hash = 'test'; //should be synchronous **SEE COMMENT AT TOP OF FILE + test(function () { + assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); + }, 'history.length should update when setting location.hash'); + test(function () { assert_true( !!history.pushState, 'critical test; ignore any failures after this' ); }, 'history.pushState must exist'); //assert_own_property does not allow prototype inheritance + test(function () { assert_true( !!iframe.contentWindow.history.pushState, 'critical test; ignore any failures after this' ); }, 'history.pushState must exist within iframes'); + test(function () { + assert_equals( iframe.contentWindow.history.state, null ); + }, 'initial history.state should be null'); + test(function () { + histlength = history.length; + iframe.contentWindow.history.pushState('',''); + assert_equals( history.length, histlength + 1 ); + }, 'history.length should update when pushing a state'); + test(function () { + assert_equals( iframe.contentWindow.history.state, '' ); + }, 'history.state should update after a state is pushed'); + histlength = history.length; + iframe.contentWindow.addEventListener("popstate", tests2, {once: true}); + history.back(); + } + function tests2() { + test(function () { + assert_equals( history.length, histlength ); + }, 'history.length should not decrease after going back'); + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' ); + }, 'traversing history must traverse pushed states'); + iframe.contentWindow.addEventListener("hashchange", tests3, {once: true}); + history.go(-1); + } + function tests3() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), '', '(this could cause other failures later on)' ); + }, 'traversing history must also traverse hash changes'); + + iframe.contentWindow.addEventListener("hashchange", tests4, {once: true}); + //Safari 5.0.3 fails here - it navigates *this* document to the *iframe's* location, instead of just navigating the iframe + history.go(2); + } + async function tests4() { + test(function () { + //Firefox 4 beta 11 has a messed up error object, which does not have the right error type or .SECURITY_ERR property + assert_throws_dom('SECURITY_ERR',function () { history.pushState('','','//exa mple'); }); + }, 'pushState must not be allowed to create invalid URLs'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.pushState('','','http://www.example.com/'); }); + }, 'pushState must not be allowed to create cross-origin URLs'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.pushState('','','about:blank'); }); + }, 'pushState must not be allowed to create cross-origin URLs (about:blank)'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.pushState('','','data:text/html,'); }); + }, 'pushState must not be allowed to create cross-origin URLs (data:URI)'); + test(function () { + assert_throws_dom('SECURITY_ERR', iframe.contentWindow.DOMException, function () { iframe.contentWindow.history.pushState('','','http://www.example.com/'); }); + }, 'security errors are expected to be thrown in the context of the document that owns the history object'); + let hashchange = + new Promise(function (resolve) { + iframe.contentWindow.addEventListener("hashchange", resolve, {once: true}); + }); + + test(function () { + iframe.contentWindow.location.hash = 'test2'; + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test2', 'location.hash did not change when told to' ); + }, 'location.hash must be allowed to change (part 1)'); + await hashchange; + history.go(-1); + iframe.contentWindow.addEventListener("hashchange", tests5, {once: true}); + } + function tests5() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test', 'location.hash did not change when going back' ); + }, 'location.hash must be allowed to change (part 2)'); + test(function () { + iframe.contentWindow.history.pushState('',''); + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test', 'location.hash changed when an unrelated state was pushed' ); + }, 'pushState must not alter location.hash when no URL is provided'); + history.go(1); //should do nothing, since the pushState should have removed the forward history + setTimeout(tests6,50); //.go is queued to end of thread + } + function tests6() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' ); + }, 'pushState must remove all history after the current state'); + test(function () { + iframe.contentWindow.history.pushState('','','#test3'); + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' ); + }, 'pushState must be able to set location.hash'); + //begin setup for "remove any tasks queued by the history traversal task source" + iframe.contentWindow.location.hash = '#test4'; + iframe.contentWindow.history.go(-1); //must be queued + try { + //must remove the queued navigation in the same browsing context + iframe.contentWindow.history.pushState('',''); + } catch(unsuperr) {} + //allow the browser to mistakenly run the .go if it is going to + //do not put two .go commands in the same thread, in case the browser mistakenly calculates the history position when + //calling .go instead of when executing the traversal task - that could give a false PASS in the next test otherwise + setTimeout(tests7,50); + } + function tests7() { + iframe.contentWindow.history.go(-1); //must be queued, but should not be removed this time + iframe.contentWindow.addEventListener("popstate", tests8, {once: true}); + } + function tests8() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test4' ); + }, 'pushState must remove any tasks queued by the history traversal task source'); + //end "remove any tasks queued by the history traversal task source" + window.addEventListener('hashchange',function () { hashchng = true; },false); + try { + //push a state that changes the hash + iframe.contentWindow.history.pushState('','',iframe.contentWindow.location.pathname+'#test5'); + } catch(unsuperr) {} + setTimeout(tests9,50); //allow the hashchange event to process, if the browser has mistakenly fired it + } + function tests9() { + test(function () { + assert_false( hashchng ); + }, 'pushState must not fire hashchange events'); + test(function () { + iframe.contentWindow.history.pushState('','','/testing_ignore_me_404'); + assert_equals( iframe.contentWindow.location.pathname, '/testing_ignore_me_404' ); + }, 'pushState must be able to set location.pathname'); + test(function () { + var newURL = location.href.replace(/\/[^\/]*$/)+'/testing_ignore_me_404/'; + iframe.contentWindow.history.pushState('','',newURL); + assert_equals( iframe.contentWindow.location.href, newURL ); + }, 'pushState must be able to set absolute URLs to the same host'); + test(function () { + assert_throws_dom( 'DATA_CLONE_ERR', function () { + history.pushState({dummy:function () {}},''); + } ); + }, 'pushState must not be able to use a function as data'); + test(function () { + assert_throws_dom( 'DATA_CLONE_ERR', function () { + history.pushState({dummy:window},''); + } ); + }, 'pushState must not be able to use a DOM node as data'); + test(function () { + try { a.b = c; } catch(errdata) { + history.pushState({dummy:errdata},''); + assert_equals(ReferenceError.prototype, Object.getPrototypeOf(history.state.dummy)); + } + }, 'pushState must be able to use an error object as data'); + test(function () { + assert_throws_dom('DATA_CLONE_ERR', iframe.contentWindow.DOMException, function () { + iframe.contentWindow.history.pushState(document,''); + }); + }, 'security errors are expected to be thrown in the context of the document that owns the history object (2)'); + cloneobj = { + nulldata: null, + udefdata: window.undefined, + booldata: true, + numdata: 1, + strdata: 'string data', + boolobj: new Boolean(true), + numobj: new Number(1), + strobj: new String('string data'), + datedata: new Date(), + regdata: /a/g, + arrdata: [1] + }; + cloneobj.regdata.lastIndex = 1; + cloneobj.looped = cloneobj; + //test the ImageData type, if the browser supports it + var canvas = document.createElement('canvas'); + if( canvas.getContext && ( canvas = canvas.getContext('2d') ) && canvas.createImageData ) { + canvassup = true; + cloneobj.imgdata = canvas.createImageData(1,1); + } + test(function () { + try { + iframe.contentWindow.history.pushState(cloneobj,'new title'); + } catch(e) { + cloneobj.looped = null; + //try again because this object is needed for future tests + iframe.contentWindow.history.pushState(cloneobj,'new title'); + //rethrow so the browser gets a FAIL for not coping with the circular reference; "internal structured cloning algorithm" step 1 + throw(e); + } + }, 'pushState must be able to make structured clones of complex objects'); + test(function () { + assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' ); + }, 'history.state should also reference a clone of the original object'); + test(function () { + assert_not_equals( cloneobj, iframe.contentWindow.history.state ); + }, 'history.state should be a clone of the original object, not a reference to it'); + /* + behaviour is not defined per spec, and no known implementations do this + test(function () { + assert_equals( iframe.contentDocument.title, 'new title', 'not required for specification conformance' ); + }, 'pushState MIGHT set the document title'); + */ + history.go(-1); + iframe.contentWindow.addEventListener("popstate", tests10, {once: true}); + } + function tests10() { + var eventtime = setTimeout(function () { tests11(false); },500); //should be cleared by the event handler long before it has a chance to fire + iframe.contentWindow.addEventListener('popstate',function (e) { clearTimeout(eventtime); tests11(true,e); },false); + history.forward(); + } + function tests11(hasFired,ev) { + test(function () { + assert_true( hasFired ); + }, 'popstate event should fire when navigation occurs'); + test(function () { + assert_true( !!ev && typeof(ev.state) != 'undefined', 'state information was not passed' ); + assert_true( !!ev.state, 'state information does not contain the expected value - browser is probably stuck in the wrong history position' ); + assert_equals( ev.state.nulldata, null, 'state null data was not correct' ); + assert_equals( ev.state.udefdata, window.undefined, 'state undefined data was not correct' ); + assert_true( ev.state.booldata, 'state boolean data was not correct' ); + assert_equals( ev.state.numdata, 1, 'state numeric data was not correct' ); + assert_equals( ev.state.strdata, 'string data', 'state string data was not correct' ); + assert_true( !!ev.state.datedata.getTime, 'state date data was not correct' ); + assert_own_property( ev.state, 'regdata', 'state regex data was not correct' ); + assert_equals( ev.state.regdata.source, 'a', 'state regex pattern data was not correct' ); + assert_true( ev.state.regdata.global, 'state regex flag data was not correct' ); + assert_equals( ev.state.regdata.lastIndex, 0, 'state regex lastIndex data was not correct' ); + assert_equals( ev.state.arrdata.length, 1, 'state array data was not correct' ); + assert_true( ev.state.boolobj.valueOf(), 'state boolean data was not correct' ); + assert_equals( ev.state.numobj.valueOf(), 1, 'state numeric data was not correct' ); + assert_equals( ev.state.strobj.valueOf(), 'string data', 'state string data was not correct' ); + if( canvassup ) { + assert_equals( ev.state.imgdata.width, 1, 'state ImageData was not correct' ); + } + }, 'popstate event should pass the state data'); + test(function () { + assert_equals( ev.state.looped, ev.state ); + }, 'state data should cope with circular object references'); + test(function () { + assert_not_equals( cloneobj, ev.state ); + }, 'state data should be a clone of the original object, not a reference to it'); + test(function () { + assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' ); + }, 'history.state should also reference a clone of the original object (2)'); + test(function () { + assert_not_equals( cloneobj, iframe.contentWindow.history.state ); + }, 'history.state should be a clone of the original object, not a reference to it (2)'); + test(function () { + assert_equals( iframe.contentWindow.history.state, ev.state ); + }, 'history.state should be identical to the object passed to the event handler unless history.state is updated'); + try { + iframe.contentWindow.persistval = true; + iframe.contentWindow.history.pushState('','', location.href.replace(/\/[^\/]*$/,'/blank3.html') ); + } catch(unsuperr) {} + //it's already cached, so this should be very fast if the browser mistakenly loads it + //it should not need to load at all, since it's just a pushed state + setTimeout(tests12,1000); + } + function tests12() { + test(function () { + assert_true( iframe.contentWindow.persistval && !iframe.contentWindow.forreal ); + }, 'pushState should not actually load the new URL'); + atstep = 3; + iframe.contentWindow.location.reload(); //load the real URL + lasttimer = setTimeout(function () { tests13(false); },3000); //should be cleared by the onload handler long before it has a chance to fire + } + function tests13(passed) { + test(function () { + assert_true( passed, 'expected a load event to fire when reloading the URL from cache, gave up waiting after 3 seconds' ); + }, 'reloading a pushed state should actually load the new URL'); + //try to make browsers behave when reloading so that the correct URL is recovered - does not always work + iframe.contentWindow.location.href = location.href.replace(/\/[^\/]*$/,'/blank.html'); + done(); + } + + if( atstep == 1 ) { + //blank2 has loaded + atstep = 2; + //use a timeout, because some browsers intentionally do not add history entries for URL changes in an onload thread + setTimeout(tests1,100); + } else if( atstep == 3 ) { + //blank3 should now have loaded after the .reload() command + atstep = 4; + clearTimeout(lasttimer); + tests13(true); + } +} + + + + </script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <p>WARNING: This test should always be loaded in a new tab/window, to avoid browsers attempting to recover the state of frames, and history length. Do not reload the test.</p> + <div id="log">Running test...</div> + <p><iframe onload="reportload();" src="blank.html"></iframe></p> + <p><iframe src="blank.html"></iframe></p> + <p><iframe src="blank2.html"></iframe></p> + <p><iframe src="blank3.html"></iframe></p> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/002.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/002.html new file mode 100644 index 0000000000..8bce7e72ff --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/002.html @@ -0,0 +1,318 @@ +<!doctype html> +<html> + <head> + <title>history.replaceState tests</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> +//does not test for firing of popstate onload, because this was dropped from the specification on 25 March 2011 +//covers history.state after load, in accordance with the specification draft from 25 March 2011 +//history.state before load is tested in 006 and 007 +//does not test for structured cloning of FileList, File or Blob interfaces, as these require manual file selection + +//**This test assumes that assignments to location.hash will be synchronous - this is how all browsers implement it. +//The spec (as of 25 March 2011) disagrees. + +var histlength, atstep = 0, lasttimer; +setup({explicit_done:true}); //tests should take under 6 seconds + execution time + +window.onload = function () { + if( location.protocol == 'file:' ) { + document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.'; + return; + } else if( location.protocol == 'https:' ) { + document.getElementsByTagName('p')[0].innerHTML += '<br>WARNING: Browsers may intentionally fail to update history.length when pages are loaded over HTTPS, as a privacy restriction. If possible, load this page over HTTP.'; + } + //use a timeout, because some browsers intentionally do not add history entries for URL changes in the onload thread + setTimeout(testinit,100); +}; +function testinit() { + atstep = 1; + histlength = history.length; + iframe = document.getElementsByTagName('iframe')[0].src = 'blank2.html'; + //reportload will now be called by the onload handler for the iframe +} +function reportload() { + var iframe = document.getElementsByTagName('iframe')[0], hashchng = false; + var canvassup = false, cloneobj; + + async function tests1() { + test(function () { assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); }, 'history.length should update when loading pages in an iframe'); + histlength = history.length; + let hashchange = new Promise(function(resolve) { + iframe.contentWindow.addEventListener("hashchange", resolve, {once: true}); + }); + iframe.contentWindow.location.hash = 'test'; //should be synchronous **SEE COMMENT AT TOP OF FILE + test(function () { + assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); + }, 'history.length should update when setting location.hash'); + test(function () { assert_true( !!history.replaceState, 'critical test; ignore any failures after this' ); }, 'history.replaceState must exist'); //assert_own_property does not allow prototype inheritance + test(function () { assert_true( !!iframe.contentWindow.history.replaceState, 'critical test; ignore any failures after this' ); }, 'history.replaceState must exist within iframes'); + test(function () { + assert_equals( iframe.contentWindow.history.state, null ); + }, 'initial history.state should be null'); + + await hashchange; + hashchange = new Promise(function(resolve) { + iframe.contentWindow.addEventListener("hashchange", resolve, {once: true}); + }); + iframe.contentWindow.location.hash = 'test2'; + await hashchange; + + iframe.contentWindow.addEventListener("hashchange", tests2, {once: true}); + history.back(); + } + function tests2() { + test(function () { + histlength = history.length; + iframe.contentWindow.history.replaceState('',''); + assert_equals( history.length, histlength ); + }, 'history.length should not update when replacing a state with no URL'); + test(function () { + assert_equals( iframe.contentWindow.history.state, '' ); + }, 'history.state should update after a state is pushed'); + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' ); + }, 'hash should not change when replaceState is called without a URL'); + test(function () { + histlength = history.length; + iframe.contentWindow.history.replaceState('','','#test3'); + assert_equals( history.length, histlength ); + }, 'history.length should not update when replacing a state with a URL'); + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' ); + }, 'hash should change when replaceState is called with a URL'); + iframe.contentWindow.addEventListener("hashchange", tests3, {once: true}); + history.go(-1); + } + function tests3() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), '' ); + }, 'replaceState must replace the existing state and not add an extra one'); + iframe.contentWindow.addEventListener("hashchange", tests4, {once: true}); + history.go(2); + } + function tests4() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test2' ); + }, 'replaceState must replace the existing state without altering the forward history'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.replaceState('','','//exa mple'); }); + }, 'replaceState must not be allowed to create invalid URLs'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.replaceState('','','http://www.example.com/'); }); + }, 'replaceState must not be allowed to create cross-origin URLs'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.replaceState('','','about:blank'); }); + }, 'replaceState must not be allowed to create cross-origin URLs (about:blank)'); + test(function () { + assert_throws_dom('SECURITY_ERR',function () { history.replaceState('','','data:text/html,'); }); + }, 'replaceState must not be allowed to create cross-origin URLs (data:URI)'); + test(function () { + assert_throws_dom('SECURITY_ERR',iframe.contentWindow.DOMException,function () { iframe.contentWindow.history.replaceState('','','http://www.example.com/'); }); + }, 'security errors are expected to be thrown in the context of the document that owns the history object'); + test(function () { + //avoids browsers running .go synchronously when only a hash change is involved + iframe.contentWindow.history.replaceState('','','/testing_ignore_me_404#test4'); + assert_equals( iframe.contentWindow.location.pathname, '/testing_ignore_me_404' ); + }, 'replaceState must be able to set location.pathname'); + test(function () { + var newURL = location.href.replace(/\/[^\/]*$/)+'/testing_ignore_me_404/'; + iframe.contentWindow.history.replaceState('','',newURL); + assert_equals( iframe.contentWindow.location.href, newURL ); + }, 'replaceState must be able to set absolute URLs to the same host'); + + //allow the browser to run the .go + iframe.contentWindow.addEventListener("popstate", tests5, {once: true}); + //begin setup for "[must not] remove any tasks queued by the history traversal task source" + iframe.contentWindow.history.go(-1); //must be queued so the next command takes place *beforehand* + try { + //must not remove the queued navigation in the same browsing context + iframe.contentWindow.history.replaceState('','',iframe.contentWindow.location.pathname+'#test5'); + } catch(unsuperr2) {} + } + function tests5() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' ); + }, 'replaceState must not remove any tasks queued by the history traversal task source'); + iframe.contentWindow.addEventListener("popstate", tests6, {once: true}); + //Safari 5.0.3 fails here - it navigates *this* document to the *iframe's* location, instead of just navigating the iframe + history.go(1); + } + function tests6() { + test(function () { + assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test5' ); + }, '.go must queue a task with the history traversal task source (run asynchronously)'); + //end "[must not] remove any tasks queued by the history traversal task source" + window.addEventListener('hashchange',function () { hashchng = true; },false); + try { + //push a state that changes the hash + iframe.contentWindow.history.replaceState('','',iframe.contentWindow.location.pathname+'#test6'); + } catch(unsuperr) {} + setTimeout(tests7,50); //allow the hashchange event to process, if the browser has mistakenly fired it + } + function tests7() { + test(function () { + assert_false( hashchng ); + }, 'replaceState must not fire hashchange events'); + test(function () { + assert_throws_dom( 'DATA_CLONE_ERR', function () { + history.replaceState({dummy:function () {}},''); + } ); + }, 'replaceState must not be able to use a function as data'); + test(function () { + assert_throws_dom( 'DATA_CLONE_ERR', function () { + history.replaceState({dummy:window},''); + } ); + }, 'replaceState must not be able to use a DOM node as data'); + test(function () { + try { a.b = c; } catch(errdata) { + history.replaceState({dummy:errdata},''); + assert_equals(ReferenceError.prototype, Object.getPrototypeOf(history.state.dummy)); + } + }, 'replaceState must be able to use an error object as data'); + test(function () { + assert_throws_dom('DATA_CLONE_ERR', iframe.contentWindow.DOMException, function () { + iframe.contentWindow.history.replaceState(document,''); + }); + }, 'security errors are expected to be thrown in the context of the document that owns the history object (2)'); + cloneobj = { + nulldata: null, + udefdata: window.undefined, + booldata: true, + numdata: 1, + strdata: 'string data', + boolobj: new Boolean(true), + numobj: new Number(1), + strobj: new String('string data'), + datedata: new Date(), + regdata: /a/g, + arrdata: [1] + }; + cloneobj.regdata.lastIndex = 1; + cloneobj.looped = cloneobj; + //test the ImageData type, if the browser supports it + var canvas = document.createElement('canvas'); + if( canvas.getContext && ( canvas = canvas.getContext('2d') ) && canvas.createImageData ) { + canvassup = true; + cloneobj.imgdata = canvas.createImageData(1,1); + } + test(function () { + try { + iframe.contentWindow.history.replaceState(cloneobj,'new title'); + } catch(e) { + cloneobj.looped = null; + //try again because this object is needed for future tests + iframe.contentWindow.history.replaceState(cloneobj,'new title'); + //rethrow so the browser gets a FAIL for not coping with the circular reference; "internal structured cloning algorithm" step 1 + throw(e); + } + }, 'replaceState must be able to make structured clones of complex objects'); + test(function () { + assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' ); + }, 'history.state should also reference a clone of the original object'); + test(function () { + assert_not_equals( cloneobj, iframe.contentWindow.history.state ); + }, 'history.state should be a clone of the original object, not a reference to it'); + iframe.contentWindow.addEventListener("popstate", tests8, {once: true}); + history.go(-1); + } + function tests8() { + var eventtime = setTimeout(function () { tests9(false); },500); //should be cleared by the event handler long before it has a chance to fire + iframe.contentWindow.addEventListener('popstate',function (e) { clearTimeout(eventtime); tests9(true,e); },false); + history.forward(); + } + function tests9(hasFired,ev) { + test(function () { + assert_true( hasFired ); + }, 'popstate event should fire when navigation occurs'); + test(function () { + assert_true( !!ev && typeof(ev.state) != 'undefined', 'state information was not passed' ); + assert_true( !!ev.state, 'state information does not contain the expected value - browser is probably stuck in the wrong history position' ); + assert_equals( ev.state.nulldata, null, 'state null data was not correct' ); + assert_equals( ev.state.udefdata, window.undefined, 'state undefined data was not correct' ); + assert_true( ev.state.booldata, 'state boolean data was not correct' ); + assert_equals( ev.state.numdata, 1, 'state numeric data was not correct' ); + assert_equals( ev.state.strdata, 'string data', 'state string data was not correct' ); + assert_true( !!ev.state.datedata.getTime, 'state date data was not correct' ); + assert_own_property( ev.state, 'regdata', 'state regex data was not correct' ); + assert_equals( ev.state.regdata.source, 'a', 'state regex pattern data was not correct' ); + assert_true( ev.state.regdata.global, 'state regex flag data was not correct' ); + assert_equals( ev.state.regdata.lastIndex, 0, 'state regex lastIndex data was not correct' ); + assert_equals( ev.state.arrdata.length, 1, 'state array data was not correct' ); + assert_true( ev.state.boolobj.valueOf(), 'state boolean data was not correct' ); + assert_equals( ev.state.numobj.valueOf(), 1, 'state numeric data was not correct' ); + assert_equals( ev.state.strobj.valueOf(), 'string data', 'state string data was not correct' ); + if( canvassup ) { + assert_equals( ev.state.imgdata.width, 1, 'state ImageData was not correct' ); + } + }, 'popstate event should pass the state data'); + test(function () { + assert_equals( ev.state.looped, ev.state ); + }, 'state data should cope with circular object references'); + test(function () { + assert_not_equals( cloneobj, ev.state ); + }, 'state data should be a clone of the original object, not a reference to it'); + test(function () { + assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' ); + }, 'history.state should also reference a clone of the original object (2)'); + test(function () { + assert_not_equals( cloneobj, iframe.contentWindow.history.state ); + }, 'history.state should be a clone of the original object, not a reference to it (2)'); + test(function () { + assert_equals( iframe.contentWindow.history.state, ev.state ); + }, 'history.state should be identical to the object passed to the event handler unless history.state is updated'); + try { + iframe.contentWindow.persistval = true; + iframe.contentWindow.history.replaceState('','', location.href.replace(/\/[^\/]*$/,'/blank3.html') ); + } catch(unsuperr) {} + //it's already cached, so this should be very fast if the browser mistakenly loads it + //it should not need to load at all, since it's just a pushed state + setTimeout(tests10,1000); + } + function tests10() { + test(function () { + assert_true( iframe.contentWindow.persistval && !iframe.contentWindow.forreal ); + }, 'replaceState should not actually load the new URL'); + atstep = 3; + iframe.contentWindow.location.reload(); //load the real URL + lasttimer = setTimeout(function () { tests11(false); },3000); //should be cleared by the onload handler long before it has a chance to fire + } + function tests11(passed) { + test(function () { + assert_true( passed, 'expected a load event to fire when reloading the URL from cache, gave up waiting after 3 seconds' ); + }, 'reloading a replaced state should actually load the new URL'); + //try to make browsers behave when reloading so that the correct URL is recovered - does not always work + iframe.contentWindow.location.href = location.href.replace(/\/[^\/]*$/,'/blank.html'); + done(); + } + + if( atstep == 1 ) { + //blank2 has loaded + atstep = 2; + //use a timeout, because some browsers intentionally do not add history entries for URL changes in an onload thread + setTimeout(tests1,100); + } else if( atstep == 3 ) { + //blank3 should now have loaded after the .reload() command + atstep = 4; + clearTimeout(lasttimer); + tests11(true); + } +} + + + + </script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <p>WARNING: This test should always be loaded in a new tab/window, to avoid browsers attempting to recover the state of frames, and history length. Do not reload the test.</p> + <div id="log">Running test...</div> + <p><iframe onload="reportload();" src="blank.html"></iframe></p> + <p><iframe src="blank.html"></iframe></p> + <p><iframe src="blank2.html"></iframe></p> + <p><iframe src="blank3.html"></iframe></p> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/004.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/004.html new file mode 100644 index 0000000000..e69889724f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/004.html @@ -0,0 +1,62 @@ +<!doctype html> +<html> + <head> + <title>Final history position for history.go should be calculated when executing the task</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> +setup({explicit_done:true}); +window.onload = function () { + var hashcount = 0; + if( location.hash && location.hash != '#' ) { + location.href = location.href.replace(/#.*$/,''); + return; + } + setTimeout(add1,100); + function add1() { + location.hash = '#foo'; + setTimeout(add2,100); + } + function add2() { + location.hash = '#bar'; + setTimeout(add3,100); + } + function add3() { + location.hash = '#baz'; + setTimeout(dojumps,100); + } + function dojumps() { + window.onhashchange = function () { + hashcount++; + }; + history.go(-2); + test(function () { + //many browsers special-case jumps that only imply hash changes and will do them synchronously - the spec does allow this + assert_equals( hashcount, 0, 'hashchange fired even though the location should not have changed' ); + assert_equals( location.hash.replace(/^#/,''), 'baz', 'the browser navigated synchronously' ); + }, '.go commands should be queued until the thread has ended'); + history.go(-1); + setTimeout(checkjumps,100); + } + function checkjumps() { + test(function () { + assert_true( !!hashcount, 'this testcase requires haschange support; the test cannot be used in this browser' ); + }, 'browser needs to support hashchange events for this testcase'); + test(function () { + assert_equals( hashcount, 2, 'the wrong number of queued commands were executed' ); + }, 'queued .go commands should all be executed when the queue is processed'); + test(function () { + assert_equals( location.hash.replace(/^#/,''), '' ); + }, 'history position should be calculated when executing, not when calling the .go command'); + done(); + } +}; + </script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/005.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/005.html new file mode 100644 index 0000000000..2152e85a3e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/005.html @@ -0,0 +1,47 @@ +<!doctype html> +<html> + <head> + <title>Popstate event listener registration</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + +//this test checks that onpopstate works on the body element + +var readyForPop = false, bodypop = false, inlinepop = false; +setup({explicit_done:true}); + +//use a timeout to avoid "popstate fires onload" from setting the variables too early +setTimeout(step1,1000); +function step1() { + readyForPop = true; + test(function () { + history.pushState('',''); + history.pushState('',''); + }, 'history.pushState support is needed for this testcase'); + history.go(-1); + setTimeout(step2,50); //.go is queued to end of thread +} +function step2() { + test(function () { + assert_true( bodypop ); + }, '<body onpopstate="..."> should register a listener for the popstate event'); + window.onpopstate = function () { inlinepop = true; }; + history.go(-1); + setTimeout(step3,50); //.go is queued to end of thread +} +function step3() { + test(function () { + assert_true( inlinepop ); + }, 'window.onpopstate should register a listener for the popstate event'); + done(); +} + </script> + </head> + <body onpopstate="if( readyForPop ) { bodypop = true; }"> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/006.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/006.html new file mode 100644 index 0000000000..442b6f8f1e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/006.html @@ -0,0 +1,53 @@ +<!doctype html> +<html> + <head> + <title>Firing popstate after onload, even if there is no pushed/replaced state</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + +//spec (25 March 2011 draft) states that popstate must not fire after onload unless there is a pushed/replaced state that is navigated +var popfired = false; +setup({explicit_done:true}); +window.addEventListener('popstate',function (e) { popfired = true; },false); +test(function () { + assert_equals( history.state, null ); +}, 'history.state should initially be null'); +window.onload = function () { + test(function () { + assert_false( popfired ); + }, 'popstate event should not fire before onload fires'); + test(function () { + assert_equals( history.state, null ); + }, 'history.state should still be null onload'); + popfired = false; + setTimeout(function () { + test(function () { + assert_false( popfired ); + }, 'popstate event should not fire after onload fires'); + test(function () { + assert_equals( history.state, null ); + }, 'history.state should still be null after onload'); + test(function () { + var failed = false, realstate = history.state; + try { + history.state = ''; + } catch(e) { + failed = e; + } + assert_equals(history.state,realstate,'property was read/write'); + assert_false(failed); + }, 'writing to history.state should be silently ignored and not throw an error'); + done(); + },100); +}; + + </script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/007.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/007.html new file mode 100644 index 0000000000..decb197624 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/007.html @@ -0,0 +1,66 @@ +<!doctype html> +<html> + <head> + <title>Firing popstate after onload with pushed state</title> + <meta name=timeout content=long> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log">It looks like the browser stopped loading the page when encountering a .go(-1) command pointing to a pushed state. This will break the tests.</div> + <script type="text/javascript"> + +//spec (25 March 2011 draft) states that popstate must fire before onload if there is a pushed/replaced state that is navigated +var popfired = false; +setup({explicit_done:true}); +test(function () { + assert_equals( history.state, null ); +}, 'history.state should initially be null'); +window.addEventListener('popstate',function (e) { popfired = e.state; },false); +test(function () { + history.pushState('state1',''); + history.pushState('state2',''); +}, 'history.pushState support is needed for this testcase'); +test(function () { + assert_equals( history.state, 'state2' ); +}, 'history.state should reflect pushed state'); +if( history.pushState ) { history.go(-1); } +window.onload = function () { + test(function () { + assert_true( !!popfired ); + }, 'popstate event should fire before onload fires'); + test(function () { + assert_equals( popfired, 'state1' ); + }, 'the correct state should be restored when navigating during initial load'); + test(function () { + assert_equals( history.state, 'state1' ); + }, 'history.state should reflect the navigated state onload'); + popfired = false; + setTimeout(function () { + test(function () { + assert_false( !!popfired ); + }, 'popstate event should not fire after onload fires'); + test(function () { + assert_equals( history.state, 'state1' ); + }, 'history.state should reflect the navigated state after onload'); + done(); + if( history.pushState ) { history.go(-1); } //go back to the start to avoid state recovery when reloading + },100); +}; + + </script> + + <!-- + Reuse an existing server side script to slow down page load so that + history.go(-1); above gets run before load event fires. + --> + <script> + // define TEST_DELAY so that executing delay.py doesn't warn about use + // of undefined variable. + var TEST_DELAY; + </script> + <script src="/xhr/resources/delay.py?ms=2500"></script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/008.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/008.html new file mode 100644 index 0000000000..c8071e3156 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/008.html @@ -0,0 +1,40 @@ +<!doctype html> +<html> + +<!-- configure this test below to point to the script --> + + <head> + <title>history.pushState/replaceState resolving</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <p></p> + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> + +/* +Location of the script (which must be hosted on a separate domain from this test) containing the test code: +var beforehref = location.href; +test(function () { + history.pushState('','','/testing_ignore_me_404'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404')); +}, 'history.pushState URL resolving should be done relative to the document, not the script'); +test(function () { + history.replaceState('','','/testing_ignore_me_404_2'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404_2')); +}, 'history.replaceState URL resolving should be done relative to the document, not the script'); +*/ +var scriptlocation = 'http://www.' + location.host + location.pathname.split("/").slice(0,-1).join("/") + "/008.js"; + +if( location.protocol == 'file:' ) { + document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.'; +} else { + document.write('<script type="text\/javascript" src="'+scriptlocation+'"><\/script>'); +} + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/008.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/008.js new file mode 100644 index 0000000000..96a1fe5d4a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/008.js @@ -0,0 +1,11 @@ +var beforehref = location.href; + +test(function () { + history.pushState('','','/testing_ignore_me_404'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404')); +}, 'history.pushState URL resolving should be done relative to the document, not the script'); + +test(function () { + history.replaceState('','','/testing_ignore_me_404_2'); + assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404_2')); +}, 'history.replaceState URL resolving should be done relative to the document, not the script'); diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/009-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-1.html new file mode 100644 index 0000000000..00b72e8ec6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-1.html @@ -0,0 +1,20 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +window.onload = function () { + setTimeout(function () { + try { history.pushState('','','009-2.html?1234'); } catch(e) {} + location.href = '009-3.html?pipe=sub'; + },10); +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/009-3.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-3.html new file mode 100644 index 0000000000..e58b8fa5e7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-3.html @@ -0,0 +1,28 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +var httpReferer = "{{headers[referer]}}"; +var lastUrl = location.href.replace(/\/[^\/]*$/,'\/009-2.html?1234'); +parent.test(function () { + parent.assert_equals( httpReferer, lastUrl ); +}, 'HTTP Referer should use the pushed state'); +parent.test(function () { + parent.assert_equals( document.referrer, lastUrl ); +}, 'document.referrer should use the pushed state'); +window.onload = function () { + setTimeout(function () { + try { history.pushState('','','009-4.html?2345'); } catch(e) {} + location.href = '009-5.html?pipe=sub'; + },10); +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/009-5.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-5.html new file mode 100644 index 0000000000..068a089af4 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/009-5.html @@ -0,0 +1,23 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +var httpReferer = unescape("{{headers[referer]}}"); +var lastUrl = location.href.replace(/\/[^\/]*$/,'\/009-4.html?2345'); +parent.test(function () { + parent.assert_equals( httpReferer, lastUrl ); +}, 'HTTP Referer should use the replaced state'); +parent.test(function () { + parent.assert_equals( document.referrer, lastUrl ); +}, 'document.referrer should use the replaced state'); +parent.done(); + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/009.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/009.html new file mode 100644 index 0000000000..c1ae0bbe03 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/009.html @@ -0,0 +1,22 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +setup({explicit_done:true}); +var iframe = document.createElement('iframe'); +window.onload = function () { + iframe.setAttribute('src','009-1.html'); + document.body.appendChild(iframe) +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/010-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-1.html new file mode 100644 index 0000000000..683397745c --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-1.html @@ -0,0 +1,16 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers (before onload)</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +try { history.pushState('','','010-2.html?1234'); } catch(e) {} +location.href = '010-3.html?pipe=sub'; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/010-3.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-3.html new file mode 100644 index 0000000000..b80f56c3dd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-3.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers (before onload)</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> + var httpReferer = "{{headers[referer]}}"; +var lastUrl = location.href.replace(/\/[^\/]*$/,'\/010-2.html?1234'); +parent.test(function () { + parent.assert_equals( httpReferer, lastUrl ); +}, 'HTTP Referer should use the pushed state (before onload)'); +parent.test(function () { + parent.assert_equals( document.referrer, lastUrl ); +}, 'document.referrer should use the pushed state (before onload)'); +try { history.pushState('','','010-4.html?2345'); } catch(e) {} +location.href = '010-5.html?pipe=sub'; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/010-5.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-5.html new file mode 100644 index 0000000000..d150449eb2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/010-5.html @@ -0,0 +1,23 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers (before onload)</title> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +var httpReferer = "{{headers[referer]}}"; +var lastUrl = location.href.replace(/\/[^\/]*$/,'\/010-4.html?2345'); +parent.test(function () { + parent.assert_equals( httpReferer, lastUrl ); +}, 'HTTP Referer should use the replaced state (before onload)'); +parent.test(function () { + parent.assert_equals( document.referrer, lastUrl ); +}, 'document.referrer should use the replaced state (before onload)'); +parent.done(); + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/010.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/010.html new file mode 100644 index 0000000000..ca109a744b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/010.html @@ -0,0 +1,22 @@ +<!doctype html> +<html> + <head> + <title>history.pushState/replaceState and referer headers (before onload)</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +setup({explicit_done:true}); +var iframe = document.createElement('iframe'); +window.onload = function () { + iframe.setAttribute('src','010-1.html'); + document.body.appendChild(iframe) +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/011.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/011.html new file mode 100644 index 0000000000..4043aff7fd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/011.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <title>history.pushState before onload</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +var newUrl = location.href.replace(/\/[^\/]*$/,'\/011-1.html'); +setup({explicit_done:true}); +test(function () { + history.pushState('','','011-1.html'); +}, 'pushState should be able to set the location state'); +test(function () { + assert_equals( location.href, newUrl ); +}, 'pushed location should be reflected immediately'); +window.onload = function () { + setTimeout(function () { + test(function () { + assert_equals( location.href, newUrl ); + }, 'pushed location should be retained after the page has loaded'); + done(); + },10); +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/012.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/012.html new file mode 100644 index 0000000000..f5e6251671 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/012.html @@ -0,0 +1,32 @@ +<!doctype html> +<html> + <head> + <title>history.replaceState before onload</title> + <script type="text/javascript" src="/resources/testharness.js"></script> + <script type="text/javascript" src="/resources/testharnessreport.js"></script> + </head> + <body> + + <noscript><p>Enable JavaScript and reload</p></noscript> + <div id="log"></div> + <script type="text/javascript"> +var newUrl = location.href.replace(/\/[^\/]*$/,'\/011-1.html'); +setup({explicit_done:true}); +test(function () { + history.replaceState('','','011-1.html'); +}, 'replaceState should be able to set the location state'); +test(function () { + assert_equals( location.href, newUrl ); +}, 'replaced location should be reflected immediately'); +window.onload = function () { + setTimeout(function () { + test(function () { + assert_equals( location.href, newUrl ); + }, 'replaced location should be retained after the page has loaded'); + done(); + },10); +}; + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-new.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-new.html new file mode 100644 index 0000000000..2a545af0ed --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-new.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<head> + <title>New page</title> +</head> +<body>This is a new page.</body> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-old.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-old.html new file mode 100644 index 0000000000..a77c00fcc6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank-old.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<head> + <title>Old page</title> +</head> +<body>This is an old page.</body> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/blank.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank.html new file mode 100644 index 0000000000..89c8724c09 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank.html @@ -0,0 +1,8 @@ +<!doctype html> +<html> + <head> + <title>Dummy page 1</title> + </head> + <body> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/blank2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank2.html new file mode 100644 index 0000000000..f79982e328 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank2.html @@ -0,0 +1,13 @@ +<!doctype html> +<html> + <head> + <title>Dummy page 2</title> + </head> + <body> + <script type="text/javascript"> +if( self == top || !parent.reportload ) { + document.write("<p>FAIL. Browser got confused when navigating forwards, and navigated the whole window to the iframe's location, instead of just navigating the iframe. It is not possible to run the testsuite.<\/p>"); +} + </script> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/blank3.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank3.html new file mode 100644 index 0000000000..2a8989f272 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/blank3.html @@ -0,0 +1,11 @@ +<!doctype html> +<html> + <head> + <title>Dummy page 3</title> + <script type="text/javascript"> +var forreal = true; + </script> + </head> + <body> + </body> +</html>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_001.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_001.html new file mode 100644 index 0000000000..21ba22f6fe --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_001.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_001(Combine pushState and replaceSate methods.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.pushState(1, document.title, '?x=1'); + assert_equals(history.state, 1, "first"); + + window.history.replaceState(2, document.title, '?x=1'); + assert_equals(history.state, 2, "second") + }, "Combine pushState and replaceSate methods"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_002.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_002.html new file mode 100644 index 0000000000..29e82f51be --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_002.html @@ -0,0 +1,22 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_002(After calling of pushState method, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var first; + var second; + first = window.history.length; + window.history.pushState(1, document.title, '?x=1'); + second = window.history.length; + + assert_equals(second - first, 1, "second - first"); + }, "After calling of pushState method, check length"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_003.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_003.html new file mode 100644 index 0000000000..7467d9b294 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_003.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_003(After calling of pushState and replaceState methods, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var first; + var second; + var third; + first = window.history.length; + window.history.pushState(1, document.title, '?x=1'); + second = window.history.length; + window.history.replaceState(2, document.title, '?x=2'); + third = window.history.length; + + assert_equals(second - first, 1, "second - first"); + assert_equals(third, second, "third"); + }, "After calling of pushState and replaceState methods, check length"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_004.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_004.html new file mode 100644 index 0000000000..4e38b56205 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_004.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_004(After calling of back method, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("After calling of back method, check length"); + + var last; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + last = window.history.length; + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + assert_equals(e.state, 1, "state"); + assert_equals(window.history.length, last, "last"); + t.done(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_005.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_005.html new file mode 100644 index 0000000000..4487678015 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_005.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_005(After calling of forward method, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("After calling of forward method, check length"); + + var last; + var fired = false; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + last = window.history.length; + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + if(fired) { + assert_equals(e.state, 2, "state"); + assert_equals(window.history.length, last, "last"); + t.done(); + } + fired = true; + window.history.forward(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_006.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_006.html new file mode 100644 index 0000000000..305f593c09 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_006.html @@ -0,0 +1,30 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_006(After calling of go method, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("After calling of go method, check length"); + + var last; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + last = window.history.length; + + window.history.go(-1); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + assert_equals(e.state, 1, "state"); + assert_equals(window.history.length, last, "last"); + t.done(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_007.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_007.html new file mode 100644 index 0000000000..cec9ea0981 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/combination_history_007.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>combination_history_007(After calling of back and pushState method, check length.)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("After calling of back and pushState method, check length"); + + var last; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + last = window.history.length; + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + assert_equals(e.state, 1, "state"); + assert_equals(window.history.length, last, "last"); + window.history.pushState(3, document.title, '?x=3'); + assert_equals(window.history.length, last, "last"); + t.done(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history-associated-with-document.window.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/history-associated-with-document.window.js new file mode 100644 index 0000000000..94c1b2cf6b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history-associated-with-document.window.js @@ -0,0 +1,6 @@ +// META: title=the History object must be associated with the Document object, not the Window object +// META: script=/common/object-association.js + +// See https://github.com/whatwg/html/issues/2566. + +testIsPerDocument("history"); diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history-state-after-bfcache.window.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/history-state-after-bfcache.window.js new file mode 100644 index 0000000000..5f04890a72 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history-state-after-bfcache.window.js @@ -0,0 +1,43 @@ +// META: title=Navigating back to a bfcached page does not reset history.state +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js + +// See https://github.com/whatwg/html/issues/6652. + +'use strict'; + +promise_test(async t => { + const rcHelper = new RemoteContextHelper(); + + // Open a window with noopener so that BFCache will work. + const rc = await rcHelper.addWindow(null, { features: "noopener" }); + + // Add a pageshow listener to stash the event, and set history.state using replaceState(). + await rc.executeScript(() => { + window.addEventListener('pageshow', (event) => { + window.pageshowEvent = event; + }); + + history.replaceState({ foo: 'bar' }, '', ''); + window.stashedHistoryState = history.state; + }); + + const rc2 = await rc.navigateToNew(); + await rc2.historyBack(); + + assert_implements_optional( + await rc.executeScript(() => window.pageshowEvent.persisted), + 'precondition: document was bfcached' + ); + + assert_equals( + await rc.executeScript(() => history.state.foo), + 'bar', + 'history.state was restored correctly' + ); + + assert_true( + await rc.executeScript(() => window.stashedHistoryState === history.state), + 'history.state did not get serialized and deserialized'); +}); diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/history.js new file mode 100644 index 0000000000..bb5ee6dde0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history.js @@ -0,0 +1,35 @@ +function parse_query() { + var query = location.search.slice(1); + var vars = query.split("&"); + var fields = {}; + vars.forEach( + function (x) { + var split = x.split("="); + return fields[split[0]] = split.slice(1).join("="); + }); + return fields; +} + +var query_parts = parse_query(); +var id = "id" in query_parts ? parseInt(query_parts.id) : 1; +var urls_to_load = query_parts.urls.split(","); + +document.write(id); + +onunload = function() {}; + +function queue_next() { + t = opener.t; + setTimeout(t.step_func( + function() { +// opener.assert_equals(history.length, id); + if (urls_to_load[0]) { + var next_page = urls_to_load[0]; + (next_page.indexOf("?") > -1) ? (next_page += "&") : (next_page += "?"); + next_page += "urls=" + urls_to_load.slice(1).join(","); + next_page += "&id=" + ++id; + location = next_page; + } + } + ), 100); +} diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back-1.html new file mode 100644 index 0000000000..78547019f3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.back(); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back.html new file mode 100644 index 0000000000..042da4e61b --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_back</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("history back"); + + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + assert_equals(e.state, 1, "history state"); + + t.done(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_1.html new file mode 100644 index 0000000000..8ccf205956 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_1.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>history.back() with session history</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [2, 1], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_back-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_cross_realm_method.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_cross_realm_method.html new file mode 100644 index 0000000000..47937ef583 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_back_cross_realm_method.html @@ -0,0 +1,22 @@ +<!doctype html> +<meta charset="utf-8"> +<title>history.back() uses this's associated document's browsing context to determine if navigation is allowed</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/history.html#dom-history-back"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="sandboxedIframe" srcdoc="hello" sandbox="allow-scripts allow-same-origin"></iframe> +<script> +const t = async_test(); + +t.step(() => { + history.pushState({}, null, "?prev"); + history.pushState({}, null, "?current"); + + sandboxedIframe.contentWindow.history.back.call(history); +}); + +window.onpopstate = t.step_func_done(() => { + assert_equals(location.search, "?prev"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_entry.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_entry.html new file mode 100644 index 0000000000..e5929ddbe8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_entry.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + } +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-1.html new file mode 100644 index 0000000000..5880eacf04 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-1.html @@ -0,0 +1,15 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + history.forward(); + } + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-2.html new file mode 100644 index 0000000000..c7a9a10682 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward-2.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(-1); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward.html new file mode 100644 index 0000000000..6c37f25215 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_forward</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("history forward"); + + var fired = false; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + if(fired) { + assert_equals(e.state, 2, "history state"); + + t.done(); + } + fired = true; + window.history.forward(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_1.html new file mode 100644 index 0000000000..220495c7f6 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_1.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>history.forward() with session history</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [3, 2, 3], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_forward-1.html,history_forward-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_cross_realm_method.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_cross_realm_method.html new file mode 100644 index 0000000000..7456099b8f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_forward_cross_realm_method.html @@ -0,0 +1,28 @@ +<!doctype html> +<meta charset="utf-8"> +<title>history.forward() uses this's associated document's browsing context to determine if navigation is allowed</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/history.html#dom-history-forward"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="sandboxedIframe" srcdoc="hello" sandbox="allow-scripts allow-same-origin"></iframe> +<script> +const t = async_test(); + +t.step(() => { + history.pushState({}, null, "?prev"); + history.pushState({}, null, "?current"); + history.back(); +}); + +let isCrossRealmForward = false; +window.onpopstate = t.step_func(() => { + if (isCrossRealmForward) { + assert_equals(location.search, "?current"); + t.done(); + } else { + sandboxedIframe.contentWindow.history.forward.call(history); + isCrossRealmForward = true; + } +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_cross_realm_method.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_cross_realm_method.html new file mode 100644 index 0000000000..d8852b9f6f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_cross_realm_method.html @@ -0,0 +1,23 @@ +<!doctype html> +<meta charset="utf-8"> +<title>history.go() uses this's associated document's browsing context to determine if navigation is allowed</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/history.html#dom-history-go"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="sandboxedIframe" srcdoc="hello" sandbox="allow-scripts allow-same-origin"></iframe> +<script> +const t = async_test(); + +t.step(() => { + history.pushState({}, null, "?prev=2"); + history.pushState({}, null, "?prev=1"); + history.pushState({}, null, "?current"); + + sandboxedIframe.contentWindow.history.go.call(history, -2); +}); + +window.onpopstate = t.step_func_done(() => { + assert_equals(location.search, "?prev=2"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_minus.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_minus.html new file mode 100644 index 0000000000..b8fe75573d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_minus.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_go_minus</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("history go minus"); + + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + window.history.go(-1); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + assert_equals(e.state, 1, "history state"); + + t.done(); + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument-1.html new file mode 100644 index 0000000000..acd9bda31d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument-1.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + if (!opener.gone) { + history.go(); + opener.gone = true; + } + } + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument.html new file mode 100644 index 0000000000..68aeab2027 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_no_argument.html @@ -0,0 +1,29 @@ +<!doctype html> +<title>history.go()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + gone = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [3, 2, 2], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_go_no_argument-1.html,history_forward-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_plus.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_plus.html new file mode 100644 index 0000000000..74d4c588ca --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_plus.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_go_plus</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + var t = async_test("history go plus"); + + var fired = false; + t.step(function () { + window.history.pushState(1, document.title, '?x=1'); + window.history.pushState(2, document.title, '?x=2'); + + window.history.back(); + }); + + window.addEventListener('popstate', t.step_func(function(e) { + if(fired) { + assert_equals(e.state, 2, "history state"); + + t.done(); + } + fired = true; + window.history.go(1); + + }), false); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri-1.html new file mode 100644 index 0000000000..46c744e95d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri-1.html @@ -0,0 +1,23 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + if (!opener.gone) { + // This is meant to test that passing a string is not supported. + // According to the spec, the value passed to 'go' must be an int. + // Internet Explorer supports passing a string and will navigate + // to that Url. This test will protect against regressing in + // this area and reverting back to IE's incorrect behavior. + history.go("history_entry.html"); + opener.gone = true; + } + } + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri.html new file mode 100644 index 0000000000..43d4a6b001 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_to_uri.html @@ -0,0 +1,32 @@ +<!doctype html> +<title>history.go() negative tests</title> +<link rel="author" title="John Jansen" href="mailto:johnjan@microsoft.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/browsers.html#dom-history-go"> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + gone = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [3, 2, 2], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_go_to_uri-1.html,history_forward-2.html"); + }); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined-1.html new file mode 100644 index 0000000000..5880eacf04 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined-1.html @@ -0,0 +1,15 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + history.forward(); + } + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined.html new file mode 100644 index 0000000000..ddb0c858c2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_undefined.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>history.forward() with session history</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [3, 2, 2], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_go_undefined-1.html,history_forward-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero-1.html new file mode 100644 index 0000000000..d9d4f330b2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero-1.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {} + + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + if (!opener.gone) { + history.go(0); + opener.gone = true; + } + } + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero.html new file mode 100644 index 0000000000..88750921b0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero.html @@ -0,0 +1,29 @@ +<!doctype html> +<title>history.go(0)</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + gone = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [3, 2, 2], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_go_zero-1.html,history_forward-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero_which_document.window.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero_which_document.window.js new file mode 100644 index 0000000000..f697783f3e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_go_zero_which_document.window.js @@ -0,0 +1,27 @@ +// META: title=history.go(0) on an iframe must reload the iframe's document, not the parent document +// META: script=/common/dispatcher/dispatcher.js +// META: script=/common/utils.js +// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js + +promise_test(async () => { + const rcHelper = new RemoteContextHelper(); + const main = await rcHelper.addWindow(); + await main.addIframe(); + + await main.executeScript(() => { + window.didNotGetReloaded = true; + + const iframe = document.querySelector("iframe"); + + // This goes beyond the original test case in https://github.com/whatwg/html/issues/2436, and + // tests where current realm != relevant realm. The spec says to use relevant realm so the + // result is still, iframe must reload, not parent. + History.prototype.go.call(iframe.contentWindow.history, 0); + + return new Promise(resolve => { + iframe.addEventListener("load", resolve); + }); + }); + + assert_true(await main.executeScript(() => window.didNotGetReloaded)); +}); diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_properties_only_fully_active.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_properties_only_fully_active.html new file mode 100644 index 0000000000..2b2c308526 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_properties_only_fully_active.html @@ -0,0 +1,23 @@ +<!doctype html> +<title>history properties should throw SecurityError when not in a fully active Document</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> + <iframe id="child"></iframe> +</body> +<script> + test(function(t) { + var ifr = document.getElementById("child"); + var cached_history = ifr.contentWindow.history; + var cached_DOMException = ifr.contentWindow.DOMException; + ifr.remove(); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.length; }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.scrollRestoration; }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.state; }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.go(0); }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.back(); }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.forward(); }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.pushState(1, document.title, "?x=1"); }); + assert_throws_dom("SecurityError", cached_DOMException, function() { cached_history.replaceState(2, document.title, "?x=2"); }); + }); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate.html new file mode 100644 index 0000000000..5180a3f6e5 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_pushState</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.pushState(1, document.title, '?x=1'); + var state; + state = window.history.state; + assert_equals(state, 1, "history state"); + }, "history pushState"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_err.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_err.html new file mode 100644 index 0000000000..6fa0a8589d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_err.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_pushState SECURITY_ERR</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + assert_throws_dom("SecurityError", function () { + window.history.pushState(1, document.title, 'http://www.microsoft.com/test.html'); + }); + }, "history pushState SECURITY_ERR"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html new file mode 100644 index 0000000000..8e4b049a19 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_pushState_NoOptionalParam</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.pushState(1, document.title); + + var state; + state = window.history.state; + assert_equals(state, 1, "history state"); + }, "history pushState NoOptionalParam"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url.html new file mode 100644 index 0000000000..cfbca35bfd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> +<meta charset="utf-8"> +<title>History pushState sets the url</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script> +async_test(function(t) { + var oldLocation = window.location.toString(); + window.history.pushState(null, "", "#hash"); + assert_equals(oldLocation + "#hash", window.location.toString(), "pushState updates url"); + history.back(); + window.onhashchange = () => { + assert_equals(oldLocation, window.location.toString(), 'history traversal restores old url'); + t.done(); + }; +}, "history pushState sets url"); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url_rewriting.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url_rewriting.html new file mode 100644 index 0000000000..03c2afe8ea --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_pushstate_url_rewriting.html @@ -0,0 +1,176 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>URL rewriting allowed/disallowed for history.pushState()</title> +<link rel="help" href="https://github.com/whatwg/html/issues/6836"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +"use strict"; +setup({ explicit_done: true }); + +const baseWithUsernamePassword = new URL(location.href); +baseWithUsernamePassword.username = "username"; +baseWithUsernamePassword.password = "password"; + +const blobURL = URL.createObjectURL(new Blob(["foo"], { type: "text/html" })); +const blobURL2 = URL.createObjectURL(new Blob(["bar"], { type: "text/html" })); + +const basicCases = [ + [new URL("/common/blank.html", location.href), new URL("/common/blank.html#newhash", location.href), true], + [new URL("/common/blank.html", location.href), new URL("/common/blank.html?newsearch", location.href), true], + [new URL("/common/blank.html", location.href), new URL("/newpath", location.href), true], + [new URL("/common/blank.html", location.href), new URL("/common/blank.html", baseWithUsernamePassword), false], + [new URL("/common/blank.html", location.href), blobURL, false], + [new URL("/common/blank.html", location.href), "about:blank", false], + [new URL("/common/blank.html", location.href), "about:srcdoc", false], + [blobURL, blobURL, true], + [blobURL, blobURL + "#newhash", true], + [blobURL, blobURL + "?newsearch", false], + [blobURL, "blob:newpath", false], + [blobURL, "blob:" + self.origin + "/syntheticblob", false], + [blobURL, blobURL2, false], + + // Note: these are cases where we create the iframe pointing at the initial URL, + // so its origin will actually be self.origin. + ["about:blank", "about:blank", true], + ["about:blank", "about:srcdoc", false], + ["about:blank", "about:blank?newsearch", false], + ["about:blank", "about:blank#newhash", true], + ["about:blank", self.origin + "/blank", false], + + // javascript: URL navigation changes the URL to the creator document's URL, so these should all + // not work because you can't rewrite a HTTP(S) URL to a javascript: URL. + [new URL("/common/blank.html", location.href), "javascript:'foo'", false], + ["javascript:'foo'", "javascript:'foo'", false], + ["javascript:'foo'", "javascript:'foo'?newsearch", false], + ["javascript:'foo'", "javascript:'foo'#newhash", false], +].map(([from, to, expectedToWork]) => [from.toString(), to.toString(), expectedToWork]); + +for (const [from, to, expectedToWork] of basicCases) { + // Otherwise the messages are not consistent between runs which breaks some systems. + const fromForTitle = from.replaceAll(blobURL, "blob:(a blob URL for this origin)") + .replaceAll(blobURL2, "blob:(another blob URL for this origin)"); + const toForTitle = to.replaceAll(blobURL, "blob:(a blob URL for this origin)") + .replaceAll(blobURL2, "blob:(another blob URL for this origin)"); + + promise_test(async () => { + const iframe = document.createElement("iframe"); + iframe.src = from; + const loadPromise = new Promise(r => iframe.onload = r); + + document.body.append(iframe); + await loadPromise; + + if (expectedToWork) { + iframe.contentWindow.history.pushState(null, "", to); + assert_equals(iframe.contentWindow.location.href, to); + } else { + assert_throws_dom("SecurityError", iframe.contentWindow.DOMException, () => { + iframe.contentWindow.history.pushState(null, "", to); + }); + } + }, `${fromForTitle} to ${toForTitle} should ${expectedToWork ? "" : "not"} work`); +} + +const srcdocCases = [ + ["about:srcdoc", true], + ["about:srcdoc?newsearch", false], + ["about:srcdoc#newhash", true], + [self.origin + "/srcdoc", false] +]; + +for (const [to, expectedToWork] of srcdocCases) { + promise_test(async () => { + const iframe = document.createElement("iframe"); + iframe.srcdoc = "foo"; + const loadPromise = new Promise(r => iframe.onload = r); + + document.body.append(iframe); + await loadPromise; + + if (expectedToWork) { + iframe.contentWindow.history.pushState(null, "", to); + assert_equals(iframe.contentWindow.location.href, to); + } else { + assert_throws_dom("SecurityError", iframe.contentWindow.DOMException, () => { + iframe.contentWindow.history.pushState(null, "", to); + }); + } + }, `about:srcdoc to ${to} should ${expectedToWork ? "" : "not"} work`); +} + +// We need to test these separately since they're cross-origin. + +const sandboxedCases = [ + [new URL("resources/url-rewriting-helper.html", location.href), new URL("resources/url-rewriting-helper.html", location.href), true], + [new URL("resources/url-rewriting-helper.html", location.href), new URL("resources/url-rewriting-helper.html#newhash", location.href), true], + [new URL("resources/url-rewriting-helper.html", location.href), new URL("resources/url-rewriting-helper.html?newsearch", location.href), true], + [new URL("resources/url-rewriting-helper.html", location.href), new URL("/newpath", location.href), true], + [new URL("resources/url-rewriting-helper.html", location.href), new URL("resources/url-rewriting-helper.html", baseWithUsernamePassword), false], +].map(([from, to, expectedToWork]) => [from.toString(), to.toString(), expectedToWork]); + +for (const [from, to, expectedToWork] of sandboxedCases) { + promise_test(async () => { + const iframe = document.createElement("iframe"); + iframe.src = from; + iframe.sandbox = "allow-scripts"; + const loadPromise = new Promise(r => iframe.onload = r); + + document.body.append(iframe); + await loadPromise; + + const messagePromise = new Promise(r => window.addEventListener("message", r, { once: true })); + iframe.contentWindow.postMessage(to, "*"); + const { data } = await messagePromise; + + if (expectedToWork) { + assert_equals(data.result, "no exception"); + assert_equals(data.locationHref, to); + } else { + assert_equals(data.result, "exception"); + assert_equals(data.exceptionName, "SecurityError"); + } + }, `sandboxed ${from} to ${to} should ${expectedToWork ? "" : "not"} work`); +} + +fetch("resources/url-rewriting-helper.html").then(r => r.text()).then(htmlInside => { + const dataURLStart = "data:text/html;base64," + btoa(htmlInside); + + const dataURLCases = [ + [dataURLStart, dataURLStart, true], + [dataURLStart, dataURLStart + "#newhash", true], + [dataURLStart, dataURLStart + "?newsearch", false], + [dataURLStart, "data:newpath", false] + ]; + + for (const [from, to, expectedToWork] of dataURLCases) { + // Otherwise the messages are unreadably long. + const fromForTitle = from.replaceAll(dataURLStart, "data:(script to run this test)"); + const toForTitle = to.replaceAll(dataURLStart, "data:(script to run this test)"); + + promise_test(async () => { + const iframe = document.createElement("iframe"); + iframe.src = from; + const loadPromise = new Promise(r => iframe.onload = r); + + document.body.append(iframe); + await loadPromise; + + const messagePromise = new Promise(r => window.addEventListener("message", r, { once: true })); + iframe.contentWindow.postMessage(to, "*"); + const { data } = await messagePromise; + if (expectedToWork) { + assert_equals(data.result, "no exception"); + assert_equals(data.locationHref, to); + } else { + assert_equals(data.result, "exception"); + assert_equals(data.exceptionName, "SecurityError"); + } + }, `${fromForTitle} to ${toForTitle} should ${expectedToWork ? "" : "not"} work`); + } + + done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate.html new file mode 100644 index 0000000000..794c2f3713 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_replaceState</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.replaceState(1, document.title, '?x=1'); + + var second; + second = window.history.state; + assert_equals(second, 1, "history state"); + }, "history replaceState"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_err.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_err.html new file mode 100644 index 0000000000..15d2181820 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_err.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_replaceState SECURITY_ERR</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + assert_throws_dom("SecurityError", function () { + window.history.replaceState(1, document.title, 'http://www.microsoft.com/test.html'); + }); + }, "history replaceState SECURITY_ERR"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html new file mode 100644 index 0000000000..838467d782 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_replaceStateNoOptionalParam</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.replaceState(1, document.title); + + var second; + second = window.history.state; + assert_equals(second, 1, "history state"); + }, "history replaceStateNoOptionalParam"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/history_state.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_state.html new file mode 100644 index 0000000000..2ee2356b1a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/history_state.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>history_state</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var first; + var second; + + first = window.history.state; + window.history.pushState(1, document.title, '?x=1'); + + second = window.history.state; + assert_equals(first, null, "first"); + assert_equals(second, 1, "second"); + }, "history state"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/iframe_history_go_0.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/iframe_history_go_0.html new file mode 100644 index 0000000000..f93f4c864e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/iframe_history_go_0.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<head> + <title>iframe_history_go_0</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<iframe></iframe> +<script> +promise_test(async (t) => { + let iframe = null; + const OLD_URL = 'blank-old.html'; + const NEW_URL = 'blank-new.html'; + + await new Promise(resolve => { + iframe = document.createElement('iframe'); + iframe.onload = () => resolve(); + iframe.src = OLD_URL; + document.body.appendChild(iframe); + t.add_cleanup(() => iframe.remove()); + }); + + assert_equals(iframe.contentDocument.body.textContent, 'This is an old page.\n'); + + await new Promise(resolve => { + iframe.onload = () => resolve(); + iframe.src = NEW_URL; + }); + + assert_equals(iframe.contentDocument.body.textContent, 'This is a new page.\n'); + + await new Promise(resolve => { + iframe.onload = () => resolve(); + iframe.contentWindow.history.go(0); + }); + + assert_equals(iframe.contentDocument.body.textContent, 'This is a new page.\n'); +}, 'iframe\'s history.go(0) performs a location.reload()'); +</script> +</body> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001-1.html new file mode 100644 index 0000000000..9aa5d30d16 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001-1.html @@ -0,0 +1,72 @@ +<!doctype html> +<script> +var o = opener; + +var frameloaded = null; + +o.t.step(function() {o.assert_equals(history.length, 1)}); + +onload = function () { + o.t.step(function() { + o.assert_equals(history.length, 1); + o.t.done(); + }); + + o.t1.step(function() { + var iframe = document.createElement("iframe"); + iframe.src = "filler.html?id=2"; + document.body.appendChild(iframe); + frameloaded = o.t1.step_func(function () { + o.assert_equals(history.length, 1); + setTimeout(o.t1.step_func(function () { + o.assert_equals(history.length, 1); + iframe.src = "filler.html?id=3"; + frameloaded = o.t2.step_func(function() { + o.assert_equals(history.length, 2); + history.go(-1); + frameloaded = o.t3.step_func(function() { + o.assert_equals(history.length, 2); + var parts = iframe.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=2"); + o.t3.done(); + o.t4.step(function() { + var iframe0 = document.getElementsByTagName("iframe")[0]; + iframe0.src = "filler.html?id=4" + frameloaded = o.t4.step_func(function() { + o.assert_equals(history.length, 2); + var parts = iframe0.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=4"); + //This is the point at which gecko and webkit stop running tests + history.go(-1); + frameloaded = o.t5.step_func(function() { + o.assert_equals(history.length, 2); + var parts = iframe0.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=1"); + var parts = iframe.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=2"); + history.go(1); + frameloaded = o.t6.step_func(function() { + o.assert_equals(history.length, 2); + var parts = iframe0.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=4"); + var parts = iframe.contentWindow.location.href.split("/") + o.assert_equals(parts[parts.length - 1], "filler.html?id=2"); + o.t6.done(); + }); + o.t5.done(); + }); + o.t4.done(); + }); + }); + }); + o.t2.done(); + }); + o.t1.done(); + }, 500)) + }); + }); + +} +</script> + +<iframe src="filler.html?id=1"></iframe> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001.html new file mode 100644 index 0000000000..c9d1c6416d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/001.html @@ -0,0 +1,18 @@ +<!doctype html> +<title>Joint session history with single iframe</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +setup({timeout:10000}); +var t = async_test("Session history length on initial load"); +var t1 = async_test("Session history length on adding new iframe"); +var t2 = async_test("Navigating second iframe"); +var t3 = async_test("Traversing history back (1)"); +var t4 = async_test("Navigating first iframe"); +var t5 = async_test("Traversing history back (2)"); +var t6 = async_test("Traversing history forward"); +var w = window.open("001-1.html"); +//add_completion_callback(function() {w.close()}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002-1.html new file mode 100644 index 0000000000..ed69d679da --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002-1.html @@ -0,0 +1,35 @@ +<!doctype html> +<script> +var o = opener; + +var frameloaded = null; + +o.t.step(function() {o.assert_equals(history.length, 1)}); + +onload = function () { + o.t.step(function() { + o.assert_equals(history.length, 1); + o.t.done(); + }); + + o.t1.step(function() { + var iframe = document.createElement("iframe"); + iframe.src = "filler.html?id=2"; + document.body.appendChild(iframe); + o.assert_equals(history.length, 1); + frameloaded = o.t2.step_func(function() { + iframe.contentDocument.open(); + iframe.contentDocument.write("3<script>onpageshow = function() {alert('pageshow'); parent.frameloaded()}<\/script>"); + iframe.contentDocument.close(); + frameloaded = o.t2.step_func(function () { + o.assert_equals(history.length, 2); + o.t2.done(); + }); + }); + o.t1.done(); + }); + +} +</script> + +<iframe src="filler.html?id=1"></iframe> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002.html new file mode 100644 index 0000000000..b08c19e52d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/002.html @@ -0,0 +1,18 @@ +<!doctype html> +<title>Joint session history with single iframe</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +setup({timeout:10000}); +var t = async_test("Session history length on initial load"); +var t1 = async_test("Session history length on adding new iframe"); +var t2 = async_test("Navigating second iframe"); +<!-- var t3 = async_test("Traversing history back (1)"); --> +<!-- var t4 = async_test("Navigating first iframe"); --> +<!-- var t5 = async_test("Traversing history back (2)"); --> +<!-- var t6 = async_test("Traversing history forward"); --> +var w = window.open("002-1.html"); +//add_completion_callback(function() {w.close()}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/filler.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/filler.html new file mode 100644 index 0000000000..93e3c7ccfc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/joint_session_history/filler.html @@ -0,0 +1,5 @@ +<!doctype html> +<script> +document.write(location.search) +onpageshow = function() {if (parent.frameloaded) {parent.frameloaded()}} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history.js b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history.js new file mode 100644 index 0000000000..bb5ee6dde0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history.js @@ -0,0 +1,35 @@ +function parse_query() { + var query = location.search.slice(1); + var vars = query.split("&"); + var fields = {}; + vars.forEach( + function (x) { + var split = x.split("="); + return fields[split[0]] = split.slice(1).join("="); + }); + return fields; +} + +var query_parts = parse_query(); +var id = "id" in query_parts ? parseInt(query_parts.id) : 1; +var urls_to_load = query_parts.urls.split(","); + +document.write(id); + +onunload = function() {}; + +function queue_next() { + t = opener.t; + setTimeout(t.step_func( + function() { +// opener.assert_equals(history.length, id); + if (urls_to_load[0]) { + var next_page = urls_to_load[0]; + (next_page.indexOf("?") > -1) ? (next_page += "&") : (next_page += "?"); + next_page += "urls=" + urls_to_load.slice(1).join(","); + next_page += "&id=" + ++id; + location = next_page; + } + } + ), 100); +} diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history_entry.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history_entry.html new file mode 100644 index 0000000000..e5929ddbe8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/history_entry.html @@ -0,0 +1,12 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onload = function() { + if (!opener.started) { + queue_next(); + } else { + opener.pages.push(id); + opener.start_test_wait(); + } +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-1.html new file mode 100644 index 0000000000..8c4401836a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-1.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onbeforeunload = function() {opener.beforeunload_ran = true; return "Opt to stay on the page"}; + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.back(); + }, 100); + } + } +</script> +<p>You should see/have seen a prompt asking if you want to leave the page.</p> +<p>Opt to stay on the page</p> +<button onclick="onbeforeunload = null; opener.start_test_wait(); document.getElementsByTagName('button')[0].disabled = true;">Click here</button> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-manual.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-manual.html new file mode 100644 index 0000000000..587cdfb124 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_1-manual.html @@ -0,0 +1,31 @@ +<!doctype html> +<title>Traversing the history, prompt in before unload, navigation denied</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + setup({timeout:3600000}); + var t = async_test(); + started = false; + pages = [] + timer = null; + beforeunload_ran = false; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_true(beforeunload_ran, "beforeunload event handler ran"); + assert_array_equals(pages, [2], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=traverse_the_history_unload_prompt_1-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-1.html new file mode 100644 index 0000000000..608a579e69 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-1.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onbeforeunload = function() {opener.beforeunload_ran = true; return "Opt to leave the page"}; + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.back(); + }, 100); + } + } +</script> +<p>You should see/have seen a prompt asking if you want to leave the page.</p> +<p>Opt to leave the page</p> +<p>If you weren't navigated away after opting to leave the page, that's a FAIL</p> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-manual.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-manual.html new file mode 100644 index 0000000000..94b66f8b55 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_history_unload_prompt_2-manual.html @@ -0,0 +1,31 @@ +<!doctype html> +<title>Traversing the history, prompt in before unload, navigation allowed</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + setup({timeout:3600000}); + var t = async_test(); + started = false; + pages = [] + timer = null; + beforeunload_ran = false; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_true(beforeunload_ran, "beforeunload event handler ran"); + assert_array_equals(pages, [2,1], "Pages opened during history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=traverse_the_history_unload_prompt_2-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-1.html new file mode 100644 index 0000000000..c0079b6bec --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function(e) {opener.unload_ran = true; return "Now refuse to leave the current page"} + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.back(); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-manual.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-manual.html new file mode 100644 index 0000000000..7f96a39240 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/non-automated/traverse_the_session_history_unload_prompt_1-manual.html @@ -0,0 +1,30 @@ +<!doctype html> +<title>Traversing the history, unload event is fired on doucment</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + unload_ran = false; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [2], "Pages opened during history navigation"); + assert_true(unload_ran, "Unload event handler ran"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=traverse_the_history_unload_prompt_1-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/message-opener.sub.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/message-opener.sub.html new file mode 100644 index 0000000000..441c08c0ea --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/message-opener.sub.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script> +"use strict"; + +opener.postMessage("{{GET[id]}}", "*"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-beforeunload.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-beforeunload.html new file mode 100644 index 0000000000..53a4a1886e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-beforeunload.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script> +"use strict"; + +window.addEventListener("beforeunload", () => { + history.back(); +}); + +location.href = "message-opener.sub.html?id=destination"; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-unload.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-unload.html new file mode 100644 index 0000000000..d5ffb7abae --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/traverse-during-unload.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script> +"use strict"; + +window.addEventListener("unload", () => { + history.back(); +}); + +location.href = "message-opener.sub.html?id=destination"; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/url-rewriting-helper.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/url-rewriting-helper.html new file mode 100644 index 0000000000..847d16cd1a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/resources/url-rewriting-helper.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<script> + window.onmessage = ({ data }) => { + try { + history.pushState(null, "", data); + } catch (e) { + parent.postMessage({ result: "exception", exceptionName: e.name }, "*"); + return; + } + parent.postMessage({ result: "no exception", locationHref: location.href }, "*"); + }; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-beforeunload.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-beforeunload.html new file mode 100644 index 0000000000..cb8cdca7ff --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-beforeunload.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Traversing the history during beforeunload</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +"use strict"; + +async_test(t => { + const w = window.open("resources/message-opener.sub.html?id=start"); + t.add_cleanup(() => w.close()); + + const messages = []; + window.addEventListener("message", t.step_func(({ data }) => { + messages.push(data); + + if (messages.length === 1) { + assert_array_equals(messages, ["start"]); + w.location.href = "resources/traverse-during-beforeunload.html"; + } else if (messages.length === 2) { + assert_array_equals(messages, ["start", "destination"]); + t.done(); + } + })); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-unload.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-unload.html new file mode 100644 index 0000000000..6f6e984402 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse-during-unload.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Traversing the history during unload</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +"use strict"; + +async_test(t => { + const w = window.open("resources/message-opener.sub.html?id=start"); + t.add_cleanup(() => w.close()); + + const messages = []; + window.addEventListener("message", t.step_func(({ data }) => { + messages.push(data); + + if (messages.length === 1) { + assert_array_equals(messages, ["start"]); + w.location.href = "resources/traverse-during-unload.html"; + } else if (messages.length === 2) { + assert_array_equals(messages, ["start", "destination"]); + t.done(); + } + })); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1-1.html new file mode 100644 index 0000000000..a11fcf2d2d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1-1.html @@ -0,0 +1,18 @@ +<!doctype html> +4 +<script> + onunload = function() {} + + opener.pages.push(4); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(-2); + history.go(-1); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1.html new file mode 100644 index 0000000000..9b59bb0587 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_1.html @@ -0,0 +1,25 @@ +<!doctype html> +<title>Multiple history traversals from the same task</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + assert_array_equals(pages, [4, 2], "Pages opened during history navigation"); + t.done(); + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_entry.html,history_entry.html,traverse_the_history_1-1.html"); + t.add_cleanup(() => { win.close() }); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2-1.html new file mode 100644 index 0000000000..64920b4f4f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(-3); + history.go(-2); + history.go(1); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2.html new file mode 100644 index 0000000000..1d10033808 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_2.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>Multiple history traversals, last would be aborted</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [6, 3], "Pages opened during history navigation"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_entry.html,history_entry.html,history_entry.html,history_entry.html,traverse_the_history_2-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3-1.html new file mode 100644 index 0000000000..c49bfd384a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(-2); + history.go(-1); + history.go(3); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3.html new file mode 100644 index 0000000000..1d10033808 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_3.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>Multiple history traversals, last would be aborted</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [6, 3], "Pages opened during history navigation"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_entry.html,history_entry.html,history_entry.html,history_entry.html,traverse_the_history_2-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4-1.html new file mode 100644 index 0000000000..cf7f72379a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(-10); //Outside the range + history.go(-1); + history.go(-2); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4.html new file mode 100644 index 0000000000..2856bf8d73 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_4.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>Multiple history traversals, last would be aborted</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [6, 5], "Pages opened during history navigation"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_entry.html,history_entry.html,history_entry.html,history_entry.html,traverse_the_history_4-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5-1.html new file mode 100644 index 0000000000..a3f2553fa0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.go(10); //Outside the range + history.go(-1); + history.go(-2); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5.html new file mode 100644 index 0000000000..8725497b50 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_5.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>Multiple history traversals, last would be aborted</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [6, 5], "Pages opened during history navigation"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_entry.html,history_entry.html,history_entry.html,history_entry.html,traverse_the_history_5-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1-1.html new file mode 100644 index 0000000000..d3f3f6d5d0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1-1.html @@ -0,0 +1,17 @@ +<!doctype html> +<script src="history.js"></script> +<script> + onunload = function() {opener.unload_ran = true;} + + opener.pages.push(id); + if (!opener.started) { + onload = function() { + setTimeout(function() { + opener.started = true; + history.back(); + }, 100); + } + } else { + opener.start_test_wait(); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html new file mode 100644 index 0000000000..b8215b29f3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_unload_1.html @@ -0,0 +1,30 @@ +<!doctype html> +<title>Traversing the history, unload event is fired on doucment</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + unload_ran = false; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + assert_array_equals(pages, [2, 1], "Pages opened during history navigation"); + assert_true(unload_ran, "Unload event handler ran"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=traverse_the_history_unload_1-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1-1.html new file mode 100644 index 0000000000..945c8d81f8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1-1.html @@ -0,0 +1,12 @@ +<!doctype html> +2 +<script> + onunload = function() {} + opener.pages.push(2); + onload = function() { + setTimeout(function() { + document.write("<!doctype html>3<script>opener.pages.push(3); if(!opener.started) {opener.started = true; history.go(-1);}<\/script>"); + document.close(); + }, 100); + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1.html new file mode 100644 index 0000000000..404d61d0cf --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_1.html @@ -0,0 +1,29 @@ +<!doctype html> +<title>Traverse the history after document.write after the load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + start_test_wait = t.step_func( + function() { + check_result = t.step_func( + function() { + if (pages.length < 3) { + setTimeout(check_result, 500); + return + } + assert_array_equals(pages, [2, 3, 1], "Pages opened during history navigation"); + t.done(); + } + ) + setTimeout(check_result, 500); + } + ); + t.step(function() { + win = window.open("history_entry.html?urls=traverse_the_history_write_after_load_1-1.html"); + t.add_cleanup(function() {win.close()}); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2-1.html new file mode 100644 index 0000000000..0e58cf573d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2-1.html @@ -0,0 +1,12 @@ +<!doctype html> +3 +<script> + onunload = function() {} + opener.pages.push(3); + onload = function() { + document.write("<!doctype html>4<script>opener.pages.push(4); if(!opener.started) {opener.started = true; history.go(-2);} opener.start_test_wait();<\/script>"); + if (opener.started) { + opener.start_test_wait(); + } + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2.html new file mode 100644 index 0000000000..28e363f916 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_after_load_2.html @@ -0,0 +1,28 @@ +<!doctype html> +<title>Traverse the history back and forward when a history entry is written after the load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + start_test_wait = t.step_func( + function() { + var check_result = t.step_func(function() { + if (pages.length < 5) { + setTimeout(check_result, 500); + return + } + //The pass condition here is based on the idea that the spec is wrong and browsers are right + assert_array_equals(pages, [3, 4, 2, 3, 4], "Pages opened during history navigation"); + t.done(); + }); + setTimeout(check_result, 500); + } + ); + t.step(function() { + win = window.open("history_entry.html?urls=history_forward-1.html,traverse_the_history_write_onload_2-1.html"); + t.add_cleanup(function() {win.close()}); + }); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1-1.html new file mode 100644 index 0000000000..261955533d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1-1.html @@ -0,0 +1,12 @@ +<!doctype html> +2 +<script> + onunload = function() {} + opener.pages.push(2); + onload = function() { + document.write("<!doctype html>3<script>opener.pages.push(3); if(!opener.started) {opener.started = true; history.go(-1);} opener.start_test_wait();<\/script>"); + if (opener.started) { + opener.start_test_wait(); + } + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1.html new file mode 100644 index 0000000000..ff2729c3cf --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_1.html @@ -0,0 +1,29 @@ +<!doctype html> +<title>Traverse the history when a history entry is written in the load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + //The pass condition here is based on the idea that the spec is wrong and browsers are right + assert_array_equals(pages, [2, 3, 1], "Pages opened durning history navigation"); + t.done(); + } finally { + // win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=traverse_the_history_write_onload_1-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2-1.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2-1.html new file mode 100644 index 0000000000..f32bee5e12 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2-1.html @@ -0,0 +1,12 @@ +<!doctype html> +3 +<script> + onunload = function() {} + opener.pages.push(3); + onload = function() { + document.write("<!doctype html>4<script>opener.pages.push(4); if(!opener.started) {opener.started = true; history.go(-1);} opener.start_test_wait();<\/script>"); + if (opener.started) { + opener.start_test_wait(); + } + } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2.html b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2.html new file mode 100644 index 0000000000..bc29174b0d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-history-interface/traverse_the_history_write_onload_2.html @@ -0,0 +1,29 @@ +<!doctype html> +<title>Traverse the history back and forward when a history entry is written in the load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + var t = async_test(); + started = false; + pages = [] + timer = null; + start_test_wait = t.step_func( + function() { + clearTimeout(timer); + timer = setTimeout(t.step_func( + function() { + try { + //The pass condition here is based on the idea that the spec is wrong and browsers are right + assert_array_equals(pages, [3, 4, 2, 3, 4], "Pages opened durning history navigation"); + t.done(); + } finally { + win.close(); + } + } + ), 500); + } + ); + t.step(function() {win = window.open("history_entry.html?urls=history_forward-1.html,traverse_the_history_write_onload_2-1.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html new file mode 100644 index 0000000000..f72ed1eaf2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html @@ -0,0 +1,197 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + + <title>Location objects' custom [[GetPrototypeOf]] trap permit [[Prototype]] chain cycles to be created through them</title> + + <link rel="author" title="Jeff Walden" href="http://whereswalden.com/" /> + <link rel="help" href="https://tc39.github.io/ecma262/#sec-ordinarysetprototypeof" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/browsers.html#location-getprototypeof" /> + + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> + +<hr /> + +<iframe id="same-origin-different-window"></iframe> +<iframe id="cross-origin-joined-via-document-domain"></iframe> + +<script> +"use strict"; + +// Handle same-origin, same-window testing first, before any async-requiring +// testing. +test(function() { + var LocationPrototype = Location.prototype; + var ObjectPrototype = Object.prototype; + + var loc = window.location; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); +}, "same-origin, same-window location cycle"); + +var pathdir = + location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1); + +var triggerCrossOriginTest = (function() { + var crossOrigin = + document.getElementById("cross-origin-joined-via-document-domain"); + + var t = async_test("cross-origin location has null prototype"); + + return new Promise(function(resolve, reject) { + crossOrigin.onload = t.step_func_done(function(e) { + try { + var win = crossOrigin.contentWindow; + + var loc = win.location; + + // Between un-opted-in windows, location objects appear to have null + // [[Prototype]]. + assert_equals(Object.getPrototypeOf(loc), null, + "cross-origin unjoined location's [[Prototype]"); + + resolve(); + } catch (e) { + reject(e); + throw e; + } + }); + + crossOrigin.src = + "//{{domains[www]}}:" + location.port + pathdir + "cross_origin_joined_frame.sub.html"; + }) + .catch(t.unreached_func("crossOrigin onload/src setting")); +})(); + +var triggerSameOriginTest = (function() { + var sameOriginDifferentWindow = + document.getElementById("same-origin-different-window"); + + var t = async_test("same-origin, different-window location cycle"); + + return new Promise(function(resolve, reject) { + sameOriginDifferentWindow.onload = t.step_func_done(function() { + try { + var win = sameOriginDifferentWindow.contentWindow; + + var loc = win.location; + var LocationPrototype = win.Location.prototype; + var ObjectPrototype = win.Object.prototype; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); + + resolve(); + } catch (e) { + reject(e); + throw e; + } + }); + + sameOriginDifferentWindow.src = "same_origin_frame.html"; + }) + .catch(t.unreached_func("sameOriginDifferentWindow onload/src setting")); +})(); + +function crossOriginJoinTest() { + var win = + document.getElementById("cross-origin-joined-via-document-domain") + .contentWindow; + + assert_equals(document.domain, "{{host}}"); + + var loc = win.location; + + var threw = false; + try { + // Still cross-origin until the document.domain set below. + win.Location; + } catch (e) { + threw = true; + } + + assert_equals(threw, true, + "accessing win.Location before joining win's origin"); + + // Join with other frames that have set |document.domain| to this same + // value -- namely, this cross-origin frame. Now access between the two + // windows should be permitted. + assert_equals(document.domain, "{{host}}", + "initial document.domain sanity check"); + document.domain = "{{host}}"; + + var LocationPrototype = win.Location.prototype; + var ObjectPrototype = win.Object.prototype; + + var locProto = Object.getPrototypeOf(loc); + assert_equals(locProto, LocationPrototype, + "loc's initial [[Prototype]]"); + + var originalLocProtoProto = Object.getPrototypeOf(locProto); + assert_equals(originalLocProtoProto, ObjectPrototype, + "Location.prototype's initial [[Prototype]]"); + + Object.setPrototypeOf(locProto, loc); + + assert_equals(Object.getPrototypeOf(locProto), loc, + "LocationPrototype's new [[Prototype]]"); + assert_equals(Object.getPrototypeOf(loc), locProto, + "loc's new [[Prototype]]"); + + // Reset so as not to muck with testharness.js expectations. + Object.setPrototypeOf(locProto, originalLocProtoProto); +} + +function run() { + var t = + async_test("cross-origin, but joined via document.domain, location cycle"); + + // The cross-origin/joined case must be tested after both unjoined same-origin + // and unjoined cross-origin tests: by mucking with document.domain, the + // cross-origin/joined case makes it impossible to perform those tests. + t.step(function() { + Promise.all([triggerCrossOriginTest, triggerSameOriginTest]) + .then(t.step_func_done(crossOriginJoinTest), + t.unreached_func("cross-origin joined error case")); + }); +} +run(); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-1.html new file mode 100644 index 0000000000..3d2b897221 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-1.html @@ -0,0 +1,9 @@ +<!doctype html> +1 +<script> +onload = parent.t.step_func(function() { + setTimeout(function() { + location = location.toString().replace("assign_after_load-1.html", "assign_after_load-2.html"); + }, 100); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-2.html new file mode 100644 index 0000000000..94679571be --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +2 +<script> +onload = parent.t.step_func(function() { + setTimeout(function() {parent.do_test()}, 100); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html new file mode 100644 index 0000000000..00dc931d4e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_after_load.html @@ -0,0 +1,23 @@ +<!doctype html> +<title>Assignment to location after document is completely loaded</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> +var t = async_test(); +var history_length; + +onload = t.step_func(function() { + setTimeout(function() { + history_length = history.length; + document.getElementsByTagName("iframe")[0].src = "assign_after_load-1.html"; + }, 100); +}); + +do_test = t.step_func(function() { + assert_equals(history.length, history_length + 2); + t.done(); +}); + +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-1.html new file mode 100644 index 0000000000..2549867c8f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-1.html @@ -0,0 +1,7 @@ +<!doctype html> +1 +<script> +onload = parent.t.step_func(function() { + location = location.toString().replace("assign_before_load-1.html", "assign_before_load-2.html"); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-2.html new file mode 100644 index 0000000000..94679571be --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +2 +<script> +onload = parent.t.step_func(function() { + setTimeout(function() {parent.do_test()}, 100); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html new file mode 100644 index 0000000000..62a2aa7c60 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/assign_before_load.html @@ -0,0 +1,23 @@ +<!doctype html> +<title>Assignment to location before document is completely loaded</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> +var t = async_test(); +var history_length; + +onload = t.step_func(function() { + setTimeout(function() { + history_length = history.length; + document.getElementsByTagName("iframe")[0].src = "assign_before_load-1.html"; + }, 100); +}); + +do_test = t.step_func(function() { + assert_equals(history.length, history_length + 1); + t.done(); +}); + +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/cross_origin_joined_frame.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/cross_origin_joined_frame.sub.html new file mode 100644 index 0000000000..a3ffdd005a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/cross_origin_joined_frame.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Cross-origin subframe for Location cyclic [[Prototype]] test</title> + <link rel="author" title="Jeff Walden" href="http://whereswalden.com/" /> +</head> +<body> +<script> +document.domain = "{{host}}"; +</script> +<!-- this should be accessible to the parent once it sets document.domain --> +<p>Cross-origin iframe with joined <code>document.domain</code></p> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/document_location.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/document_location.html new file mode 100644 index 0000000000..3bdb028212 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/document_location.html @@ -0,0 +1,39 @@ +<!doctype html> +<title>document.location</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +test(function() { + var doc = document.implementation.createHTMLDocument(""); + assert_equals(doc.location, null); +}, "document not in a browsing context"); + +test(function() { + assert_equals(document.location, location); +}, "document.location equals window.location"); + +test(function() { + var desc1 = Object.getOwnPropertyDescriptor(new Document(), "location"); + assert_not_equals(desc1, undefined); + assert_equals(typeof desc1.get, "function"); + + var desc2 = Object.getOwnPropertyDescriptor(new Document(), "location"); + assert_not_equals(desc2, undefined); + assert_equals(typeof desc2.get, "function"); + + assert_equals(desc1.get, desc2.get); +}, "Attribute getter deduplication"); + +test(function() { + var desc1 = Object.getOwnPropertyDescriptor(new Document(), "location"); + assert_not_equals(desc1, undefined); + assert_equals(typeof desc1.set, "function"); + + var desc2 = Object.getOwnPropertyDescriptor(new Document(), "location"); + assert_not_equals(desc2, undefined); + assert_equals(typeof desc2.set, "function"); + + assert_equals(desc1.set, desc2.set); +}, "Attribute setter deduplication"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-non-configurable-toString-valueOf.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-non-configurable-toString-valueOf.html new file mode 100644 index 0000000000..80760ac9e4 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-non-configurable-toString-valueOf.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Same-origin Location objects have non-configurable "toString" and "valueOf" properties</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/history.html#location-defineownproperty"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +"use strict"; + +test(() => { + assert_own_property(location, "toString"); + const origToString = location.toString; + + assert_throws_js(TypeError, () => { + Object.defineProperty(location, "toString", { + get() {}, + set(_v) {}, + enumerable: true, + configurable: true, + }); + }); + + assert_equals(location.toString, origToString); +}, "'toString' redefinition with accessor fails"); + +test(() => { + assert_own_property(location, "valueOf"); + const origValueOf = location.valueOf; + + assert_throws_js(TypeError, () => { + Object.defineProperty(location, "valueOf", { + get() {}, + enumerable: false, + configurable: true, + }); + }); + + assert_equals(location.valueOf, origValueOf); +}, "'valueOf' redefinition with accessor fails"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-origin-idna.sub.window.js b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-origin-idna.sub.window.js new file mode 100644 index 0000000000..83b030f886 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-origin-idna.sub.window.js @@ -0,0 +1,11 @@ +async_test(t => { + const frame = document.createElement("iframe"), + asciiOrigin = location.protocol + "//{{domains[天気の良い日]}}:" + location.port, + path = new URL("resources/post-your-origin.html", location).pathname; + frame.src = asciiOrigin + path; + self.onmessage = t.step_func_done(e => { + assert_equals(e.data.origin, asciiOrigin); + }); + document.body.appendChild(frame); + t.add_cleanup(() => frame.remove()); +}, "Test that location.origin returns ASCII"); diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-pathname-setter-question-mark.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-pathname-setter-question-mark.html new file mode 100644 index 0000000000..09546020f7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-pathname-setter-question-mark.html @@ -0,0 +1,16 @@ +<!doctype html> +<title>Set location.pathname to ?</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<iframe src=/common/blank.html></iframe> +<script> +async_test((t) => { + onload = t.step_func(() => { + self[0].frameElement.onload = t.step_func_done(() => { + assert_equals(self[0].location.pathname, "/%3F") + }) + self[0].location.pathname = "?" + }) +}) +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prevent-extensions.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prevent-extensions.html new file mode 100644 index 0000000000..a8c777aded --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prevent-extensions.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[PreventExtensions]] on a Location object should return false</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/history.html#location-preventextensions"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +"use strict"; + +test(() => { + assert_throws_js(TypeError, () => { + Object.preventExtensions(location); + }); +}, "Object.preventExtensions throws a TypeError"); + +test(() => { + assert_false(Reflect.preventExtensions(location)); +}, "Reflect.preventExtensions returns false"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html new file mode 100644 index 0000000000..544eb4ad9a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html @@ -0,0 +1,35 @@ +<!doctype html> +<title>Set location.protocol from an HTTP URL</title> +<!-- In particular, valid non-broken schemes that are nevertheless not going to work --> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<iframe src=/common/blank.html></iframe> +<iframe src=/common/blank.html></iframe> +<iframe src=/common/blank.html></iframe> +<iframe src=/common/blank.html></iframe> +<iframe src=/common/blank.html></iframe> +<iframe src=/common/blank.html></iframe> +<script> +self.onload = () => { + [ + 'x', + 'data', + 'file', + 'ftp', + 'http+x' + ].forEach((val, index) => { + async_test((t) => { + self[index].location.protocol = val + t.step_timeout(() => { + assert_equals(self[index].location.protocol, location.protocol) + assert_equals(self[index].location.host, location.host) + assert_equals(self[index].location.port, location.port) + t.done() + // Experimentally, 4 seconds is long enough for the navigation to + // complete, if it happens. + }, 4000) + }, "Set location.protocol to " + val) + }) +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html new file mode 100644 index 0000000000..32d1f1f314 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html @@ -0,0 +1,59 @@ +<!doctype html> +<title>Set location.protocol to a non-broken-non-functioning scheme</title> +<!-- In particular, valid non-broken schemes that are nevertheless not going to work --> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +self.onload = () => { + [ + 'x', + 'data', + // 'mailto' opens an email client in Firefox... + 'file', + 'ftp', + 'http+x' + ].forEach((val) => { + async_test((t) => { + // HTTP URL <iframe> + const frame = document.createElement("iframe") + frame.src = "/common/blank.html" + frame.onload = t.step_func(() => { + frame.contentWindow.location.protocol = val + t.step_timeout(() => { + assert_equals(frame.contentWindow.location.protocol, location.protocol) + assert_equals(frame.contentWindow.location.host, location.host) + assert_equals(frame.contentWindow.location.port, location.port) + t.done() + }, 500) + }) + document.body.appendChild(frame) + }, "Set HTTP URL frame location.protocol to " + val) + + async_test((t) => { + // data URL <iframe> + const dataFrame = document.createElement("iframe") + const channel = new MessageChannel() + dataFrame.src = `data:text/html,<script> +onmessage = (e) => { + let result = false; + try { + location.protocol = e.data + } catch(e) { + result = true + } + setTimeout(() => e.ports[0].postMessage([result, location.protocol]), 100) +} +<\/script>` + dataFrame.onload = t.step_func(() => { + dataFrame.contentWindow.postMessage(val, "*", [channel.port2]) + }) + channel.port1.onmessage = t.step_func_done((e) => { + assert_false(e.data[0]) + assert_equals(e.data[1], "data:") + }) + document.body.appendChild(dataFrame) + }, "Set data URL frame location.protocol to " + val) + }) +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html new file mode 100644 index 0000000000..0612b5c709 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter-with-colon.sub.html @@ -0,0 +1,52 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<iframe id="existing" src="resources/post-your-protocol.html?existing"></iframe> +<iframe id="http-and-gunk" src="resources/post-your-protocol.html?http-and-gunk"></iframe> +<!-- iframe id="https-and-gunk" src="resources/post-your-protocol.html?https-and-gunk"></iframe --> +<script> +// NOTE: we do not listen to message events until our load event fires, so we +// only get them for the things we actually care about. +var wrapper_test = async_test("General setup"); +var tests = { + "existing": { test: async_test("Set location.protocol = location.protocol"), + result: location.protocol }, + "http-and-gunk": { test: async_test("Set location.protocol to http:gunk"), + result: "http:" }, + // We should really test the "https:gunk" case too, and assert that it ends up + // with a protocol of "https:", but can't. See comments below for why. +}; + +function messageListener(e) { + var data = e.data; + var id = data.id; + var t = tests[id].test; + t.step(function() { + assert_equals(data.protocol, tests[id].result, "Protocol should match"); + }) + t.done(); +} + +addEventListener("load", wrapper_test.step_func_done(function() { + addEventListener("message", messageListener); + + tests["existing"].test.step(function() { + var loc = document.getElementById("existing").contentWindow.location; + loc.protocol = loc.protocol; + }); + tests["http-and-gunk"].test.step(function() { + var loc = document.getElementById("http-and-gunk").contentWindow.location; + loc.protocol = "http:gunk"; + }); + // I wish we could test the https bit, but can't figure out a non-racy way to + // do it, because we need to change both protocol (to https) _and_ port to + // {{ports[https][0]}} to get a successful load unless we're running on the + // default http port, but the setter uses the current value, which doesn't get + // updated sync, as the url to start with for the set. Oh, and there's no + // good way to detect when the port set is "done" either. +})); + +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter.html new file mode 100644 index 0000000000..da6859b19f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-protocol-setter.html @@ -0,0 +1,110 @@ +<!doctype html> +<title>Set location.protocol to broken schemes</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<iframe src="data:text/html,<script> +onmessage = (e) => { + let results = []; + e.data.forEach((val) => { + try { + location.protocol = val; + results.push('failure') + } catch(e) { + results.push(e.name) + } + }); + parent.postMessage(results, '*') +} +</script>"></iframe> +<iframe srcdoc="<script> +onmessage = (e) => { + let results = []; + e.data.forEach((val) => { + try { + location.protocol = val; + results.push('failure') + } catch(e) { + results.push(e.name) + } + }); + parent.postMessage(results, '*') +} +</script>"></iframe> +<script> + // Tests with '\x0A' (i.e., '\n') don't conform to the URL Standard as of the + // time of writing, as according to spec they should be ignored. + // See https://github.com/whatwg/url/issues/609. + + let broken = [ + '\x00', + '\x01', + '\x0A', + '\x20', + '\x21', + '\x7F', + '\x80', + '\xFF', + ':', + '†', + '\x00x', + '\x01x', + '\x0Ax', + '\x20x', + '\x21x', + '\x7Fx', + '\x80x', + '\xFFx', + ':x', + '†x', + '\x00X', + '\x01X', + '\x0AX', + '\x20X', + '\x21X', + '\x7FX', + '\x80X', + '\xFFX', + ':X', + '†X', + 'x\x00', + 'x\x01', + 'x\x0A', + 'x\x20', + 'x\x21', + 'x\x7F', + 'x\x80', + 'x\xFF', + 'x†', + 'X\x00', + 'X\x01', + 'X\x0A', + 'X\x20', + 'X\x21', + 'X\x7F', + 'X\x80', + 'X\xFF', + 'X†', + 'a\x0A', + 'a+-.\x0A' + ] + ;broken.forEach((val) => { + test(() => { + assert_throws_dom("SyntaxError", () => { location.protocol = val }) + }, encodeURI(val) + " (percent-encoded) is not a scheme") + }) + let c = 0 + async_test((t) => { + self.onload = t.step_func(() => { + self.onmessage = t.step_func((e) => { + assert_array_equals(e.data, broken.map(() => "SyntaxError")) + c++ + if(c === 2) { + t.done() + } + }) + self[0].postMessage(broken, "*") + self[1].postMessage(broken, "*") + }) + }, "Equivalent tests for data URL and srcdoc <iframe>s") +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-no-toString-valueOf.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-no-toString-valueOf.html new file mode 100644 index 0000000000..56316320af --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-no-toString-valueOf.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Location.prototype objects don't have own "toString" and "valueOf" properties</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +"use strict"; + +test(t => { + assert_not_own_property(Location.prototype, "toString"); + t.add_cleanup(() => { delete Location.prototype.toString; }); + + let val; + Object.defineProperty(Location.prototype, "toString", { + get: () => val, + set: newVal => { val = newVal; }, + enumerable: false, + configurable: true, + }); + + Location.prototype.toString = 2; + assert_equals(Location.prototype.toString, 2); +}, "'toString' accessor property is defined"); + +test(t => { + assert_not_own_property(Location.prototype, "toString"); + t.add_cleanup(() => { delete Location.prototype.toString; }); + + Location.prototype.toString = 4; + assert_equals(Location.prototype.toString, 4); +}, "'toString' data property is created via [[Set]]"); + +test(t => { + assert_not_own_property(Location.prototype, "valueOf"); + t.add_cleanup(() => { delete Location.prototype.valueOf; }); + + Object.defineProperty(Location.prototype, "valueOf", { + get: () => 6, + enumerable: true, + configurable: true, + }); + + assert_equals(Location.prototype.valueOf, 6); +}, "'valueOf' accessor property is defined"); + +test(t => { + assert_not_own_property(Location.prototype, "valueOf"); + t.add_cleanup(() => { delete Location.prototype.valueOf; }); + + Location.prototype.valueOf = 8; + assert_equals(Object.getOwnPropertyDescriptor(Location.prototype, "valueOf").value, 8); +}, "'valueOf' data property is created via [[Set]]"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub.html new file mode 100644 index 0000000000..1e677b0365 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin via document.domain</title> +<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/test-setting-immutable-prototype.js"></script> + +<iframe src="/common/domain-setter.sub.html"></iframe> + +<script> +"use strict"; +// This page does *not* set document.domain, so it's cross-origin with the iframe +setup({ explicit_done: true }); + +window.onload = () => { + const targetLocation = frames[0].location; + const origProto = Object.getPrototypeOf(targetLocation); + + test(() => { + assert_equals(Object.getPrototypeOf(targetLocation), null); + }, "Cross-origin via document.domain: the prototype is null"); + + testSettingImmutablePrototype("Cross-origin via document.domain", targetLocation, origProto, + { isSameOriginDomain: false }); + + done(); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub.html new file mode 100644 index 0000000000..7bb6a27e21 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin</title> +<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/test-setting-immutable-prototype.js"></script> + +<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/blank.html"></iframe> + +<script> +"use strict"; +setup({ explicit_done: true }); + +window.onload = () => { + const targetLocation = frames[0].location; + + test(() => { + assert_equals(Object.getPrototypeOf(targetLocation), null); + }, "Cross-origin: the prototype is null"); + + testSettingImmutablePrototype("Cross-origin", targetLocation, null, { isSameOriginDomain: false }); + + done(); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub.html new file mode 100644 index 0000000000..8966a814c5 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin via document.domain after initially getting the object</title> +<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/test-setting-immutable-prototype.js"></script> + +<iframe src="/common/blank.html"></iframe> + +<script> +"use strict"; +setup({ explicit_done: true }); + +window.onload = () => { + const targetLocation = frames[0].location; + const origProto = Object.getPrototypeOf(targetLocation); + + test(() => { + assert_not_equals(origProto, null); + }, "Same-origin (for now): the prototype is accessible"); + + document.domain = "{{host}}"; + + test(() => { + assert_equals(Object.getPrototypeOf(targetLocation), null); + }, "Became cross-origin via document.domain: the prototype is now null"); + + testSettingImmutablePrototype("Became cross-origin via document.domain", targetLocation, null, { isSameOriginDomain: false }); + + testSettingImmutablePrototypeToNewValueOnly( + "Became cross-origin via document.domain", targetLocation, origProto, + "the original value from before going cross-origin", { isSameOriginDomain: false }); + + done(); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html new file mode 100644 index 0000000000..8ec7585daa --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[SetPrototypeOf]] on a Location object should not allow changing its value: cross-origin, but same-origin-domain</title> +<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/test-setting-immutable-prototype.js"></script> + +<iframe src="//{{domains[www]}}:{{ports[http][1]}}/common/domain-setter.sub.html"></iframe> + +<script> +"use strict"; +document.domain = "{{host}}"; +setup({ explicit_done: true }); + +window.onload = () => { + const targetLocation = frames[0].location; + const origProto = Object.getPrototypeOf(targetLocation); + + test(() => { + assert_not_equals(origProto, null); + }, "Same-origin-domain prerequisite check: the original prototype is accessible"); + + testSettingImmutablePrototype("Same-origin-domain", targetLocation, origProto, { isSameOriginDomain: true }, frames[0]); + + done(); +}; +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin.html new file mode 100644 index 0000000000..f912004f73 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-prototype-setting-same-origin.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>[[SetPrototypeOf]] on a location object should not allow changing its value: same-origin</title> +<link rel="help" href="http://html.spec.whatwg.org/multipage/#location-setprototypeof"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src="/common/test-setting-immutable-prototype.js"></script> + +<script> +"use strict"; + +const origProto = Object.getPrototypeOf(location); + +test(() => { + assert_not_equals(origProto, null); +}, "Same-origin prerequisite check: the original prototype is accessible"); + +testSettingImmutablePrototype("Same-origin", location, origProto, { isSameOriginDomain: true }); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-stringifier.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-stringifier.html new file mode 100644 index 0000000000..48bad7af0e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-stringifier.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Location stringifier</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="help" href="https://webidl.spec.whatwg.org/#es-stringifier"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/stringifiers.js></script> +<div id=log></div> +<script> +test_stringifier_attribute(location, "href", true); + +test(function() { + const prop1 = Object.getOwnPropertyDescriptor(location, "toString"), + prop2 = Object.getOwnPropertyDescriptor(location, "href") + + assert_true(prop1.enumerable) + assert_false(prop1.writable) + assert_false(prop1.configurable) + + assert_true(prop2.enumerable) + assert_false(prop2.configurable) + assert_equals(typeof prop2.get, "function") +}) +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-symbol-toprimitive.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-symbol-toprimitive.html new file mode 100644 index 0000000000..e666a3e703 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-symbol-toprimitive.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Location Symbol.toPrimitive</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(() => { + assert_equals(location[Symbol.toPrimitive], undefined) + const prop = Object.getOwnPropertyDescriptor(location, Symbol.toPrimitive) + assert_false(prop.enumerable) + assert_false(prop.writable) + assert_false(prop.configurable) +}) +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-tojson.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-tojson.html new file mode 100644 index 0000000000..5f20a6e15c --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-tojson.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Location has no toJSON</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(() => { + assert_equals(location.toJSON, undefined) + assert_equals(Object.getOwnPropertyDescriptor(location, "toJSON"), undefined) + assert_false(location.hasOwnProperty("toJSON")) +}) +</script> +<!-- See https://github.com/whatwg/html/pull/2294 for context. (And the HTML Standard of course.) --> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location-valueof.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-valueof.html new file mode 100644 index 0000000000..978bbb63a0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location-valueof.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Location valueOf</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +test(() => { + assert_equals(location.valueOf, Object.prototype.valueOf) + assert_equals(typeof location.valueOf.call(5), "object") + const prop = Object.getOwnPropertyDescriptor(location, "valueOf") + assert_false(prop.enumerable) + assert_false(prop.writable) + assert_false(prop.configurable) +}) +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign.html new file mode 100644 index 0000000000..55f26d5660 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_assign</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var href = location.href; + location.assign('#x'); + + assert_equals((href + "#x"), location.href, "location href"); + + }, "location assign"); + + test(function () { + var href = location.href; + assert_throws_dom('SYNTAX_ERR', function() { location.assign("http://:"); }); + assert_equals(location.href, href); + }, "URL that fails to parse"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank-1.html new file mode 100644 index 0000000000..b43598f2cd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank-1.html @@ -0,0 +1,2 @@ +<!doctype html> +Filler text diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank.html new file mode 100644 index 0000000000..f3f7cf26b8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_assign_about_blank.html @@ -0,0 +1,24 @@ +<!doctype html> +<title>location.assign with initial about:blank browsing context</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<iframe></iframe> +<script> +var t = async_test(); +var history_length; +onload = t.step_func(function() { + setTimeout(t.step_func(function() { + var iframe = document.getElementsByTagName("iframe")[0]; + iframe.onload = t.step_func(function() { + setTimeout(t.step_func(function() { + assert_equals(history.length, history_length); + t.done(); + }), 100); + }); + history_length = history.length; + iframe.src = "location_assign_about_blank-1.html" + }), 100); +}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hash.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hash.html new file mode 100644 index 0000000000..c063e285ea --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hash.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_hash</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <iframe id="srcdoc-iframe" + srcdoc="<div style='height: 200vh'></div><div id='test'></div>"></iframe> + <script> + function resetHash() { + location.hash = ""; + } + + test(function (t) { + t.add_cleanup(resetHash); + window.history.pushState(1, document.title, '#x=1'); + var hash = location.hash; + + assert_equals(hash, "#x=1", "hash"); + + }, "location hash"); + + var t = async_test("Setting location.hash on srcdoc iframe"); + addEventListener("load", t.step_func_done(function() { + var frameWin = document.getElementById("srcdoc-iframe").contentWindow; + assert_equals(frameWin.location.href, "about:srcdoc"); + assert_equals(frameWin.scrollY, 0, "Should not have scrolled yet"); + frameWin.location.hash = "test"; + assert_equals(frameWin.location.href, "about:srcdoc#test"); + assert_true(frameWin.scrollY > frameWin.innerHeight, + "Should have scrolled by more than one viewport height"); + })); + + test(function(t) { + t.add_cleanup(resetHash); + location.hash = "test"; + assert_equals(location.hash, "#test"); + }, "Setting hash should automatically include hash character"); + + test(function(t) { + t.add_cleanup(resetHash); + location.hash = "#not encoded"; + assert_equals(location.hash, "#not%20encoded"); + }, "Setting hash should encode incompatible characters"); + + test(function(t) { + t.add_cleanup(resetHash); + location.hash = "#already%20encoded"; + assert_equals(location.hash, "#already%20encoded"); + }, "Setting hash to an already encoded value should not double encode it"); + + test(function(t) { + t.add_cleanup(resetHash); + location.hash = "#mixed encoding%20here"; + assert_equals(location.hash, "#mixed%20encoding%20here"); + }, "Setting hash which is partially encoded should only encode incompatible characters"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_host.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_host.html new file mode 100644 index 0000000000..d93bf47e50 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_host.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_host</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var host = location.host; + var url = location.href; + + var pos = url.indexOf("//"); + if (pos != -1) { + url = url.substr(pos+2, url.length-pos-2); + pos = url.indexOf("/"); + if (pos != -1) + url = url.substr(0, pos); + } + + assert_equals(host, url, "host"); + + }, "location host"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hostname.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hostname.html new file mode 100644 index 0000000000..2ffa0e5fc8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_hostname.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_hostname</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var hostname = location.hostname; + var url = location.href; + + var pos = url.indexOf("//"); + if (pos != -1) { + url = url.substr(pos+2, url.length-pos-2); + pos = url.indexOf(":"); + if (pos != -1) { + url = url.substr(0, pos); + } else { + pos = url.indexOf("/"); + if (pos != -1) + url = url.substr(0, pos); + } + } + + assert_equals(hostname, url, "hostname"); + + }, "location hostname"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_href.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_href.html new file mode 100644 index 0000000000..1aa85dcdc8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_href.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_href</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var href = location.href; + + assert_equals(href, document.URL, "href"); + + }, "location href"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html new file mode 100644 index 0000000000..2325f4018a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_origin.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset="utf-8"> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + test(function () { + assert_equals( + location.origin, + location.protocol + '//' + location.host, + "origin" + ); + }, "location origin"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_pathname.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_pathname.html new file mode 100644 index 0000000000..dea05d2f37 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_pathname.html @@ -0,0 +1,22 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_pathname</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var pathname = location.pathname; + var url = location.href + + url = url.replace(location.protocol + "//" + location.host, ""); + + assert_equals(pathname, url, "pathname"); + + }, "location pathname"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_port.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_port.html new file mode 100644 index 0000000000..fa1308ca5d --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_port.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_port</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var port = location.port; + var url = location.href; + + var pos = url.indexOf("//"); + if (pos != -1) { + url = url.substr(pos+2, url.length-pos-2); + pos = url.indexOf("/"); + if (pos != -1) + url = url.substr(0, pos); + pos = url.indexOf(":"); + if (pos != -1) + url = url.substr(pos+1, url.length-pos-1); + } + + assert_equals(port, url, "port"); + + }, "location port"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_protocol.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_protocol.html new file mode 100644 index 0000000000..d28bd56393 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_protocol.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_protocol</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var protocol = location.protocol; + var url = location.href; + + var pos = url.indexOf("//"); + if (pos != -1) { + url = url.substr(0, pos); + } + + assert_equals(protocol, url, "protocol"); + + }, "location protocol"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload-iframe.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload-iframe.html new file mode 100644 index 0000000000..f08cf5de3e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload-iframe.html @@ -0,0 +1,4 @@ +<script> + parent._ping(window.location.href) + if (parent._pingCount < 5) { location.reload(); } +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload.html new file mode 100644 index 0000000000..0a2d21d8d2 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_reload</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body onload="startTest();"> + <div id="log"></div> + + <iframe></iframe> + + <script> + var history_length; + async_test(function(t) { + + var url = new URL("./location_reload-iframe.html", window.location).href; + + window._pingCount = 0; + window._ping = t.step_func(function(innerURL) { + // Some browsers keep 'about:blank' in the session history + if (_pingCount == 0) { + history_length = history.length; + } + assert_equals(url, innerURL, "iframe url (" + _pingCount + ")"); + assert_equals(history_length, history.length, "history length (" + _pingCount + ")"); + _pingCount++; + if (_pingCount == 5) { + t.done(); + } + }); + }); + + function startTest() { + var url = new URL("./location_reload-iframe.html", window.location).href; + var iframe = document.querySelector("iframe"); + iframe.src = url; + history_length = history.length; + } + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload_javascript_url.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload_javascript_url.html new file mode 100644 index 0000000000..737cafbcd3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_reload_javascript_url.html @@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_reload_javascript_url</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + + <iframe></iframe> + + <script> + async_test(function(t) { + const URL = "/common/blank.html"; + const URL2 = "/common/blank.html#foo"; + const JS_URL_TEXT = "javascript generated page"; + const JS_URL = "javascript:'<html>" + JS_URL_TEXT + "</html>'"; + + var iframe = document.querySelector("iframe"); + var count = 0; + iframe.onload = t.step_func(function() { + // The URL should initially be "blank.html", and then "blank.html#foo"; + // The textContent of the iframe's document should initially be blank, + // then become js generated text, and then be blank again after reload. + switch (count) { + case 0: + assert_equals(iframe.contentWindow.document.URL, + location.href.replace(location.pathname, URL), + "iframe url (" + count + ")"); + assert_equals(iframe.contentDocument.body.textContent, "", + "text of blank page"); + iframe.contentWindow.location = JS_URL; + iframe.contentWindow.location = URL2; + break; + case 1: + assert_equals(iframe.contentWindow.document.URL, + location.href.replace(location.pathname, URL2), + "iframe url (" + count + ")"); + assert_equals(iframe.contentDocument.body.textContent, + JS_URL_TEXT, "text of js generated page"); + iframe.contentWindow.location.reload(); + break; + case 2: + assert_equals(iframe.contentWindow.document.URL, + location.href.replace(location.pathname, URL2), + "iframe url (" + count + ")"); + assert_equals(iframe.contentDocument.body.textContent, "", + "text of blank page"); + t.done(); + break; + } + count++; + }); + iframe.src = URL; + }); + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_replace.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_replace.html new file mode 100644 index 0000000000..0593420d40 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_replace.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_replace</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + var href = location.href; + location.replace('#x'); + + assert_equals((href + "#x"), location.href, "location href"); + + }, "location replace"); + + test(function () { + var href = location.href; + assert_throws_dom('SYNTAX_ERR', function() { location.replace("//"); }); + assert_equals(location.href, href); + }, "URL that fails to parse"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/location_search.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_search.html new file mode 100644 index 0000000000..f9db757841 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/location_search.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>location_search</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="log"></div> + <script> + test(function () { + window.history.pushState(1, document.title, '?x=1'); + var search = location.search; + + assert_equals(search, "?x=1", "search"); + + }, "location search"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/no-browsing-context.window.js b/testing/web-platform/tests/html/browsers/history/the-location-interface/no-browsing-context.window.js new file mode 100644 index 0000000000..4077d90971 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/no-browsing-context.window.js @@ -0,0 +1,86 @@ +test(() => { + const frame = document.body.appendChild(document.createElement("iframe")), + win = frame.contentWindow, + loc = win.location; + frame.remove(); + assert_equals(win.location, loc); +}, "Window and Location are 1:1 after browsing context removal"); + +function bcLessLocation() { + const frame = document.body.appendChild(document.createElement("iframe")), + win = frame.contentWindow, + loc = win.location; + frame.remove(); + return loc; +} + +[ + { + "property": "href", + "expected": "about:blank", + "values": ["https://example.com/", "/", "http://test:test/", "test test", "test:test", "chrome:fail"] + }, + { + "property": "protocol", + "expected": "about:", + "values": ["http", "about", "test"] + }, + { + "property": "host", + "expected": "", + "values": ["example.com", "test test", "()"] + }, + { + "property": "hostname", + "expected": "", + "values": ["example.com"] + }, + { + "property": "port", + "expected": "", + "values": ["80", "", "443", "notaport"] + }, + { + "property": "pathname", + "expected": "blank", + "values": ["/", "x"] + }, + { + "property": "search", + "expected": "", + "values": ["test"] + }, + { + "property": "hash", + "expected": "", + "values": ["test", "#"] + } +].forEach(testSetup => { + testSetup.values.forEach(value => { + test(() => { + const loc = bcLessLocation(); + loc[testSetup.property] = value; + assert_equals(loc[testSetup.property], testSetup.expected); + }, "Setting `" + testSetup.property + "` to `" + value + "` of a `Location` object sans browsing context is a no-op"); + }); +}); + +test(() => { + const loc = bcLessLocation(); + assert_equals(loc.origin, "null"); +}, "Getting `origin` of a `Location` object sans browsing context should be \"null\""); + +["assign", "replace", "reload"].forEach(method => { + ["about:blank", "https://example.com/", "/", "http://test:test/", "test test", "test:test", "chrome:fail"].forEach(value => { + test(() => { + const loc = bcLessLocation(); + loc[method](value); + assert_equals(loc.href, "about:blank"); + }, "Invoking `" + method + "` with `" + value + "` on a `Location` object sans browsing context is a no-op"); + }); +}); + +test(() => { + const loc = bcLessLocation(); + assert_array_equals(loc.ancestorOrigins, []); +}, "Getting `ancestorOrigins` of a `Location` object sans browsing context should be []"); diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-1.html new file mode 100644 index 0000000000..c762ece3bc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-1.html @@ -0,0 +1,7 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<a onclick="location = 'manual_click_assign_during_load-2.html'; return false;" href>Click Here</a> +<p>Filler image to keep the page loading:</p> +<img src="/images/smiley.png?pipe=trickle(20:d1:r2)"> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-manual.html new file mode 100644 index 0000000000..45a0e3e2fd --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_assign_during_load-manual.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Assignment to location with click during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("manual_click_assign_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length + 1); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-1.html new file mode 100644 index 0000000000..e9d03e9364 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-1.html @@ -0,0 +1,10 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<a onclick="location.replace('manual_click_location_replace_during_load-2.html'); return false;" href>Click Here</a> +<p>Filler image to keep the page loading:</p> +<img> +<script> +document.images[0].src = "/images/smiley.png?pipe=trickle(20:d1:r2)&random=" + Math.random(); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-manual.html new file mode 100644 index 0000000000..a453de34bf --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_location_replace_during_load-manual.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>location.replace with click during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("manual_click_location_replace_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_replace_during_load-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_replace_during_load-manual.html new file mode 100644 index 0000000000..482858bcd7 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_click_replace_during_load-manual.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Assignment to location with click during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("manual_click_replace_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-1.html new file mode 100644 index 0000000000..08f7e2dd68 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-1.html @@ -0,0 +1,9 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<form onsubmit="location = 'manual_form_submit_assign_during_load-2.html'; return false;"> +<input type=submit value="Click Me"> +</form> +<p>Filler image to keep the page loading:</p> +<img src="/images/smiley.png?pipe=trickle(20:d1:r2)"> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-manual.html new file mode 100644 index 0000000000..d71b206ac5 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/manual_form_submit_assign_during_load-manual.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Assignment to location with form submit during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("manual_form_submit_assign_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length + 1); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-1.html new file mode 100644 index 0000000000..05b44f4c40 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-1.html @@ -0,0 +1,15 @@ +<!doctype html> +<p>Resize this window. FAIL if the window doesn't close shortly afterwards.</p> +<script> +onload = opener.t.step_func(function() { + opener.load_count++; + if (opener.load_count > 1) { + opener.do_test(); + } +}) + +onresize = opener.t.step_func(function() { + opener.flag_resized(); + location.reload(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-manual.html new file mode 100644 index 0000000000..5cb3fac964 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/non-automated/reload_in_resize-manual.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>Reload called from resize event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>Resize the popup window. That window should then close and the result be presented here. If that window doesn't close after resize that's a FAIL.</p> +<div id="log"></div> +<script> +setup({timeout:3600000}) +var t = async_test(); +var load_count = 0; +var resized = false; +var win = window.open("reload_in_resize-1.html") + +flag_resized = t.step_func(function() { + resized = true; + setTimeout(do_test, 1000); +}); + +do_test = t.step_func(function() { + win.close(); + assert_true(resized, "Resize event happened"); + assert_equals(load_count, 1, "Number of load events"); + t.done(); +}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/per-global.window.js b/testing/web-platform/tests/html/browsers/history/the-location-interface/per-global.window.js new file mode 100644 index 0000000000..b2956fd21f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/per-global.window.js @@ -0,0 +1,3 @@ +// META: script=/common/object-association.js + +testIsPerWindow("location"); diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write-1.html new file mode 100644 index 0000000000..e1a2e811c9 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write-1.html @@ -0,0 +1,19 @@ +<!doctype html> +1 +<script> +function f() { + opener.postMessage("original", "*"); + if (opener.data.length >= 2) { + // If we proceed here, then our document.write will be racing with the + // setTimeout in our opener. Just stop. + return; + } + setTimeout(function () { + document.open(); + document.write("<!doctype html>2<script>opener.postMessage('written', '*');<\/script>"); + document.close(); + }); +} + +window.onload = f +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write.html new file mode 100644 index 0000000000..905ef88743 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_open_write.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>Reload document with document.open and document.written content</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var win = window.open("reload_document_open_write-1.html"); +var t = async_test(); + +var data = []; + +window.onmessage = t.step_func(function(e) { + data.push(e.data); + if (data.length == 2) { + win.location.reload(); + } else if (data.length >= 3) { + setTimeout(t.step_func(function() { + assert_array_equals(data, ["original", "written", "original"]); + t.done(); + }), 500); + } +}); + +add_completion_callback(function() {win.close()}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write-1.html new file mode 100644 index 0000000000..9a08433920 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write-1.html @@ -0,0 +1,4 @@ +<script> +document.write(Math.random()); +opener.postMessage(document.body.innerHTML, "*"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write.html new file mode 100644 index 0000000000..fb5fddc7da --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write.html @@ -0,0 +1,21 @@ +<!doctype html> +<title>Reload document with document.written content</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var win = window.open("reload_document_write-1.html"); +var t = async_test(); + +window.onmessage = t.step_func(function(e) { + var initial_value = e.data; + win.location.reload(); + window.onmessage = t.step_func(function(e) { + assert_not_equals(e.data, initial_value); + t.done(); + }); +}); + +add_completion_callback(function() {win.close()}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload-1.html new file mode 100644 index 0000000000..36445af3c8 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload-1.html @@ -0,0 +1,9 @@ +<script> +function f() { + opener.postMessage("original", "*"); + document.write("<!doctype html>2<script>opener.postMessage('written', '*');<\/script>"); + document.close(); +} + +window.onload = f +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload.html new file mode 100644 index 0000000000..b2cf31147a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_document_write_onload.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>Reload document with document.written content written in load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var win = window.open("reload_document_write_onload-1.html"); +var t = async_test(); + +var data = []; + +window.onmessage = t.step_func(function(e) { + data.push(e.data); + if (data.length < 3) { + win.location.reload(); + } else { + setTimeout(t.step_func(function() { + assert_array_equals(data, ["original", "written", "written"]); + t.done(); + }), 500); + } +}); + +add_completion_callback(function() {win.close()}); +</script> + diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_post_1-manual.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_post_1-manual.html new file mode 100644 index 0000000000..95ef660559 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/reload_post_1-manual.html @@ -0,0 +1,27 @@ +<!doctype html> +<title>Reload document with POST</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var win = window.open("resources/reload_post_1-1.py"); +var t = async_test(); +var posted = false; +var reloaded = false; + +next = t.step_func(function() { + +if (posted && !reloaded) { + reloaded = true; + win.location.reload(); +} else if (posted && reloaded) { + t.done(); +} else { + posted = true; + win.document.forms[0].submit(); +} + +}); + +add_completion_callback(function() {win.close()}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-origin.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-origin.html new file mode 100644 index 0000000000..a8a614c182 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-origin.html @@ -0,0 +1,3 @@ +<script> +parent.postMessage({origin: location.origin}, "*"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-protocol.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-protocol.html new file mode 100644 index 0000000000..c50d623893 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/post-your-protocol.html @@ -0,0 +1,4 @@ +<script> + var id = location.search.substring(1); + parent.postMessage({ id: id, protocol: location.protocol }, "*"); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/reload_post_1-1.py b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/reload_post_1-1.py new file mode 100644 index 0000000000..56397f07b4 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/resources/reload_post_1-1.py @@ -0,0 +1,13 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/html")] + return headers, u''' + <script> + onload = function() {opener.next()} + document.write(Math.random()); + </script> + <form method="POST" action=""> + <input type=hidden name=test value=test> + <input type=submit> + </form> + <button onclick="location.reload()">Reload</button> + ''' diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/same-hash.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/same-hash.html new file mode 100644 index 0000000000..430a57662a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/same-hash.html @@ -0,0 +1,101 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Using the location interface to navigate to the same hash as the current one</title> +<link rel="help" href="https://github.com/whatwg/html/issues/7386"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe id="i" srcdoc="<div style='height: 200vh'></div><div id='te<st'></div>"></iframe> + +<script type="module"> +setup({ explicit_done: true }); +await new Promise(r => window.onload = r); + +for (const value of ["#te<st", "te<st", "#te%3Cst", "te%3Cst"]) { + promise_test(async t => { + t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); + assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); + + i.contentWindow.location.hash = "te<st"; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); + + i.contentWindow.scroll({ top: 0, behavior: "instant" }); + assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); + + i.contentWindow.location.hash = value; + await delayForFragmentNavigationScrolling(t); + + assert_equals(i.contentWindow.scrollY, 0, "Reassigning the same hash must not change the scroll position"); + }, `Using location.hash = "${value}" must not reset scroll position`); +} + +// These don't canonicalize to the current value of location.hash; the post-parsing version of +// "te<st" is "te%3Cst", uppercase. +for (const value of ["#te%3cst", "te%3cst"]) { + promise_test(async t => { + t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); + assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); + + i.contentWindow.location.hash = "te<st"; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); + + i.contentWindow.scroll({ top: 0, behavior: "instant" }); + assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); + + i.contentWindow.location.hash = value; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Reassigning the same-ish hash scrolls the iframe"); + }, `Using location.hash = "${value}" must reset scroll position`); +} + +for (const value of ["about:srcdoc#te<st", "about:srcdoc#te%3cst", "about:srcdoc#te%3Cst"]) { + promise_test(async t => { + t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); + assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); + + i.contentWindow.location.hash = "te<st"; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); + + i.contentWindow.scroll({ top: 0, behavior: "instant" }); + assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); + + i.contentWindow.location.href = value; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe"); + }, `Using location.href = "${value}" must reset scroll position`); + + promise_test(async t => { + t.add_cleanup(() => { i.contentWindow.location.hash = ""; }); + assert_equals(i.contentWindow.scrollY, 0, "Setup: iframe starts at top"); + + i.contentWindow.location.hash = "te<st"; + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "First hash assignment scrolls the iframe"); + + i.contentWindow.scroll({ top: 0, behavior: "instant" }); + assert_equals(i.contentWindow.scrollY, 0, "Resetting the scroll position must work"); + + i.contentWindow.location.assign(value); + await delayForFragmentNavigationScrolling(t); + + assert_greater_than(i.contentWindow.scrollY, i.contentWindow.innerHeight, "Setting href must scroll the iframe"); + }, `Using location.assign("${value}") must reset scroll position`); +} + +function delayForFragmentNavigationScrolling(t) { + // Scroll behavior for fragment navigation is set to "auto" in the spec, so we can't guarantee it's instant. + // In practice 10 milliseconds seems to be enough. + return new Promise(r => t.step_timeout(r, 10)); +} + +done(); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/same_origin_frame.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/same_origin_frame.html new file mode 100644 index 0000000000..953e696b2a --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/same_origin_frame.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>Same-origin subframe for Location cyclic [[Prototype]] test</title> + <link rel="author" title="Jeff Walden" href="http://whereswalden.com/" /> +</head> +<body> +<!-- nothing to do, this window should be accessible to the parent frame --> +<p>Same-origin iframe</p> +</body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-1.html new file mode 100644 index 0000000000..9561cabdd1 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-1.html @@ -0,0 +1,10 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<a onclick="location = 'scripted_click_assign_during_load-2.html'; return false;" href>Click Here</a> +<script> +document.links[0].click() +</script> +<p>Filler image to keep the page loading:</p> +<img src="/images/smiley.png?pipe=trickle(20:d1:r2)"> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load.html new file mode 100644 index 0000000000..7ccc6cdc09 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_assign_during_load.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Assignment to location with click during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("scripted_click_assign_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-1.html new file mode 100644 index 0000000000..05bb42f967 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-1.html @@ -0,0 +1,13 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<a onclick="location.assign('scripted_click_location_assign_during_load-2.html'); return false;" href>Click Here</a> +<script> +document.links[0].click() +</script> +<p>Filler image to keep the page loading:</p> +<img> +<script> +document.images[0].src = "/images/smiley.png?pipe=trickle(20:d1:r2)&random=" + Math.random() +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load.html new file mode 100644 index 0000000000..64f3ff942f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_click_location_assign_during_load.html @@ -0,0 +1,16 @@ +<!doctype html> +<title>location.assign with click during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +var t = async_test(); +var win = window.open("scripted_click_location_assign_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length + 1); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-1.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-1.html new file mode 100644 index 0000000000..ae07ac5cfc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-1.html @@ -0,0 +1,12 @@ +<!doctype html> +<script> +opener.history_length = history.length; +</script> +<form onsubmit="location = 'scripted_form_submit_assign_during_load-2.html'; return false;"> +<input type=submit value="Click Me"> +</form> +<script> +document.forms[0].elements[0].click() +</script> +<p>Filler image to keep the page loading:</p> +<img src="/images/smiley.png?pipe=trickle(20:d1:r2)"> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-2.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-2.html new file mode 100644 index 0000000000..1bf7f41e00 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load-2.html @@ -0,0 +1,7 @@ +<!doctype html> +<p>This window should close itself and the test result appear in the original window +<script> +onload = function() { + setTimeout(function() {opener.do_test(history.length); window.close();}, 100); +} +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load.html b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load.html new file mode 100644 index 0000000000..2a6eba63ab --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/scripted_form_submit_assign_during_load.html @@ -0,0 +1,17 @@ +<!doctype html> +<title>Assignment to location with form submit during load</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<p>The popup blocker must be disabled for this test</p> +<div id="log"></div> +<script> +setup({timeout:3600000}); +var t = async_test(); +var win = window.open("scripted_form_submit_assign_during_load-1.html"); + +var history_length; +do_test = t.step_func(function(new_length) { + assert_equals(new_length, history_length); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/browsers/history/the-location-interface/security_location_0.htm b/testing/web-platform/tests/html/browsers/history/the-location-interface/security_location_0.htm new file mode 100644 index 0000000000..f509c23b18 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-location-interface/security_location_0.htm @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> + <head> + <title>Location interface Security</title> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#security-location" /> + <meta name="assert" content="access location object from different origins doesn't raise SECURITY_ERR exception" /> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <p>Access location object from different origins doesn't raise SECURITY_ERR exception</p> + <div id=log></div> + <script src="/common/get-host-info.sub.js"></script> + <script> + var runTest = async_test("Accessing location object from different origins doesn't raise SECURITY_ERR exception").step_func_done(function() { + var frame = document.getElementById('testframe'); + frame.setAttribute('onload', ''); + frame.contentWindow.location = get_host_info().HTTP_REMOTE_ORIGIN + "/"; + }); + </script> + <iframe id='testframe' onload="runTest()">Test Frame</iframe> + <script> + document.getElementById('testframe').setAttribute('src', get_host_info().HTTP_REMOTE_ORIGIN + '/'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.html b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.html new file mode 100644 index 0000000000..367d7eea3e --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.html @@ -0,0 +1,37 @@ + +<!doctype html> +<meta charset=utf-8> +<title>Navigation in onload handler</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> + var testFiles = [ + "navigation-in-onload_form-submission-1.html", + "navigation-in-onload_form-submission-iframe.html", + "navigation-in-onload_form-submission-dynamic-iframe.html" + ] + + var t = async_test(); + + function scheduleNextTest() { + setTimeout(runNextTest, 0); + } + + function runNextTest() { + var file = testFiles.shift(); + if (!file) { + t.done(); + return; + } + + window.open(file); + } + + function verify(actual, expected, desc) { + setTimeout(t.step_func(function() { + assert_equals(actual, expected, desc); + }), 0); + } + +</script> +<body onload="scheduleNextTest();"></body> diff --git a/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-1.html b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-1.html new file mode 100644 index 0000000000..2079224467 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-1.html @@ -0,0 +1,15 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Navigation in onload handler through form submission</title> + <script> + function redirect() { + document.querySelector("#redirectionForm").submit(); + } + </script> + </head> + <body onload="redirect();"> + <form id="redirectionForm" action="navigation-in-onload_form-submission-2.html" method="get"></form> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.html b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.html new file mode 100644 index 0000000000..11fbe2a2ba --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.html @@ -0,0 +1,22 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Navigation in onload handler through form submission</title> + <script> + + // Verify is called after onload event to ensure history has been stable. + function verify() { + // Navigation in onload handler through form submission should not + // increse history length. + var runner = window.top.opener; + runner.verify(history.length, 1, + "history.length of subtest '" + top.document.title + "'."); + runner.scheduleNextTest(); + setTimeout(window.close.bind(top), 0); + } + </script> + </head> + <body onload="setTimeout(verify, 0);"> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-dynamic-iframe.html b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-dynamic-iframe.html new file mode 100644 index 0000000000..aabae3d770 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-dynamic-iframe.html @@ -0,0 +1,16 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Navigation in onload handler through form submission in a dynamically created iframe</title> + <script> + function test() { + let testFrame = document.createElement("iframe"); + testFrame.src = "navigation-in-onload_form-submission-1.html"; + document.body.appendChild(testFrame); + } + </script> + </head> + <body onload="test();"> + </body> +</html> diff --git a/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-iframe.html b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-iframe.html new file mode 100644 index 0000000000..5fa786d1f5 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-iframe.html @@ -0,0 +1,10 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Navigation in onload handler through form submission in an iframe</title> + </head> + <body> + <iframe id="testFrame" src="navigation-in-onload_form-submission-1.html"></iframe> + </body> +</html> |