summaryrefslogtreecommitdiffstats
path: root/docshell/test/mochitest
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /docshell/test/mochitest
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docshell/test/mochitest')
-rw-r--r--docshell/test/mochitest/bug1422334_redirect.html3
-rw-r--r--docshell/test/mochitest/bug1422334_redirect.html^headers^2
-rw-r--r--docshell/test/mochitest/bug404548-subframe.html7
-rw-r--r--docshell/test/mochitest/bug404548-subframe_window.html1
-rw-r--r--docshell/test/mochitest/bug413310-post.sjs10
-rw-r--r--docshell/test/mochitest/bug413310-subframe.html7
-rw-r--r--docshell/test/mochitest/bug529119-window.html7
-rw-r--r--docshell/test/mochitest/bug530396-noref.sjs22
-rw-r--r--docshell/test/mochitest/bug530396-subframe.html7
-rw-r--r--docshell/test/mochitest/bug570341_recordevents.html21
-rw-r--r--docshell/test/mochitest/bug668513_redirect.html1
-rw-r--r--docshell/test/mochitest/bug668513_redirect.html^headers^2
-rw-r--r--docshell/test/mochitest/bug691547_frame.html12
-rw-r--r--docshell/test/mochitest/clicker.html7
-rw-r--r--docshell/test/mochitest/double_submit.sjs79
-rw-r--r--docshell/test/mochitest/dummy_page.html6
-rw-r--r--docshell/test/mochitest/file_anchor_scroll_after_document_open.html15
-rw-r--r--docshell/test/mochitest/file_bfcache_plus_hash_1.html24
-rw-r--r--docshell/test/mochitest/file_bfcache_plus_hash_2.html17
-rw-r--r--docshell/test/mochitest/file_bug1121701_1.html29
-rw-r--r--docshell/test/mochitest/file_bug1121701_2.html23
-rw-r--r--docshell/test/mochitest/file_bug1151421.html19
-rw-r--r--docshell/test/mochitest/file_bug1186774.html1
-rw-r--r--docshell/test/mochitest/file_bug1450164.html16
-rw-r--r--docshell/test/mochitest/file_bug1729662.html8
-rw-r--r--docshell/test/mochitest/file_bug1740516_1.html29
-rw-r--r--docshell/test/mochitest/file_bug1740516_1_inner.html15
-rw-r--r--docshell/test/mochitest/file_bug1740516_2.html11
-rw-r--r--docshell/test/mochitest/file_bug1741132.html29
-rw-r--r--docshell/test/mochitest/file_bug1742865.sjs77
-rw-r--r--docshell/test/mochitest/file_bug1742865_outer.sjs25
-rw-r--r--docshell/test/mochitest/file_bug1743353.html37
-rw-r--r--docshell/test/mochitest/file_bug1747033.sjs110
-rw-r--r--docshell/test/mochitest/file_bug1773192_1.html13
-rw-r--r--docshell/test/mochitest/file_bug1773192_2.html13
-rw-r--r--docshell/test/mochitest/file_bug1773192_3.sjs3
-rw-r--r--docshell/test/mochitest/file_bug385434_1.html29
-rw-r--r--docshell/test/mochitest/file_bug385434_2.html26
-rw-r--r--docshell/test/mochitest/file_bug385434_3.html22
-rw-r--r--docshell/test/mochitest/file_bug475636.sjs97
-rw-r--r--docshell/test/mochitest/file_bug509055.html9
-rw-r--r--docshell/test/mochitest/file_bug511449.html6
-rw-r--r--docshell/test/mochitest/file_bug540462.html25
-rw-r--r--docshell/test/mochitest/file_bug580069_1.html8
-rw-r--r--docshell/test/mochitest/file_bug580069_2.sjs8
-rw-r--r--docshell/test/mochitest/file_bug590573_1.html7
-rw-r--r--docshell/test/mochitest/file_bug590573_2.html8
-rw-r--r--docshell/test/mochitest/file_bug598895_1.html1
-rw-r--r--docshell/test/mochitest/file_bug598895_2.html1
-rw-r--r--docshell/test/mochitest/file_bug634834.html5
-rw-r--r--docshell/test/mochitest/file_bug637644_1.html1
-rw-r--r--docshell/test/mochitest/file_bug637644_2.html1
-rw-r--r--docshell/test/mochitest/file_bug640387.html26
-rw-r--r--docshell/test/mochitest/file_bug653741.html13
-rw-r--r--docshell/test/mochitest/file_bug66040413
-rw-r--r--docshell/test/mochitest/file_bug660404-1.html12
-rw-r--r--docshell/test/mochitest/file_bug660404^headers^1
-rw-r--r--docshell/test/mochitest/file_bug662170.html13
-rw-r--r--docshell/test/mochitest/file_bug668513.html101
-rw-r--r--docshell/test/mochitest/file_bug669671.sjs17
-rw-r--r--docshell/test/mochitest/file_bug675587.html1
-rw-r--r--docshell/test/mochitest/file_bug680257.html16
-rw-r--r--docshell/test/mochitest/file_bug703855.html2
-rw-r--r--docshell/test/mochitest/file_bug728939.html3
-rw-r--r--docshell/test/mochitest/file_close_onpagehide1.html5
-rw-r--r--docshell/test/mochitest/file_close_onpagehide2.html5
-rw-r--r--docshell/test/mochitest/file_compressed_multipartbin0 -> 111 bytes
-rw-r--r--docshell/test/mochitest/file_compressed_multipart^headers^2
-rw-r--r--docshell/test/mochitest/file_content_javascript_loads_frame.html17
-rw-r--r--docshell/test/mochitest/file_content_javascript_loads_root.html42
-rw-r--r--docshell/test/mochitest/file_form_restoration_no_store.html38
-rw-r--r--docshell/test/mochitest/file_form_restoration_no_store.html^headers^1
-rw-r--r--docshell/test/mochitest/file_framedhistoryframes.html16
-rw-r--r--docshell/test/mochitest/file_load_during_reload.html12
-rw-r--r--docshell/test/mochitest/file_pushState_after_document_open.html11
-rw-r--r--docshell/test/mochitest/file_redirect_history.html18
-rw-r--r--docshell/test/mochitest/form_submit.sjs40
-rw-r--r--docshell/test/mochitest/form_submit_redirect.sjs15
-rw-r--r--docshell/test/mochitest/historyframes.html176
-rw-r--r--docshell/test/mochitest/mochitest.ini209
-rw-r--r--docshell/test/mochitest/ping.html6
-rw-r--r--docshell/test/mochitest/start_historyframe.html1
-rw-r--r--docshell/test/mochitest/test_anchor_scroll_after_document_open.html55
-rw-r--r--docshell/test/mochitest/test_bfcache_plus_hash.html153
-rw-r--r--docshell/test/mochitest/test_bug1045096.html29
-rw-r--r--docshell/test/mochitest/test_bug1121701.html108
-rw-r--r--docshell/test/mochitest/test_bug1151421.html61
-rw-r--r--docshell/test/mochitest/test_bug1186774.html51
-rw-r--r--docshell/test/mochitest/test_bug1422334.html40
-rw-r--r--docshell/test/mochitest/test_bug1450164.html31
-rw-r--r--docshell/test/mochitest/test_bug1507702.html57
-rw-r--r--docshell/test/mochitest/test_bug1645781.html90
-rw-r--r--docshell/test/mochitest/test_bug1729662.html76
-rw-r--r--docshell/test/mochitest/test_bug1740516.html79
-rw-r--r--docshell/test/mochitest/test_bug1741132.html79
-rw-r--r--docshell/test/mochitest/test_bug1742865.html137
-rw-r--r--docshell/test/mochitest/test_bug1743353.html57
-rw-r--r--docshell/test/mochitest/test_bug1747033.html97
-rw-r--r--docshell/test/mochitest/test_bug1773192.html61
-rw-r--r--docshell/test/mochitest/test_bug385434.html211
-rw-r--r--docshell/test/mochitest/test_bug387979.html52
-rw-r--r--docshell/test/mochitest/test_bug402210.html50
-rw-r--r--docshell/test/mochitest/test_bug404548.html39
-rw-r--r--docshell/test/mochitest/test_bug413310.html106
-rw-r--r--docshell/test/mochitest/test_bug475636.html52
-rw-r--r--docshell/test/mochitest/test_bug509055.html115
-rw-r--r--docshell/test/mochitest/test_bug511449.html56
-rw-r--r--docshell/test/mochitest/test_bug529119-1.html110
-rw-r--r--docshell/test/mochitest/test_bug529119-2.html116
-rw-r--r--docshell/test/mochitest/test_bug530396.html56
-rw-r--r--docshell/test/mochitest/test_bug540462.html44
-rw-r--r--docshell/test/mochitest/test_bug551225.html32
-rw-r--r--docshell/test/mochitest/test_bug570341.html142
-rw-r--r--docshell/test/mochitest/test_bug580069.html58
-rw-r--r--docshell/test/mochitest/test_bug590573.html198
-rw-r--r--docshell/test/mochitest/test_bug598895.html52
-rw-r--r--docshell/test/mochitest/test_bug634834.html52
-rw-r--r--docshell/test/mochitest/test_bug637644.html52
-rw-r--r--docshell/test/mochitest/test_bug640387_1.html107
-rw-r--r--docshell/test/mochitest/test_bug640387_2.html89
-rw-r--r--docshell/test/mochitest/test_bug653741.html49
-rw-r--r--docshell/test/mochitest/test_bug660404.html76
-rw-r--r--docshell/test/mochitest/test_bug662170.html51
-rw-r--r--docshell/test/mochitest/test_bug668513.html28
-rw-r--r--docshell/test/mochitest/test_bug669671.html145
-rw-r--r--docshell/test/mochitest/test_bug675587.html33
-rw-r--r--docshell/test/mochitest/test_bug680257.html76
-rw-r--r--docshell/test/mochitest/test_bug691547.html59
-rw-r--r--docshell/test/mochitest/test_bug694612.html34
-rw-r--r--docshell/test/mochitest/test_bug703855.html79
-rw-r--r--docshell/test/mochitest/test_bug728939.html37
-rw-r--r--docshell/test/mochitest/test_bug797909.html66
-rw-r--r--docshell/test/mochitest/test_close_onpagehide_by_history_back.html24
-rw-r--r--docshell/test/mochitest/test_close_onpagehide_by_window_close.html20
-rw-r--r--docshell/test/mochitest/test_compressed_multipart.html41
-rw-r--r--docshell/test/mochitest/test_content_javascript_loads.html163
-rw-r--r--docshell/test/mochitest/test_double_submit.html98
-rw-r--r--docshell/test/mochitest/test_forceinheritprincipal_overrule_owner.html57
-rw-r--r--docshell/test/mochitest/test_form_restoration.html77
-rw-r--r--docshell/test/mochitest/test_framedhistoryframes.html32
-rw-r--r--docshell/test/mochitest/test_iframe_srcdoc_to_remote.html44
-rw-r--r--docshell/test/mochitest/test_javascript_sandboxed_popup.html27
-rw-r--r--docshell/test/mochitest/test_load_during_reload.html49
-rw-r--r--docshell/test/mochitest/test_navigate_after_pagehide.html34
-rw-r--r--docshell/test/mochitest/test_pushState_after_document_open.html39
-rw-r--r--docshell/test/mochitest/test_redirect_history.html58
-rw-r--r--docshell/test/mochitest/test_triggeringprincipal_location_seturi.html105
-rw-r--r--docshell/test/mochitest/test_windowedhistoryframes.html32
-rw-r--r--docshell/test/mochitest/url1_historyframe.html1
-rw-r--r--docshell/test/mochitest/url2_historyframe.html1
150 files changed, 6479 insertions, 0 deletions
diff --git a/docshell/test/mochitest/bug1422334_redirect.html b/docshell/test/mochitest/bug1422334_redirect.html
new file mode 100644
index 0000000000..eec7fda2c7
--- /dev/null
+++ b/docshell/test/mochitest/bug1422334_redirect.html
@@ -0,0 +1,3 @@
+<html>
+ <body>You should never see this</body>
+</html>
diff --git a/docshell/test/mochitest/bug1422334_redirect.html^headers^ b/docshell/test/mochitest/bug1422334_redirect.html^headers^
new file mode 100644
index 0000000000..fbf2d1b745
--- /dev/null
+++ b/docshell/test/mochitest/bug1422334_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Moved Temporarily
+Location: ../navigation/blank.html?x=y
diff --git a/docshell/test/mochitest/bug404548-subframe.html b/docshell/test/mochitest/bug404548-subframe.html
new file mode 100644
index 0000000000..9a248b40b3
--- /dev/null
+++ b/docshell/test/mochitest/bug404548-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body onload="setTimeout(function() { window.location = 'bug404548-subframe_window.html'; }, 10)">
+<iframe srcdoc="<body onpagehide='var p = window.parent.opener; var e = window.frameElement; e.parentNode.removeChild(e); if (e.parentNode == null && e.contentWindow == null) { p.firstRemoved = true; }'>">
+</iframe>
+<iframe srcdoc="<body onpagehide='window.parent.opener.secondHidden = true;'>">
+</iframe>
diff --git a/docshell/test/mochitest/bug404548-subframe_window.html b/docshell/test/mochitest/bug404548-subframe_window.html
new file mode 100644
index 0000000000..82ea73ea83
--- /dev/null
+++ b/docshell/test/mochitest/bug404548-subframe_window.html
@@ -0,0 +1 @@
+<body onload='window.opener.finishTest()'>
diff --git a/docshell/test/mochitest/bug413310-post.sjs b/docshell/test/mochitest/bug413310-post.sjs
new file mode 100644
index 0000000000..f87937ab56
--- /dev/null
+++ b/docshell/test/mochitest/bug413310-post.sjs
@@ -0,0 +1,10 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html");
+ response.write(
+ "<body onload='window.parent.onloadCount++'>" +
+ request.method +
+ " " +
+ Date.now() +
+ "</body>"
+ );
+}
diff --git a/docshell/test/mochitest/bug413310-subframe.html b/docshell/test/mochitest/bug413310-subframe.html
new file mode 100644
index 0000000000..bcff1886fd
--- /dev/null
+++ b/docshell/test/mochitest/bug413310-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body onload="window.parent.onloadCount++">
+ <form action="bug413310-post.sjs" method="POST">
+ </form>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/bug529119-window.html b/docshell/test/mochitest/bug529119-window.html
new file mode 100644
index 0000000000..f1908835a7
--- /dev/null
+++ b/docshell/test/mochitest/bug529119-window.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119, sub-window</title>
+<body onload="window.opener.windowLoaded();">
+</body>
+</html>
diff --git a/docshell/test/mochitest/bug530396-noref.sjs b/docshell/test/mochitest/bug530396-noref.sjs
new file mode 100644
index 0000000000..6a65882160
--- /dev/null
+++ b/docshell/test/mochitest/bug530396-noref.sjs
@@ -0,0 +1,22 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+ response.write("<body onload='");
+
+ if (!request.hasHeader("Referer")) {
+ response.write("window.parent.onloadCount++;");
+ }
+
+ if (request.queryString == "newwindow") {
+ response.write(
+ "if (window.opener) { window.opener.parent.onloadCount++; window.opener.parent.doNextStep(); }"
+ );
+ response.write("if (!window.opener) window.close();");
+ response.write("'>");
+ } else {
+ response.write("window.parent.doNextStep();'>");
+ }
+
+ response.write(request.method + " " + Date.now());
+ response.write("</body>");
+}
diff --git a/docshell/test/mochitest/bug530396-subframe.html b/docshell/test/mochitest/bug530396-subframe.html
new file mode 100644
index 0000000000..be81b9f144
--- /dev/null
+++ b/docshell/test/mochitest/bug530396-subframe.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body onload="window.parent.onloadCount++">
+ <a href="bug530396-noref.sjs" rel="noreferrer foo" id="target1">bug530396-noref.sjs</a>
+ <a href="bug530396-noref.sjs?newwindow" rel="nofollow noreferrer" id="target2" target="newwindow">bug530396-noref.sjs with new window</a>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/bug570341_recordevents.html b/docshell/test/mochitest/bug570341_recordevents.html
new file mode 100644
index 0000000000..45b04866ec
--- /dev/null
+++ b/docshell/test/mochitest/bug570341_recordevents.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<script>
+ var start = Date.now();
+ window._testing_js_start = Date.now();
+ window["_testing_js_after_" + document.readyState] = start;
+ document.addEventListener("DOMContentLoaded",
+ function() {
+ window._testing_evt_DOMContentLoaded = Date.now();
+ }, true);
+ document.addEventListener("readystatechange", function() {
+ window["_testing_evt_DOM_" + document.readyState] = Date.now();
+ }, true);
+ function recordLoad() {
+ window._testing_evt_load = Date.now();
+ }
+</script>
+</head>
+<body onload="recordLoad()">This document collects time
+for events related to the page load progress.</body>
+</html>
diff --git a/docshell/test/mochitest/bug668513_redirect.html b/docshell/test/mochitest/bug668513_redirect.html
new file mode 100644
index 0000000000..1b8f66c631
--- /dev/null
+++ b/docshell/test/mochitest/bug668513_redirect.html
@@ -0,0 +1 @@
+<html><body>This document is redirected to a blank document.</body></html>
diff --git a/docshell/test/mochitest/bug668513_redirect.html^headers^ b/docshell/test/mochitest/bug668513_redirect.html^headers^
new file mode 100644
index 0000000000..0e785833c6
--- /dev/null
+++ b/docshell/test/mochitest/bug668513_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Moved Temporarily
+Location: navigation/blank.html
diff --git a/docshell/test/mochitest/bug691547_frame.html b/docshell/test/mochitest/bug691547_frame.html
new file mode 100644
index 0000000000..00172f7119
--- /dev/null
+++ b/docshell/test/mochitest/bug691547_frame.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691547
+-->
+<head>
+ <title>Test for Bug 691547</title>
+</head>
+<body>
+<iframe style="width:95%"></iframe>
+</body>
+</html>
diff --git a/docshell/test/mochitest/clicker.html b/docshell/test/mochitest/clicker.html
new file mode 100644
index 0000000000..b655e27ea5
--- /dev/null
+++ b/docshell/test/mochitest/clicker.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<script>
+ "use strict";
+ let target = window.opener ? window.opener : window.parent;
+
+ onmessage = ({data}) => target.postMessage({}, "*");
+</script>
diff --git a/docshell/test/mochitest/double_submit.sjs b/docshell/test/mochitest/double_submit.sjs
new file mode 100644
index 0000000000..487150d456
--- /dev/null
+++ b/docshell/test/mochitest/double_submit.sjs
@@ -0,0 +1,79 @@
+"use strict";
+
+let self = this;
+
+let { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+const CC = Components.Constructor;
+const BinaryInputStream = CC(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+function log(str) {
+ // dump(`LOG: ${str}\n`);
+}
+
+function readStream(inputStream) {
+ let available = 0;
+ let result = [];
+ while ((available = inputStream.available()) > 0) {
+ result.push(inputStream.readBytes(available));
+ }
+
+ return result.join("");
+}
+
+function now() {
+ return Date.now();
+}
+
+async function handleRequest(request, response) {
+ log("Get query parameters");
+ Cu.importGlobalProperties(["URLSearchParams"]);
+ let params = new URLSearchParams(request.queryString);
+
+ let start = now();
+ let delay = parseInt(params.get("delay")) || 0;
+ log(`Delay for ${delay}`);
+
+ let message = "good";
+ if (request.method !== "POST") {
+ message = "bad";
+ } else {
+ log("Read POST body");
+ let body = new URLSearchParams(
+ readStream(new BinaryInputStream(request.bodyInputStream))
+ );
+ message = body.get("token") || "bad";
+ log(`The result was ${message}`);
+ }
+
+ let body = `<!doctype html>
+ <script>
+ "use strict";
+ let target = (opener || parent);
+ target.postMessage(${JSON.stringify(message)}, '*');
+ </script>`;
+
+ // Sieze power from the response to allow manually transmitting data at any
+ // rate we want, so we can delay transmitting headers.
+ response.seizePower();
+
+ log(`Writing HTTP status line at ${now() - start}`);
+ response.write("HTTP/1.1 200 OK\r\n");
+
+ await new Promise(resolve => setTimeout(() => resolve(), delay));
+
+ log(`Delay completed at ${now() - start}`);
+ response.write("Content-Type: text/html\r\n");
+ response.write(`Content-Length: ${body.length}\r\n`);
+ response.write("\r\n");
+ response.write(body);
+ response.finish();
+
+ log("Finished");
+}
diff --git a/docshell/test/mochitest/dummy_page.html b/docshell/test/mochitest/dummy_page.html
new file mode 100644
index 0000000000..59bf2a5f8f
--- /dev/null
+++ b/docshell/test/mochitest/dummy_page.html
@@ -0,0 +1,6 @@
+<html>
+<head> <meta charset="utf-8"> </head>
+ <body>
+ just a dummy html file
+ </body>
+</html>
diff --git a/docshell/test/mochitest/file_anchor_scroll_after_document_open.html b/docshell/test/mochitest/file_anchor_scroll_after_document_open.html
new file mode 100644
index 0000000000..7903380eac
--- /dev/null
+++ b/docshell/test/mochitest/file_anchor_scroll_after_document_open.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script>
+ if (location.hash == "#target") {
+ parent.postMessage("haveHash", "*");
+ } else {
+ document.addEventListener("DOMContentLoaded", function() {
+ document.open();
+ document.write("<!DOCTYPE html><html style='height: 100%'><body style='height: 100%'><div style='height: 200%'></div><div id='target'></div></body></html>");
+ document.close();
+ // Notify parent via postMessage, since otherwise exceptions will not get
+ // caught by its onerror handler.
+ parent.postMessage("doTest", "*");
+ });
+ }
+</script>
diff --git a/docshell/test/mochitest/file_bfcache_plus_hash_1.html b/docshell/test/mochitest/file_bfcache_plus_hash_1.html
new file mode 100644
index 0000000000..199f6003e0
--- /dev/null
+++ b/docshell/test/mochitest/file_bfcache_plus_hash_1.html
@@ -0,0 +1,24 @@
+<html><body>
+ Popup 1
+ <script type="application/javascript">
+ var bc = new BroadcastChannel("bug646641_1");
+ window.onload = () => {
+ bc.postMessage({ message: "childLoad", num: 1 })
+ }
+
+ window.onpageshow = () => {
+ bc.postMessage({ message: "childPageshow", num: 1 })
+ }
+ bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ if (msg == "pushState") {
+ history.pushState("", "", "");
+ location = "file_bfcache_plus_hash_2.html";
+ } else if (msg == "close") {
+ bc.postMessage({ message: "closed" });
+ bc.close();
+ window.close();
+ }
+ }
+ </script>
+</body></html>
diff --git a/docshell/test/mochitest/file_bfcache_plus_hash_2.html b/docshell/test/mochitest/file_bfcache_plus_hash_2.html
new file mode 100644
index 0000000000..c27d4eaa3b
--- /dev/null
+++ b/docshell/test/mochitest/file_bfcache_plus_hash_2.html
@@ -0,0 +1,17 @@
+<html><body>
+ Popup 2
+ <script type="application/javascript">
+ var bc = new BroadcastChannel("bug646641_2");
+ window.onload = () => {
+ bc.postMessage({ message: "childLoad", num: 2 })
+ requestAnimationFrame(() => bc.postMessage({message: "childPageshow", num: 2}));
+ }
+ bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ if (msg == "go-2") {
+ history.go(-2);
+ bc.close();
+ }
+ }
+ </script>
+</body></html>
diff --git a/docshell/test/mochitest/file_bug1121701_1.html b/docshell/test/mochitest/file_bug1121701_1.html
new file mode 100644
index 0000000000..62c58495f7
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1121701_1.html
@@ -0,0 +1,29 @@
+<script>
+ var bc = new BroadcastChannel("file_bug1121701_1");
+ var pageHideAsserts = undefined;
+ bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "setInnerHTML") {
+ document.body.innerHTML = "modified";
+ window.onpagehide = function(event) {
+ window.onpagehide = null;
+ pageHideAsserts = {};
+ pageHideAsserts.persisted = event.persisted;
+ // eslint-disable-next-line no-unsanitized/property
+ pageHideAsserts.innerHTML = window.document.body.innerHTML;
+ };
+ window.location.href = msg.testUrl2;
+ } else if (command == "close") {
+ bc.postMessage({command: "closed"});
+ bc.close();
+ window.close();
+ }
+ }
+ window.onpageshow = function(e) {
+ var msg = {command: "child1PageShow", persisted: e.persisted, pageHideAsserts};
+ // eslint-disable-next-line no-unsanitized/property
+ msg.innerHTML = window.document.body.innerHTML;
+ bc.postMessage(msg);
+ };
+</script>
diff --git a/docshell/test/mochitest/file_bug1121701_2.html b/docshell/test/mochitest/file_bug1121701_2.html
new file mode 100644
index 0000000000..6cec88cd5d
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1121701_2.html
@@ -0,0 +1,23 @@
+<script>
+ var bc = new BroadcastChannel("file_bug1121701_2");
+ bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "setInnerHTML") {
+ window.document.body.innerHTML = "<img>";
+ window.onmessage = function() {
+ bc.postMessage({command: "onmessage"});
+ window.document.body.firstChild.src = msg.location;
+ bc.close();
+ };
+ window.onbeforeunload = function() {
+ window.postMessage("foo", "*");
+ };
+
+ history.back();
+ }
+ }
+ window.onpageshow = function(e) {
+ bc.postMessage({command: "child2PageShow", persisted: e.persisted});
+ };
+</script>
diff --git a/docshell/test/mochitest/file_bug1151421.html b/docshell/test/mochitest/file_bug1151421.html
new file mode 100644
index 0000000000..7bb8c8f363
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1151421.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+<style>
+body, html {
+ height: 100%;
+}
+.spacer {
+ height: 80%;
+}
+</style>
+</head>
+<body onload='(parent || opener).childLoad()'>
+
+<div class="spacer"></div>
+<div id="content">content</div>
+<div class="spacer"></div>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1186774.html b/docshell/test/mochitest/file_bug1186774.html
new file mode 100644
index 0000000000..9af95b09bd
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1186774.html
@@ -0,0 +1 @@
+<div style='height: 9000px;'></div>
diff --git a/docshell/test/mochitest/file_bug1450164.html b/docshell/test/mochitest/file_bug1450164.html
new file mode 100644
index 0000000000..55e32ce93d
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1450164.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script>
+ function go() {
+ var a = window.history.state;
+ window.history.replaceState(a, "", "1");
+ var ok = opener.ok;
+ var SimpleTest = opener.SimpleTest;
+ ok("Addition of history in unload did not crash browser");
+ SimpleTest.finish();
+ }
+ </script>
+ </head>
+ <body onunload="go()">
+ </body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1729662.html b/docshell/test/mochitest/file_bug1729662.html
new file mode 100644
index 0000000000..f5710e1c49
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1729662.html
@@ -0,0 +1,8 @@
+<script>
+addEventListener("load", () => {
+ (new BroadcastChannel("bug1729662")).postMessage("load");
+ history.pushState(1, null, location.href);
+ history.back();
+ history.forward();
+});
+</script>
diff --git a/docshell/test/mochitest/file_bug1740516_1.html b/docshell/test/mochitest/file_bug1740516_1.html
new file mode 100644
index 0000000000..ac8ca71d93
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1740516_1.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("pageshow", ({ persisted }) => {
+ let bc = new BroadcastChannel("bug1740516_1");
+ bc.addEventListener("message", ({ data }) => {
+ bc.close();
+ switch (data) {
+ case "block_bfcache_and_navigate":
+ window.blockBFCache = new RTCPeerConnection();
+ // Fall through
+ case "navigate":
+ document.location = "file_bug1740516_2.html";
+ break;
+ case "close":
+ window.close();
+ break;
+ }
+ });
+ bc.postMessage(persisted);
+ });
+ </script>
+</head>
+<body>
+ <iframe src="file_bug1740516_1_inner.html"></iframe>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1740516_1_inner.html b/docshell/test/mochitest/file_bug1740516_1_inner.html
new file mode 100644
index 0000000000..159c6bde5a
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1740516_1_inner.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("pageshow", ({ persisted }) => {
+ let bc = new BroadcastChannel("bug1740516_1_inner");
+ bc.postMessage(persisted);
+ bc.close();
+ });
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1740516_2.html b/docshell/test/mochitest/file_bug1740516_2.html
new file mode 100644
index 0000000000..2dc714feef
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1740516_2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ addEventListener("pageshow", () => { history.back(); });
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1741132.html b/docshell/test/mochitest/file_bug1741132.html
new file mode 100644
index 0000000000..d863b9f015
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1741132.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("pageshow", ({ persisted }) => {
+ let bc = new BroadcastChannel("bug1741132");
+ bc.addEventListener("message", ({ data: { cmd, arg } }) => {
+ bc.close();
+ switch (cmd) {
+ case "load":
+ document.location = arg;
+ break;
+ case "go":
+ window.blockBFCache = new RTCPeerConnection();
+ history.go(arg);
+ break;
+ case "close":
+ window.close();
+ break;
+ }
+ });
+ bc.postMessage(persisted);
+ });
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1742865.sjs b/docshell/test/mochitest/file_bug1742865.sjs
new file mode 100644
index 0000000000..950c30ecd2
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1742865.sjs
@@ -0,0 +1,77 @@
+Cu.importGlobalProperties(["URLSearchParams"]);
+
+function handleRequest(request, response) {
+ if (request.queryString == "reset") {
+ setState("index", "0");
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.write("Reset");
+ return;
+ }
+
+ let refresh = "";
+ let index = Number(getState("index"));
+ // index == 0 First load, returns first meta refresh
+ // index == 1 Second load, caused by first meta refresh, returns second meta refresh
+ // index == 2 Third load, caused by second meta refresh, doesn't return a meta refresh
+ let query = new URLSearchParams(request.queryString);
+ if (index < 2) {
+ refresh = query.get("seconds");
+ if (query.get("crossOrigin") == "true") {
+ const hosts = ["example.org", "example.com"];
+
+ let url = `${request.scheme}://${hosts[index]}${request.path}?${request.queryString}`;
+ refresh += `; url=${url}`;
+ }
+ refresh = `<meta http-equiv="Refresh" content="${refresh}">`;
+ }
+ // We want to scroll for the first load, and check that the meta refreshes keep the same
+ // scroll position.
+ let scroll = index == 0 ? `scrollTo(0, ${query.get("scrollTo")});` : "";
+
+ setState("index", String(index + 1));
+
+ response.write(
+ `<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Cache-Control" content="no-cache">
+ ${refresh}
+ <script>
+ window.addEventListener("pageshow", () => {
+ ${scroll}
+ window.top.opener.postMessage({
+ commandType: "pageShow",
+ commandData: {
+ inputValue: document.getElementById("input").value,
+ scrollPosition: window.scrollY,
+ },
+ }, "*");
+ });
+ window.addEventListener("message", ({ data }) => {
+ if (data == "changeInputValue") {
+ document.getElementById("input").value = "1234";
+ window.top.opener.postMessage({
+ commandType: "onChangedInputValue",
+ commandData: {
+ historyLength: history.length,
+ inputValue: document.getElementById("input").value,
+ },
+ }, "*");
+ } else if (data == "loadNext") {
+ location.href += "&loadnext=1";
+ } else if (data == "back") {
+ history.back();
+ }
+ });
+ </script>
+</head>
+<body>
+<input type="text" id="input" value="initial"></input>
+<div style='height: 9000px;'></div>
+<p>
+</p>
+</body>
+</html>`
+ );
+}
diff --git a/docshell/test/mochitest/file_bug1742865_outer.sjs b/docshell/test/mochitest/file_bug1742865_outer.sjs
new file mode 100644
index 0000000000..bad8b23f00
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1742865_outer.sjs
@@ -0,0 +1,25 @@
+Cu.importGlobalProperties(["URLSearchParams"]);
+
+function handleRequest(request, response) {
+ response.write(
+ `<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("message", ({ data }) => {
+ if (data == "loadNext") {
+ location.href += "&loadnext=1";
+ return;
+ }
+ // Forward other messages to the frame.
+ document.getElementById("frame").contentWindow.postMessage(data, "*");
+ });
+ </script>
+</head>
+<body>
+ <iframe src="file_bug1742865.sjs?${request.queryString}" id="frame"></iframe>
+</body>
+</html>`
+ );
+}
diff --git a/docshell/test/mochitest/file_bug1743353.html b/docshell/test/mochitest/file_bug1743353.html
new file mode 100644
index 0000000000..c08f8d143f
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1743353.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("pageshow", () => {
+ let bc = new BroadcastChannel("bug1743353");
+ bc.addEventListener("message", ({ data: cmd }) => {
+ switch (cmd) {
+ case "load":
+ bc.close();
+ document.location += "?1";
+ break;
+ case "back":
+ window.blockBFCache = new RTCPeerConnection();
+ window.addEventListener("pagehide", () => {
+ bc.postMessage("pagehide");
+ });
+ window.addEventListener("unload", () => {
+ bc.postMessage("unload");
+ bc.close();
+ });
+ history.back();
+ break;
+ case "close":
+ bc.close();
+ window.close();
+ break;
+ }
+ });
+ bc.postMessage("pageshow");
+ });
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1747033.sjs b/docshell/test/mochitest/file_bug1747033.sjs
new file mode 100644
index 0000000000..14401101b2
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1747033.sjs
@@ -0,0 +1,110 @@
+"use strict";
+
+const BOUNDARY = "BOUNDARY";
+
+// waitForPageShow should be false if this is for multipart/x-mixed-replace
+// and it's not the last part, Gecko doesn't fire pageshow for those parts.
+function documentString(waitForPageShow = true) {
+ return `<html>
+ <head>
+ <script>
+ let bc = new BroadcastChannel("bug1747033");
+ bc.addEventListener("message", ({ data: { cmd, arg = undefined } }) => {
+ switch (cmd) {
+ case "load":
+ location.href = arg;
+ break;
+ case "replaceState":
+ history.replaceState({}, "Replaced state", arg);
+ bc.postMessage({ "historyLength": history.length, "location": location.href });
+ break;
+ case "back":
+ history.back();
+ break;
+ case "close":
+ close();
+ break;
+ }
+ });
+
+ function reply() {
+ bc.postMessage({ "historyLength": history.length, "location": location.href });
+ }
+
+ ${waitForPageShow ? `addEventListener("pageshow", reply);` : "reply();"}
+ </script>
+ </head>
+ <body></body>
+</html>
+`;
+}
+
+function boundary(last = false) {
+ let b = `--${BOUNDARY}`;
+ if (last) {
+ b += "--";
+ }
+ return b + "\n";
+}
+
+function sendMultipart(response, last = false) {
+ setState("sendMore", "");
+
+ response.write(`Content-Type: text/html
+
+${documentString(last)}
+`);
+ response.write(boundary(last));
+}
+
+function shouldSendMore() {
+ return new Promise(resolve => {
+ let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ () => {
+ let sendMore = getState("sendMore");
+ if (sendMore !== "") {
+ timer.cancel();
+ resolve(sendMore);
+ }
+ },
+ 100,
+ Ci.nsITimer.TYPE_REPEATING_SLACK
+ );
+ });
+}
+
+async function handleRequest(request, response) {
+ if (request.queryString == "") {
+ // This is for non-multipart/x-mixed-replace loads.
+ response.write(documentString());
+ return;
+ }
+
+ if (request.queryString == "sendNextPart") {
+ setState("sendMore", "next");
+ return;
+ }
+
+ if (request.queryString == "sendLastPart") {
+ setState("sendMore", "last");
+ return;
+ }
+
+ response.processAsync();
+
+ response.setHeader(
+ "Content-Type",
+ `multipart/x-mixed-replace; boundary=${BOUNDARY}`,
+ false
+ );
+ response.setStatusLine(request.httpVersion, 200, "OK");
+
+ response.write(boundary());
+ sendMultipart(response);
+ while ((await shouldSendMore("sendMore")) !== "last") {
+ sendMultipart(response);
+ }
+ sendMultipart(response, true);
+ response.finish();
+}
diff --git a/docshell/test/mochitest/file_bug1773192_1.html b/docshell/test/mochitest/file_bug1773192_1.html
new file mode 100644
index 0000000000..42d5b3fced
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1773192_1.html
@@ -0,0 +1,13 @@
+<script>
+ let bc = new BroadcastChannel("bug1743353");
+ bc.addEventListener("message", ({ data }) => {
+ if (data == "next") {
+ location = "file_bug1773192_2.html";
+ } else if (data == "close") {
+ window.close();
+ }
+ });
+ window.addEventListener("pageshow", () => {
+ bc.postMessage({ location: location.href, referrer: document.referrer });
+ });
+</script>
diff --git a/docshell/test/mochitest/file_bug1773192_2.html b/docshell/test/mochitest/file_bug1773192_2.html
new file mode 100644
index 0000000000..3b1e5bcb28
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1773192_2.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <meta http-equiv="Cache-Control" content="no-cache, no-store">
+ <meta name="referrer" content="same-origin">
+ </head>
+ <body>
+ <form method="POST" action="file_bug1773192_3.sjs"></form>
+ <script>
+ history.replaceState({}, "", document.referrer);
+ document.forms[0].submit();
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/file_bug1773192_3.sjs b/docshell/test/mochitest/file_bug1773192_3.sjs
new file mode 100644
index 0000000000..ce889c7035
--- /dev/null
+++ b/docshell/test/mochitest/file_bug1773192_3.sjs
@@ -0,0 +1,3 @@
+function handleRequest(request, response) {
+ response.write("<script>history.back();</script>");
+}
diff --git a/docshell/test/mochitest/file_bug385434_1.html b/docshell/test/mochitest/file_bug385434_1.html
new file mode 100644
index 0000000000..5c951f1fa6
--- /dev/null
+++ b/docshell/test/mochitest/file_bug385434_1.html
@@ -0,0 +1,29 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ function hashchange() {
+ parent.onIframeHashchange();
+ }
+
+ function load() {
+ parent.onIframeLoad();
+ }
+
+ function scroll() {
+ parent.onIframeScroll();
+ }
+ </script>
+</head>
+
+<body onscroll="scroll()" onload="load()" onhashchange="hashchange()">
+<a href="#link1" id="link1">link1</a>
+<!-- Our parent loads us in an iframe with height 100px, so this spacer ensures
+ that switching between #link1 and #link2 causes us to scroll -->
+<div style="height:200px;"></div>
+<a href="#link2" id="link2">link2</a>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug385434_2.html b/docshell/test/mochitest/file_bug385434_2.html
new file mode 100644
index 0000000000..4aa5ef82b8
--- /dev/null
+++ b/docshell/test/mochitest/file_bug385434_2.html
@@ -0,0 +1,26 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ function hashchange(e) {
+ // pass the event back to the parent so it can check its properties.
+ parent.gSampleEvent = e;
+
+ parent.statusMsg("Hashchange in 2.");
+ parent.onIframeHashchange();
+ }
+
+ function load() {
+ parent.statusMsg("Loading 2.");
+ parent.onIframeLoad();
+ }
+ </script>
+</head>
+
+<frameset onload="load()" onhashchange="hashchange(event)">
+ <frame src="about:blank" />
+</frameset>
+</html>
diff --git a/docshell/test/mochitest/file_bug385434_3.html b/docshell/test/mochitest/file_bug385434_3.html
new file mode 100644
index 0000000000..34dd68ef45
--- /dev/null
+++ b/docshell/test/mochitest/file_bug385434_3.html
@@ -0,0 +1,22 @@
+<!--
+Inner frame for test of bug 385434.
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<html>
+<head>
+ <script type="application/javascript">
+ // Notify our parent if we have a hashchange and once we're done loading.
+ window.addEventListener("hashchange", parent.onIframeHashchange);
+
+ window.addEventListener("DOMContentLoaded", function() {
+ // This also should trigger a hashchange, becuase the readystate is
+ // "interactive", not "complete" during DOMContentLoaded.
+ window.location.hash = "2";
+ });
+
+ </script>
+</head>
+
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug475636.sjs b/docshell/test/mochitest/file_bug475636.sjs
new file mode 100644
index 0000000000..cba9a968d6
--- /dev/null
+++ b/docshell/test/mochitest/file_bug475636.sjs
@@ -0,0 +1,97 @@
+let jsURL =
+ "javascript:" +
+ escape(
+ 'window.parent.postMessage("JS uri ran", "*");\
+return \'\
+<script>\
+window.parent.postMessage("Able to access private: " +\
+ window.parent.private, "*");\
+</script>\''
+ );
+let dataURL =
+ "data:text/html," +
+ escape(
+ '<!DOCTYPE HTML>\
+<script>\
+try {\
+ window.parent.postMessage("Able to access private: " +\
+ window.parent.private, "*");\
+}\
+catch (e) {\
+ window.parent.postMessage("pass", "*");\
+}\
+</script>'
+ );
+
+let tests = [
+ // Plain document should work as normal
+ '<!DOCTYPE HTML>\
+<script>\
+try {\
+ window.parent.private;\
+ window.parent.postMessage("pass", "*");\
+}\
+catch (e) {\
+ window.parent.postMessage("Unble to access private", "*");\
+}\
+</script>',
+
+ // refresh to plain doc
+ { refresh: "file_bug475636.sjs?1", doc: "<!DOCTYPE HTML>" },
+
+ // meta-refresh to plain doc
+ '<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=file_bug475636.sjs?1">\
+</head>',
+
+ // refresh to data url
+ { refresh: dataURL, doc: "<!DOCTYPE HTML>" },
+
+ // meta-refresh to data url
+ '<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=' +
+ dataURL +
+ '">\
+</head>',
+
+ // refresh to js url should not be followed
+ {
+ refresh: jsURL,
+ doc: '<!DOCTYPE HTML>\
+<script>\
+setTimeout(function() {\
+ window.parent.postMessage("pass", "*");\
+}, 2000);\
+</script>',
+ },
+
+ // meta refresh to js url should not be followed
+ '<!DOCTYPE HTML>\
+<head>\
+ <meta http-equiv="refresh" content="0; url=' +
+ jsURL +
+ '">\
+</head>\
+<script>\
+setTimeout(function() {\
+ window.parent.postMessage("pass", "*");\
+}, 2000);\
+</script>',
+];
+
+function handleRequest(request, response) {
+ dump("@@@@@@@@@hi there: " + request.queryString + "\n");
+ let test = tests[parseInt(request.queryString, 10) - 1];
+ response.setHeader("Content-Type", "text/html");
+
+ if (!test) {
+ response.write('<script>parent.postMessage("done", "*");</script>');
+ } else if (typeof test == "string") {
+ response.write(test);
+ } else if (test.refresh) {
+ response.setHeader("Refresh", "0; url=" + test.refresh);
+ response.write(test.doc);
+ }
+}
diff --git a/docshell/test/mochitest/file_bug509055.html b/docshell/test/mochitest/file_bug509055.html
new file mode 100644
index 0000000000..ac30876bbf
--- /dev/null
+++ b/docshell/test/mochitest/file_bug509055.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test inner frame for bug 509055</title>
+</head>
+<body onhashchange="hashchangeCallback()">
+ file_bug509055.html
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug511449.html b/docshell/test/mochitest/file_bug511449.html
new file mode 100644
index 0000000000..637732dbbf
--- /dev/null
+++ b/docshell/test/mochitest/file_bug511449.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<title>Used in test for bug 511449</title>
+<input type="text" id="input">
+<script type="text/javascript">
+ document.getElementById("input").focus();
+</script>
diff --git a/docshell/test/mochitest/file_bug540462.html b/docshell/test/mochitest/file_bug540462.html
new file mode 100644
index 0000000000..ab8c07eba5
--- /dev/null
+++ b/docshell/test/mochitest/file_bug540462.html
@@ -0,0 +1,25 @@
+<html>
+ <head>
+ <script>
+ // <!--
+ function test() {
+ document.open();
+ document.write(
+ `<html>
+ <body onload='opener.documentWriteLoad(); rel();'>
+ <a href='foo.html'>foo</a>
+ <script>
+ function rel() { setTimeout('location.reload()', 0); }
+ <\/script>
+ </body>
+ </html>`
+ );
+ document.close();
+ }
+ // -->
+ </script>
+ </head>
+ <body onload="setTimeout('test()', 0)">
+ Test for bug 540462
+ </body>
+</html>
diff --git a/docshell/test/mochitest/file_bug580069_1.html b/docshell/test/mochitest/file_bug580069_1.html
new file mode 100644
index 0000000000..7ab4610334
--- /dev/null
+++ b/docshell/test/mochitest/file_bug580069_1.html
@@ -0,0 +1,8 @@
+<html>
+<body onload='parent.page1Load();'>
+file_bug580069_1.html
+
+<form id='form' action='file_bug580069_2.sjs' method='POST'></form>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug580069_2.sjs b/docshell/test/mochitest/file_bug580069_2.sjs
new file mode 100644
index 0000000000..ff03c74e68
--- /dev/null
+++ b/docshell/test/mochitest/file_bug580069_2.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/html", false);
+ response.write(
+ "<html><body onload='parent.page2Load(\"" +
+ request.method +
+ "\")'>file_bug580069_2.sjs</body></html>"
+ );
+}
diff --git a/docshell/test/mochitest/file_bug590573_1.html b/docshell/test/mochitest/file_bug590573_1.html
new file mode 100644
index 0000000000..b859ca7469
--- /dev/null
+++ b/docshell/test/mochitest/file_bug590573_1.html
@@ -0,0 +1,7 @@
+<html>
+<body onload='opener.page1Load();' onpageshow='opener.page1PageShow();'>
+
+<div style='height:10000px' id='div1'>This is a very tall div.</div>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug590573_2.html b/docshell/test/mochitest/file_bug590573_2.html
new file mode 100644
index 0000000000..5f9ca22be4
--- /dev/null
+++ b/docshell/test/mochitest/file_bug590573_2.html
@@ -0,0 +1,8 @@
+<html>
+<body onpopstate='opener.page2Popstate();' onload='opener.page2Load();'
+ onpageshow='opener.page2PageShow();'>
+
+<div style='height:300%' id='div2'>The second page also has a big div.</div>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug598895_1.html b/docshell/test/mochitest/file_bug598895_1.html
new file mode 100644
index 0000000000..d21f2b4a5d
--- /dev/null
+++ b/docshell/test/mochitest/file_bug598895_1.html
@@ -0,0 +1 @@
+<script>window.onload = function() { opener.postMessage("loaded", "*"); };</script><body>Should show</body>
diff --git a/docshell/test/mochitest/file_bug598895_2.html b/docshell/test/mochitest/file_bug598895_2.html
new file mode 100644
index 0000000000..680c9bf22b
--- /dev/null
+++ b/docshell/test/mochitest/file_bug598895_2.html
@@ -0,0 +1 @@
+<script>window.onload = function() { opener.postMessage("loaded", "*"); };</script><body></body>
diff --git a/docshell/test/mochitest/file_bug634834.html b/docshell/test/mochitest/file_bug634834.html
new file mode 100644
index 0000000000..3ff0897451
--- /dev/null
+++ b/docshell/test/mochitest/file_bug634834.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Nothing to see here; just an empty page.
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug637644_1.html b/docshell/test/mochitest/file_bug637644_1.html
new file mode 100644
index 0000000000..d21f2b4a5d
--- /dev/null
+++ b/docshell/test/mochitest/file_bug637644_1.html
@@ -0,0 +1 @@
+<script>window.onload = function() { opener.postMessage("loaded", "*"); };</script><body>Should show</body>
diff --git a/docshell/test/mochitest/file_bug637644_2.html b/docshell/test/mochitest/file_bug637644_2.html
new file mode 100644
index 0000000000..680c9bf22b
--- /dev/null
+++ b/docshell/test/mochitest/file_bug637644_2.html
@@ -0,0 +1 @@
+<script>window.onload = function() { opener.postMessage("loaded", "*"); };</script><body></body>
diff --git a/docshell/test/mochitest/file_bug640387.html b/docshell/test/mochitest/file_bug640387.html
new file mode 100644
index 0000000000..3a939fb41e
--- /dev/null
+++ b/docshell/test/mochitest/file_bug640387.html
@@ -0,0 +1,26 @@
+<html>
+<body onhashchange='hashchange()' onload='load()' onpopstate='popstate()'>
+
+<script>
+function hashchange() {
+ var f = (opener || parent).childHashchange;
+ if (f)
+ f();
+}
+
+function load() {
+ var f = (opener || parent).childLoad;
+ if (f)
+ f();
+}
+
+function popstate() {
+ var f = (opener || parent).childPopstate;
+ if (f)
+ f();
+}
+</script>
+
+Not much to see here...
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug653741.html b/docshell/test/mochitest/file_bug653741.html
new file mode 100644
index 0000000000..3202b52573
--- /dev/null
+++ b/docshell/test/mochitest/file_bug653741.html
@@ -0,0 +1,13 @@
+<html>
+<body onload='(parent || opener).childLoad()'>
+
+<div style='height:500px; background:yellow'>
+<a id='#top'>Top of the page</a>
+</div>
+
+<div id='bottom'>
+<a id='#bottom'>Bottom of the page</a>
+</div>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug660404 b/docshell/test/mochitest/file_bug660404
new file mode 100644
index 0000000000..ed773420ef
--- /dev/null
+++ b/docshell/test/mochitest/file_bug660404
@@ -0,0 +1,13 @@
+--testingtesting
+Content-Type: text/html
+
+<script>
+ var bc = new BroadcastChannel("bug660404_multipart");
+ bc.postMessage({command: "finishTest",
+ textContent: window.document.documentElement.textContent,
+ innerHTML: window.document.documentElement.innerHTML
+ });
+ bc.close();
+ window.close();
+</script>
+--testingtesting--
diff --git a/docshell/test/mochitest/file_bug660404-1.html b/docshell/test/mochitest/file_bug660404-1.html
new file mode 100644
index 0000000000..878bd80426
--- /dev/null
+++ b/docshell/test/mochitest/file_bug660404-1.html
@@ -0,0 +1,12 @@
+<script>
+ var bc = new BroadcastChannel("bug660404");
+ window.onload = function() {
+ setTimeout(() => {
+ window.onpagehide = function(ev) {
+ bc.postMessage({command: "pagehide", persisted: ev.persisted});
+ bc.close();
+ };
+ window.location.href = "file_bug660404";
+ }, 0);
+ };
+</script>
diff --git a/docshell/test/mochitest/file_bug660404^headers^ b/docshell/test/mochitest/file_bug660404^headers^
new file mode 100644
index 0000000000..5c821f3f48
--- /dev/null
+++ b/docshell/test/mochitest/file_bug660404^headers^
@@ -0,0 +1 @@
+Content-Type: multipart/x-mixed-replace; boundary="testingtesting"
diff --git a/docshell/test/mochitest/file_bug662170.html b/docshell/test/mochitest/file_bug662170.html
new file mode 100644
index 0000000000..3202b52573
--- /dev/null
+++ b/docshell/test/mochitest/file_bug662170.html
@@ -0,0 +1,13 @@
+<html>
+<body onload='(parent || opener).childLoad()'>
+
+<div style='height:500px; background:yellow'>
+<a id='#top'>Top of the page</a>
+</div>
+
+<div id='bottom'>
+<a id='#bottom'>Bottom of the page</a>
+</div>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug668513.html b/docshell/test/mochitest/file_bug668513.html
new file mode 100644
index 0000000000..ae417a35bd
--- /dev/null
+++ b/docshell/test/mochitest/file_bug668513.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test file for Bug 668513</title>
+<script>
+ var SimpleTest = opener.SimpleTest;
+ var ok = opener.ok;
+ var is = opener.is;
+
+ function finish() {
+ SimpleTest.finish();
+ close();
+ }
+
+ function onload_test() {
+ var win = frames[0];
+ ok(win.performance, "Window.performance should be defined");
+ ok(win.performance.navigation, "Window.performance.navigation should be defined");
+ var navigation = win.performance && win.performance.navigation;
+ if (navigation === undefined) {
+ // avoid script errors
+ finish();
+ return;
+ }
+
+ // do this with a timeout to see the visuals of the navigations.
+ setTimeout(nav_frame, 100);
+ }
+
+ var step = 1;
+ function nav_frame() {
+ var navigation_frame = frames[0];
+ var navigation = navigation_frame.performance.navigation;
+ switch (step) {
+ case 1:
+ {
+ navigation_frame.location.href = "bug570341_recordevents.html";
+ step++;
+ break;
+ }
+ case 2:
+ {
+ is(navigation.type, navigation.TYPE_NAVIGATE,
+ "Expected window.performance.navigation.type == TYPE_NAVIGATE");
+ navigation_frame.history.back();
+ step++;
+ break;
+ }
+ case 3:
+ {
+ is(navigation.type, navigation.TYPE_BACK_FORWARD,
+ "Expected window.performance.navigation.type == TYPE_BACK_FORWARD");
+ step++;
+ navigation_frame.history.forward();
+ break;
+ }
+ case 4:
+ {
+ is(navigation.type, navigation.TYPE_BACK_FORWARD,
+ "Expected window.performance.navigation.type == TYPE_BACK_FORWARD");
+ navigation_frame.location.href = "bug668513_redirect.html";
+ step++;
+ break;
+ }
+ case 5:
+ {
+ is(navigation.type, navigation.TYPE_NAVIGATE,
+ "Expected timing.navigation.type as TYPE_NAVIGATE");
+ is(navigation.redirectCount, 1,
+ "Expected navigation.redirectCount == 1 on an server redirected navigation");
+
+ var timing = navigation_frame.performance && navigation_frame.performance.timing;
+ if (timing === undefined) {
+ // avoid script errors
+ finish();
+ break;
+ }
+ ok(timing.navigationStart > 0, "navigationStart should be > 0");
+ var sequence = ["navigationStart", "redirectStart", "redirectEnd", "fetchStart"];
+ for (var j = 1; j < sequence.length; ++j) {
+ var prop = sequence[j];
+ var prevProp = sequence[j - 1];
+ ok(timing[prevProp] <= timing[prop],
+ ["Expected ", prevProp, " to happen before ", prop,
+ ", got ", prevProp, " = ", timing[prevProp],
+ ", ", prop, " = ", timing[prop]].join(""));
+ }
+ step++;
+ finish();
+ break;
+ }
+ }
+ }
+</script>
+</head>
+<body>
+<div id="frames">
+<iframe name="child0" onload="onload_test();" src="navigation/blank.html"></iframe>
+</div>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug669671.sjs b/docshell/test/mochitest/file_bug669671.sjs
new file mode 100644
index 0000000000..5871419de8
--- /dev/null
+++ b/docshell/test/mochitest/file_bug669671.sjs
@@ -0,0 +1,17 @@
+function handleRequest(request, response) {
+ var count = parseInt(getState("count"));
+ if (!count || request.queryString == "countreset") {
+ count = 0;
+ }
+
+ setState("count", count + 1 + "");
+
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Cache-Control", "max-age=0");
+ response.write(
+ '<html><body onload="opener.onChildLoad()" ' +
+ "onunload=\"parseInt('0')\">" +
+ count +
+ "</body></html>"
+ );
+}
diff --git a/docshell/test/mochitest/file_bug675587.html b/docshell/test/mochitest/file_bug675587.html
new file mode 100644
index 0000000000..842ab9ae79
--- /dev/null
+++ b/docshell/test/mochitest/file_bug675587.html
@@ -0,0 +1 @@
+<script>location.hash = "";</script>
diff --git a/docshell/test/mochitest/file_bug680257.html b/docshell/test/mochitest/file_bug680257.html
new file mode 100644
index 0000000000..ff480e96a5
--- /dev/null
+++ b/docshell/test/mochitest/file_bug680257.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <style type='text/css'>
+ a { color: black; }
+ a:target { color: red; }
+ </style>
+</head>
+
+<body onload='(opener || parent).popupLoaded()'>
+
+<a id='a' href='#a'>link</a>
+<a id='b' href='#b'>link2</a>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_bug703855.html b/docshell/test/mochitest/file_bug703855.html
new file mode 100644
index 0000000000..fe15b6e3df
--- /dev/null
+++ b/docshell/test/mochitest/file_bug703855.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<!-- Just need an empty file here, as long as it's served over HTTP -->
diff --git a/docshell/test/mochitest/file_bug728939.html b/docshell/test/mochitest/file_bug728939.html
new file mode 100644
index 0000000000..1cd52a44e1
--- /dev/null
+++ b/docshell/test/mochitest/file_bug728939.html
@@ -0,0 +1,3 @@
+<html>
+<body onload="opener.popupLoaded()">file_bug728939</body>
+</html>
diff --git a/docshell/test/mochitest/file_close_onpagehide1.html b/docshell/test/mochitest/file_close_onpagehide1.html
new file mode 100644
index 0000000000..ccf3b625a1
--- /dev/null
+++ b/docshell/test/mochitest/file_close_onpagehide1.html
@@ -0,0 +1,5 @@
+<script>
+ window.onload = () => {
+ opener.postMessage("initial", "*");
+ };
+</script>
diff --git a/docshell/test/mochitest/file_close_onpagehide2.html b/docshell/test/mochitest/file_close_onpagehide2.html
new file mode 100644
index 0000000000..a8e9479f47
--- /dev/null
+++ b/docshell/test/mochitest/file_close_onpagehide2.html
@@ -0,0 +1,5 @@
+<script>
+ window.onload = () => {
+ opener.postMessage("second", "*");
+ };
+</script>;
diff --git a/docshell/test/mochitest/file_compressed_multipart b/docshell/test/mochitest/file_compressed_multipart
new file mode 100644
index 0000000000..3c56226951
--- /dev/null
+++ b/docshell/test/mochitest/file_compressed_multipart
Binary files differ
diff --git a/docshell/test/mochitest/file_compressed_multipart^headers^ b/docshell/test/mochitest/file_compressed_multipart^headers^
new file mode 100644
index 0000000000..9376927812
--- /dev/null
+++ b/docshell/test/mochitest/file_compressed_multipart^headers^
@@ -0,0 +1,2 @@
+Content-Type: multipart/x-mixed-replace; boundary="testingtesting"
+Content-Encoding: gzip
diff --git a/docshell/test/mochitest/file_content_javascript_loads_frame.html b/docshell/test/mochitest/file_content_javascript_loads_frame.html
new file mode 100644
index 0000000000..9e2851aa8b
--- /dev/null
+++ b/docshell/test/mochitest/file_content_javascript_loads_frame.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<script type="application/javascript">
+"use strict";
+
+addEventListener("message", event => {
+ if ("ping" in event.data) {
+ event.source.postMessage({ pong: event.data.ping }, event.origin);
+ }
+});
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_content_javascript_loads_root.html b/docshell/test/mochitest/file_content_javascript_loads_root.html
new file mode 100644
index 0000000000..b9f2c1faa7
--- /dev/null
+++ b/docshell/test/mochitest/file_content_javascript_loads_root.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<script type="application/javascript">
+"use strict";
+
+window.onload = () => {
+ opener.postMessage("ready", "*");
+};
+
+// eslint-disable-next-line no-shadow
+function promiseMessage(source, filter = event => true) {
+ return new Promise(resolve => {
+ function listener(event) {
+ if (event.source == source && filter(event)) {
+ removeEventListener("message", listener);
+ resolve(event);
+ }
+ }
+ addEventListener("message", listener);
+ });
+}
+
+// Sends a message to the given target window and waits for the response.
+function ping(target) {
+ let msg = { ping: Math.random() };
+ target.postMessage(msg, "*");
+ return promiseMessage(
+ target,
+ event => event.data && event.data.pong == msg.ping
+ );
+}
+
+function setFrameLocation(name, uri) {
+ window[name].location = uri;
+}
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_form_restoration_no_store.html b/docshell/test/mochitest/file_form_restoration_no_store.html
new file mode 100644
index 0000000000..6e8756a693
--- /dev/null
+++ b/docshell/test/mochitest/file_form_restoration_no_store.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ window.addEventListener("pageshow", ({ persisted }) => {
+ let bc = new BroadcastChannel("form_restoration");
+ bc.addEventListener("message", ({ data }) => {
+ switch (data) {
+ case "enter_data":
+ document.getElementById("formElement").value = "test";
+ break;
+ case "reload":
+ bc.close();
+ location.reload();
+ break;
+ case "navigate":
+ bc.close();
+ document.location = "file_form_restoration_no_store.html?1";
+ break;
+ case "back":
+ bc.close();
+ history.back();
+ break;
+ case "close":
+ bc.close();
+ window.close();
+ break;
+ }
+ });
+ bc.postMessage({ persisted, formData: document.getElementById("formElement").value });
+ });
+ </script>
+</head>
+<body>
+ <input id="formElement" type="text" value="initial">
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_form_restoration_no_store.html^headers^ b/docshell/test/mochitest/file_form_restoration_no_store.html^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/docshell/test/mochitest/file_form_restoration_no_store.html^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/docshell/test/mochitest/file_framedhistoryframes.html b/docshell/test/mochitest/file_framedhistoryframes.html
new file mode 100644
index 0000000000..314f9c72d8
--- /dev/null
+++ b/docshell/test/mochitest/file_framedhistoryframes.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<iframe id="iframe" src="historyframes.html"></iframe>
+<script type="application/javascript">
+
+var SimpleTest = window.opener.SimpleTest;
+var is = window.opener.is;
+
+function done() {
+ window.opener.done();
+}
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/file_load_during_reload.html b/docshell/test/mochitest/file_load_during_reload.html
new file mode 100644
index 0000000000..600d5c1728
--- /dev/null
+++ b/docshell/test/mochitest/file_load_during_reload.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <script>
+ function notifyOpener() {
+ opener.postMessage("loaded", "*");
+ }
+ </script>
+ </head>
+ <body onload="notifyOpener()">
+ </body>
+</html>
diff --git a/docshell/test/mochitest/file_pushState_after_document_open.html b/docshell/test/mochitest/file_pushState_after_document_open.html
new file mode 100644
index 0000000000..97a6954f2e
--- /dev/null
+++ b/docshell/test/mochitest/file_pushState_after_document_open.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+ document.addEventListener("DOMContentLoaded", function() {
+ document.open();
+ document.write("<!DOCTYPE html>New Document here");
+ document.close();
+ // Notify parent via postMessage, since otherwise exceptions will not get
+ // caught by its onerror handler.
+ parent.postMessage("doTest", "*");
+ });
+</script>
diff --git a/docshell/test/mochitest/file_redirect_history.html b/docshell/test/mochitest/file_redirect_history.html
new file mode 100644
index 0000000000..3971faf4fd
--- /dev/null
+++ b/docshell/test/mochitest/file_redirect_history.html
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <script>
+ function loaded() {
+ addEventListener("message", ({ data }) => {
+ document.getElementById("form").action = data;
+ document.getElementById("button").click();
+ }, { once: true });
+ opener.postMessage("loaded", "*");
+ }
+ </script>
+ </head>
+ <body onload="loaded();">
+ <form id="form" method="POST">
+ <input id="button" type="submit" />
+ </form>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/form_submit.sjs b/docshell/test/mochitest/form_submit.sjs
new file mode 100644
index 0000000000..1a1fa5d89c
--- /dev/null
+++ b/docshell/test/mochitest/form_submit.sjs
@@ -0,0 +1,40 @@
+"use strict";
+
+const CC = Components.Constructor;
+const BinaryInputStream = CC(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+const BinaryOutputStream = CC(
+ "@mozilla.org/binaryoutputstream;1",
+ "nsIBinaryOutputStream",
+ "setOutputStream"
+);
+
+function log(str) {
+ // dump(`LOG: ${str}\n`);
+}
+
+async function handleRequest(request, response) {
+ if (request.method !== "POST") {
+ throw new Error("Expected a post request");
+ } else {
+ log("Reading request");
+ let available = 0;
+ let inputStream = new BinaryInputStream(request.bodyInputStream);
+ while ((available = inputStream.available()) > 0) {
+ log(inputStream.readBytes(available));
+ }
+ }
+
+ log("Setting Headers");
+ response.setHeader("Content-Type", "text/html", false);
+ response.setStatusLine(request.httpVersion, "200", "OK");
+ log("Writing body");
+ response.write(
+ '<script>"use strict"; let target = opener ? opener : parent; target.postMessage("done", "*");</script>'
+ );
+ log("Done");
+}
diff --git a/docshell/test/mochitest/form_submit_redirect.sjs b/docshell/test/mochitest/form_submit_redirect.sjs
new file mode 100644
index 0000000000..dbc32b9643
--- /dev/null
+++ b/docshell/test/mochitest/form_submit_redirect.sjs
@@ -0,0 +1,15 @@
+"use strict";
+
+Cu.importGlobalProperties(["URLSearchParams"]);
+
+async function handleRequest(request, response) {
+ if (request.method !== "POST") {
+ throw new Error("Expected a post request");
+ } else {
+ let params = new URLSearchParams(request.queryString);
+ let redirect = params.get("redirectTo");
+
+ response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
+ response.setHeader("Location", redirect);
+ }
+}
diff --git a/docshell/test/mochitest/historyframes.html b/docshell/test/mochitest/historyframes.html
new file mode 100644
index 0000000000..31f46a5071
--- /dev/null
+++ b/docshell/test/mochitest/historyframes.html
@@ -0,0 +1,176 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</title>
+</head>
+<body onload="SimpleTest.executeSoon(run_test)">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602256">Mozilla Bug 602256</a>
+<div id="content">
+ <iframe id="iframe" src="start_historyframe.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 */
+
+var testWin = window.opener ? window.opener : window.parent;
+
+var SimpleTest = testWin.SimpleTest;
+function is() { testWin.is.apply(testWin, arguments); }
+
+var gFrame = null;
+
+function gState() {
+ return location.hash.replace(/^#/, "");
+}
+
+function waitForLoad(aCallback) {
+ function listener() {
+ gFrame.removeEventListener("load", listener);
+ SimpleTest.executeSoon(aCallback);
+ }
+
+ gFrame.addEventListener("load", listener);
+}
+
+function loadContent(aURL, aCallback) {
+ waitForLoad(aCallback);
+
+ gFrame.src = aURL;
+}
+
+function getURL() {
+ return gFrame.contentDocument.documentURI;
+}
+
+function getContent() {
+ return gFrame.contentDocument.getElementById("text").textContent;
+}
+
+var BASE_URI = "http://mochi.test:8888/tests/docshell/test/mochitest/";
+var START = BASE_URI + "start_historyframe.html";
+var URL1 = BASE_URI + "url1_historyframe.html";
+var URL2 = BASE_URI + "url2_historyframe.html";
+
+function run_test() {
+ window.location.hash = "START";
+
+ gFrame = document.getElementById("iframe");
+
+ test_basic_inner_navigation();
+}
+
+function end_test() {
+ testWin.done();
+}
+
+var gTestContinuation = null;
+function continueAsync() {
+ setTimeout(function() { gTestContinuation.next(); })
+}
+
+function test_basic_inner_navigation() {
+ // Navigate the inner frame a few times
+ loadContent(URL1, function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ loadContent(URL2, function() {
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ // Test that history is working
+ waitForLoad(function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ waitForLoad(function() {
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ gTestContinuation = test_state_navigation();
+ gTestContinuation.next();
+ });
+ window.history.forward();
+ });
+ window.history.back();
+ });
+ });
+}
+
+function* test_state_navigation() {
+ window.location.hash = "STATE1";
+
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.location.hash = "STATE2";
+
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.addEventListener("popstate", (e) => {
+ continueAsync();
+ }, {once: true});
+ window.history.back();
+ yield;
+
+ is(gState(), "STATE1", "State should be correct after going back");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.addEventListener("popstate", (e) => {
+ continueAsync();
+ }, {once: true});
+ window.history.forward();
+ yield;
+
+ is(gState(), "STATE2", "State should be correct after going forward");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ window.addEventListener("popstate", (e) => {
+ continueAsync();
+ }, {once: true});
+ window.history.back();
+ yield;
+
+ window.addEventListener("popstate", (e) => {
+ continueAsync();
+ }, {once: true});
+ window.history.back();
+ yield;
+
+ is(gState(), "START", "State should be correct");
+ is(getURL(), URL2, "URL should be correct");
+ is(getContent(), "Test2", "Page should be correct");
+
+ waitForLoad(function() {
+ is(getURL(), URL1, "URL should be correct");
+ is(getContent(), "Test1", "Page should be correct");
+
+ waitForLoad(function() {
+ is(gState(), "START", "State should be correct");
+ is(getURL(), START, "URL should be correct");
+ is(getContent(), "Start", "Page should be correct");
+
+ end_test();
+ });
+
+ window.history.back();
+
+ is(gState(), "START", "State should be correct after going back twice");
+ });
+
+ window.history.back();
+ continueAsync();
+ yield;
+ is(gState(), "START", "State should be correct");
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/mochitest.ini b/docshell/test/mochitest/mochitest.ini
new file mode 100644
index 0000000000..598d629673
--- /dev/null
+++ b/docshell/test/mochitest/mochitest.ini
@@ -0,0 +1,209 @@
+[DEFAULT]
+support-files =
+ bug404548-subframe.html
+ bug404548-subframe_window.html
+ bug413310-post.sjs
+ bug413310-subframe.html
+ bug529119-window.html
+ bug570341_recordevents.html
+ bug668513_redirect.html
+ bug668513_redirect.html^headers^
+ bug691547_frame.html
+ dummy_page.html
+ file_anchor_scroll_after_document_open.html
+ file_bfcache_plus_hash_1.html
+ file_bfcache_plus_hash_2.html
+ file_bug385434_1.html
+ file_bug385434_2.html
+ file_bug385434_3.html
+ file_bug475636.sjs
+ file_bug509055.html
+ file_bug540462.html
+ file_bug580069_1.html
+ file_bug580069_2.sjs
+ file_bug598895_1.html
+ file_bug598895_2.html
+ file_bug590573_1.html
+ file_bug590573_2.html
+ file_bug634834.html
+ file_bug637644_1.html
+ file_bug637644_2.html
+ file_bug640387.html
+ file_bug653741.html
+ file_bug660404
+ file_bug660404^headers^
+ file_bug660404-1.html
+ file_bug662170.html
+ file_bug669671.sjs
+ file_bug680257.html
+ file_bug703855.html
+ file_bug728939.html
+ file_bug1121701_1.html
+ file_bug1121701_2.html
+ file_bug1186774.html
+ file_bug1151421.html
+ file_bug1450164.html
+ file_close_onpagehide1.html
+ file_close_onpagehide2.html
+ file_compressed_multipart
+ file_compressed_multipart^headers^
+ file_pushState_after_document_open.html
+ historyframes.html
+ ping.html
+ start_historyframe.html
+ url1_historyframe.html
+ url2_historyframe.html
+
+[test_anchor_scroll_after_document_open.html]
+[test_bfcache_plus_hash.html]
+[test_bug1422334.html]
+support-files =
+ bug1422334_redirect.html
+ bug1422334_redirect.html^headers^
+ !/docshell/test/navigation/blank.html
+[test_bug385434.html]
+[test_bug387979.html]
+[test_bug402210.html]
+skip-if =
+ http3
+[test_bug404548.html]
+[test_bug413310.html]
+skip-if = true
+# Disabled for too many intermittent failures (bug 719186)
+[test_bug475636.html]
+[test_bug509055.html]
+[test_bug511449.html]
+skip-if = toolkit != "cocoa" || headless # Headless: bug 1410525
+support-files = file_bug511449.html
+[test_bug529119-1.html]
+skip-if =
+ fission && os == "android" # Bug 1827321
+[test_bug529119-2.html]
+skip-if =
+ http3
+ fission && os == "android" # Bug 1827321
+[test_bug530396.html]
+support-files = bug530396-noref.sjs bug530396-subframe.html
+skip-if =
+ http3
+[test_bug540462.html]
+skip-if = toolkit == 'android' && debug
+[test_bug551225.html]
+[test_bug570341.html]
+skip-if = (verify && !debug && (os == 'win'))
+[test_bug580069.html]
+skip-if = (verify && !debug && (os == 'win'))
+[test_bug590573.html]
+[test_bug598895.html]
+[test_bug634834.html]
+skip-if =
+ http3
+[test_bug637644.html]
+[test_bug640387_1.html]
+[test_bug640387_2.html]
+[test_bug653741.html]
+[test_bug660404.html]
+[test_bug662170.html]
+[test_bug668513.html]
+support-files = file_bug668513.html
+[test_bug669671.html]
+[test_bug675587.html]
+support-files = file_bug675587.html
+[test_bug680257.html]
+[test_bug691547.html]
+[test_bug694612.html]
+[test_bug703855.html]
+[test_bug728939.html]
+[test_bug797909.html]
+[test_bug1045096.html]
+[test_bug1121701.html]
+[test_bug1151421.html]
+[test_bug1186774.html]
+[test_bug1450164.html]
+[test_bug1507702.html]
+[test_bug1645781.html]
+support-files =
+ form_submit.sjs
+skip-if =
+ http3
+[test_bug1729662.html]
+support-files =
+ file_bug1729662.html
+[test_bug1740516.html]
+support-files =
+ file_bug1740516_1.html
+ file_bug1740516_1_inner.html
+ file_bug1740516_2.html
+[test_form_restoration.html]
+support-files =
+ file_form_restoration_no_store.html
+ file_form_restoration_no_store.html^headers^
+[test_bug1741132.html]
+support-files =
+ file_bug1741132.html
+skip-if = toolkit == "android" && !sessionHistoryInParent
+[test_bug1742865.html]
+support-files =
+ file_bug1742865.sjs
+ file_bug1742865_outer.sjs
+skip-if =
+ toolkit == "android" && debug && fission && verify # Bug 1745937
+ http3
+[test_bug1743353.html]
+support-files =
+ file_bug1743353.html
+[test_bug1747033.html]
+support-files =
+ file_bug1747033.sjs
+skip-if =
+ http3
+[test_bug1773192.html]
+support-files =
+ file_bug1773192_1.html
+ file_bug1773192_2.html
+ file_bug1773192_3.sjs
+[test_close_onpagehide_by_history_back.html]
+[test_close_onpagehide_by_window_close.html]
+[test_compressed_multipart.html]
+[test_content_javascript_loads.html]
+support-files =
+ file_content_javascript_loads_root.html
+ file_content_javascript_loads_frame.html
+skip-if =
+ http3
+[test_forceinheritprincipal_overrule_owner.html]
+skip-if =
+ http3
+[test_framedhistoryframes.html]
+support-files = file_framedhistoryframes.html
+skip-if =
+ http3
+[test_load_during_reload.html]
+support-files = file_load_during_reload.html
+[test_pushState_after_document_open.html]
+[test_navigate_after_pagehide.html]
+skip-if =
+ http3
+[test_redirect_history.html]
+support-files =
+ file_redirect_history.html
+ form_submit_redirect.sjs
+skip-if =
+ http3
+[test_windowedhistoryframes.html]
+skip-if =
+ (!debug && os == 'android') # Bug 1573892
+ http3
+[test_triggeringprincipal_location_seturi.html]
+skip-if =
+ http3
+[test_double_submit.html]
+support-files =
+ clicker.html
+ double_submit.sjs
+skip-if =
+ http3
+[test_iframe_srcdoc_to_remote.html]
+skip-if =
+ http3
+[test_javascript_sandboxed_popup.html]
diff --git a/docshell/test/mochitest/ping.html b/docshell/test/mochitest/ping.html
new file mode 100644
index 0000000000..7d84560dd1
--- /dev/null
+++ b/docshell/test/mochitest/ping.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<script>
+ "use strict";
+ let target = (window.opener || window.parent);
+ target.postMessage("ping", "*");
+</script>
diff --git a/docshell/test/mochitest/start_historyframe.html b/docshell/test/mochitest/start_historyframe.html
new file mode 100644
index 0000000000..a791af4e64
--- /dev/null
+++ b/docshell/test/mochitest/start_historyframe.html
@@ -0,0 +1 @@
+<p id='text'>Start</p>
diff --git a/docshell/test/mochitest/test_anchor_scroll_after_document_open.html b/docshell/test/mochitest/test_anchor_scroll_after_document_open.html
new file mode 100644
index 0000000000..5309f6cf19
--- /dev/null
+++ b/docshell/test/mochitest/test_anchor_scroll_after_document_open.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=881487
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 881487</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 881487 */
+ SimpleTest.waitForExplicitFinish();
+ // Child needs to invoke us, otherwise our onload will fire before the child
+ // has done the write/close bit.
+ var gotOnload = false;
+ addLoadEvent(function() {
+ gotOnload = true;
+ });
+ onmessage = function handleMessage(msg) {
+ if (msg.data == "doTest") {
+ if (!gotOnload) {
+ addLoadEvent(function() { handleMessage(msg); });
+ return;
+ }
+ frames[0].onscroll = function() {
+ ok(true, "Got a scroll event");
+ SimpleTest.finish();
+ };
+ frames[0].location.hash = "#target";
+ return;
+ }
+ if (msg.data == "haveHash") {
+ ok(false, "Child got reloaded");
+ } else {
+ ok(false, "Unexpected message");
+ }
+ SimpleTest.finish();
+ };
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=881487">Mozilla Bug 881487</a>
+<p id="display">
+ <!-- iframe goes here so it can scroll -->
+<iframe src="file_anchor_scroll_after_document_open.html"></iframe>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bfcache_plus_hash.html b/docshell/test/mochitest/test_bfcache_plus_hash.html
new file mode 100644
index 0000000000..cb5bc06f21
--- /dev/null
+++ b/docshell/test/mochitest/test_bfcache_plus_hash.html
@@ -0,0 +1,153 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=646641
+-->
+<head>
+ <title>Test for Bug 646641</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=646641">Mozilla Bug 646641</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 646641 */
+
+/**
+ * Steps:
+ * - Main page (this one) opens file_bfcache_plus_hash_1.html (subpage 1)
+ * - subpage 1 sends msg { "childLoad", 1 }
+ * - subpage 1 sends msg { "childPageshow", 1 }
+ * - main page sends message "pushState"
+ * - subpage 1 does pushState()
+ * - subpage 1 navigates to file_bfcache_plus_hash_2.html (subpage 2)
+ * - subpage 2 sends msg { "childLoad", 2 }
+ * - subpage 2 sends msg { "childPageshow", 2 }
+ * - main page sends msg "go-2"
+ * - subpage 2 goes back two history entries
+ * - subpage 1 sends msg { "childPageshow", 1 }
+ * - Receiving only this msg shows we have retrieved the document from bfcache
+ * - main page sends msg "close"
+ * - subpage 1 sends msg "closed"
+ */
+SimpleTest.waitForExplicitFinish();
+
+function debug(msg) {
+ // Wrap dump so we can turn debug messages on and off easily.
+ dump(msg + "\n");
+}
+
+var expectedLoadNum = -1;
+var expectedPageshowNum = -1;
+
+function waitForLoad(n) {
+ debug("Waiting for load " + n);
+ expectedLoadNum = n;
+}
+
+function waitForShow(n) {
+ debug("Waiting for show " + n);
+ expectedPageshowNum = n;
+}
+
+
+
+function executeTest() {
+ function* test() {
+ window.open("file_bfcache_plus_hash_1.html", "", "noopener");
+ waitForLoad(1);
+ waitForShow(1);
+ yield undefined;
+ yield undefined;
+
+ bc1.postMessage("pushState");
+
+ waitForLoad(2);
+ waitForShow(2);
+ yield undefined;
+ yield undefined;
+
+ // Now go back 2. The first page should be retrieved from bfcache.
+ bc2.postMessage("go-2");
+ waitForShow(1);
+ yield undefined;
+
+ bc1.postMessage("close");
+ }
+
+ var bc1 = new BroadcastChannel("bug646641_1");
+ var bc2 = new BroadcastChannel("bug646641_2");
+ bc1.onmessage = (msgEvent) => {
+ var msg = msgEvent.data.message;
+ var n = msgEvent.data.num;
+ if (msg == "childLoad") {
+ if (n == expectedLoadNum) {
+ debug("Got load " + n);
+ expectedLoadNum = -1;
+
+ // Spin the event loop before calling gGen.next() so the generator runs
+ // outside the onload handler. This prevents us from encountering all
+ // sorts of docshell quirks.
+ setTimeout(function() { gGen.next(); }, 0);
+ } else {
+ debug("Got unexpected load " + n);
+ ok(false, "Got unexpected load " + n);
+ }
+ } else if (msg == "childPageshow") {
+ if (n == expectedPageshowNum) {
+ debug("Got expected pageshow " + n);
+ expectedPageshowNum = -1;
+ ok(true, "Got expected pageshow " + n);
+ setTimeout(function() { gGen.next(); }, 0);
+ } else {
+ debug("Got unexpected pageshow " + n);
+ ok(false, "Got unexpected pageshow " + n);
+ }
+ } else if (msg == "closed") {
+ bc1.close();
+ bc2.close();
+ SimpleTest.finish();
+ }
+ }
+
+ bc2.onmessage = bc1.onmessage;
+
+ var gGen = test();
+
+ // If Fission is disabled, the pref is no-op.
+ SpecialPowers.pushPrefEnv({set: [["fission.bfcacheInParent", true]]}, () => {
+ gGen.next();
+ });
+}
+if (isXOrigin) {
+ // Bug 1746646: Make mochitests work with TCP enabled (cookieBehavior = 5)
+ // Acquire storage access permission here so that the BroadcastChannel used to
+ // communicate with the opened windows works in xorigin tests. Otherwise,
+ // the iframe containing this page is isolated from first-party storage access,
+ // which isolates BroadcastChannel communication.
+ SpecialPowers.wrap(document).notifyUserGestureActivation();
+ SpecialPowers.addPermission("storageAccessAPI", true, window.location.href).then(() => {
+ SpecialPowers.wrap(document).requestStorageAccess().then(() => {
+ SpecialPowers.pushPrefEnv({
+ set: [["privacy.partition.always_partition_third_party_non_cookie_storage", false]],
+ }).then(() => {
+ executeTest();
+ });
+ });
+ });
+} else {
+ executeTest();
+}
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1045096.html b/docshell/test/mochitest/test_bug1045096.html
new file mode 100644
index 0000000000..2df2232b7e
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1045096.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1045096
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1045096</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045096">Mozilla Bug 1045096</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+ <script type="application/javascript">
+
+ /** Test for Bug 1045096 */
+ var i = document.createElement("iframe");
+ i.src = "javascript:false"; // This is required!
+ $("content").appendChild(i);
+ ok(i.contentWindow.performance, "Should have a performance object");
+ </script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1121701.html b/docshell/test/mochitest/test_bug1121701.html
new file mode 100644
index 0000000000..cd0b2529d4
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1121701.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1121701
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1121701</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1121701 */
+ SimpleTest.waitForExplicitFinish();
+
+ var testUrl1 = "file_bug1121701_1.html";
+ var testUrl2 = "file_bug1121701_2.html";
+
+ var page1LoadCount = 0;
+ let page1Done = {};
+ page1Done.promise = new Promise(resolve => {
+ page1Done.resolve = resolve;
+ });
+ let page2Done = {};
+ page2Done.promise = new Promise(resolve => {
+ page2Done.resolve = resolve;
+ });
+
+ addLoadEvent(async function() {
+
+ // Bug 1746646: Make mochitests work with TCP enabled (cookieBehavior = 5)
+ // Acquire storage access permission here so that the BroadcastChannel used to
+ // communicate with the opened windows works in xorigin tests. Otherwise,
+ // the iframe containing this page is isolated from first-party storage access,
+ // which isolates BroadcastChannel communication.
+ if (isXOrigin) {
+ await SpecialPowers.pushPrefEnv({
+ set: [["privacy.partition.always_partition_third_party_non_cookie_storage", false]],
+ });
+ SpecialPowers.wrap(document).notifyUserGestureActivation();
+ await SpecialPowers.addPermission("storageAccessAPI", true, window.location.href);
+ await SpecialPowers.wrap(document).requestStorageAccess();
+ }
+
+ var bc = new BroadcastChannel("file_bug1121701_1");
+ var bc2 = new BroadcastChannel("file_bug1121701_2");
+
+ async function scheduleFinish() {
+ await Promise.all([page1Done.promise, page2Done.promise]);
+ bc2.close();
+ bc.close();
+ SimpleTest.finish();
+ }
+
+ bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "child1PageShow") {
+ ++page1LoadCount;
+ var persisted = msg.persisted;
+ var pageHideAsserts = msg.pageHideAsserts;
+ if (pageHideAsserts) {
+ ok(pageHideAsserts.persisted, "onpagehide: test page 1 should get persisted");
+ is(pageHideAsserts.innerHTML, "modified", "onpagehide: innerHTML text is 'modified'");
+ }
+ if (page1LoadCount == 1) {
+ SimpleTest.executeSoon(function() {
+ is(persisted, false, "Initial page load shouldn't be persisted.");
+ bc.postMessage({command: "setInnerHTML", testUrl2});
+ });
+ } else if (page1LoadCount == 2) {
+ is(persisted, true, "Page load from bfcache should be persisted.");
+ is(msg.innerHTML, "modified", "innerHTML text is 'modified'");
+ bc.postMessage({command: "close"});
+ }
+ } else if (command == "closed") {
+ page1Done.resolve();
+ }
+ }
+ bc2.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "child2PageShow") {
+ bc2.postMessage({command: "setInnerHTML", location: location.href});
+ } else if (command == "onmessage") {
+ page2Done.resolve();
+ }
+ }
+
+ scheduleFinish();
+ // If Fission is disabled, the pref is no-op.
+ SpecialPowers.pushPrefEnv({set: [["fission.bfcacheInParent", true]]}, () => {
+ window.open(testUrl1, "", "noopener");
+ });
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1121701">Mozilla Bug 1121701</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1151421.html b/docshell/test/mochitest/test_bug1151421.html
new file mode 100644
index 0000000000..0738ee783e
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1151421.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1151421
+-->
+<head>
+ <title>Test for Bug 1151421</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151421">Mozilla Bug 1151421</a>
+
+<script type="application/javascript">
+
+/** Test for Bug 1151421 */
+SimpleTest.waitForExplicitFinish();
+
+function childLoad() {
+ // Spin the event loop so we leave the onload handler.
+ SimpleTest.executeSoon(childLoad2);
+}
+
+function childLoad2() {
+ let iframe = document.getElementById("iframe");
+ let cw = iframe.contentWindow;
+ let content = cw.document.getElementById("content");
+
+ // Create a function to calculate an invariant.
+ let topPlusOffset = function() {
+ return Math.round(content.getBoundingClientRect().top + cw.pageYOffset);
+ };
+
+ let initialTPO = topPlusOffset();
+
+ // Scroll the iframe to various positions, and check the TPO.
+ // Scrolling down to the bottom will adjust the page offset by a fractional amount.
+ let positions = [-100, 0.17, 0, 1.5, 10.41, 1e6, 12.1];
+
+ // Run some tests with scrollTo() and ensure we have the same invariant after scrolling.
+ positions.forEach(function(pos) {
+ cw.scrollTo(0, pos);
+ is(topPlusOffset(), initialTPO, "Top plus offset should remain invariant across scrolling.");
+ });
+
+ positions.reverse().forEach(function(pos) {
+ cw.scrollTo(0, pos);
+ is(topPlusOffset(), initialTPO, "(reverse) Top plus offset should remain invariant across scrolling.");
+ });
+
+ SimpleTest.finish();
+}
+
+</script>
+
+<!-- When the iframe loads, it calls childLoad(). -->
+<br>
+<iframe height='100px' id='iframe' src='file_bug1151421.html'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1186774.html b/docshell/test/mochitest/test_bug1186774.html
new file mode 100644
index 0000000000..9ec56baf11
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1186774.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1186774
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1186774</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1186774 */
+
+var child;
+
+function runTest() {
+ child = window.open("file_bug1186774.html", "", "width=100,height=100");
+ child.onload = function() {
+ setTimeout(function() {
+ child.scrollTo(0, 0);
+ child.history.pushState({}, "initial");
+ child.scrollTo(0, 3000);
+ child.history.pushState({}, "scrolled");
+ child.scrollTo(0, 6000);
+ child.history.back();
+ });
+ };
+
+ child.onpopstate = function() {
+ is(Math.round(child.scrollY), 6000, "Shouldn't have scrolled before popstate");
+ child.close();
+ SimpleTest.finish();
+ };
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1186774">Mozilla Bug 1186774</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1422334.html b/docshell/test/mochitest/test_bug1422334.html
new file mode 100644
index 0000000000..b525ae1d9c
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1422334.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Ensure that reload after replaceState after 3xx redirect does the right thing.</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ var ifr = document.querySelector("iframe");
+ var win = ifr.contentWindow;
+ is(win.location.href, location.href.replace(location.search, "")
+ .replace("mochitest/test_bug1422334.html",
+ "navigation/blank.html?x=y"),
+ "Should have the right location on initial load");
+
+ win.history.replaceState(null, '', win.location.pathname);
+ is(win.location.href, location.href.replace(location.search, "")
+ .replace("mochitest/test_bug1422334.html",
+ "navigation/blank.html"),
+ "Should have the right location after replaceState call");
+
+ ifr.onload = function() {
+ is(win.location.href, location.href.replace(location.search, "")
+ .replace("mochitest/test_bug1422334.html",
+ "navigation/blank.html"),
+ "Should have the right location after reload");
+ SimpleTest.finish();
+ }
+ win.location.reload();
+ });
+ </script>
+</head>
+<body>
+<p id="display"><iframe src="bug1422334_redirect.html"></iframe></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1450164.html b/docshell/test/mochitest/test_bug1450164.html
new file mode 100644
index 0000000000..546a988394
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1450164.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1450164
+ -->
+ <head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1450164</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1450164 */
+
+ function runTest() {
+ var child = window.open("file_bug1450164.html", "", "width=100,height=100");
+ child.onload = function() {
+ // After the window loads, close it. If we don't crash in debug, consider that a pass.
+ child.close();
+ };
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(runTest);
+
+ </script>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1450164">Mozilla Bug 1450164</a>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1507702.html b/docshell/test/mochitest/test_bug1507702.html
new file mode 100644
index 0000000000..fd88ee60a5
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1507702.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1507702
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1507702</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <link rel="icon" href="about:crashparent"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1507702">Mozilla Bug 1507702</a>
+<img src="about:crashparent">
+<img src="about:crashcontent">
+<iframe src="about:crashparent"></iframe>
+<iframe src="about:crashcontent"></iframe>
+<script>
+ let urls = ["about:crashparent", "about:crashcontent"];
+ async function testFetch() {
+ const url = urls.shift();
+ if (!url) {
+ return Promise.resolve();
+ }
+
+ let threw;
+ try {
+ await fetch(url);
+ threw = false;
+ } catch (e) {
+ threw = true;
+ }
+
+ ok(threw === true, "fetch should reject");
+ return testFetch();
+ }
+
+ document.body.onload = async () => {
+ for (const url of ["about:crashparent", "about:crashcontent"]) {
+ SimpleTest.doesThrow(() => {
+ top.location.href = url;
+ }, "navigation should throw");
+
+ SimpleTest.doesThrow(() => {
+ location.href = url;
+ }, "navigation should throw");
+ }
+
+ await testFetch();
+ SimpleTest.finish();
+ };
+
+ SimpleTest.waitForExplicitFinish();
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1645781.html b/docshell/test/mochitest/test_bug1645781.html
new file mode 100644
index 0000000000..6cf676b7a9
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1645781.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Test for Bug 1590762</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <form id="form" action="form_submit.sjs" method="POST" target="targetFrame">
+ <input id="input" type="text" name="name" value="">
+ <input id="button" type="submit">
+ </form>
+ <script>
+ "use strict";
+ const PATH = "/tests/docshell/test/mochitest/";
+ const SAME_ORIGIN = new URL(PATH, window.location.origin);;
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ const CROSS_ORIGIN_1 = new URL(PATH, "http://test1.example.com/");
+ const CROSS_ORIGIN_2 = new URL(PATH, "https://example.com/");
+ const TARGET = "ping.html";
+ const ACTION = "form_submit.sjs";
+
+ function generateBody(size) {
+ let data = new Uint8Array(size);
+ for (let i = 0; i < size; ++i) {
+ data[i] = 97 + Math.random() * (123 - 97);
+ }
+
+ return new TextDecoder().decode(data);
+ }
+
+ async function withFrame(url) {
+ info("Creating frame");
+ let frame = document.createElement('iframe');
+ frame.name = "targetFrame";
+
+ return new Promise(resolve => {
+ addEventListener('message', async function({source}) {
+ info("Frame loaded");
+ if (frame.contentWindow == source) {
+ resolve(frame);
+ }
+ }, { once: true });
+ frame.src = url;
+ document.body.appendChild(frame);
+ });
+ }
+
+ function click() {
+ synthesizeMouse(document.getElementById('button'), 5, 5, {});
+ }
+
+ function* spec() {
+ let urls = [SAME_ORIGIN, CROSS_ORIGIN_1, CROSS_ORIGIN_2];
+ for (let action of urls) {
+ for (let target of urls) {
+ yield { action: new URL(ACTION, action),
+ target: new URL(TARGET, target) };
+ }
+ }
+ }
+
+ info("Starting tests");
+ let form = document.getElementById('form');
+
+ // The body of the POST needs to be large to trigger this.
+ // 1024*1024 seems to be enough, but scaling to get a margin.
+ document.getElementById('input').value = generateBody(1024*1024);
+ for (let { target, action } of spec()) {
+ add_task(async function runTest() {
+ info(`Running test ${target} with ${action}`);
+ form.action = action;
+ let frame = await withFrame(target);
+ await new Promise(resolve => {
+ addEventListener('message', async function() {
+ info("Form loaded");
+ frame.remove();
+ resolve();
+ }, { once: true });
+
+ click();
+ });
+
+ ok(true, `Submitted to ${origin} with target ${action}`)
+ });
+ };
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1729662.html b/docshell/test/mochitest/test_bug1729662.html
new file mode 100644
index 0000000000..ec43508494
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1729662.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test back/forward after pushState</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("Need to wait to make sure an event does not fire");
+
+ async function runTest() {
+ let win = window.open();
+ let goneBackAndForwardOnce = new Promise((resolve) => {
+ let timeoutID;
+
+ // We should only get one load event in win.
+ let bc = new BroadcastChannel("bug1729662");
+ bc.addEventListener("message", () => {
+ bc.addEventListener("message", () => {
+ clearTimeout(timeoutID);
+ resolve(false);
+ });
+ }, { once: true });
+
+ let goneBack = false, goneForward = false;
+ win.addEventListener("popstate", ({ state }) => {
+ // We should only go back and forward once, if we get another
+ // popstate after that then we should fall through to the
+ // failure case below.
+ if (!(goneBack && goneForward)) {
+ // Check if this is the popstate for the forward (the one for
+ // back will have state == undefined).
+ if (state == 1) {
+ ok(goneBack, "We should have gone back before going forward");
+
+ goneForward = true;
+
+ // Wait a bit to make sure there are no more popstate events.
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ timeoutID = setTimeout(resolve, 1000, true);
+
+ return;
+ }
+
+ // Check if we've gone back once before, if we get another
+ // popstate after that then we should fall through to the
+ // failure case below.
+ if (!goneBack) {
+ goneBack = true;
+
+ return;
+ }
+ }
+
+ clearTimeout(timeoutID);
+ resolve(false);
+ });
+ });
+
+ win.location = "file_bug1729662.html";
+
+ ok(await goneBackAndForwardOnce, "Stopped navigating history");
+
+ win.close();
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1740516.html b/docshell/test/mochitest/test_bug1740516.html
new file mode 100644
index 0000000000..b54932c736
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1740516.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test pageshow event order for iframe</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function waitForPageShow(outer, inner) {
+ return new Promise((resolve) => {
+ let results = [];
+ outer.addEventListener("message", ({ data: persisted }) => {
+ results.push({ name: outer.name, persisted });
+ if (results.length == 2) {
+ resolve(results);
+ }
+ }, { once: true });
+ inner.addEventListener("message", ({ data: persisted }) => {
+ results.push({ name: inner.name, persisted });
+ if (results.length == 2) {
+ resolve(results);
+ }
+ }, { once: true });
+ });
+ }
+ async function runTest() {
+ let outerBC = new BroadcastChannel("bug1740516_1");
+ let innerBC = new BroadcastChannel("bug1740516_1_inner");
+
+ let check = waitForPageShow(outerBC, innerBC).then(([first, second]) => {
+ is(first.name, "bug1740516_1_inner", "Should get pageShow from inner iframe page first.");
+ ok(!first.persisted, "First navigation shouldn't come from BFCache.");
+ is(second.name, "bug1740516_1", "Should get pageShow from outer page second.");
+ ok(!second.persisted, "First navigation shouldn't come from BFCache.");
+ }, () => {
+ ok(false, "The promises should not be rejected.");
+ });
+ window.open("file_bug1740516_1.html", "", "noopener");
+ await check;
+
+ check = waitForPageShow(outerBC, innerBC).then(([first, second]) => {
+ is(first.name, "bug1740516_1_inner", "Should get pageShow from inner iframe page first.");
+ ok(first.persisted, "Second navigation should come from BFCache");
+ is(second.name, "bug1740516_1", "Should get pageShow from outer page second.");
+ ok(second.persisted, "Second navigation should come from BFCache");
+ }, () => {
+ ok(false, "The promises should not be rejected.");
+ });
+ outerBC.postMessage("navigate");
+ await check;
+
+ check = waitForPageShow(outerBC, innerBC).then(([first, second]) => {
+ is(first.name, "bug1740516_1_inner", "Should get pageShow from inner iframe page first.");
+ ok(!first.persisted, "Third navigation should not come from BFCache");
+ is(second.name, "bug1740516_1", "Should get pageShow from outer page second.");
+ ok(!second.persisted, "Third navigation should not come from BFCache");
+ }, () => {
+ ok(false, "The promises should not be rejected.");
+ });
+ outerBC.postMessage("block_bfcache_and_navigate");
+ await check;
+
+ outerBC.postMessage("close");
+
+ outerBC.close();
+ innerBC.close();
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1741132.html b/docshell/test/mochitest/test_bug1741132.html
new file mode 100644
index 0000000000..1ae9727d9c
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1741132.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test form restoration for no-store pages</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ // The number of entries which we keep in the BFCache (see nsSHistory.h).
+ const VIEWER_WINDOW = 3;
+
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ let bc = new BroadcastChannel("bug1741132");
+
+ // Setting the pref to 0 should evict all content viewers.
+ let load = SpecialPowers.pushPrefEnv({
+ set: [["browser.sessionhistory.max_total_viewers", 0]],
+ }).then(() => {
+ // Set the pref to VIEWER_WINDOW + 2 now, to be sure we
+ // could fit all entries.
+ SpecialPowers.pushPrefEnv({
+ set: [["browser.sessionhistory.max_total_viewers", VIEWER_WINDOW + 2]],
+ });
+ }).then(() => {
+ return new Promise(resolve => {
+ bc.addEventListener("message", resolve, { once: true });
+ window.open("file_bug1741132.html", "", "noopener");
+ });
+ });
+ // We want to try to keep one entry too many in the BFCache,
+ // so we ensure that there's at least VIEWER_WINDOW + 2
+ // entries in session history (with one for the displayed
+ // page).
+ for (let i = 0; i < VIEWER_WINDOW + 2; ++i) {
+ load = load.then(() => {
+ return new Promise((resolve) => {
+ bc.addEventListener("message", resolve, { once: true });
+ bc.postMessage({ cmd: "load", arg: `file_bug1741132.html?${i}` });
+ });
+ });
+ }
+ load.then(() => {
+ return new Promise((resolve) => {
+ bc.addEventListener("message", ({ data: persisted }) => {
+ resolve(persisted);
+ }, { once: true });
+ // Go back past the first entry that should be in the BFCache.
+ bc.postMessage({ cmd: "go", arg: -(VIEWER_WINDOW + 1) });
+ });
+ }).then((persisted) => {
+ ok(!persisted, "Only 3 pages should be kept in the BFCache");
+ }).then(() => {
+ return new Promise((resolve) => {
+ bc.addEventListener("message", ({ data: persisted }) => {
+ resolve(persisted);
+ }, { once: true });
+ // Go forward to the first entry that should be in the BFCache.
+ bc.postMessage({ cmd: "go", arg: 1 });
+ });
+ }).then((persisted) => {
+ ok(persisted, "3 pages should be kept in the BFCache");
+
+ bc.postMessage("close");
+
+ bc.close();
+
+ SimpleTest.finish();
+ });
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1742865.html b/docshell/test/mochitest/test_bug1742865.html
new file mode 100644
index 0000000000..c8f9a4eca3
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1742865.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Auto refreshing pages shouldn't add an entry to session history</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ const REFRESH_REDIRECT_TIMER = 15;
+
+ // 2 tests (same and cross origin) consisting of 2 refreshes of maximum 1 seconds
+ // 2 tests (same and cross origin) consisting of 2 refreshes of REFRESH_REDIRECT_TIMER seconds
+ // => We need (2 * 1) + (2 * 15) seconds
+ SimpleTest.requestLongerTimeout(3);
+ SimpleTest.waitForExplicitFinish();
+
+ const SJS = new URL("file_bug1742865.sjs", location.href);
+ const SJS_OUTER = new URL("file_bug1742865_outer.sjs", location.href);
+ const SCROLL = 500;
+
+ let tolerance;
+ function setup() {
+ return SpecialPowers.spawn(window.top, [], () => {
+ return SpecialPowers.getDOMWindowUtils(content.window).getResolution();
+ }).then(resolution => {
+ // Allow a half pixel difference if the top document's resolution is lower
+ // than 1.0 because the scroll position is aligned with screen pixels
+ // instead of CSS pixels.
+ tolerance = resolution < 1.0 ? 0.5 : 0.0;
+ });
+ }
+
+ function checkScrollPosition(scrollPosition, shouldKeepScrollPosition) {
+ isfuzzy(scrollPosition, shouldKeepScrollPosition ? SCROLL : 0, tolerance,
+ `Scroll position ${shouldKeepScrollPosition ? "should" : "shouldn't"} be maintained for meta refresh`);
+ }
+
+ function openWindowAndCheckRefresh(url, params, shouldAddToHistory, shouldKeepScrollPosition) {
+ info(`Running test for ${JSON.stringify(params)}`);
+
+ url = new URL(url);
+ Object.entries(params).forEach(([k, v]) => { url.searchParams.append(k, v) });
+ url.searchParams.append("scrollTo", SCROLL);
+
+ let resetURL = new URL(SJS);
+ resetURL.search = "?reset";
+ return fetch(resetURL).then(() => {
+ return new Promise((resolve) => {
+ let count = 0;
+ window.addEventListener("message", function listener({ data: { commandType, commandData = {} } }) {
+ if (commandType == "onChangedInputValue") {
+ let { historyLength, inputValue } = commandData;
+
+ if (shouldAddToHistory) {
+ is(historyLength, count, "Auto-refresh should add entries to session history");
+ } else {
+ is(historyLength, 1, "Auto-refresh shouldn't add entries to session history");
+ }
+
+ is(inputValue, "1234", "Input's value should have been changed");
+
+ win.postMessage("loadNext", "*");
+ return;
+ }
+
+ is(commandType, "pageShow", "Unknown command type");
+
+ let { inputValue, scrollPosition } = commandData;
+
+ switch (++count) {
+ // file_bug1742865.sjs causes 3 loads:
+ // * first load, returns first meta refresh
+ // * second load, caused by first meta refresh, returns second meta refresh
+ // * third load, caused by second meta refresh, doesn't return a meta refresh
+ case 2:
+ checkScrollPosition(scrollPosition, shouldKeepScrollPosition);
+ break;
+ case 3:
+ checkScrollPosition(scrollPosition, shouldKeepScrollPosition);
+ win.postMessage("changeInputValue", "*");
+ break;
+ case 4:
+ win.postMessage("back", "*");
+ break;
+ case 5:
+ is(inputValue, "1234", "Entries for auto-refresh should be attached to session history");
+ checkScrollPosition(scrollPosition, shouldKeepScrollPosition);
+ removeEventListener("message", listener);
+ win.close();
+ resolve();
+ break;
+ }
+ });
+ let win = window.open(url);
+ });
+ });
+ }
+
+ function doTest(seconds, crossOrigin, shouldAddToHistory, shouldKeepScrollPosition) {
+ let params = {
+ seconds,
+ crossOrigin,
+ };
+
+ return openWindowAndCheckRefresh(SJS, params, shouldAddToHistory, shouldKeepScrollPosition).then(() =>
+ openWindowAndCheckRefresh(SJS_OUTER, params, shouldAddToHistory, shouldKeepScrollPosition)
+ );
+ }
+
+ async function runTest() {
+ const FAST = Math.min(1, REFRESH_REDIRECT_TIMER);
+ const SLOW = REFRESH_REDIRECT_TIMER + 1;
+ let tests = [
+ // [ time, crossOrigin, shouldAddToHistory, shouldKeepScrollPosition ]
+ [ FAST, false, false, true ],
+ [ FAST, true, false, false ],
+ [ SLOW, false, false, true ],
+ [ SLOW, true, true, false ],
+ ];
+
+ await setup();
+
+ for (let [ time, crossOrigin, shouldAddToHistory, shouldKeepScrollPosition ] of tests) {
+ await doTest(time, crossOrigin, shouldAddToHistory, shouldKeepScrollPosition);
+ }
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1743353.html b/docshell/test/mochitest/test_bug1743353.html
new file mode 100644
index 0000000000..a5d88df3f6
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1743353.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test back/forward after pushState</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ let bc = new BroadcastChannel("bug1743353");
+ new Promise((resolve) => {
+ bc.addEventListener("message", () => {
+ resolve();
+ }, { once: true });
+
+ window.open("file_bug1743353.html", "", "noopener");
+ }).then(() => {
+ return new Promise(resolve => {
+ bc.addEventListener("message", () => {
+ resolve();
+ }, { once: true });
+
+ bc.postMessage("load");
+ })
+ }).then(() => {
+ return new Promise(resolve => {
+ let results = [];
+ bc.addEventListener("message", function listener({ data }) {
+ results.push(data);
+ if (results.length == 3) {
+ bc.removeEventListener("message", listener);
+ resolve(results);
+ }
+ });
+
+ bc.postMessage("back");
+ });
+ }).then((results) => {
+ is(results[0], "pagehide", "First event should be 'pagehide'.");
+ is(results[1], "unload", "Second event should be 'unload'.");
+ is(results[2], "pageshow", "Third event should be 'pageshow'.");
+
+ bc.postMessage("close");
+
+ SimpleTest.finish();
+ });
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1747033.html b/docshell/test/mochitest/test_bug1747033.html
new file mode 100644
index 0000000000..539b78fec0
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1747033.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test history after loading multipart</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ let bc = new BroadcastChannel("bug1747033");
+ new Promise(resolve => {
+ bc.addEventListener("message", ({ data: { historyLength } }) => {
+ is(historyLength, 1, "Correct length for first normal load.");
+
+ resolve();
+ }, { once: true });
+
+ window.open("file_bug1747033.sjs", "", "noopener");
+ }).then(() => {
+ return new Promise(resolve => {
+ let loaded = 0;
+ bc.addEventListener("message", function listener({ data: { historyLength } }) {
+ ++loaded;
+
+ is(historyLength, 2, `Correct length for multipart load ${loaded}.`);
+
+ // We want 3 parts in total.
+ if (loaded < 3) {
+ if (loaded == 2) {
+ // We've had 2 parts, make the server send the last part.
+ fetch("file_bug1747033.sjs?sendLastPart");
+ } else {
+ fetch("file_bug1747033.sjs?sendNextPart");
+ }
+ return;
+ }
+
+ bc.removeEventListener("message", listener);
+ resolve();
+ });
+
+ bc.postMessage({ cmd: "load", arg: "file_bug1747033.sjs?multipart" });
+ });
+ }).then(() => {
+ return new Promise(resolve => {
+ bc.addEventListener("message", ({ data: { historyLength } }) => {
+ is(historyLength, 2, "Correct length after calling replaceState in multipart.");
+
+ resolve();
+ }, { once: true });
+
+ bc.postMessage({ cmd: "replaceState", arg: "file_bug1747033.sjs?replaced" });
+ });
+ }).then(() => {
+ return new Promise(resolve => {
+ bc.addEventListener("message", ({ data: { historyLength } }) => {
+ is(historyLength, 3, "Correct length for first normal load after multipart.");
+
+ resolve();
+ }, { once: true });
+
+ bc.postMessage({ cmd: "load", arg: "file_bug1747033.sjs" });
+ });
+ }).then(() => {
+ return new Promise(resolve => {
+ let goneBack = 0;
+ bc.addEventListener("message", function listener({ data: { historyLength } }) {
+ ++goneBack;
+
+ is(historyLength, 3, "Correct length after going back.");
+
+ if (goneBack == 1) {
+ bc.postMessage({ cmd: "back" });
+ } else if (goneBack == 2) {
+ bc.removeEventListener("message", listener);
+ resolve();
+ }
+ });
+
+ bc.postMessage({ cmd: "back" });
+ });
+ }).then(() => {
+ bc.postMessage({ cmd: "close" });
+
+ SimpleTest.finish();
+ });
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug1773192.html b/docshell/test/mochitest/test_bug1773192.html
new file mode 100644
index 0000000000..d4c42dc1a7
--- /dev/null
+++ b/docshell/test/mochitest/test_bug1773192.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test referrer with going back</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ SimpleTest.waitForExplicitFinish();
+
+ // file_bug1773192_1.html will send a message with some data on pageshow.
+ function waitForData(bc) {
+ return new Promise(resolve => {
+ bc.addEventListener(
+ "message",
+ ({ data }) => {
+ resolve(data);
+ },
+ { once: true }
+ );
+ });
+ }
+ async function runTest() {
+ let bc = new BroadcastChannel("bug1743353");
+
+ let getData = waitForData(bc);
+
+ window.open("file_bug1773192_1.html", "", "noreferrer");
+
+ await getData.then(({ referrer }) => {
+ is(referrer, "", "Referrer should be empty at first.");
+ });
+
+ getData = waitForData(bc);
+
+ // When file_bug1773192_1.html receives this message it will navigate to
+ // file_bug1773192_2.html. file_bug1773192_2.html removes itself from
+ // history with replaceState and submits a form with the POST method to
+ // file_bug1773192_3.sjs. file_bug1773192_3.sjs goes back in history.
+ // We should end up back at file_bug1773192_1.html, which will send a
+ // message with some data on pageshow.
+ bc.postMessage("next");
+
+ await getData.then(({ location, referrer }) => {
+ let firstURL = new URL("file_bug1773192_1.html", location).toString();
+ is(location, firstURL, "Location should be the first page again.");
+ is(referrer, firstURL, "Referrer should also be the first page.");
+ });
+
+ bc.postMessage("close");
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body onload="runTest();">
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug385434.html b/docshell/test/mochitest/test_bug385434.html
new file mode 100644
index 0000000000..bc82de9daf
--- /dev/null
+++ b/docshell/test/mochitest/test_bug385434.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=385434
+-->
+<head>
+ <title>Test for Bug 385434</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=385434">Mozilla Bug 385434</a>
+<p id="display"></p>
+<div id="content">
+ <iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
+ <div id="status" style="display: none"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 385434 */
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+SimpleTest.expectAssertions(0, 1); // bug 1333702
+
+var gNumHashchanges = 0;
+var gCallbackOnIframeLoad = false;
+var gSampleEvent;
+
+function statusMsg(msg) {
+ var msgElem = document.createElement("p");
+ msgElem.appendChild(document.createTextNode(msg));
+
+ document.getElementById("status").appendChild(msgElem);
+}
+
+function longWait() {
+ setTimeout(function() { gGen.next(); }, 1000);
+}
+
+// onIframeHashchange, onIframeLoad, and onIframeScroll are all called by the
+// content we load into our iframe in order to notify the parent frame of an
+// event which was fired.
+function onIframeHashchange() {
+ gNumHashchanges++;
+ gGen.next();
+}
+
+function onIframeLoad() {
+ if (gCallbackOnIframeLoad) {
+ gCallbackOnIframeLoad = false;
+ gGen.next();
+ }
+}
+
+function onIframeScroll() {
+ is(gNumHashchanges, 0, "onscroll should fire before onhashchange.");
+}
+
+function enableIframeLoadCallback() {
+ gCallbackOnIframeLoad = true;
+}
+
+function noEventExpected(msg) {
+ is(gNumHashchanges, 0, msg);
+
+ // Even if there's an error, set gNumHashchanges to 0 so other tests don't
+ // fail.
+ gNumHashchanges = 0;
+}
+
+function eventExpected(msg) {
+ is(gNumHashchanges, 1, msg);
+
+ // Eat up this event, whether the test above was true or not
+ gNumHashchanges = 0;
+}
+
+/*
+ * The hashchange event is dispatched asynchronously, so if we want to observe
+ * it, we have to yield within run_test(), transferring control back to the
+ * event loop.
+ *
+ * When we're expecting our iframe to observe a hashchange event after we poke
+ * it, we just yield and wait for onIframeHashchange() to call gGen.next() and
+ * wake us up.
+ *
+ * When we're testing to ensure that the iframe doesn't dispatch a hashchange
+ * event, we try to hook onto the iframe's load event. We call
+ * enableIframeLoadCallback(), which causes onIframeLoad() to call gGen.next()
+ * upon the next observed load. After we get our callback, we check that a
+ * hashchange didn't occur.
+ *
+ * We can't always just wait for page load in order to observe that a
+ * hashchange didn't happen. In these cases, we call longWait() and yield
+ * until either a hashchange occurs or longWait's callback is scheduled. This
+ * is something of a hack; it's entirely possible that longWait won't wait long
+ * enough, and we won't observe what should have been a failure of the test.
+ * But it shouldn't happen that good code will randomly *fail* this test.
+ */
+function* run_test() {
+ /*
+ * TEST 1 tests that:
+ * <body onhashchange = ... > works,
+ * the event is (not) fired at the correct times
+ */
+ var frame = document.getElementById("frame");
+ var frameCw = frame.contentWindow;
+
+ enableIframeLoadCallback();
+ frameCw.document.location = "file_bug385434_1.html";
+ // Wait for the iframe to load and for our callback to fire
+ yield undefined;
+
+ noEventExpected("No hashchange expected initially.");
+
+ sendMouseEvent({type: "click"}, "link1", frameCw);
+ yield undefined;
+ eventExpected("Clicking link1 should trigger a hashchange.");
+
+ sendMouseEvent({type: "click"}, "link1", frameCw);
+ longWait();
+ yield undefined;
+ // succeed if a hashchange event wasn't triggered while we were waiting
+ noEventExpected("Clicking link1 again should not trigger a hashchange.");
+
+ sendMouseEvent({type: "click"}, "link2", frameCw);
+ yield undefined;
+ eventExpected("Clicking link2 should trigger a hashchange.");
+
+ frameCw.history.go(-1);
+ yield undefined;
+ eventExpected("Going back should trigger a hashchange.");
+
+ frameCw.history.go(1);
+ yield undefined;
+ eventExpected("Going forward should trigger a hashchange.");
+
+ // window.location has a trailing '#' right now, so we append "link1", not
+ // "#link1".
+ frameCw.window.location = frameCw.window.location + "link1";
+ yield undefined;
+ eventExpected("Assigning to window.location should trigger a hashchange.");
+
+ // Set up history in the iframe which looks like:
+ // file_bug385434_1.html#link1
+ // file_bug385434_2.html
+ // file_bug385434_1.html#foo <-- current page
+ enableIframeLoadCallback();
+ frameCw.window.location = "file_bug385434_2.html";
+ yield undefined;
+
+ enableIframeLoadCallback();
+ frameCw.window.location = "file_bug385434_1.html#foo";
+ yield undefined;
+
+ // Now when we do history.go(-2) on the frame, it *shouldn't* fire a
+ // hashchange. Although the URIs differ only by their hashes, they belong to
+ // two different Documents.
+ frameCw.history.go(-2);
+ longWait();
+ yield undefined;
+ noEventExpected("Moving between different Documents shouldn't " +
+ "trigger a hashchange.");
+
+ /*
+ * TEST 2 tests that:
+ * <frameset onhashchange = ... > works,
+ * the event is targeted at the window object
+ * the event's cancelable, bubbles settings are correct
+ */
+
+ enableIframeLoadCallback();
+ frameCw.document.location = "file_bug385434_2.html";
+ yield undefined;
+
+ frameCw.document.location = "file_bug385434_2.html#foo";
+ yield undefined;
+
+ eventExpected("frame onhashchange should fire events.");
+ // iframe should set gSampleEvent
+ is(gSampleEvent.target, frameCw,
+ "The hashchange event should be targeted to the window.");
+ is(gSampleEvent.type, "hashchange",
+ "Event type should be 'hashchange'.");
+ is(gSampleEvent.cancelable, false,
+ "The hashchange event shouldn't be cancelable.");
+ is(gSampleEvent.bubbles, false,
+ "The hashchange event should not bubble.");
+
+ /*
+ * TEST 3 tests that:
+ * hashchange is dispatched if the current document readyState is
+ * not "complete" (bug 504837).
+ */
+ frameCw.document.location = "file_bug385434_3.html";
+ yield undefined;
+ eventExpected("Hashchange should fire even if the document " +
+ "hasn't finished loading.");
+
+ SimpleTest.finish();
+}
+
+var gGen = run_test();
+gGen.next();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug387979.html b/docshell/test/mochitest/test_bug387979.html
new file mode 100644
index 0000000000..0aca2ee89b
--- /dev/null
+++ b/docshell/test/mochitest/test_bug387979.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=387979
+-->
+<head>
+ <title>Test for Bug 387979</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=387979">Mozilla Bug 387979</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 387979 */
+function a(s) {
+ var r;
+ try { r = frames[0].document.body; } catch (e) { r = e; }
+ is(r instanceof frames[0].HTMLBodyElement, true, "Can't get body" + s);
+}
+var p = 0;
+function b() {
+ switch (++p) {
+ case 1:
+ frames[0].location = "about:blank";
+ break;
+ case 2:
+ a("before reload");
+ frames[0].location.reload();
+ break;
+ case 3:
+ a("after reload");
+ SimpleTest.finish();
+ break;
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<p id="display">
+ <iframe onload="b()"></iframe>
+ <pre id="p">-</pre>
+</p>
+</body>
+</html>
+
diff --git a/docshell/test/mochitest/test_bug402210.html b/docshell/test/mochitest/test_bug402210.html
new file mode 100644
index 0000000000..326f98cf9f
--- /dev/null
+++ b/docshell/test/mochitest/test_bug402210.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+While working on bug 402210, it came up that the code was doing
+
+a.href = proto + host
+
+which technically produces "https:host" instead of "https://host" and
+that the code was relying on href's setting having fixup behaviour
+for this kind of thing.
+
+If we rely on it, we might as well test for it, even if it isn't the
+problem 402210 was meant to fix.
+
+https://bugzilla.mozilla.org/show_bug.cgi?id=402210
+-->
+<head>
+ <title>Test for Bug 402210</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=402210">Mozilla Bug 402210</a>
+<p id="display">
+ <a id="testlink">Test Link</a>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+ $("testlink").href = "https:example.com";
+ is($("testlink").href, "https://example.com/", "Setting href on an anchor tag should fixup missing slashes after https protocol");
+
+ $("testlink").href = "ftp:example.com";
+ is($("testlink").href, "ftp://example.com/", "Setting href on an anchor tag should fixup missing slashes after non-http protocol");
+
+ SimpleTest.finish();
+}
+
+addLoadEvent(runTest);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/mochitest/test_bug404548.html b/docshell/test/mochitest/test_bug404548.html
new file mode 100644
index 0000000000..a8a773dce5
--- /dev/null
+++ b/docshell/test/mochitest/test_bug404548.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=404548
+-->
+<head>
+ <title>Test for Bug 404548</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=404548">Mozilla Bug 404548</a>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 404548 */
+var firstRemoved = false;
+var secondHidden = false;
+
+SimpleTest.waitForExplicitFinish();
+
+var w = window.open("bug404548-subframe.html", "", "width=10,height=10");
+
+function finishTest() {
+ is(firstRemoved, true, "Should have removed iframe from the DOM");
+ is(secondHidden, true, "Should have fired pagehide on second kid");
+ w.close();
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/mochitest/test_bug413310.html b/docshell/test/mochitest/test_bug413310.html
new file mode 100644
index 0000000000..4299605575
--- /dev/null
+++ b/docshell/test/mochitest/test_bug413310.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=413310
+-->
+<head>
+ <title>Test for Bug 413310</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=413310">Mozilla Bug 413310</a>
+<p id="display">
+<script class="testbody" type="text/javascript">
+
+if (navigator.platform.startsWith("Mac")) {
+ SimpleTest.expectAssertions(0, 2);
+} else {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 413310 */
+
+// NOTE: If we ever make subframes do bfcache stuff, this test will need to be
+// modified accordingly! It assumes that subframes do NOT get bfcached.
+var onloadCount = 0;
+
+var step = -1; // One increment will come from the initial subframe onload.
+ // Note that this script should come before the subframe,
+ // so that doNextStep is defined when its onload handler fires.
+
+var textContent;
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(doNextStep);
+
+function doNextStep() {
+ ++step;
+ switch (step) {
+ case 1:
+ is(onloadCount, 1, "Loaded initial page");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-subframe.html"),
+ "Unexpected subframe location after initial load");
+ $("i").contentDocument.forms[0].submit();
+ break;
+ case 2:
+ is(onloadCount, 2, "Loaded POST result");
+
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs"),
+ "Unexpected subframe location after POST load");
+
+ textContent = $("i").contentDocument.body.textContent;
+ isDeeply(textContent.match(/^POST /), ["POST "], "Not a POST?");
+
+ $("i").contentWindow.location.hash = "foo";
+ setTimeout(doNextStep, 0);
+ break;
+ case 3:
+ is(onloadCount, 2, "Anchor scroll should not fire onload");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs#foo"),
+ "Unexpected subframe location after anchor scroll");
+ is(textContent, $("i").contentDocument.body.textContent,
+ "Did a load when scrolling?");
+ $("i").contentWindow.location.href = "bug413310-subframe.html";
+ break;
+ case 4:
+ is(onloadCount, 3, "Done new load");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-subframe.html"),
+ "Unexpected subframe location after new load");
+ history.back();
+ break;
+ case 5:
+ is(onloadCount, 4,
+ "History traversal didn't fire onload: bfcache issues!");
+ is($("i").contentWindow.location.href,
+ location.href.replace(/test_bug413310.html/,
+ "bug413310-post.sjs#foo"),
+ "Unexpected subframe location");
+ is(textContent, $("i").contentDocument.body.textContent,
+ "Did a load when going back?");
+ SimpleTest.finish();
+ break;
+ }
+}
+</script>
+<!-- Use a timeout in onload so that we don't do a load immediately inside onload -->
+<iframe id="i" src="bug413310-subframe.html" onload="setTimeout(doNextStep, 20)">
+</iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/mochitest/test_bug475636.html b/docshell/test/mochitest/test_bug475636.html
new file mode 100644
index 0000000000..fb1827ad04
--- /dev/null
+++ b/docshell/test/mochitest/test_bug475636.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=475636
+Test that refresh to data: URIs don't inherit the principal
+-->
+<head>
+ <title>Test for Bug 475636</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="gen.next()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=475636">Mozilla Bug 475636</a>
+
+<div id="content" style="display: none">
+
+</div>
+<iframe id=loader></iframe>
+<pre id="test">
+<script class="testbody" type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var gen = runTests();
+
+window.private = 42;
+
+window.addEventListener("message", function(e) {
+ gen.next(e.data);
+});
+
+var url = "file_bug475636.sjs?";
+
+function* runTests() {
+ var loader = document.getElementById("loader");
+ for (var testNum = 1; ; ++testNum) {
+ loader.src = url + testNum;
+ let res = (yield);
+ if (res == "done") {
+ SimpleTest.finish();
+ return;
+ }
+ is(res, "pass");
+ }
+}
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug509055.html b/docshell/test/mochitest/test_bug509055.html
new file mode 100644
index 0000000000..57ede19b43
--- /dev/null
+++ b/docshell/test/mochitest/test_bug509055.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=509055
+-->
+<head>
+ <title>Test for Bug 509055</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=509055">Mozilla Bug 509055</a>
+<p id="display"></p>
+<div id="status"></div>
+<div id="content">
+</div>
+<pre id="test">
+ <script type="application/javascript">
+
+ /** Test for Bug 509055 */
+
+ SimpleTest.waitForExplicitFinish();
+
+ var gGen;
+
+ function shortWait() {
+ setTimeout(function() { gGen.next(); }, 0, false);
+ }
+
+ function onChildHashchange(e) {
+ // gGen might be undefined when we refresh the page, so we have to check here
+ dump("onChildHashchange() called.\n");
+ if (gGen)
+ gGen.next();
+ }
+
+ function onChildLoad(e) {
+ if (gGen)
+ gGen.next();
+ }
+
+ async function* runTest() {
+ var popup = window.open("file_bug509055.html", "popup 0",
+ "height=200,width=200,location=yes," +
+ "menubar=yes,status=yes,toolbar=yes,dependent=yes");
+ popup.hashchangeCallback = onChildHashchange;
+ popup.onload = onChildLoad;
+ dump("Waiting for initial load.\n");
+ yield undefined;
+
+ // Without this wait, the change to location.hash below doesn't create a
+ // SHEntry or enable the back button.
+ shortWait();
+ dump("Got initial load. Spinning event loop.\n");
+ yield undefined;
+
+ popup.location.hash = "#1";
+ dump("Waiting for hashchange.\n");
+ yield undefined;
+
+ popup.history.back();
+ dump("Waiting for second hashchange.\n");
+ yield undefined; // wait for hashchange
+
+ popup.document.title = "Changed";
+
+ // Wait for listeners to be notified of the title change.
+ shortWait();
+ dump("Got second hashchange. Spinning event loop.\n");
+ yield undefined;
+
+ let sheTitle = "";
+ if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ var sh = SpecialPowers.wrap(popup)
+ .docShell
+ .QueryInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ // Get the title of the inner popup's current SHEntry
+ sheTitle = sh.legacySHistory.getEntryAtIndex(sh.index).title;
+ } else {
+ let chromeScript = SpecialPowers.loadChromeScript(() => {
+ /* eslint-env mozilla/chrome-script */
+ addMessageListener("getTitle", browsingContext => {
+ // eslint-disable-next-line no-shadow
+ let sh = browsingContext.sessionHistory;
+ let title = sh.getEntryAtIndex(sh.index).title;
+ sendAsyncMessage("title", title);
+ });
+ });
+
+ let p = chromeScript.promiseOneMessage("title");
+ let browsingContext = SpecialPowers.wrap(popup)
+ .docShell.browsingContext;
+ chromeScript.sendAsyncMessage("getTitle", browsingContext);
+ sheTitle = await p;
+ chromeScript.destroy();
+ }
+ is(sheTitle, "Changed", "SHEntry's title should change when we change.");
+
+ popup.close();
+
+ SimpleTest.executeSoon(SimpleTest.finish);
+ }
+
+ window.addEventListener("load", function() {
+ gGen = runTest();
+ gGen.next();
+ });
+
+ </script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug511449.html b/docshell/test/mochitest/test_bug511449.html
new file mode 100644
index 0000000000..da95909d1c
--- /dev/null
+++ b/docshell/test/mochitest/test_bug511449.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=511449
+-->
+<head>
+ <title>Test for Bug 511449</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <script src="/tests/SimpleTest/NativeKeyCodes.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=511449">Mozilla Bug 511449</a>
+<p id="display"></p>
+<div id="status"></div>
+<div id="content">
+</div>
+<input type="text" id="input">
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 511449 */
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+window.addEventListener("load", runTest);
+
+var win = null;
+
+function runTest() {
+ document.getElementById("input").focus();
+ win = window.open("file_bug511449.html", "");
+ SimpleTest.waitForFocus(runNextTest, win);
+}
+
+function runNextTest() {
+ var didClose = false;
+ win.onunload = function() {
+ didClose = true;
+ };
+ synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US, MAC_VK_ANSI_W, {metaKey: 1}, "w", "w");
+
+ setTimeout(function() {
+ ok(didClose, "Cmd+W should have closed the tab");
+ if (!didClose) {
+ win.close();
+ }
+ SimpleTest.finish();
+ }, 1000);
+}
+
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug529119-1.html b/docshell/test/mochitest/test_bug529119-1.html
new file mode 100644
index 0000000000..1c89780fc7
--- /dev/null
+++ b/docshell/test/mochitest/test_bug529119-1.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var workingURL = "http://mochi.test:8888/tests/docshell/test/mochitest/bug529119-window.html";
+var faultyURL = "https://www.some-nonexistent-domain-27489274c892748217cn2384.test/";
+
+var w = null;
+var phase = 0;
+var gotWrongPageOnTryAgainClick = false;
+// Token that represents which page we currently have loaded.
+var token = 0;
+
+function delay(msec) {
+ return new Promise(resolve => setTimeout(resolve, msec));
+}
+
+async function assignToken(tokenToAssign) {
+ await SpecialPowers.spawn(w, [tokenToAssign],
+ newToken => { this.content.token = newToken });
+}
+
+async function pollForPage(win) {
+ while (true) {
+ try {
+ // When we do our navigation, there may be an interstitial about:blank
+ // page if the navigation involves a process switch. That about:blank
+ // will exist between the new process's docshell being created and the
+ // actual page that's being loaded loading (which can happen async from
+ // the docshell creation). We want to avoid treating the initial
+ // about:blank as a new page.
+ //
+ // We could conceivably expose Document::IsInitialDocument() as a
+ // ChromeOnly thing and use it here, but let's just filter out all
+ // about:blank, since we don't expect any in this test.
+ var haveNewPage = await SpecialPowers.spawn(w, [token],
+ currentToken => this.content.token != currentToken &&
+ this.content.location.href != "about:blank");
+
+ if (haveNewPage) {
+ ++token;
+ assignToken(token);
+ break;
+ }
+ } catch (e) {
+ // Something went wrong; just keep waiting.
+ }
+
+ await delay(100);
+ }
+}
+
+async function windowLoaded() {
+ switch (phase) {
+ case 0:
+ assignToken(token);
+
+ /* 2. We have succeededfully loaded a page, now go to a faulty URL */
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ phase = 1;
+
+ await pollForPage(w);
+ is(await SpecialPowers.spawn(w, [], () => this.content.location.href),
+ faultyURL,
+ "Is on an error page initially");
+
+ /* 3. now, while we are on the error page, try to reload it, actually
+ click the "Try Again" button */
+ SpecialPowers.spawn(w, [], () => this.content.location.reload());
+
+ await pollForPage(w);
+
+ /* 4-finish, check we are still on the error page */
+ is(await SpecialPowers.spawn(w, [], () => this.content.location.href),
+ faultyURL,
+ "Is on an error page");
+ is(gotWrongPageOnTryAgainClick, false,
+ "Must not get www.example.com page on reload of an error page");
+ w.close();
+ SimpleTest.finish();
+ break;
+
+ case 1:
+ /* 4-check, we must not get here! */
+ gotWrongPageOnTryAgainClick = true;
+ break;
+ }
+}
+
+function startTest() {
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug529119-2.html b/docshell/test/mochitest/test_bug529119-2.html
new file mode 100644
index 0000000000..a8bd57d4f7
--- /dev/null
+++ b/docshell/test/mochitest/test_bug529119-2.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test bug 529119</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var workingURL = "http://mochi.test:8888/tests/docshell/test/mochitest/bug529119-window.html";
+// eslint-disable-next-line @microsoft/sdl/no-insecure-url
+var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.test/";
+
+var w = null;
+var phase = 0;
+var isWindowLoaded = false;
+// Token that represents which page we currently have loaded.
+var token = 0;
+
+function delay(msec) {
+ return new Promise(resolve => setTimeout(resolve, msec));
+}
+
+async function assignToken(tokenToAssign) {
+ await SpecialPowers.spawn(w, [tokenToAssign],
+ newToken => { this.content.token = newToken });
+}
+
+// Returns when a new page is loaded and returns whether that page is an
+// error page.
+async function pollForPage(win) {
+ while (true) {
+ try {
+ // When we do our navigation, there may be an interstitial about:blank
+ // page if the navigation involves a process switch. That about:blank
+ // will exist between the new process's docshell being created and the
+ // actual page that's being loaded loading (which can happen async from
+ // the docshell creation). We want to avoid treating the initial
+ // about:blank as a new page.
+ //
+ // We could conceivably expose Document::IsInitialDocument() as a
+ // ChromeOnly thing and use it here, but let's just filter out all
+ // about:blank, since we don't expect any in this test.
+ var haveNewPage = await SpecialPowers.spawn(w, [token],
+ currentToken => this.content.token != currentToken &&
+ this.content.location.href != "about:blank");
+
+ if (haveNewPage) {
+ ++token;
+ assignToken(token);
+
+ // In this test, error pages are non-same-origin with us, and non-error
+ // pages are same-origin.
+ let haveErrorPage = false;
+ try {
+ win.document.title;
+ } catch (ex) {
+ haveErrorPage = true;
+ }
+ return haveErrorPage;
+ }
+ } catch (e) {
+ // Something went wrong; just keep waiting.
+ }
+
+ await delay(100);
+ }
+}
+
+async function windowLoaded() {
+ // The code under here should only be run once
+ // The test popup window workingURL was already opened
+ if (isWindowLoaded)
+ return;
+ isWindowLoaded = true;
+
+ assignToken(token);
+
+ /* 2. We have successfully loaded a page, now go to a faulty URL */
+ // XXX The test fails when we change the location synchronously
+ window.setTimeout(function() {
+ w.location.href = faultyURL;
+ }, 0);
+
+ ok(await pollForPage(w), "Waiting for error page succeeded");
+ /* 3. now, while we are on the error page, navigate back */
+ try {
+ // We need the SpecialPowers bit, because this is a cross-origin window
+ // and we normally can't touch .history on those.
+ await SpecialPowers.spawn(w, [], () => this.content.history.back());
+ } catch (ex) {
+ ok(false, "w.history.back() threw " + ex);
+ }
+
+ ok(!await pollForPage(w), "Waiting for original page succeeded");
+ /* 4-finish, check we are back at the original page */
+ is(await SpecialPowers.spawn(w, [], () => this.content.location.href),
+ workingURL,
+ "Is on the previous page");
+ w.close();
+ SimpleTest.finish();
+}
+
+function startTest() {
+ /* 1. load a URL that leads to an error page */
+ w = window.open(workingURL);
+}
+
+</script>
+</head>
+<body onload="startTest();">
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug530396.html b/docshell/test/mochitest/test_bug530396.html
new file mode 100644
index 0000000000..fa3ddc6db6
--- /dev/null
+++ b/docshell/test/mochitest/test_bug530396.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=530396
+-->
+<head>
+ <title>Test for Bug 530396</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=530396">Mozilla Bug 530396</a>
+
+<p>
+
+<iframe id="testFrame" src="http://mochi.test:8888/tests/docshell/test/mochitest/bug530396-subframe.html"></iframe>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+// NOTE: If we ever make subframes do bfcache stuff, this test will need to be
+// modified accordingly! It assumes that subframes do NOT get bfcached.
+var onloadCount = 0;
+
+var step = 0;
+
+var gTestFrame = document.getElementById("testFrame");
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+addLoadEvent(doNextStep);
+
+function doNextStep() {
+ ++step;
+ switch (step) {
+ case 1:
+ is(onloadCount, 1, "Loaded initial page");
+ sendMouseEvent({type: "click"}, "target2", gTestFrame.contentWindow);
+ window.setTimeout(doNextStep, 1000);
+ break;
+
+ case 2:
+ is(onloadCount, 1, "opener must be null");
+ sendMouseEvent({type: "click"}, "target1", gTestFrame.contentWindow);
+ break;
+
+ case 3:
+ is(onloadCount, 2, "don't send referrer with rel=referrer");
+ SimpleTest.finish();
+ break;
+ }
+}
+</script>
+</pre>
+</html>
diff --git a/docshell/test/mochitest/test_bug540462.html b/docshell/test/mochitest/test_bug540462.html
new file mode 100644
index 0000000000..e0a0861aaf
--- /dev/null
+++ b/docshell/test/mochitest/test_bug540462.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=540462
+-->
+<head>
+ <title>Test for Bug 540462</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=540462">Mozilla Bug 540462</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 540462 */
+
+var win;
+function runTest() {
+ win = window.open("file_bug540462.html", "", "width=100,height=100");
+}
+
+var dwlCount = 0;
+var originalURL;
+function documentWriteLoad() {
+ if (++dwlCount == 1) {
+ originalURL = win.document.body.firstChild.href;
+ } else if (dwlCount == 2) {
+ is(win.document.body.firstChild.href, originalURL, "Wrong href!");
+ win.close();
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug551225.html b/docshell/test/mochitest/test_bug551225.html
new file mode 100644
index 0000000000..b2862fcad8
--- /dev/null
+++ b/docshell/test/mochitest/test_bug551225.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=551225
+-->
+<head>
+ <title>Test for Bug 551225</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551225">Mozilla Bug 551225</a>
+
+<script type="application/javascript">
+
+/** Test for Bug 551225 */
+
+var obj = {
+ a: new Date("1/1/2000"),
+ b: /^foo$/,
+ c: "bar",
+};
+
+history.replaceState(obj, "", "");
+is(history.state.a.toString(), new Date("1/1/2000").toString(), "Date object.");
+is(history.state.b.toString(), "/^foo$/", "Regex");
+is(history.state.c, "bar", "Other state");
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug570341.html b/docshell/test/mochitest/test_bug570341.html
new file mode 100644
index 0000000000..363f985407
--- /dev/null
+++ b/docshell/test/mochitest/test_bug570341.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=570341
+-->
+<head>
+ <title>Test for Bug 570341</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<script>
+ var start = Date.now();
+ var moments = {};
+
+ var unload = 0;
+ var wasEnabled = true;
+
+ function collectMoments() {
+ var win = frames[0];
+ var timing = (win.performance && win.performance.timing) || {};
+ for (let p in timing) {
+ moments[p] = timing[p];
+ }
+ for (let p in win) {
+ if (p.substring(0, 9) == "_testing_") {
+ moments[p.substring(9)] = win[p];
+ }
+ }
+ moments.evt_unload = unload;
+ return moments;
+ }
+
+ function showSequence(node) {
+ while (node.firstChild) {
+ node.firstChild.remove();
+ }
+ var sequence = [];
+ for (var p in moments) {
+ sequence.push(p);
+ }
+ sequence.sort(function(a, b) {
+ return moments[a] - moments[b];
+ });
+ var table = document.createElement("table");
+ node.appendChild(table);
+ var row = document.createElement("tr");
+ table.appendChild(row);
+ var cell = document.createElement("td");
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode("start"));
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(start));
+ for (var i = 0; i < sequence.length; ++i) {
+ var prop = sequence[i];
+ row = document.createElement("tr");
+ table.appendChild(row);
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(prop));
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ cell.appendChild(document.createTextNode(moments[prop]));
+ }
+ }
+
+ function checkValues() {
+ var win = frames[0];
+ ok(win.performance,
+ "window.performance is missing or not accessible for frame");
+ ok(!win.performance || win.performance.timing,
+ "window.performance.timing is missing or not accessible for frame");
+ collectMoments();
+
+ var sequences = [
+ ["navigationStart", "unloadEventStart", "unloadEventEnd"],
+ ["navigationStart", "fetchStart", "domainLookupStart", "domainLookupEnd",
+ "connectStart", "connectEnd", "requestStart", "responseStart", "responseEnd"],
+ ["responseStart", "domLoading", "domInteractive", "domComplete"],
+ ["domContentLoadedEventStart", "domContentLoadedEventEnd",
+ "loadEventStart", "loadEventEnd"],
+ ];
+
+ for (var i = 0; i < sequences.length; ++i) {
+ var seq = sequences[i];
+ for (var j = 0; j < seq.length; ++j) {
+ var prop = seq[j];
+ if (j > 0) {
+ var prevProp = seq[j - 1];
+ ok(moments[prevProp] <= moments[prop],
+ ["Expected ", prevProp, " to happen before ", prop,
+ ", got ", prevProp, " = ", moments[prevProp],
+ ", ", prop, " = ", moments[prop]].join(""));
+ }
+ }
+ }
+
+ SimpleTest.finish();
+ }
+
+window.onload = function() {
+ var win = frames[0];
+ win.addEventListener("unload", function() {
+ unload = Date.now();
+ }, true);
+ var seenLoad = 0;
+ win.addEventListener("load", function() {
+ seenLoad = Date.now();
+ }, true);
+ frames[0].location = "bug570341_recordevents.html";
+ var interval = setInterval(function() {
+ // time constants here are arbitrary, chosen to allow the test to pass
+ var stopPolling = (win.performance && win.performance.loadEventEnd) ||
+ (seenLoad && Date.now() >= seenLoad + 3000) ||
+ Date.now() >= start + 30000;
+ if (stopPolling) {
+ clearInterval(interval);
+ checkValues();
+ } else if (win._testing_evt_load) {
+ seenLoad = Date.now();
+ }
+ }, 100);
+};
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570341">Mozilla Bug 570341</a>
+<div id="frames">
+<iframe name="child0" src="navigation/blank.html"></iframe>
+</div>
+<button type="button" onclick="showSequence(document.getElementById('display'))">
+ Show Events</button>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug580069.html b/docshell/test/mochitest/test_bug580069.html
new file mode 100644
index 0000000000..bb0a3bc823
--- /dev/null
+++ b/docshell/test/mochitest/test_bug580069.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=580069
+-->
+<head>
+ <title>Test for Bug 580069</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=580069">Mozilla Bug 580069</a>
+
+<script type="application/javascript">
+
+add_task(async function() {
+ let iframe = document.createElement("iframe");
+ iframe.setAttribute("src", "file_bug580069_1.html");
+
+ // Insert the initial <iframe> document, and wait for page1Load to be called
+ // after it loads.
+ document.body.appendChild(iframe);
+ await new Promise(resolve => {
+ window.page1Load = resolve;
+ });
+ let iframeCw = iframe.contentWindow;
+
+ info("iframe's location is: " + iframeCw.location + "\n");
+
+ // Submit the forum and wait for the initial page load using a POST load.
+ iframeCw.document.getElementById("form").submit();
+ let method1 = await new Promise(resolve => {
+ window.page2Load = resolve;
+ });
+ info("iframe's location is: " + iframeCw.location + ", method is " + method1 + "\n");
+ is(method1, "POST", "Method for first load should be POST.");
+
+ // Push a new state, and refresh the page. This refresh shouldn't pop up the
+ // "are you sure you want to refresh a page with POST data?" dialog. If it
+ // does, this test will hang and fail, and we'll see 'Refreshing iframe...' at
+ // the end of the test log.
+ iframeCw.history.replaceState("", "", "?replaced");
+
+ info("Refreshing iframe...\n");
+ iframeCw.location.reload();
+ let method2 = await new Promise(resolve => {
+ window.page2Load = resolve;
+ });
+
+ info("iframe's location is: " + iframeCw.location + ", method is " + method2 + "\n");
+ is(method2, "GET", "Method for second load should be GET.");
+ is(iframeCw.location.search, "?replaced", "Wrong search on iframe after refresh.");
+});
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug590573.html b/docshell/test/mochitest/test_bug590573.html
new file mode 100644
index 0000000000..83554a7a66
--- /dev/null
+++ b/docshell/test/mochitest/test_bug590573.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=590573
+-->
+<head>
+ <title>Test for Bug 590573</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590573">Mozilla Bug 590573</a>
+
+<script type='application/javascript'>
+SimpleTest.waitForExplicitFinish();
+
+// Listen to the first callback, since this indicates that the page loaded.
+var page1LoadCallbackEnabled = true;
+function page1Load() {
+ if (page1LoadCallbackEnabled) {
+ page1LoadCallbackEnabled = false;
+ dump("Got page1 load.\n");
+ pageLoad();
+ } else {
+ dump("Ignoring page1 load.\n");
+ }
+}
+
+var page1PageShowCallbackEnabled = false;
+function page1PageShow() {
+ if (page1PageShowCallbackEnabled) {
+ page1PageShowCallbackEnabled = false;
+ dump("Got page1 pageshow.\n");
+ pageLoad();
+ } else {
+ dump("Ignoring page1 pageshow.\n");
+ }
+}
+
+var page2LoadCallbackEnabled = false;
+function page2Load() {
+ if (page2LoadCallbackEnabled) {
+ page2LoadCallbackEnabled = false;
+ dump("Got page2 popstate.\n");
+ pageLoad();
+ } else {
+ dump("Ignoring page2 popstate.\n");
+ }
+}
+
+var page2PopstateCallbackEnabled = false;
+function page2Popstate() {
+ if (page2PopstateCallbackEnabled) {
+ page2PopstateCallbackEnabled = false;
+ dump("Got page2 popstate.\n");
+ pageLoad();
+ } else {
+ dump("Ignoring page2 popstate.\n");
+ }
+}
+
+var page2PageShowCallbackEnabled = false;
+function page2PageShow() {
+ if (page2PageShowCallbackEnabled) {
+ page2PageShowCallbackEnabled = false;
+ dump("Got page2 pageshow.\n");
+ pageLoad();
+ } else {
+ dump("Ignoring page2 pageshow.\n");
+ }
+}
+
+var popup = window.open("file_bug590573_1.html");
+
+var gTestContinuation = null;
+var loads = 0;
+function pageLoad() {
+ loads++;
+ dump("pageLoad(loads=" + loads + ", page location=" + popup.location + ")\n");
+
+ if (!gTestContinuation) {
+ gTestContinuation = testBody();
+ }
+ var ret = gTestContinuation.next();
+ if (ret.done) {
+ SimpleTest.finish();
+ }
+}
+
+function continueAsync() {
+ popup.addEventListener("popstate", function() {
+ popup.requestAnimationFrame(function() { gTestContinuation.next(); });
+ },
+ {once: true});
+}
+
+function* testBody() {
+ is(popup.scrollY, 0, "test 1");
+ popup.scroll(0, 100);
+
+ popup.history.pushState("", "", "?pushed");
+ is(Math.round(popup.scrollY), 100, "test 2");
+ popup.scroll(0, 200); // set state-2's position to 200
+
+ popup.history.back();
+ continueAsync();
+ yield;
+ is(Math.round(popup.scrollY), 100, "test 3");
+ popup.scroll(0, 150); // set original page's position to 150
+
+ popup.history.forward();
+ continueAsync();
+ yield;
+ is(Math.round(popup.scrollY), 200, "test 4");
+
+ popup.history.back();
+ continueAsync();
+ yield;
+ is(Math.round(popup.scrollY), 150, "test 5");
+
+ popup.history.forward();
+ continueAsync();
+ yield;
+ is(Math.round(popup.scrollY), 200, "test 6");
+
+ // At this point, the history looks like:
+ // PATH POSITION
+ // file_bug590573_1.html 150 <-- oldest
+ // file_bug590573_1.html?pushed 200 <-- newest, current
+
+ // Now test that the scroll position is persisted when we have real
+ // navigations involved. First, we need to spin the event loop so that the
+ // navigation doesn't replace our current history entry.
+
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page2LoadCallbackEnabled = true;
+ popup.location = "file_bug590573_2.html";
+ yield;
+
+ ok(popup.location.href.match("file_bug590573_2.html$"),
+ "Location was " + popup.location +
+ " but should end with file_bug590573_2.html");
+
+ is(popup.scrollY, 0, "test 7");
+ popup.scroll(0, 300);
+
+ // We need to spin the event loop again before we go back, otherwise the
+ // scroll positions don't get updated properly.
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page1PageShowCallbackEnabled = true;
+ popup.history.back();
+ yield;
+
+ // Spin the event loop again so that we get the right scroll positions.
+ setTimeout(pageLoad, 0);
+ yield;
+
+ is(popup.location.search, "?pushed");
+ ok(popup.document.getElementById("div1"), "page should have div1.");
+
+ is(Math.round(popup.scrollY), 200, "test 8");
+
+ popup.history.back();
+ continueAsync();
+ yield;
+ is(Math.round(popup.scrollY), 150, "test 9");
+ popup.history.forward();
+ continueAsync();
+ yield;
+
+ is(Math.round(popup.scrollY), 200, "test 10");
+
+ // Spin one last time...
+ setTimeout(pageLoad, 0);
+ yield;
+
+ page2PageShowCallbackEnabled = true;
+ popup.history.forward();
+ yield;
+
+ // Bug 821821, on Android tegras we get 299 instead of 300 sometimes
+ const scrollY = Math.floor(popup.scrollY);
+ if (scrollY >= 299 && scrollY <= 300) {
+ is(1, 1, "test 11");
+ } else {
+ is(1, 0, "test 11, got " + popup.scrollY + " for popup.scrollY instead of 299|300");
+ }
+ popup.close();
+}
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug598895.html b/docshell/test/mochitest/test_bug598895.html
new file mode 100644
index 0000000000..e0b17e2663
--- /dev/null
+++ b/docshell/test/mochitest/test_bug598895.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=598895
+-->
+<head>
+ <title>Test for Bug 598895</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598895">Mozilla Bug 598895</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 598895 */
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+var win1 = window.open();
+win1.document.body.textContent = "Should show";
+
+var windowsLoaded = 0;
+
+window.onmessage = async function(ev) {
+ is(ev.data, "loaded", "Message should be 'loaded'");
+ if (++windowsLoaded == 2) {
+ var one = await snapshotWindow(win1);
+ var two = await snapshotWindow(win2);
+ var three = await snapshotWindow(win3);
+ win1.close();
+ win2.close();
+ win3.close();
+ ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
+ ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
+
+ SimpleTest.finish();
+ }
+};
+
+var win2 = window.open("file_bug598895_1.html");
+var win3 = window.open("file_bug598895_2.html");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug634834.html b/docshell/test/mochitest/test_bug634834.html
new file mode 100644
index 0000000000..e1f87de000
--- /dev/null
+++ b/docshell/test/mochitest/test_bug634834.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=634834
+-->
+<head>
+ <title>Test for Bug 634834</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=634834">Mozilla Bug 634834</a>
+
+<script type='application/javascript'>
+SimpleTest.waitForExplicitFinish();
+
+function iframe_loaded() {
+ var loadedAfterPushstate = false;
+ $("iframe").onload = function() {
+ loadedAfterPushstate = true;
+ };
+
+ var obj = { name: "name" };
+ obj.__defineGetter__("a", function() {
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ $("iframe").contentWindow.location = "http://example.com";
+
+ // Wait until we've loaded example.com.
+ do {
+ var r = new XMLHttpRequest();
+ r.open("GET", location.href, false);
+ r.overrideMimeType("text/plain");
+ try { r.send(null); } catch (e) {}
+ } while (!loadedAfterPushstate);
+ });
+
+ try {
+ $("iframe").contentWindow.history.pushState(obj, "");
+ ok(false, "pushState should throw exception.");
+ } catch (e) {
+ ok(true, "pushState threw an exception.");
+ }
+ SimpleTest.finish();
+}
+
+</script>
+
+<iframe id='iframe' src='file_bug634834.html' onload='iframe_loaded()'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug637644.html b/docshell/test/mochitest/test_bug637644.html
new file mode 100644
index 0000000000..1e5f4380b4
--- /dev/null
+++ b/docshell/test/mochitest/test_bug637644.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=637644
+-->
+<head>
+ <title>Test for Bug 637644</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=637644">Mozilla Bug 637644</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 637644 */
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+var win1 = window.open("", "", "height=500,width=500");
+win1.document.body.textContent = "Should show";
+
+var windowsLoaded = 0;
+
+window.onmessage = async function(ev) {
+ is(ev.data, "loaded", "Message should be 'loaded'");
+ if (++windowsLoaded == 2) {
+ var one = await snapshotWindow(win1);
+ var two = await snapshotWindow(win2);
+ var three = await snapshotWindow(win3);
+ win1.close();
+ win2.close();
+ win3.close();
+ ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
+ ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
+
+ SimpleTest.finish();
+ }
+};
+
+var win2 = window.open("file_bug637644_1.html", "", "height=500,width=500");
+var win3 = window.open("file_bug637644_2.html", "", "height=500,width=500");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug640387_1.html b/docshell/test/mochitest/test_bug640387_1.html
new file mode 100644
index 0000000000..b8aab054a1
--- /dev/null
+++ b/docshell/test/mochitest/test_bug640387_1.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=640387
+-->
+<head>
+ <title>Test for Bug 640387</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=640387">Mozilla Bug 640387</a>
+
+<script type='application/javascript'>
+SimpleTest.waitForExplicitFinish();
+
+function* test() {
+ /* Spin the event loop so we get out of the onload handler. */
+ SimpleTest.executeSoon(function() { gGen.next(); });
+ yield undefined;
+
+ popup.history.pushState("", "", "#hash1");
+ popup.history.pushState("", "", "#hash2");
+
+ // Now the history looks like:
+ // file_bug640387.html
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash2 <-- current
+
+ // Going back should trigger a hashchange, which will wake us up from the
+ // yield.
+ popup.history.back();
+ yield undefined;
+ ok(true, "Got first hashchange.");
+
+ // Going back should wake us up again.
+ popup.history.back();
+ yield undefined;
+ ok(true, "Got second hashchange.");
+
+ // Now the history looks like:
+ // file_bug640387.html <-- current
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash2
+
+ // Going forward should trigger a hashchange.
+ popup.history.forward();
+ yield undefined;
+ ok(true, "Got third hashchange.");
+
+ // Now modify the history so it looks like:
+ // file_bug640387.html
+ // file_bug640387.html#hash1
+ // file_bug640387.html#hash1 <-- current
+ popup.history.pushState("", "", "#hash1");
+
+ // Now when we go back, we should not get a hashchange. Instead, wait for a
+ // popstate. We need to asynchronously go back because popstate is fired
+ // sync.
+ gHashchangeExpected = false;
+ gCallbackOnPopstate = true;
+ SimpleTest.executeSoon(function() { popup.history.back(); });
+ yield undefined;
+ ok(true, "Got popstate.");
+ gCallbackOnPopstate = false;
+
+ // Spin the event loop so hashchange has a chance to fire, if it's going to.
+ SimpleTest.executeSoon(function() { gGen.next(); });
+ yield undefined;
+
+ popup.close();
+ SimpleTest.finish();
+}
+
+var gGen = null;
+function childLoad() {
+ gGen = test();
+ gGen.next();
+}
+
+var gHashchangeExpected = true;
+function childHashchange() {
+ if (gHashchangeExpected) {
+ gGen.next();
+ } else {
+ ok(false, "Got hashchange when we weren't expecting one.");
+ }
+}
+
+var gCallbackOnPopstate = false;
+function childPopstate() {
+ if (gCallbackOnPopstate) {
+ gGen.next();
+ }
+}
+
+/* We need to run this test in a popup, because navigating an iframe
+ * back/forwards tends to cause intermittent orange. */
+var popup = window.open("file_bug640387.html");
+
+/* Control now flows up to childLoad(), called once the popup loads. */
+
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug640387_2.html b/docshell/test/mochitest/test_bug640387_2.html
new file mode 100644
index 0000000000..c248a64836
--- /dev/null
+++ b/docshell/test/mochitest/test_bug640387_2.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=640387
+-->
+<head>
+ <title>Test for Bug 640387</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=640387">Mozilla Bug 640387</a>
+
+<!-- Test that, when going from
+
+ http://example.com/#foo
+
+to
+
+ http://example.com/
+
+via a non-history load, we do a true load, rather than a scroll. -->
+
+<script type='application/javascript'>
+SimpleTest.waitForExplicitFinish();
+
+var callbackOnLoad = false;
+function childLoad() {
+ if (callbackOnLoad) {
+ callbackOnLoad = false;
+ gGen.next();
+ }
+}
+
+var errorOnHashchange = false;
+var callbackOnHashchange = false;
+function childHashchange() {
+ if (errorOnHashchange) {
+ ok(false, "Got unexpected hashchange.");
+ }
+ if (callbackOnHashchange) {
+ callbackOnHashchange = false;
+ gGen.next();
+ }
+}
+
+function* run_test() {
+ var iframe = $("iframe").contentWindow;
+
+ ok(true, "Got first load");
+
+ // Spin the event loop so we exit the onload handler.
+ SimpleTest.executeSoon(function() { gGen.next(); });
+ yield undefined;
+
+ let origLocation = iframe.location + "";
+ callbackOnHashchange = true;
+ iframe.location.hash = "#1";
+ // Wait for a hashchange event.
+ yield undefined;
+
+ ok(true, "Got hashchange.");
+
+ iframe.location = origLocation;
+ // This should produce a load event and *not* a hashchange, because the
+ // result of the load is a different document than we had previously.
+ callbackOnLoad = true;
+ errorOnHashchange = true;
+ yield undefined;
+
+ ok(true, "Got final load.");
+
+ // Spin the event loop to give hashchange a chance to fire, if it's going to.
+ SimpleTest.executeSoon(function() { gGen.next(); });
+ yield undefined;
+
+ SimpleTest.finish();
+}
+
+callbackOnLoad = true;
+var gGen = run_test();
+
+</script>
+
+<iframe id='iframe' src='file_bug640387.html'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug653741.html b/docshell/test/mochitest/test_bug653741.html
new file mode 100644
index 0000000000..33ba7077e4
--- /dev/null
+++ b/docshell/test/mochitest/test_bug653741.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=653741
+-->
+<head>
+ <title>Test for Bug 653741</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=653741">Mozilla Bug 653741</a>
+
+<script type="application/javascript">
+
+/** Test for Bug 653741 */
+SimpleTest.waitForExplicitFinish();
+
+function childLoad() {
+ // Spin the event loop so we leave the onload handler.
+ SimpleTest.executeSoon(childLoad2);
+}
+
+function childLoad2() {
+ let cw = $("iframe").contentWindow;
+
+ // Save the Y offset. For sanity's sake, make sure it's not 0, because we
+ // should be at the bottom of the page!
+ let origYOffset = Math.round(cw.pageYOffset);
+ ok(origYOffset != 0, "Original Y offset is not 0.");
+
+ // Scroll the iframe to the top, then navigate to #bottom again.
+ cw.scrollTo(0, 0);
+
+ // Our current location is #bottom, so this should scroll us down to the
+ // bottom again.
+ cw.location = cw.location + "";
+
+ is(Math.round(cw.pageYOffset), origYOffset, "Correct offset after reloading page.");
+ SimpleTest.finish();
+}
+
+</script>
+
+<iframe height='100px' id='iframe' src='file_bug653741.html#bottom'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug660404.html b/docshell/test/mochitest/test_bug660404.html
new file mode 100644
index 0000000000..94e3f67aa1
--- /dev/null
+++ b/docshell/test/mochitest/test_bug660404.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660404
+-->
+<head>
+ <title>Test for Bug 660404</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660404">Mozilla Bug 660404</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 660404 */
+SimpleTest.waitForExplicitFinish();
+
+var textContent =
+`
+ var bc = new BroadcastChannel("bug660404_multipart");
+ bc.postMessage({command: "finishTest",
+ textContent: window.document.documentElement.textContent,
+ innerHTML: window.document.documentElement.innerHTML
+ });
+ bc.close();
+ window.close();
+`;
+var innerHTML =
+`<head><script>
+ var bc = new BroadcastChannel("bug660404_multipart");
+ bc.postMessage({command: "finishTest",
+ textContent: window.document.documentElement.textContent,
+ innerHTML: window.document.documentElement.innerHTML
+ });
+ bc.close();
+ window.close();
+</`
+// eslint-disable-next-line no-useless-concat
++ `script></head>`
+;
+var bc_multipart = new BroadcastChannel("bug660404_multipart");
+bc_multipart.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "finishTest") {
+ is(msg.textContent, textContent);
+ is(msg.innerHTML, innerHTML);
+ bc_multipart.close();
+ SimpleTest.finish();
+ }
+}
+var bc = new BroadcastChannel("bug660404");
+bc.onmessage = (msgEvent) => {
+ var msg = msgEvent.data;
+ var command = msg.command;
+ if (command == "pagehide") {
+ is(msg.persisted, true, "Should be bfcached when navigating to multipart");
+ bc.close();
+ }
+}
+
+// If Fission is disabled, the pref is no-op.
+SpecialPowers.pushPrefEnv({set: [["fission.bfcacheInParent", true]]}, () => {
+ // Have to open a new window, since there's no bfcache in subframes
+ window.open("file_bug660404-1.html", "", "noopener");
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug662170.html b/docshell/test/mochitest/test_bug662170.html
new file mode 100644
index 0000000000..d25ee3bd0f
--- /dev/null
+++ b/docshell/test/mochitest/test_bug662170.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=662170
+-->
+<head>
+ <title>Test for Bug 662170</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=662170">Mozilla Bug 662170</a>
+
+<script type="application/javascript">
+
+/** Test for Bug 662170 */
+SimpleTest.waitForExplicitFinish();
+
+function childLoad() {
+ // Spin the event loop so we leave the onload handler.
+ SimpleTest.executeSoon(childLoad2);
+}
+
+function childLoad2() {
+ let cw = $("iframe").contentWindow;
+
+ // When we initially load the page, we should be at the top.
+ is(cw.pageYOffset, 0, "Initial Y offset should be 0.");
+
+ // Scroll the iframe to the bottom.
+ cw.scrollTo(0, 300);
+
+ // Did we actually scroll somewhere?
+ isnot(Math.round(cw.pageYOffset), 0, "Y offset should be non-zero after scrolling.");
+
+ // Now load file_bug662170.html#, which should take us to the top of the
+ // page.
+ cw.location = cw.location + "#";
+
+ is(cw.pageYOffset, 0, "Correct Y offset after loading #.");
+ SimpleTest.finish();
+}
+
+</script>
+
+<!-- When the iframe loads, it calls childLoad(). -->
+<iframe height='100px' id='iframe' src='file_bug662170.html'></iframe>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug668513.html b/docshell/test/mochitest/test_bug668513.html
new file mode 100644
index 0000000000..09c848b6c1
--- /dev/null
+++ b/docshell/test/mochitest/test_bug668513.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=668513
+-->
+<head>
+ <title>Test for Bug 668513</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=668513">Mozilla Bug 668513</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+if (navigator.platform.startsWith("Linux")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+SimpleTest.waitForExplicitFinish();
+window.open("file_bug668513.html");
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug669671.html b/docshell/test/mochitest/test_bug669671.html
new file mode 100644
index 0000000000..4470cd6682
--- /dev/null
+++ b/docshell/test/mochitest/test_bug669671.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=669671
+-->
+<head>
+ <title>Test for Bug 669671</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=669671">Mozilla Bug 669671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 669671.
+ *
+ * This is a bit complicated. We have a script, file_bug669671.sjs, which counts
+ * how many times it's loaded and returns that count in the body of an HTML
+ * document. For brevity, call this page X.
+ *
+ * X is sent with Cache-Control: max-age=0 and can't be bfcached (it has an
+ * onunload handler). Our test does the following in a popup:
+ *
+ * 1) Load X?pushed, to prime the cache.
+ * 2) Navigate to X.
+ * 3) Call pushState and navigate from X to X?pushed.
+ * 4) Navigate to X?navigated.
+ * 5) Go back (to X?pushed).
+ *
+ * We do all this work so we can check that in step 5, we fetch X?pushed from
+ * the network -- we shouldn't use our cached copy, because of the
+ * cache-control header X sends.
+ *
+ * Then we go back and repeat the whole process but call history.replaceState
+ * instead of pushState. And for good measure, we test once more, this time
+ * modifying only the hash of the URI using replaceState. In this case, we
+ * should* load from the cache.
+ *
+ */
+SimpleTest.requestLongerTimeout(2);
+SimpleTest.waitForExplicitFinish();
+
+function onChildLoad() {
+ SimpleTest.executeSoon(function() { gGen.next(); });
+}
+
+var _loadCount = 0;
+function checkPopupLoadCount() {
+ is(popup.document.body.innerHTML, _loadCount + "", "Load count");
+
+ // We normally want to increment _loadCount here. But if the test fails
+ // because we didn't do a load we should have, let's not cause a cascade of
+ // failures by incrementing _loadCount.
+ var origCount = _loadCount;
+ if (popup.document.body.innerHTML >= _loadCount + "")
+ _loadCount++;
+ return origCount;
+}
+
+function* test() {
+ // Step 0 - Make sure the count is reset to 0 in case of reload
+ popup.location = "file_bug669671.sjs?countreset";
+ yield;
+ is(popup.document.body.innerHTML, "0",
+ "Load count should be reset to 0");
+
+ // Step 1 - The popup's body counts how many times we've requested the
+ // resource. This is the first time we've requested it, so it should be '0'.
+ checkPopupLoadCount();
+
+ // Step 2 - We'll get another onChildLoad when this finishes.
+ popup.location = "file_bug669671.sjs";
+ yield undefined;
+
+ // Step 3 - Call pushState and change the URI back to ?pushed.
+ checkPopupLoadCount();
+ popup.history.pushState("", "", "?pushed");
+
+ // Step 4 - Navigate away. This should trigger another onChildLoad.
+ popup.location = "file_bug669671.sjs?navigated-1";
+ yield undefined;
+
+ // Step 5 - Go back. This should result in another onload (because the file is
+ // not in bfcache) and should be the fourth time we've requested the sjs file.
+ checkPopupLoadCount();
+ popup.history.back();
+ yield undefined;
+
+ // This is the check which was failing before we fixed the bug.
+ checkPopupLoadCount();
+
+ popup.close();
+
+ // Do the whole thing again, but with replaceState.
+ popup = window.open("file_bug669671.sjs?replaced");
+ yield undefined;
+ checkPopupLoadCount();
+ popup.location = "file_bug669671.sjs";
+ yield undefined;
+ checkPopupLoadCount();
+ popup.history.replaceState("", "", "?replaced");
+ popup.location = "file_bug669671.sjs?navigated-2";
+ yield undefined;
+ checkPopupLoadCount();
+ popup.history.back();
+ yield undefined;
+ checkPopupLoadCount();
+ popup.close();
+
+ // Once more, with feeling. Notice that we don't have to prime the cache
+ // with an extra load here, because X and X#hash share the same cache entry.
+ popup = window.open("file_bug669671.sjs?hash-test");
+ yield undefined;
+ var initialCount = checkPopupLoadCount();
+ popup.history.replaceState("", "", "#hash");
+ popup.location = "file_bug669671.sjs?navigated-3";
+ yield undefined;
+ checkPopupLoadCount();
+ popup.history.back();
+ yield undefined;
+ is(popup.document.body.innerHTML, initialCount + "",
+ "Load count (should be cached)");
+ popup.close();
+
+ SimpleTest.finish();
+}
+
+var gGen = test();
+var popup;
+
+// Disable RCWN to make cache behavior deterministic.
+SpecialPowers.pushPrefEnv({set: [["network.http.rcwn.enabled", false]]}, () => {
+ // This will call into onChildLoad once it loads.
+ popup = window.open("file_bug669671.sjs?pushed");
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug675587.html b/docshell/test/mochitest/test_bug675587.html
new file mode 100644
index 0000000000..452bbc8058
--- /dev/null
+++ b/docshell/test/mochitest/test_bug675587.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=675587
+-->
+<head>
+ <title>Test for Bug 675587</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675587">Mozilla Bug 675587</a>
+<p id="display">
+ <iframe src="file_bug675587.html#hash"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 675587 */
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ ok(window.frames[0].location.href.endsWith("file_bug675587.html#"),
+ "Should have the right href");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug680257.html b/docshell/test/mochitest/test_bug680257.html
new file mode 100644
index 0000000000..4d5736ac0a
--- /dev/null
+++ b/docshell/test/mochitest/test_bug680257.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=680257
+-->
+<head>
+ <title>Test for Bug 680257</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=680257">Mozilla Bug 680257</a>
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var popup = window.open("file_bug680257.html");
+
+var gTestContinuation = null;
+function continueAsync() {
+ popup.addEventListener("hashchange",
+ function(e) { gTestContinuation.next(); }, { once: true });
+}
+
+// The popup will call into popupLoaded() once it loads.
+function popupLoaded() {
+ // runTests() needs to be called from outside popupLoaded's onload handler.
+ // Otherwise, the navigations we do in runTests won't create new SHEntries.
+ SimpleTest.executeSoon(function() {
+ if (!gTestContinuation) {
+ gTestContinuation = runTests();
+ }
+ gTestContinuation.next();
+ });
+}
+
+function* runTests() {
+ checkPopupLinkStyle(false, "Initial");
+
+ popup.location.hash = "a";
+ continueAsync();
+ yield;
+ checkPopupLinkStyle(true, "After setting hash");
+
+ popup.history.back();
+ continueAsync();
+ yield;
+
+ checkPopupLinkStyle(false, "After going back");
+
+ popup.history.forward();
+ continueAsync();
+ yield;
+ checkPopupLinkStyle(true, "After going forward");
+
+ popup.close();
+ SimpleTest.finish();
+}
+
+function checkPopupLinkStyle(isTarget, desc) {
+ var link = popup.document.getElementById("a");
+ var style = popup.getComputedStyle(link);
+ var color = style.getPropertyValue("color");
+
+ // Color is red if isTarget, black otherwise.
+ if (isTarget) {
+ is(color, "rgb(255, 0, 0)", desc);
+ } else {
+ is(color, "rgb(0, 0, 0)", desc);
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug691547.html b/docshell/test/mochitest/test_bug691547.html
new file mode 100644
index 0000000000..706cd5013b
--- /dev/null
+++ b/docshell/test/mochitest/test_bug691547.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691547
+-->
+<head>
+ <title>Test for Bug 691547</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+ var navStart = 0;
+ var beforeReload = 0;
+ function onContentLoad() {
+ var frame = frames[0];
+ if (!navStart) {
+ // First time we perform navigation in subframe. The bug is that
+ // load in subframe causes timing.navigationStart to be recorded
+ // as if it was a start of the next navigation.
+ var innerFrame = frame.frames[0];
+ navStart = frame.performance.timing.navigationStart;
+ innerFrame.location = "bug570341_recordevents.html";
+ // Let's wait a bit so the difference is clear anough.
+ setTimeout(reload, 3000);
+ } else {
+ // Content reloaded, time to check. We are allowing a huge time slack,
+ // in case clock is imprecise. If we have a bug, the difference is
+ // expected to be about the timeout value set above.
+ var diff = frame.performance.timing.navigationStart - beforeReload;
+ ok(diff >= -200,
+ "navigationStart should be set after reload request. " +
+ "Measured difference: " + diff + " (should be positive)");
+ SimpleTest.finish();
+ }
+ }
+ function reload() {
+ var frame = frames[0];
+ ok(navStart == frame.performance.timing.navigationStart,
+ "navigationStart should not change when frame loads.");
+ beforeReload = Date.now();
+ frame.location.reload();
+ }
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=570341">Mozilla Bug 570341</a>
+<div id="frames">
+<iframe name="frame0" id="frame0" src="bug691547_frame.html" onload="onContentLoad()"></iframe>
+</div>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug694612.html b/docshell/test/mochitest/test_bug694612.html
new file mode 100644
index 0000000000..8ea4331c43
--- /dev/null
+++ b/docshell/test/mochitest/test_bug694612.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=694612
+-->
+<head>
+ <title>Test for Bug 694612</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=694612">Mozilla Bug 694612</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 694612 */
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("message", receiveMessage);
+function receiveMessage(event) {
+ ok(event.data.result, "should have performance API in an <object>");
+ window.removeEventListener("message", receiveMessage);
+ SimpleTest.finish();
+}
+</script>
+<object type="text/html"
+ data="data:text/html,<script>parent.postMessage({result:performance!=null},'*');</script>">
+</object>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug703855.html b/docshell/test/mochitest/test_bug703855.html
new file mode 100644
index 0000000000..4aa7b08800
--- /dev/null
+++ b/docshell/test/mochitest/test_bug703855.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=703855
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 703855</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=703855">Mozilla Bug 703855</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe id="f" src="file_bug703855.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 703855 */
+
+SimpleTest.waitForExplicitFinish();
+
+var timingAttributes = [
+ "connectEnd",
+ "connectStart",
+ "domComplete",
+ "domContentLoadedEventEnd",
+ "domContentLoadedEventStart",
+ "domInteractive",
+ "domLoading",
+ "domainLookupEnd",
+ "domainLookupStart",
+ "fetchStart",
+ "loadEventEnd",
+ "loadEventStart",
+ "navigationStart",
+ "redirectEnd",
+ "redirectStart",
+ "requestStart",
+ "responseEnd",
+ "responseStart",
+ "unloadEventEnd",
+ "unloadEventStart",
+];
+var originalTiming = {};
+
+function runTest() {
+ var timing = $("f").contentWindow.performance.timing;
+ for (let i in timingAttributes) {
+ originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
+ }
+
+ var doc = $("f").contentDocument;
+ doc.open();
+ doc.write("<!DOCTYPE html>");
+ doc.close();
+
+ SimpleTest.executeSoon(function() {
+ var newTiming = $("f").contentWindow.performance.timing;
+ for (let i in timingAttributes) {
+ is(newTiming[timingAttributes[i]], originalTiming[timingAttributes[i]],
+ "document.open should not affect value of " + timingAttributes[i]);
+ }
+ SimpleTest.finish();
+ });
+}
+
+addLoadEvent(function() {
+ SimpleTest.executeSoon(runTest);
+});
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug728939.html b/docshell/test/mochitest/test_bug728939.html
new file mode 100644
index 0000000000..168184099a
--- /dev/null
+++ b/docshell/test/mochitest/test_bug728939.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=728939
+-->
+<head>
+ <title>Test for Bug 728939</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=728939">Mozilla Bug 728939</a>
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// Called when the popup finishes loading.
+function popupLoaded() {
+ popup.location.hash = "#foo";
+ is(popup.document.URL, popup.location.href, "After hashchange.");
+
+ popup.history.pushState("", "", "bar");
+ is(popup.document.URL, popup.location.href, "After pushState.");
+
+ popup.history.replaceState("", "", "baz");
+ is(popup.document.URL, popup.location.href, "After replaceState.");
+
+ popup.close();
+ SimpleTest.finish();
+}
+
+var popup = window.open("file_bug728939.html");
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_bug797909.html b/docshell/test/mochitest/test_bug797909.html
new file mode 100644
index 0000000000..15b7c27c0f
--- /dev/null
+++ b/docshell/test/mochitest/test_bug797909.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=797909
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 797909</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=797909">Mozilla Bug 797909</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+ /** Test for Bug 797909 */
+
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ var iframe = document.getElementById("ifr");
+ try {
+ iframe.contentWindow.document;
+ ok(false, "Should have thrown an exception");
+ } catch (ex) {
+ ok(true, "Got an exception");
+ }
+
+ iframe = document.createElement("iframe");
+ // set sandbox attribute
+ iframe.sandbox = "allow-scripts";
+ // and then insert into the doc
+ document.body.appendChild(iframe);
+
+ try {
+ iframe.contentWindow.document;
+ ok(false, "Should have thrown an exception");
+ } catch (ex) {
+ ok(true, "Got an exception");
+ }
+
+ iframe = document.createElement("iframe");
+ // set sandbox attribute
+ iframe.sandbox = "allow-same-origin";
+ // and then insert into the doc
+ document.body.appendChild(iframe);
+
+ try {
+ iframe.contentWindow.document;
+ ok(true, "Shouldn't have thrown an exception");
+ } catch (ex) {
+ ok(false, "Got an unexpected exception");
+ }
+
+ SimpleTest.finish();
+ }
+
+</script>
+</pre>
+<iframe id="ifr" sandbox = "allow-scripts"></iframe>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_close_onpagehide_by_history_back.html b/docshell/test/mochitest/test_close_onpagehide_by_history_back.html
new file mode 100644
index 0000000000..33140502f7
--- /dev/null
+++ b/docshell/test/mochitest/test_close_onpagehide_by_history_back.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Test for closing window in pagehide event callback caused by history.back()</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432396">Mozilla Bug 1432396</a>
+<p id="display"></p>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+const w = window.open("file_close_onpagehide1.html");
+window.addEventListener("message", e => {
+ is(e.data, "initial", "The initial page loaded");
+ window.addEventListener("message", evt => {
+ is(evt.data, "second", "The second page loaded");
+ w.onpagehide = () => {
+ w.close();
+ info("try to close the popped up window in onpagehide");
+ SimpleTest.finish();
+ };
+ w.history.back();
+ }, { once: true });
+ w.location = "file_close_onpagehide2.html";
+}, { once: true });
+</script>
diff --git a/docshell/test/mochitest/test_close_onpagehide_by_window_close.html b/docshell/test/mochitest/test_close_onpagehide_by_window_close.html
new file mode 100644
index 0000000000..8b094cdaa4
--- /dev/null
+++ b/docshell/test/mochitest/test_close_onpagehide_by_window_close.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Test for closing window in pagehide event callback caused by window.close()</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1432396">Mozilla Bug 1432396</a>
+<p id="display"></p>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+const w = window.open("file_close_onpagehide1.html");
+window.addEventListener("message", e => {
+ is(e.data, "initial", "The initial page loaded");
+ w.onpagehide = () => {
+ w.close();
+ info("try to close the popped up window in onpagehide");
+ SimpleTest.finish();
+ };
+ w.close();
+}, { once: true });
+</script>
diff --git a/docshell/test/mochitest/test_compressed_multipart.html b/docshell/test/mochitest/test_compressed_multipart.html
new file mode 100644
index 0000000000..438819b643
--- /dev/null
+++ b/docshell/test/mochitest/test_compressed_multipart.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1600211
+
+Loads a document that is served as multipart/x-mixed-replace as well as gzip compressed.
+Checks that we correctly decompress and display it (via running JS within the document to notify us).
+-->
+<head>
+ <title>Test for Bug 1600211</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1600211">Mozilla Bug 1600211</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1600211 */
+SimpleTest.waitForExplicitFinish();
+
+var w;
+
+function finishTest() {
+ is(w.document.documentElement.textContent, "opener.finishTest();");
+ is(w.document.documentElement.innerHTML, "<head><script>opener.finishTest();</" +
+ "script></head>");
+ w.close();
+ SimpleTest.finish();
+}
+
+w = window.open("file_compressed_multipart");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_content_javascript_loads.html b/docshell/test/mochitest/test_content_javascript_loads.html
new file mode 100644
index 0000000000..eabc1d314e
--- /dev/null
+++ b/docshell/test/mochitest/test_content_javascript_loads.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for Bug 1647519</title>
+ <meta charset="utf-8">
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1647519">Mozilla Bug 1647519</a>
+
+<script type="application/javascript">
+"use strict";
+
+function promiseMessage(source, filter = event => true) {
+ return new Promise(resolve => {
+ function listener(event) {
+ if (event.source == source && filter(event)) {
+ window.removeEventListener("message", listener);
+ resolve(event);
+ }
+ }
+ window.addEventListener("message", listener);
+ });
+}
+
+async function runTests(resourcePath) {
+ /* globals Assert, content */
+ let doc = content.document;
+
+ // Sends a message to the given target window and waits for a response a few
+ // times to (more or less) ensure that a `javascript:` load request has had
+ // time to succeed, if it were going to.
+ async function doSomeRoundTrips(target) {
+ for (let i = 0; i < 3; i++) {
+ // Note: The ping message needs to be sent from a script running in the
+ // content scope or there will be no source window for the reply to be
+ // sent to.
+ await content.wrappedJSObject.ping(target);
+ }
+ }
+
+ function promiseEvent(target, name) {
+ return new Promise(resolve => {
+ target.addEventListener(name, resolve, { once: true });
+ });
+ }
+
+ function createIframe(host, id) {
+ let iframe = doc.createElement("iframe");
+ iframe.id = id;
+ iframe.name = id;
+ iframe.src = `https://${host}${resourcePath}file_content_javascript_loads_frame.html`;
+ doc.body.appendChild(iframe);
+ return promiseEvent(iframe, "load");
+ }
+
+ const ID_SAME_ORIGIN = "frame-same-origin";
+ const ID_SAME_BASE_DOMAIN = "frame-same-base-domain";
+ const ID_CROSS_BASE_DOMAIN = "frame-cross-base-domain";
+
+ await Promise.all([
+ createIframe("example.com", ID_SAME_ORIGIN),
+ createIframe("test1.example.com", ID_SAME_BASE_DOMAIN),
+ createIframe("example.org", ID_CROSS_BASE_DOMAIN),
+ ]);
+
+ let gotJSLoadFrom = null;
+ let pendingJSLoadID = null;
+ content.addEventListener("message", event => {
+ if ("javascriptLoadID" in event.data) {
+ Assert.equal(
+ event.data.javascriptLoadID,
+ pendingJSLoadID,
+ "Message from javascript: load should have the expected ID"
+ );
+ Assert.equal(
+ gotJSLoadFrom,
+ null,
+ "Should not have seen a previous load message this cycle"
+ );
+ gotJSLoadFrom = event.source.name;
+ }
+ });
+
+ async function watchForJSLoads(frameName, expected, task) {
+ let loadId = Math.random();
+
+ let jsURI =
+ "javascript:" +
+ encodeURI(`parent.postMessage({ javascriptLoadID: ${loadId} }, "*")`);
+
+ pendingJSLoadID = loadId;
+ gotJSLoadFrom = null;
+
+ await task(jsURI);
+
+ await doSomeRoundTrips(content.wrappedJSObject[frameName]);
+
+ if (expected) {
+ Assert.equal(
+ gotJSLoadFrom,
+ frameName,
+ `Should have seen javascript: URI loaded into ${frameName}`
+ );
+ } else {
+ Assert.equal(
+ gotJSLoadFrom,
+ null,
+ "Should not have seen javascript: URI loaded"
+ );
+ }
+ }
+
+ let frames = [
+ { name: ID_SAME_ORIGIN, expectLoad: true },
+ { name: ID_SAME_BASE_DOMAIN, expectLoad: false },
+ { name: ID_CROSS_BASE_DOMAIN, expectLoad: false },
+ ];
+ for (let { name, expectLoad } of frames) {
+ info(`Checking loads for frame "${name}". Expecting loads: ${expectLoad}`);
+
+ info("Checking location setter");
+ await watchForJSLoads(name, expectLoad, jsURI => {
+ // Note: We need to do this from the content scope since security checks
+ // depend on the JS caller scope.
+ content.wrappedJSObject.setFrameLocation(name, jsURI);
+ });
+
+ info("Checking targeted <a> load");
+ await watchForJSLoads(name, expectLoad, jsURI => {
+ let a = doc.createElement("a");
+ a.target = name;
+ a.href = jsURI;
+ doc.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+
+ info("Checking targeted window.open load");
+ await watchForJSLoads(name, expectLoad, jsURI => {
+ content.wrappedJSObject.open(jsURI, name);
+ });
+ }
+}
+
+add_task(async function() {
+ const resourcePath = location.pathname.replace(/[^\/]+$/, "");
+
+ let win = window.open(
+ `https://example.com${resourcePath}file_content_javascript_loads_root.html`
+ );
+ await promiseMessage(win, event => event.data == "ready");
+
+ await SpecialPowers.spawn(win, [resourcePath], runTests);
+
+ win.close();
+});
+</script>
+
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_double_submit.html b/docshell/test/mochitest/test_double_submit.html
new file mode 100644
index 0000000000..640930718d
--- /dev/null
+++ b/docshell/test/mochitest/test_double_submit.html
@@ -0,0 +1,98 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Test for Bug 1590762</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <iframe name="targetFrame" id="targetFrame"></iframe>
+ <form id="form" action="double_submit.sjs?delay=1000" method="POST" target="targetFrame">
+ <input id="token" type="text" name="token" value="">
+ <input id="button" type="submit">
+ </form>
+ <script>
+ "use strict";
+
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ const CROSS_ORIGIN_URI = "http://test1.example.com/tests/docshell/test/mochitest/ping.html";
+
+ function asyncClick(counts) {
+ let frame = document.createElement('iframe');
+ frame.addEventListener(
+ 'load', () => frame.contentWindow.postMessage({command: "start"}, "*"),
+ { once:true });
+ frame.src = "clicker.html";
+
+ addEventListener('message', ({source}) => {
+ if (source === frame.contentWindow) {
+ counts.click++;
+ synthesizeMouse(document.getElementById('button'), 5, 5, {});
+ }
+ }, { once: true });
+
+ document.body.appendChild(frame);
+ return stop;
+ }
+
+ function click(button) {
+ synthesizeMouse(button, 5, 5, {});
+ }
+
+ add_task(async function runTest() {
+ let frame = document.getElementById('targetFrame');
+ await new Promise(resolve => {
+ addEventListener('message', resolve, {once: true});
+ frame.src = CROSS_ORIGIN_URI;
+ });
+
+ let form = document.getElementById('form');
+ let button = document.getElementById('button');
+
+ let token = document.getElementById('token');
+ token.value = "first";
+
+ await new Promise((resolve, reject) => {
+ let counts = { click: 0, submit: 0 };
+ form.addEventListener('submit', () => counts.submit++);
+ asyncClick(counts);
+ form.requestSubmit(button);
+ token.value = "bad";
+ let steps = {
+ good: {
+ entered: false,
+ next: () => { steps.good.entered = true; resolve(); },
+ assertion: () => {
+ ok(steps.first.entered && !steps.bad.entered, "good comes after first, but not bad")
+ }
+ },
+ first: {
+ entered: false,
+ next: () => { steps.first.entered = true; token.value = "good"; click(button); },
+ assertion: () => {
+ ok(!steps.good.entered && !steps.bad.entered, "first message is first")
+ is(counts.click, 1, "clicked");
+ is(counts.submit, 2, "did submit");
+ }
+ },
+ bad: {
+ entered: false,
+ next: () => { reject(); },
+ assertion: () => ok(false, "we got a bad message")
+ }
+ };
+ addEventListener('message', ({source, data}) => {
+ if (source !== frame.contentWindow) {
+ return;
+ }
+
+ let step = steps[data] || reject;
+ step.assertion();
+ step.next();
+ })
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/test_forceinheritprincipal_overrule_owner.html b/docshell/test/mochitest/test_forceinheritprincipal_overrule_owner.html
new file mode 100644
index 0000000000..70d610a677
--- /dev/null
+++ b/docshell/test/mochitest/test_forceinheritprincipal_overrule_owner.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<script type="text/javascript">
+
+var channel = SpecialPowers.wrap(window).docShell.currentDocumentChannel;
+var loadInfo = channel.loadInfo;
+
+// 1) perform some sanity checks
+var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.asciiSpec;
+var loadingPrincipal = channel.loadInfo.loadingPrincipal.asciiSpec;
+var principalToInherit = channel.loadInfo.principalToInherit.asciiSpec;
+
+ok(triggeringPrincipal.startsWith("http://mochi.test:8888/")
+ || triggeringPrincipal.startsWith("http://mochi.xorigin-test:8888/"),
+ "initial triggeringPrincipal correct");
+ok(loadingPrincipal.startsWith("http://mochi.test:8888/")
+ || loadingPrincipal.startsWith("http://mochi.xorigin-test:8888/"),
+ "initial loadingPrincipal correct");
+ok(principalToInherit.startsWith("http://mochi.test:8888/")
+ || principalToInherit.startsWith("http://mochi.xorigin-test:8888/"),
+ "initial principalToInherit correct");
+
+// reset principals on the loadinfo
+loadInfo.resetPrincipalToInheritToNullPrincipal();
+
+// 2) verify loadInfo contains the correct principals
+triggeringPrincipal = channel.loadInfo.triggeringPrincipal.asciiSpec;
+loadingPrincipal = channel.loadInfo.loadingPrincipal.asciiSpec;
+principalToInherit = channel.loadInfo.principalToInherit;
+
+ok(triggeringPrincipal.startsWith("http://mochi.test:8888/")
+ || triggeringPrincipal.startsWith("http://mochi.xorigin-test:8888/"),
+ "triggeringPrincipal after resetting correct");
+ok(loadingPrincipal.startsWith("http://mochi.test:8888/")
+ || loadingPrincipal.startsWith("http://mochi.xorigin-test:8888/"),
+ "loadingPrincipal after resetting correct");
+ok(principalToInherit.isNullPrincipal
+ || principalToInherit.startsWith("http://mochi.xorigin-test:8888/"),
+ "principalToInherit after resetting correct");
+
+// 3) verify that getChannelResultPrincipal returns right principal
+var resultPrincipal = SpecialPowers.Services.scriptSecurityManager
+ .getChannelResultPrincipal(channel);
+
+ok(resultPrincipal.isNullPrincipal,
+ "resultPrincipal after resetting correct");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_form_restoration.html b/docshell/test/mochitest/test_form_restoration.html
new file mode 100644
index 0000000000..b929236770
--- /dev/null
+++ b/docshell/test/mochitest/test_form_restoration.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test form restoration for no-store pages</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ function waitForMessage(aBroadcastChannel) {
+ return new Promise(resolve => {
+ aBroadcastChannel.addEventListener("message", ({ data }) => {
+ resolve(data);
+ }, { once: true });
+ });
+ }
+
+ function postMessageAndWait(aBroadcastChannel, aMsg) {
+ let promise = waitForMessage(aBroadcastChannel);
+ aBroadcastChannel.postMessage(aMsg);
+ return promise;
+ }
+
+ async function startTest(aTestFun) {
+ let bc = new BroadcastChannel("form_restoration");
+
+ let promise = waitForMessage(bc);
+ window.open("file_form_restoration_no_store.html", "", "noopener");
+ await promise;
+
+ // test steps
+ await aTestFun(bc);
+
+ // close broadcast channel and window
+ bc.postMessage("close");
+ bc.close();
+ }
+
+ /* Test for bug1740517 */
+ add_task(async function history_back() {
+ await startTest(async (aBroadcastChannel) => {
+ // update form data
+ aBroadcastChannel.postMessage("enter_data");
+
+ // navigate
+ await postMessageAndWait(aBroadcastChannel, "navigate");
+
+ // history back
+ let { persisted, formData } = await postMessageAndWait(aBroadcastChannel, "back");
+
+ // check form data
+ ok(!persisted, "Page with a no-store header shouldn't be bfcached.");
+ is(formData, "initial", "We shouldn't restore form data when going back to a page with a no-store header.");
+ });
+ });
+
+ /* Test for bug1752250 */
+ add_task(async function location_reload() {
+ await startTest(async (aBroadcastChannel) => {
+ // update form data
+ aBroadcastChannel.postMessage("enter_data");
+
+ // reload
+ let { persisted, formData } = await postMessageAndWait(aBroadcastChannel, "reload");
+
+ // check form data
+ ok(!persisted, "Page with a no-store header shouldn't be bfcached.");
+ is(formData, "initial", "We shouldn't restore form data when reload a page with a no-store header.");
+ });
+ });
+ </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_framedhistoryframes.html b/docshell/test/mochitest/test_framedhistoryframes.html
new file mode 100644
index 0000000000..f90028af0a
--- /dev/null
+++ b/docshell/test/mochitest/test_framedhistoryframes.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602256">Mozilla Bug 602256</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 */
+
+SimpleTest.waitForExplicitFinish();
+var win = window.open("file_framedhistoryframes.html");
+
+function done() {
+ win.close();
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_iframe_srcdoc_to_remote.html b/docshell/test/mochitest/test_iframe_srcdoc_to_remote.html
new file mode 100644
index 0000000000..05e0934d50
--- /dev/null
+++ b/docshell/test/mochitest/test_iframe_srcdoc_to_remote.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body onload="test()">
+ <script>
+ /*
+ Test to verify that when we change an OOP iframe to one that has a
+ srcdoc it loads in the correct process, which in this case is this
+ test document.
+ */
+ SimpleTest.waitForExplicitFinish();
+ async function test() {
+ // Create an OOP iframe
+ let frame = document.createElement("iframe");
+ await new Promise(r => {
+ frame.onload = r;
+ document.body.appendChild(frame);
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ frame.contentWindow.location = "http://example.net/tests/docshell/test/dummy_page.html";
+ });
+ if (SpecialPowers.useRemoteSubframes) {
+ ok(SpecialPowers.Cu.isRemoteProxy(frame.contentWindow), "should be a remote frame");
+ }
+
+ // Remove the attribute so we can set a srcdoc attribute on it
+ frame.removeAttribute("src");
+
+ // Set a srcdoc attribute on this iframe and wait for the load
+ await new Promise(r => {
+ frame.onload = r;
+ frame.setAttribute("srcdoc", '<html><body>body of the srcdoc frame</body></html>');
+ });
+
+ // We should be in the same process as this test document
+ ok(!SpecialPowers.Cu.isRemoteProxy(frame.contentWindow), "should NOT be a remote frame");
+ SimpleTest.finish();
+ }
+ </script>
+</body>
+
diff --git a/docshell/test/mochitest/test_javascript_sandboxed_popup.html b/docshell/test/mochitest/test_javascript_sandboxed_popup.html
new file mode 100644
index 0000000000..edce93c26f
--- /dev/null
+++ b/docshell/test/mochitest/test_javascript_sandboxed_popup.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body>
+<iframe srcdoc="<a href='javascript:opener.parent.ok(false, `The JS ran!`)' target=_blank rel=opener>click</a>"
+ sandbox="allow-popups allow-same-origin"></iframe>
+
+<script>
+add_task(async function() {
+ let promise = new Promise(resolve =>{
+ SpecialPowers.addObserver(function obs(subject) {
+ is(subject.opener, window[0],
+ "blocked javascript URI should have been targeting the pop-up document");
+ subject.close();
+ SpecialPowers.removeObserver(obs, "javascript-uri-blocked-by-sandbox");
+ resolve();
+ }, "javascript-uri-blocked-by-sandbox");
+ });
+ document.querySelector("iframe").contentDocument.querySelector("a").click();
+ await promise;
+});
+</script>
+</body>
diff --git a/docshell/test/mochitest/test_load_during_reload.html b/docshell/test/mochitest/test_load_during_reload.html
new file mode 100644
index 0000000000..88856b0100
--- /dev/null
+++ b/docshell/test/mochitest/test_load_during_reload.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test loading a new page after calling reload()</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+
+ function promiseForLoad() {
+ return new Promise(resolve => {
+ addEventListener("message", resolve, { once: true });
+ });
+ }
+
+ add_task(async function runTest() {
+ let win = window.open("file_load_during_reload.html");
+ await promiseForLoad();
+
+ win.location.reload();
+ win.location.href = "file_load_during_reload.html?nextpage";
+ await promiseForLoad();
+
+ ok(win.location.href.includes("nextpage"), "Should have loaded the next page.");
+ win.close();
+ });
+
+ add_task(async function runTest2() {
+ let win = window.open("file_load_during_reload.html");
+ await promiseForLoad();
+
+ win.history.replaceState("", "", "?1");
+ win.location.reload();
+ win.history.pushState("", "", "?2");
+ win.location.reload();
+ await promiseForLoad();
+
+ ok(win.location.href.includes("2"), "Should have loaded the second page.");
+ win.close();
+ });
+
+ </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_navigate_after_pagehide.html b/docshell/test/mochitest/test_navigate_after_pagehide.html
new file mode 100644
index 0000000000..17d58d6e62
--- /dev/null
+++ b/docshell/test/mochitest/test_navigate_after_pagehide.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Test for navigation attempts by scripts in inactive inner window</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+<body>
+<iframe src="dummy_page.html" id="iframe"></iframe>
+
+<script>
+"use strict";
+
+add_task(async function() {
+ let iframe = document.getElementById("iframe");
+
+ let navigate = iframe.contentWindow.eval(`(function() {
+ location.href = "/";
+ })`);
+
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ iframe.src = "http://example.com/";
+ await new Promise(resolve =>
+ iframe.addEventListener("load", resolve, { once: true })
+ );
+
+ // This should do nothing. But, importantly, it should especially not crash.
+ navigate();
+
+ ok(true, "We didn't crash");
+});
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_pushState_after_document_open.html b/docshell/test/mochitest/test_pushState_after_document_open.html
new file mode 100644
index 0000000000..b81951b7ae
--- /dev/null
+++ b/docshell/test/mochitest/test_pushState_after_document_open.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=957479
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 957479</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 957479 */
+ SimpleTest.waitForExplicitFinish();
+ // Child needs to invoke us, otherwise our onload will fire before the child
+ // has done the write/close bit.
+ onmessage = function doTest() {
+ is(frames[0].location.pathname, "/tests/docshell/test/mochitest/file_pushState_after_document_open.html",
+ "Should have the right path here");
+ is(frames[0].location.hash, "", "Should have the right hash here");
+ frames[0].history.pushState({}, "", frames[0].document.URL + "#foopy");
+ is(frames[0].location.pathname, "/tests/docshell/test/mochitest/file_pushState_after_document_open.html",
+ "Pathname should not have changed");
+ is(frames[0].location.hash, "#foopy", "Hash should have changed");
+ SimpleTest.finish();
+ };
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=957479">Mozilla Bug 957479</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe src="file_pushState_after_document_open.html"></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_redirect_history.html b/docshell/test/mochitest/test_redirect_history.html
new file mode 100644
index 0000000000..a67c808405
--- /dev/null
+++ b/docshell/test/mochitest/test_redirect_history.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Test for redirect from POST</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <script>
+ "use strict";
+
+ info("Starting tests");
+
+ let tests = new Map([
+ ["sameorigin", window.location.origin],
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ ["crossorigin", "http://test1.example.com"],
+ ]);
+ for (let [kind, origin] of tests) {
+ add_task(async function runTest() {
+ info(`Submitting to ${origin}`);
+
+ let win;
+ await new Promise(resolve => {
+ addEventListener("message", resolve, { once: true });
+ info("Loading file_redirect_history.html");
+ win = window.open("file_redirect_history.html");
+ });
+ info("Done loading file_redirect_history.html");
+
+ let length = win.history.length;
+ let loc = win.location.toString();
+
+ await new Promise(resolve => {
+ addEventListener("message", resolve, { once: true });
+ info("Posting");
+ win.postMessage(`${origin}/tests/docshell/test/mochitest/form_submit_redirect.sjs?redirectTo=${loc}`, "*")
+ });
+ info("Done posting\n");
+ is(win.history.length, length, `Test ${kind}: history length should not change.`);
+ info(`Length=${win.history.length}`);
+ is(win.location.toString(), loc, `Test ${kind}: location should not change.`);
+
+ await new Promise(resolve => {
+ addEventListener("message", resolve, { once: true });
+ info("Reloading");
+ win.location.reload();
+ });
+ info("Done reloading\n");
+ is(win.location.toString(), loc, `Test ${kind}: location should not change after reload.`);
+
+ win.close();
+ });
+ }
+ </script>
+ </body>
+</html>
diff --git a/docshell/test/mochitest/test_triggeringprincipal_location_seturi.html b/docshell/test/mochitest/test_triggeringprincipal_location_seturi.html
new file mode 100644
index 0000000000..92e20b03ea
--- /dev/null
+++ b/docshell/test/mochitest/test_triggeringprincipal_location_seturi.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<script type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+const SAME_ORIGIN_URI = "http://mochi.test:8888/tests/docshell/test/dummy_page.html";
+// eslint-disable-next-line @microsoft/sdl/no-insecure-url
+const CROSS_ORIGIN_URI = "http://example.com/tests/docshell/test/dummy_page.html";
+const NUMBER_OF_TESTS = 3;
+let testCounter = 0;
+
+function checkFinish() {
+ testCounter++;
+ if (testCounter < NUMBER_OF_TESTS) {
+ return;
+ }
+ SimpleTest.finish();
+}
+
+// ---- test 1 ----
+
+let myFrame1 = document.createElement("iframe");
+myFrame1.src = SAME_ORIGIN_URI;
+myFrame1.addEventListener("load", checkLoadFrame1);
+document.documentElement.appendChild(myFrame1);
+
+function checkLoadFrame1() {
+ myFrame1.removeEventListener("load", checkLoadFrame1);
+ // window.location.href is no longer cross-origin accessible in gecko.
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI,
+ "initial same origin dummy loaded into frame1");
+
+ SpecialPowers.wrap(myFrame1.contentWindow).location.hash = "#bar";
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI + "#bar",
+ "initial same origin dummy#bar loaded into iframe1");
+
+ myFrame1.addEventListener("load", checkNavFrame1);
+ myFrame1.src = CROSS_ORIGIN_URI;
+}
+
+async function checkNavFrame1() {
+ myFrame1.removeEventListener("load", checkNavFrame1);
+ is(await SpecialPowers.spawn(myFrame1, [], () => this.content.location.href),
+ CROSS_ORIGIN_URI,
+ "cross origin dummy loaded into frame1");
+
+ myFrame1.addEventListener("load", checkBackNavFrame1);
+ myFrame1.src = SAME_ORIGIN_URI + "#bar";
+}
+
+async function checkBackNavFrame1() {
+ myFrame1.removeEventListener("load", checkBackNavFrame1);
+ is(await SpecialPowers.spawn(myFrame1, [], () => this.content.location.href),
+ SAME_ORIGIN_URI + "#bar",
+ "navagiating back to same origin dummy for frame1");
+ checkFinish();
+}
+
+// ---- test 2 ----
+
+let myFrame2 = document.createElement("iframe");
+myFrame2.src = "about:blank";
+myFrame2.addEventListener("load", checkLoadFrame2);
+document.documentElement.appendChild(myFrame2);
+
+function checkLoadFrame2() {
+ myFrame2.removeEventListener("load", checkLoadFrame2);
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
+ "initial about:blank frame loaded");
+
+ myFrame2.contentWindow.location.hash = "#foo";
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank#foo",
+ "about:blank#foo frame loaded");
+
+ myFrame2.addEventListener("load", checkHistoryFrame2);
+ myFrame2.src = "about:blank";
+}
+
+function checkHistoryFrame2() {
+ myFrame2.removeEventListener("load", checkHistoryFrame2);
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
+ "about:blank frame loaded again");
+ checkFinish();
+}
+
+// ---- test 3 ----
+
+let myFrame3 = document.createElement("frame");
+document.documentElement.appendChild(myFrame3);
+myFrame3.contentWindow.location.hash = "#foo";
+
+is(myFrame3.contentWindow.location.href, "about:blank#foo",
+ "created history entry with about:blank#foo");
+checkFinish();
+
+</script>
+</body>
+</html>
diff --git a/docshell/test/mochitest/test_windowedhistoryframes.html b/docshell/test/mochitest/test_windowedhistoryframes.html
new file mode 100644
index 0000000000..a874da098c
--- /dev/null
+++ b/docshell/test/mochitest/test_windowedhistoryframes.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602256
+-->
+<head>
+ <title>Test for Bug 602256</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602256">Mozilla Bug 602256</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 602256 */
+
+SimpleTest.waitForExplicitFinish();
+
+function done() {
+ subWin.close();
+ SimpleTest.finish();
+}
+
+var subWin = window.open("historyframes.html", "_blank");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/docshell/test/mochitest/url1_historyframe.html b/docshell/test/mochitest/url1_historyframe.html
new file mode 100644
index 0000000000..b86af4b3fa
--- /dev/null
+++ b/docshell/test/mochitest/url1_historyframe.html
@@ -0,0 +1 @@
+<p id='text'>Test1</p>
diff --git a/docshell/test/mochitest/url2_historyframe.html b/docshell/test/mochitest/url2_historyframe.html
new file mode 100644
index 0000000000..24374d1a5b
--- /dev/null
+++ b/docshell/test/mochitest/url2_historyframe.html
@@ -0,0 +1 @@
+<p id='text'>Test2</p>