summaryrefslogtreecommitdiffstats
path: root/docshell/test/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/test/chrome')
-rw-r--r--docshell/test/chrome/112564_nocache.html10
-rw-r--r--docshell/test/chrome/112564_nocache.html^headers^1
-rw-r--r--docshell/test/chrome/215405_nocache.html14
-rw-r--r--docshell/test/chrome/215405_nocache.html^headers^1
-rw-r--r--docshell/test/chrome/215405_nostore.html14
-rw-r--r--docshell/test/chrome/215405_nostore.html^headers^1
-rw-r--r--docshell/test/chrome/582176_dummy.html1
-rw-r--r--docshell/test/chrome/582176_xml.xml2
-rw-r--r--docshell/test/chrome/582176_xslt.xsl8
-rw-r--r--docshell/test/chrome/662200a.html8
-rw-r--r--docshell/test/chrome/662200b.html8
-rw-r--r--docshell/test/chrome/662200c.html7
-rw-r--r--docshell/test/chrome/89419.html7
-rw-r--r--docshell/test/chrome/92598_nostore.html10
-rw-r--r--docshell/test/chrome/92598_nostore.html^headers^1
-rw-r--r--docshell/test/chrome/DocShellHelpers.sys.mjs74
-rw-r--r--docshell/test/chrome/allowContentRetargeting.sjs7
-rw-r--r--docshell/test/chrome/blue.pngbin0 -> 2745 bytes
-rw-r--r--docshell/test/chrome/bug112564_window.xhtml86
-rw-r--r--docshell/test/chrome/bug113934_window.xhtml165
-rw-r--r--docshell/test/chrome/bug215405_window.xhtml177
-rw-r--r--docshell/test/chrome/bug293235.html13
-rw-r--r--docshell/test/chrome/bug293235_p2.html8
-rw-r--r--docshell/test/chrome/bug293235_window.xhtml118
-rw-r--r--docshell/test/chrome/bug294258_testcase.html43
-rw-r--r--docshell/test/chrome/bug294258_window.xhtml72
-rw-r--r--docshell/test/chrome/bug298622_window.xhtml135
-rw-r--r--docshell/test/chrome/bug301397_1.html9
-rw-r--r--docshell/test/chrome/bug301397_2.html10
-rw-r--r--docshell/test/chrome/bug301397_3.html10
-rw-r--r--docshell/test/chrome/bug301397_4.html9
-rw-r--r--docshell/test/chrome/bug301397_window.xhtml218
-rw-r--r--docshell/test/chrome/bug303267.html23
-rw-r--r--docshell/test/chrome/bug303267_window.xhtml83
-rw-r--r--docshell/test/chrome/bug311007_window.xhtml204
-rw-r--r--docshell/test/chrome/bug321671_window.xhtml128
-rw-r--r--docshell/test/chrome/bug360511_case1.html15
-rw-r--r--docshell/test/chrome/bug360511_case2.html15
-rw-r--r--docshell/test/chrome/bug360511_window.xhtml127
-rw-r--r--docshell/test/chrome/bug364461_window.xhtml253
-rw-r--r--docshell/test/chrome/bug396519_window.xhtml132
-rw-r--r--docshell/test/chrome/bug396649_window.xhtml119
-rw-r--r--docshell/test/chrome/bug449778_window.xhtml107
-rw-r--r--docshell/test/chrome/bug449780_window.xhtml80
-rw-r--r--docshell/test/chrome/bug454235-subframe.xhtml7
-rw-r--r--docshell/test/chrome/bug582176_window.xhtml74
-rw-r--r--docshell/test/chrome/bug608669.xhtml14
-rw-r--r--docshell/test/chrome/bug662200_window.xhtml119
-rw-r--r--docshell/test/chrome/bug690056_window.xhtml171
-rw-r--r--docshell/test/chrome/bug846906.html10
-rw-r--r--docshell/test/chrome/bug89419.sjs12
-rw-r--r--docshell/test/chrome/bug89419_window.xhtml69
-rw-r--r--docshell/test/chrome/bug909218.html11
-rw-r--r--docshell/test/chrome/bug909218.js2
-rw-r--r--docshell/test/chrome/bug92598_window.xhtml89
-rw-r--r--docshell/test/chrome/chrome.ini105
-rw-r--r--docshell/test/chrome/docshell_helpers.js758
-rw-r--r--docshell/test/chrome/file_viewsource_forbidden_in_iframe.html11
-rw-r--r--docshell/test/chrome/gen_template.pl39
-rw-r--r--docshell/test/chrome/generic.html12
-rw-r--r--docshell/test/chrome/mozFrameType_window.xhtml49
-rw-r--r--docshell/test/chrome/red.pngbin0 -> 82 bytes
-rw-r--r--docshell/test/chrome/test.template.txt41
-rw-r--r--docshell/test/chrome/test_allowContentRetargeting.html76
-rw-r--r--docshell/test/chrome/test_bug112564.xhtml37
-rw-r--r--docshell/test/chrome/test_bug113934.xhtml29
-rw-r--r--docshell/test/chrome/test_bug215405.xhtml37
-rw-r--r--docshell/test/chrome/test_bug293235.xhtml38
-rw-r--r--docshell/test/chrome/test_bug294258.xhtml38
-rw-r--r--docshell/test/chrome/test_bug298622.xhtml38
-rw-r--r--docshell/test/chrome/test_bug301397.xhtml38
-rw-r--r--docshell/test/chrome/test_bug303267.xhtml39
-rw-r--r--docshell/test/chrome/test_bug311007.xhtml42
-rw-r--r--docshell/test/chrome/test_bug321671.xhtml38
-rw-r--r--docshell/test/chrome/test_bug360511.xhtml39
-rw-r--r--docshell/test/chrome/test_bug364461.xhtml43
-rw-r--r--docshell/test/chrome/test_bug396519.xhtml28
-rw-r--r--docshell/test/chrome/test_bug396649.xhtml41
-rw-r--r--docshell/test/chrome/test_bug428288.html37
-rw-r--r--docshell/test/chrome/test_bug449778.xhtml29
-rw-r--r--docshell/test/chrome/test_bug449780.xhtml29
-rw-r--r--docshell/test/chrome/test_bug453650.xhtml120
-rw-r--r--docshell/test/chrome/test_bug454235.xhtml40
-rw-r--r--docshell/test/chrome/test_bug456980.xhtml29
-rw-r--r--docshell/test/chrome/test_bug565388.xhtml79
-rw-r--r--docshell/test/chrome/test_bug582176.xhtml38
-rw-r--r--docshell/test/chrome/test_bug608669.xhtml80
-rw-r--r--docshell/test/chrome/test_bug662200.xhtml38
-rw-r--r--docshell/test/chrome/test_bug690056.xhtml26
-rw-r--r--docshell/test/chrome/test_bug789773.xhtml67
-rw-r--r--docshell/test/chrome/test_bug846906.xhtml94
-rw-r--r--docshell/test/chrome/test_bug89419.xhtml38
-rw-r--r--docshell/test/chrome/test_bug909218.html117
-rw-r--r--docshell/test/chrome/test_bug92598.xhtml37
-rw-r--r--docshell/test/chrome/test_docRedirect.sjs6
-rw-r--r--docshell/test/chrome/test_docRedirect.xhtml91
-rw-r--r--docshell/test/chrome/test_mozFrameType.xhtml42
-rw-r--r--docshell/test/chrome/test_open_and_immediately_close_opener.html54
-rw-r--r--docshell/test/chrome/test_viewsource_forbidden_in_iframe.xhtml159
-rw-r--r--docshell/test/chrome/window.template.txt44
100 files changed, 6021 insertions, 0 deletions
diff --git a/docshell/test/chrome/112564_nocache.html b/docshell/test/chrome/112564_nocache.html
new file mode 100644
index 0000000000..29fb990b86
--- /dev/null
+++ b/docshell/test/chrome/112564_nocache.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>test1</title>
+</head>
+<body>
+<p>
+This document will be sent with a no-cache cache-control header. When sent over a secure connection, it should not be stored in bfcache.
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/112564_nocache.html^headers^ b/docshell/test/chrome/112564_nocache.html^headers^
new file mode 100644
index 0000000000..c829a41ae9
--- /dev/null
+++ b/docshell/test/chrome/112564_nocache.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-cache
diff --git a/docshell/test/chrome/215405_nocache.html b/docshell/test/chrome/215405_nocache.html
new file mode 100644
index 0000000000..c7d48c4eba
--- /dev/null
+++ b/docshell/test/chrome/215405_nocache.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>test1</title>
+</head>
+<body style="height: 100%">
+ <input type="text" id="inp" value="">
+ </input>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%; width: 300%">Some more text</div>
+</body>
+</html>
diff --git a/docshell/test/chrome/215405_nocache.html^headers^ b/docshell/test/chrome/215405_nocache.html^headers^
new file mode 100644
index 0000000000..c829a41ae9
--- /dev/null
+++ b/docshell/test/chrome/215405_nocache.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-cache
diff --git a/docshell/test/chrome/215405_nostore.html b/docshell/test/chrome/215405_nostore.html
new file mode 100644
index 0000000000..4f5bd0f4f0
--- /dev/null
+++ b/docshell/test/chrome/215405_nostore.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>test1</title>
+</head>
+<body style="height: 100%">
+ <input type="text" id="inp" value="">
+ </input>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%">Some text</div>
+ <div style="height: 50%; width: 350%">Some more text</div>
+</body>
+</html>
diff --git a/docshell/test/chrome/215405_nostore.html^headers^ b/docshell/test/chrome/215405_nostore.html^headers^
new file mode 100644
index 0000000000..59ba296103
--- /dev/null
+++ b/docshell/test/chrome/215405_nostore.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-store
diff --git a/docshell/test/chrome/582176_dummy.html b/docshell/test/chrome/582176_dummy.html
new file mode 100644
index 0000000000..3b18e512db
--- /dev/null
+++ b/docshell/test/chrome/582176_dummy.html
@@ -0,0 +1 @@
+hello world
diff --git a/docshell/test/chrome/582176_xml.xml b/docshell/test/chrome/582176_xml.xml
new file mode 100644
index 0000000000..d3dd576dfe
--- /dev/null
+++ b/docshell/test/chrome/582176_xml.xml
@@ -0,0 +1,2 @@
+<?xml-stylesheet type="text/xsl" href="582176_xslt.xsl"?>
+<out/>
diff --git a/docshell/test/chrome/582176_xslt.xsl b/docshell/test/chrome/582176_xslt.xsl
new file mode 100644
index 0000000000..5957416899
--- /dev/null
+++ b/docshell/test/chrome/582176_xslt.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="out">
+ <html>
+ <head><title>XSLT result doc</title></head>
+ <body><p>xslt result</p></body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/docshell/test/chrome/662200a.html b/docshell/test/chrome/662200a.html
new file mode 100644
index 0000000000..0b9ead6f3e
--- /dev/null
+++ b/docshell/test/chrome/662200a.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>A</title>
+ </head>
+ <body>
+ <a id="link" href="662200b.html">Next</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/662200b.html b/docshell/test/chrome/662200b.html
new file mode 100644
index 0000000000..91e6b971d6
--- /dev/null
+++ b/docshell/test/chrome/662200b.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>B</title>
+ </head>
+ <body>
+ <a id="link" href="662200c.html">Next</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/662200c.html b/docshell/test/chrome/662200c.html
new file mode 100644
index 0000000000..bc00e6b14b
--- /dev/null
+++ b/docshell/test/chrome/662200c.html
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ <title>C</title>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/docshell/test/chrome/89419.html b/docshell/test/chrome/89419.html
new file mode 100644
index 0000000000..b36b8d788c
--- /dev/null
+++ b/docshell/test/chrome/89419.html
@@ -0,0 +1,7 @@
+<html>
+<head>
+<title>Bug 89419</title>
+</head>
+<body>
+<img src="http://mochi.test:8888/tests/docshell/test/chrome/bug89419.sjs">
+</body>
diff --git a/docshell/test/chrome/92598_nostore.html b/docshell/test/chrome/92598_nostore.html
new file mode 100644
index 0000000000..47bb90441e
--- /dev/null
+++ b/docshell/test/chrome/92598_nostore.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>test1</title>
+</head>
+<body>
+<p>
+This document will be sent with a no-store cache-control header. It should not be stored in bfcache.
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/92598_nostore.html^headers^ b/docshell/test/chrome/92598_nostore.html^headers^
new file mode 100644
index 0000000000..59ba296103
--- /dev/null
+++ b/docshell/test/chrome/92598_nostore.html^headers^
@@ -0,0 +1 @@
+Cache-control: no-store
diff --git a/docshell/test/chrome/DocShellHelpers.sys.mjs b/docshell/test/chrome/DocShellHelpers.sys.mjs
new file mode 100644
index 0000000000..5f4eee8724
--- /dev/null
+++ b/docshell/test/chrome/DocShellHelpers.sys.mjs
@@ -0,0 +1,74 @@
+/* Any copyright is dedicated to the Public Domain.
+http://creativecommons.org/publicdomain/zero/1.0/ */
+
+export class DocShellHelpersParent extends JSWindowActorParent {
+ static eventListener;
+
+ // These static variables should be set when registering the actor
+ // (currently doPageNavigation in docshell_helpers.js).
+ static eventsToListenFor;
+ static observers;
+
+ constructor() {
+ super();
+ }
+ receiveMessage({ name, data }) {
+ if (name == "docshell_helpers:event") {
+ let { event, originalTargetIsHTMLDocument } = data;
+
+ if (this.constructor.eventsToListenFor.includes(event.type)) {
+ this.constructor.eventListener(event, originalTargetIsHTMLDocument);
+ }
+ } else if (name == "docshell_helpers:observe") {
+ let { topic } = data;
+
+ this.constructor.observers.get(topic).call();
+ }
+ }
+}
+
+export class DocShellHelpersChild extends JSWindowActorChild {
+ constructor() {
+ super();
+ }
+ receiveMessage({ name, data }) {
+ if (name == "docshell_helpers:preventBFCache") {
+ // Add an RTCPeerConnection to prevent the page from being bfcached.
+ let win = this.contentWindow;
+ win.blockBFCache = new win.RTCPeerConnection();
+ }
+ }
+ handleEvent(event) {
+ if (
+ Document.isInstance(event.originalTarget) &&
+ event.originalTarget.isInitialDocument
+ ) {
+ dump(`TEST: ignoring a ${event.type} event for an initial about:blank\n`);
+ return;
+ }
+
+ this.sendAsyncMessage("docshell_helpers:event", {
+ event: {
+ type: event.type,
+ persisted: event.persisted,
+ originalTarget: {
+ title: event.originalTarget.title,
+ location: event.originalTarget.location.href,
+ visibilityState: event.originalTarget.visibilityState,
+ hidden: event.originalTarget.hidden,
+ },
+ },
+ originalTargetIsHTMLDocument: HTMLDocument.isInstance(
+ event.originalTarget
+ ),
+ });
+ }
+ observe(subject, topic) {
+ if (Window.isInstance(subject) && subject.document.isInitialDocument) {
+ dump(`TEST: ignoring a topic notification for an initial about:blank\n`);
+ return;
+ }
+
+ this.sendAsyncMessage("docshell_helpers:observe", { topic });
+ }
+}
diff --git a/docshell/test/chrome/allowContentRetargeting.sjs b/docshell/test/chrome/allowContentRetargeting.sjs
new file mode 100644
index 0000000000..96e467ef68
--- /dev/null
+++ b/docshell/test/chrome/allowContentRetargeting.sjs
@@ -0,0 +1,7 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(req, resp) {
+ resp.setHeader("Content-Type", "application/octet-stream", false);
+ resp.write("hi");
+}
diff --git a/docshell/test/chrome/blue.png b/docshell/test/chrome/blue.png
new file mode 100644
index 0000000000..8df58f3a5f
--- /dev/null
+++ b/docshell/test/chrome/blue.png
Binary files differ
diff --git a/docshell/test/chrome/bug112564_window.xhtml b/docshell/test/chrome/bug112564_window.xhtml
new file mode 100644
index 0000000000..b4c7d05dc2
--- /dev/null
+++ b/docshell/test/chrome/bug112564_window.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="112564Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="112564 test">
+
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ var gTestsIterator;
+
+ function onLoad() {
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function nextTest() {
+ gTestsIterator.next();
+ }
+
+ function* testsIterator() {
+ // Load a secure page with a no-cache header, followed by a simple page.
+ // no-cache should not interfere with the bfcache in the way no-store
+ // does.
+ var test1DocURI = "https://example.com:443/chrome/docshell/test/chrome/112564_nocache.html";
+
+ doPageNavigation({
+ uri: test1DocURI,
+ eventsToListenFor: ["load", "pageshow"],
+ expectedEvents: [ { type: "load",
+ title: "test1" },
+ { type: "pageshow",
+ title: "test1",
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ var test2DocURI = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ doPageNavigation({
+ uri: test2DocURI,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test1",
+ persisted: true },
+ { type: "load",
+ title: "test2" },
+ { type: "pageshow",
+ title: "test2",
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now go back in history. First page has been cached.
+ // Check persisted property to confirm
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test2",
+ persisted: true },
+ { type: "pageshow",
+ title: "test1",
+ persisted: true } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug113934_window.xhtml b/docshell/test/chrome/bug113934_window.xhtml
new file mode 100644
index 0000000000..cf6343f309
--- /dev/null
+++ b/docshell/test/chrome/bug113934_window.xhtml
@@ -0,0 +1,165 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 113934" onload="doTheTest()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox>
+ <vbox id="box1">
+ </vbox>
+ <vbox id="box2">
+ </vbox>
+ <spacer flex="1"/>
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ /* globals SimpleTest, is, isnot, ok, snapshotWindow, compareSnapshots,
+ onerror */
+ var imports = [ "SimpleTest", "is", "isnot", "ok", "snapshotWindow",
+ "compareSnapshots", "onerror" ];
+ for (var name of imports) {
+ window[name] = window.arguments[0][name];
+ }
+
+ function $(id) {
+ return document.getElementById(id);
+ }
+
+ function addBrowser(parent, id, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ var type = window.location.search.slice(1);
+ is(type == "chrome" || type == "content", true, "Unexpected type");
+ b.setAttribute("type", type);
+ b.setAttribute("id", id);
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ $(parent).appendChild(b);
+ }
+ addBrowser("box1", "f1", 300, 200);
+ addBrowser("box1", "f2", 300, 200);
+ addBrowser("box2", "f3", 30, 200);
+
+ /** Test for Bug 113934 **/
+ var doc1 =
+ "data:text/html,<html><body onbeforeunload='document.documentElement.textContent = \"\"' onunload='document.documentElement.textContent = \"\"' onpagehide='document.documentElement.textContent = \"\"'>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><head></head><body>This is a second test</body></html>";
+
+
+ $("f1").setAttribute("src", doc1);
+ $("f2").setAttribute("src", doc2);
+ $("f3").setAttribute("src", doc2);
+
+ async function doTheTest() {
+ var s2 = await snapshotWindow($("f2").contentWindow);
+ // var s3 = await snapshotWindow($("f3").contentWindow);
+
+ // This test is broken - see bug 1090274
+ //ok(!compareSnapshots(s2, s3, true)[0],
+ // "Should look different due to different sizing");
+
+ function getDOM(id) {
+ return $(id).contentDocument.documentElement.innerHTML;
+ }
+
+ var dom1 = getDOM("f1");
+
+ var dom2 = getDOM("f2");
+ $("f2").contentDocument.body.textContent = "Modified the text";
+ var dom2star = getDOM("f2");
+ isnot(dom2, dom2star, "We changed the DOM!");
+
+ $("f1").swapDocShells($("f2"));
+ // now we have doms 2*, 1, 2 in the frames
+
+ is(getDOM("f1"), dom2star, "Shouldn't have changed the DOM on swap");
+ is(getDOM("f2"), dom1, "Shouldn't have fired event handlers");
+
+ // Test for bug 480149
+ // The DOMLink* events are dispatched asynchronously, thus I cannot
+ // just include the <link> element in the initial DOM and swap the
+ // docshells. Instead, the link element is added now. Then, when the
+ // first DOMLinkAdded event (which is a result of the actual addition)
+ // is dispatched, the docshells are swapped and the pageshow and pagehide
+ // events are tested. Only then, we wait for the DOMLink* events,
+ // which are a result of swapping the docshells.
+ var DOMLinkListener = {
+ _afterFirst: false,
+ _removedDispatched: false,
+ _addedDispatched: false,
+ async handleEvent(aEvent) {
+ if (!this._afterFirst) {
+ is(aEvent.type, "DOMLinkAdded");
+
+ var strs = { "f1": "", "f3" : "" };
+ function attachListener(node, type) {
+ var listener = function(e) {
+ if (strs[node.id]) strs[node.id] += " ";
+ strs[node.id] += node.id + ".page" + type;
+ }
+ node.addEventListener("page" + type, listener);
+
+ listener.detach = function() {
+ node.removeEventListener("page" + type, listener);
+ }
+ return listener;
+ }
+
+ var l1 = attachListener($("f1"), "show");
+ var l2 = attachListener($("f1"), "hide");
+ var l3 = attachListener($("f3"), "show");
+ var l4 = attachListener($("f3"), "hide");
+
+ $("f1").swapDocShells($("f3"));
+ // now we have DOMs 2, 1, 2* in the frames
+
+ l1.detach();
+ l2.detach();
+ l3.detach();
+ l4.detach();
+
+ // swapDocShells reflows asynchronously, ensure layout is
+ // clean so that the viewport of f1 is the right size.
+ $("f1").getBoundingClientRect();
+ var s1_new = await snapshotWindow($("f1").contentWindow);
+ var [same, first, second] = compareSnapshots(s1_new, s2, true);
+ ok(same, "Should reflow on swap. Expected " + second + " but got " + first);
+
+ is(strs.f1, "f1.pagehide f1.pageshow");
+ is(strs.f3, "f3.pagehide f3.pageshow");
+ this._afterFirst = true;
+ return;
+ }
+ if (aEvent.type == "DOMLinkAdded") {
+ is(this._addedDispatched, false);
+ this._addedDispatched = true;
+ }
+ else {
+ is(this._removedDispatched, false);
+ this._removedDispatched = true;
+ }
+
+ if (this._addedDispatched && this._removedDispatched) {
+ $("f1").removeEventListener("DOMLinkAdded", this);
+ $("f1").removeEventListener("DOMLinkRemoved", this);
+ $("f3").removeEventListener("DOMLinkAdded", this);
+ $("f3").removeEventListener("DOMLinkRemoved", this);
+ window.close();
+ SimpleTest.finish();
+ }
+ }
+ };
+
+ $("f1").addEventListener("DOMLinkAdded", DOMLinkListener);
+ $("f1").addEventListener("DOMLinkRemoved", DOMLinkListener);
+ $("f3").addEventListener("DOMLinkAdded", DOMLinkListener);
+ $("f3").addEventListener("DOMLinkRemoved", DOMLinkListener);
+
+ var linkElement = $("f1").contentDocument.createElement("link");
+ linkElement.setAttribute("rel", "alternate");
+ linkElement.setAttribute("href", "about:blank");
+ $("f1").contentDocument.documentElement.firstChild.appendChild(linkElement);
+ }
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug215405_window.xhtml b/docshell/test/chrome/bug215405_window.xhtml
new file mode 100644
index 0000000000..73366482b7
--- /dev/null
+++ b/docshell/test/chrome/bug215405_window.xhtml
@@ -0,0 +1,177 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="215405Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="215405 test">
+
+ <script type="application/javascript"><![CDATA[
+ const {BrowserTestUtils} = ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ /* globals SimpleTest, is, isnot, ok */
+ var imports = [ "SimpleTest", "is", "isnot", "ok"];
+ for (var name of imports) {
+ window[name] = window.arguments[0][name];
+ }
+
+ const text="MOZILLA";
+ const nostoreURI = "http://mochi.test:8888/tests/docshell/test/chrome/" +
+ "215405_nostore.html";
+ const nocacheURI = "https://example.com:443/tests/docshell/test/chrome/" +
+ "215405_nocache.html";
+
+ var gBrowser;
+ var gTestsIterator;
+ var currScrollX = 0;
+ var currScrollY = 0;
+
+ function finish() {
+ gBrowser.removeEventListener("pageshow", eventListener, true);
+ // Work around bug 467960
+ let historyPurged;
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ let history = gBrowser.browsingContext.sessionHistory;
+ history.purgeHistory(history.count);
+ historyPurged = Promise.resolve();
+ } else {
+ historyPurged = SpecialPowers.spawn(gBrowser, [], () => {
+ let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory
+ .legacySHistory;
+ history.purgeHistory(history.count);
+ });
+ }
+
+ historyPurged.then(_ => {
+ window.close();
+ window.arguments[0].SimpleTest.finish();
+ });
+ }
+
+ function onLoad(e) {
+ gBrowser = document.getElementById("content");
+ gBrowser.addEventListener("pageshow", eventListener, true);
+
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function eventListener(event) {
+ setTimeout(nextTest, 0);
+ }
+
+ function nextTest() {
+ gTestsIterator.next();
+ }
+
+ function* testsIterator() {
+ // No-store tests
+ var testName = "[nostore]";
+
+ // Load a page with a no-store header
+ BrowserTestUtils.loadURI(gBrowser, nostoreURI);
+ yield undefined;
+
+
+ // Now that the page has loaded, amend the form contents
+ var form = gBrowser.contentDocument.getElementById("inp");
+ form.value = text;
+
+ // Attempt to scroll the page
+ var originalXPosition = gBrowser.contentWindow.scrollX;
+ var originalYPosition = gBrowser.contentWindow.scrollY;
+ var scrollToX = gBrowser.contentWindow.scrollMaxX;
+ var scrollToY = gBrowser.contentWindow.scrollMaxY;
+ gBrowser.contentWindow.scrollBy(scrollToX, scrollToY);
+
+ // Save the scroll position for future comparison
+ currScrollX = gBrowser.contentWindow.scrollX;
+ currScrollY = gBrowser.contentWindow.scrollY;
+ isnot(currScrollX, originalXPosition,
+ testName + " failed to scroll window horizontally");
+ isnot(currScrollY, originalYPosition,
+ testName + " failed to scroll window vertically");
+
+ // Load a new document into the browser
+ var simple = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+ BrowserTestUtils.loadURI(gBrowser, simple);
+ yield undefined;
+
+
+ // Now go back in history. First page should not have been cached.
+ gBrowser.goBack();
+ yield undefined;
+
+
+ // First uncacheable page will now be reloaded. Check scroll position
+ // restored, and form contents not
+ is(gBrowser.contentWindow.scrollX, currScrollX, testName +
+ " horizontal axis scroll position not correctly restored");
+ is(gBrowser.contentWindow.scrollY, currScrollY, testName +
+ " vertical axis scroll position not correctly restored");
+ var formValue = gBrowser.contentDocument.getElementById("inp").value;
+ isnot(formValue, text, testName + " form value incorrectly restored");
+
+
+ // https no-cache
+ testName = "[nocache]";
+
+ // Load a page with a no-cache header. This should not be
+ // restricted like no-store (bug 567365)
+ BrowserTestUtils.loadURI(gBrowser, nocacheURI);
+ yield undefined;
+
+
+ // Now that the page has loaded, amend the form contents
+ form = gBrowser.contentDocument.getElementById("inp");
+ form.value = text;
+
+ // Attempt to scroll the page
+ originalXPosition = gBrowser.contentWindow.scrollX;
+ originalYPosition = gBrowser.contentWindow.scrollY;
+ scrollToX = gBrowser.contentWindow.scrollMaxX;
+ scrollToY = gBrowser.contentWindow.scrollMaxY;
+ gBrowser.contentWindow.scrollBy(scrollToX, scrollToY);
+
+ // Save the scroll position for future comparison
+ currScrollX = gBrowser.contentWindow.scrollX;
+ currScrollY = gBrowser.contentWindow.scrollY;
+ isnot(currScrollX, originalXPosition,
+ testName + " failed to scroll window horizontally");
+ isnot(currScrollY, originalYPosition,
+ testName + " failed to scroll window vertically");
+
+ BrowserTestUtils.loadURI(gBrowser, simple);
+ yield undefined;
+
+
+ // Now go back in history to the cached page.
+ gBrowser.goBack();
+ yield undefined;
+
+
+ // First page will now be reloaded. Check scroll position
+ // and form contents are restored
+ is(gBrowser.contentWindow.scrollX, currScrollX, testName +
+ " horizontal axis scroll position not correctly restored");
+ is(gBrowser.contentWindow.scrollY, currScrollY, testName +
+ " vertical axis scroll position not correctly restored");
+ formValue = gBrowser.contentDocument.getElementById("inp").value;
+ is(formValue, text, testName + " form value not correctly restored");
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug293235.html b/docshell/test/chrome/bug293235.html
new file mode 100644
index 0000000000..458f88431c
--- /dev/null
+++ b/docshell/test/chrome/bug293235.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>Bug 293235 page1</title>
+ <style type="text/css">
+ a:visited, a.forcevisited.forcevisited { color: rgb(128, 0, 128); }
+ a:link, a.forcelink.forcelink { color: rgb(0, 0, 128); }
+ a:focus { color: rgb(128, 0, 0); }
+ </style>
+ </head>
+ <body>
+ <a id="link1" href="bug293235_p2.html">This is a test link.</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug293235_p2.html b/docshell/test/chrome/bug293235_p2.html
new file mode 100644
index 0000000000..2de067b80e
--- /dev/null
+++ b/docshell/test/chrome/bug293235_p2.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Bug 293235 page2</title>
+ </head>
+ <body>
+ Nothing to see here, move along.
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug293235_window.xhtml b/docshell/test/chrome/bug293235_window.xhtml
new file mode 100644
index 0000000000..7d87517824
--- /dev/null
+++ b/docshell/test/chrome/bug293235_window.xhtml
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="293235Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTests, 0);"
+ title="bug 293235 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <script type="application/javascript"><![CDATA[
+ var {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+ // Return the Element object for the specified element id
+ function $(id) { return TestWindow.getDocument().getElementById(id); }
+
+ ////
+ // Generator function for test steps for bug 293235:
+ // A visited link should have the :visited style applied
+ // to it when displayed on a page which was fetched from
+ // the bfcache.
+ //
+ async function runTests() {
+ // Register our observer to know when the link lookup is complete.
+ let testURI = NetUtil.newURI(getHttpUrl("bug293235_p2.html"));
+ let os = SpecialPowers.Services.obs;
+ // Load a test page containing a link that should be initially
+ // blue, per the :link style.
+ await new Promise(resolve => {
+ doPageNavigation({
+ uri: getHttpUrl("bug293235.html"),
+ onNavComplete: resolve,
+ });
+ });
+
+ // Now that we've been notified, we can check our link color.
+ // Since we can't use getComputedStyle() for this because
+ // getComputedStyle lies about styles that result from :visited,
+ // we have to take snapshots.
+ // First, take two reference snapshots.
+ var link1 = $("link1");
+ link1.className = "forcelink";
+ var refLink = await snapshotWindow(TestWindow.getWindow());
+ link1.className = "forcevisited";
+ var refVisited = await snapshotWindow(TestWindow.getWindow());
+ link1.className = "";
+ function snapshotsEqual(snap1, snap2) {
+ return compareSnapshots(snap1, snap2, true)[0];
+ }
+ ok(!snapshotsEqual(refLink, refVisited), "references should not match");
+ ok(snapshotsEqual(refLink, await snapshotWindow(TestWindow.getWindow())),
+ "link should initially be blue");
+
+ let observedVisit = false, observedPageShow = false;
+ await new Promise(resolve => {
+ function maybeResolve() {
+ ok(true, "maybe run next test? visited: " + observedVisit + " pageShow: " + observedPageShow);
+ if (observedVisit && observedPageShow)
+ resolve();
+ }
+
+ // Because adding visits is async, we will not be notified immediately.
+ let visitObserver = {
+ observe(aSubject, aTopic, aData)
+ {
+ if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
+ return;
+ }
+ os.removeObserver(this, aTopic);
+ observedVisit = true;
+ maybeResolve();
+ },
+ };
+ os.addObserver(visitObserver, "uri-visit-saved");
+ // Load the page that the link on the previous page points to.
+ doPageNavigation({
+ uri: getHttpUrl("bug293235_p2.html"),
+ onNavComplete() {
+ observedPageShow = true;
+ maybeResolve();
+ }
+ });
+ })
+
+ // And the nodes get notified after the "uri-visit-saved" topic, so
+ // we need to execute soon...
+ await new Promise(SimpleTest.executeSoon);
+
+ // Go back, verify the original page was loaded from the bfcache,
+ // and verify that the link is now purple, per the
+ // :visited style.
+ await new Promise(resolve => {
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ { type: "pageshow",
+ persisted: true,
+ title: "Bug 293235 page1" } ],
+ onNavComplete: resolve,
+ });
+ })
+
+ // Now we can test the link color.
+ ok(snapshotsEqual(refVisited, await snapshotWindow(TestWindow.getWindow())),
+ "visited link should be purple");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug294258_testcase.html b/docshell/test/chrome/bug294258_testcase.html
new file mode 100644
index 0000000000..cd80fefd06
--- /dev/null
+++ b/docshell/test/chrome/bug294258_testcase.html
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Bug 294258 Testcase</title>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml"/>
+ <style type="text/css">
+ * {
+ font-family: monospace;
+ }
+ </style>
+ </head>
+ <body>
+ <div>
+ <p>
+ input type="text": <input id="text" type="text"/>
+ </p>
+ <p>
+ input type="checkbox": <input id="checkbox" type="checkbox"/>
+ </p>
+ <p>
+ input type="file": <input id="file" type="file"/>
+ </p>
+ <p>
+ input type="radio":
+ <input type="radio" id="radio1" name="radio" value="radio1"/>
+ <input id="radio2" type="radio" name="radio" value="radio2"/>
+ </p>
+ <p>
+ textarea: <textarea id="textarea" rows="4" cols="80"></textarea>
+ </p>
+ <p>
+ select -> option: <select id="select">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option>4</option>
+ </select>
+ </p>
+ </div>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug294258_window.xhtml b/docshell/test/chrome/bug294258_window.xhtml
new file mode 100644
index 0000000000..fe47f3e70f
--- /dev/null
+++ b/docshell/test/chrome/bug294258_window.xhtml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="294258Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest, 0);"
+ title="bug 294258 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ function $(id) { return TestWindow.getDocument().getElementById(id); }
+
+ ////
+ // Generator function for test steps for bug 294258:
+ // Form values should be preserved on reload.
+ //
+ function* testIterator()
+ {
+ // Load a page containing a form.
+ doPageNavigation( {
+ uri: getHttpUrl("bug294258_testcase.html"),
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Change the data for each of the form fields, and reload.
+ $("text").value = "text value";
+ $("checkbox").checked = true;
+ var file = SpecialPowers.Services.dirsvc.get("TmpD", Ci.nsIFile);
+ file.append("294258_test.file");
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ let filePath = file.path;
+ $("file").value = filePath;
+ $("textarea").value = "textarea value";
+ $("radio1").checked = true;
+ $("select").selectedIndex = 2;
+ doPageNavigation( {
+ reload: true,
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+
+ // Verify that none of the form data has changed.
+ is($("text").value, "text value", "Text value changed");
+ is($("checkbox").checked, true, "Checkbox value changed");
+ is($("file").value, filePath, "File value changed");
+ is($("textarea").value, "textarea value", "Textarea value changed");
+ is($("radio1").checked, true, "Radio value changed");
+ is($("select").selectedIndex, 2, "Select value changed");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug298622_window.xhtml b/docshell/test/chrome/bug298622_window.xhtml
new file mode 100644
index 0000000000..318fb9d1d3
--- /dev/null
+++ b/docshell/test/chrome/bug298622_window.xhtml
@@ -0,0 +1,135 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="298622Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTest, 0);"
+ title="bug 298622 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src= "docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ // Global variable that holds a reference to the find bar.
+ var gFindBar;
+
+ ////
+ // Test for bug 298622:
+ // Find should work correctly on a page loaded from the
+ // bfcache.
+ //
+ async function runTest()
+ {
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load a test page which contains some text to be found.
+ await promisePageNavigation({
+ uri: "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>find this!</body></html>",
+ });
+
+ // Load a second, dummy page, verifying that the original
+ // page gets stored in the bfcache.
+ await promisePageNavigation({
+ uri: getHttpUrl("generic.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test1",
+ persisted: true },
+ { type: "pageshow",
+ title: "generic page" } ],
+ });
+
+ // Make sure we unsuppress painting before continuing
+ await new Promise(resolve => {
+ SimpleTest.executeSoon(resolve);
+ });
+
+ // Search for some text that's on the second page (but not on
+ // the first page), and verify that it can be found.
+ gFindBar = document.getElementById("FindToolbar");
+ document.getElementById("cmd_find").doCommand();
+ ok(!gFindBar.hidden, "failed to open findbar");
+ gFindBar._findField.value = "A generic page";
+ gFindBar._find();
+ await new Promise(resolve => {
+ SimpleTest.executeSoon(resolve);
+ });
+
+ // Make sure Find bar's internal status is not 'notfound'
+ isnot(gFindBar._findField.getAttribute("status"), "notfound",
+ "Findfield status attribute should not have been 'notfound'" +
+ " after Find");
+
+ // Make sure the key events above have time to be processed
+ // before continuing
+ await promiseTrue(() =>
+ SpecialPowers.spawn(document.getElementById("content"), [], function() {
+ return content.document.getSelection().toString().toLowerCase() == "a generic page";
+ }), 20
+ );
+
+ is(gFindBar._findField.value, "A generic page",
+ "expected text not present in find input field");
+ is(await SpecialPowers.spawn(document.getElementById("content"), [], async function() {
+ return content.document.getSelection().toString().toLowerCase();
+ }),
+ "a generic page",
+ "find failed on second page loaded");
+
+ // Go back to the original page and verify it's loaded from the
+ // bfcache.
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ { type: "pageshow",
+ title: "test1",
+ persisted: true } ],
+ });
+
+ // Search for some text that's on the original page (but not
+ // the dummy page loaded above), and verify that it can
+ // be found.
+ gFindBar = document.getElementById("FindToolbar");
+ document.getElementById("cmd_find").doCommand();
+ ok(!gFindBar.hidden, "failed to open findbar");
+ gFindBar._findField.value = "find this";
+ gFindBar._find();
+ await new Promise(resolve => {
+ SimpleTest.executeSoon(resolve);
+ });
+
+ // Make sure Find bar's internal status is not 'notfound'
+ isnot(gFindBar._findField.getAttribute("status"), "notfound",
+ "Findfield status attribute should not have been 'notfound'" +
+ " after Find");
+
+ // Make sure the key events above have time to be processed
+ // before continuing
+ await promiseTrue(() =>
+ SpecialPowers.spawn(document.getElementById("content"), [], function() {
+ return content.document.getSelection().toString().toLowerCase() == "find this";
+ }), 20
+ );
+
+ is(await SpecialPowers.spawn(document.getElementById("content"), [], async function() {
+ return content.document.getSelection().toString().toLowerCase();
+ }),
+ "find this",
+ "find failed on page loaded from bfcache");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <commandset>
+ <command id="cmd_find"
+ oncommand="document.getElementById('FindToolbar').onFindCommand();"/>
+ </commandset>
+ <browser type="content" primary="true" flex="1" id="content" messagemanagergroup="test" remote="true" />
+ <findbar id="FindToolbar" browserid="content"/>
+</window>
diff --git a/docshell/test/chrome/bug301397_1.html b/docshell/test/chrome/bug301397_1.html
new file mode 100644
index 0000000000..9943c2efe6
--- /dev/null
+++ b/docshell/test/chrome/bug301397_1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe parent</title>
+ </head>
+<body>
+ <iframe id="iframe" src="bug301397_2.html"/>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_2.html b/docshell/test/chrome/bug301397_2.html
new file mode 100644
index 0000000000..4237107060
--- /dev/null
+++ b/docshell/test/chrome/bug301397_2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe content #1</title>
+ </head>
+<body>
+ iframe page 1<br/>
+ <a id="link" href="bug301397_3.html">go to next page</a>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_3.html b/docshell/test/chrome/bug301397_3.html
new file mode 100644
index 0000000000..8d36e92461
--- /dev/null
+++ b/docshell/test/chrome/bug301397_3.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>iframe content #2</title>
+ </head>
+<body>
+ iframe page 2<br/>
+ You made it!
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_4.html b/docshell/test/chrome/bug301397_4.html
new file mode 100644
index 0000000000..5584a4554a
--- /dev/null
+++ b/docshell/test/chrome/bug301397_4.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>dummy page, no iframe</title>
+ </head>
+<body>
+ Just a boring test page, nothing special.
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug301397_window.xhtml b/docshell/test/chrome/bug301397_window.xhtml
new file mode 100644
index 0000000000..bf0f33c794
--- /dev/null
+++ b/docshell/test/chrome/bug301397_window.xhtml
@@ -0,0 +1,218 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="301397Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTest, 0);"
+ title="bug 301397 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ ////
+ // Verifies that the given string exists in the innerHTML of the iframe
+ // content.
+ //
+ async function verifyIframeInnerHtml(string) {
+ var iframeInnerHtml = await SpecialPowers.spawn(document.getElementById("content"), [string], (string) =>
+ content.document.getElementById("iframe").contentDocument.body.innerHTML);
+ ok(iframeInnerHtml.includes(string),
+ "iframe contains wrong document: " + iframeInnerHtml);
+ }
+
+ ////
+ // Generator function for test steps for bug 301397:
+ // The correct page should be displayed in an iframe when
+ // navigating back and forwards, when the parent page
+ // occupies multiple spots in the session history.
+ //
+ async function runTest()
+ {
+ // Make sure the bfcache is enabled.
+ enableBFCache(8);
+
+ // Load a dummy page.
+ await promisePageNavigation({
+ uri: getHttpUrl("generic.html"),
+ });
+
+ // Load a page containing an iframe.
+ await promisePageNavigation({
+ uri: getHttpUrl("bug301397_1.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "generic page",
+ persisted: true },
+ { type: "pageshow",
+ title: "iframe content #1",
+ persisted: false }, // false on initial load
+ { type: "pageshow",
+ title: "iframe parent",
+ persisted: false } ], // false on initial load
+ });
+
+ // Click a link in the iframe to cause the iframe to navigate
+ // to a new page, and wait until the related pagehide/pageshow
+ // events have occurred.
+ let waitForLinkNavigation = promisePageEvents({
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #2",
+ persisted: false } ], // false on initial load
+ });
+ SpecialPowers.spawn(document.getElementById("content"), [], function() {
+ let iframe = content.document.getElementById("iframe");
+ let link = iframe.contentDocument.getElementById("link");
+ let event = iframe.contentDocument.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, iframe.contentWindow,
+ 0, 0, 0, 0, 0,
+ false, false, false, false,
+ 0, null);
+ link.dispatchEvent(event);
+ });
+ await waitForLinkNavigation;
+
+ // Load another dummy page. Verify that both the outgoing parent and
+ // iframe pages are stored in the bfcache.
+ await promisePageNavigation({
+ uri: getHttpUrl("bug301397_4.html"),
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: true },
+ { type: "pageshow",
+ title: "dummy page, no iframe",
+ persisted: false } ], // false on initial load
+ });
+
+ // Go back. The iframe should show the second page loaded in it.
+ // Both the parent and the iframe pages should be loaded from
+ // the bfcache.
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "dummy page, no iframe",
+ persisted: true },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe content #2" },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe parent" } ],
+ });
+
+ verifyIframeInnerHtml("You made it");
+
+ // Go gack again. The iframe should show the first page loaded in it.
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #1",
+ // false since this page was never stored
+ // in the bfcache in the first place
+ persisted: false } ],
+ });
+
+ verifyIframeInnerHtml("go to next page");
+
+ // Go back to the generic page. Now go forward to the last page,
+ // again verifying that the iframe shows the first and second
+ // pages in order.
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: true },
+ { type: "pageshow",
+ title: "generic page",
+ persisted: true } ],
+ });
+
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow",
+ title: "iframe content #1",
+ persisted: true},
+ {type: "pageshow",
+ title: "iframe parent",
+ persisted: true} ],
+ });
+
+ verifyIframeInnerHtml("go to next page");
+
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe content #1",
+ persisted: false }, // false, subframe nav
+ { type: "pageshow",
+ title: "iframe content #2",
+ // false because the page wasn't stored in
+ // bfcache last time it was unloaded
+ persisted: false } ],
+ });
+
+ verifyIframeInnerHtml("You made it");
+
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "iframe parent",
+ persisted: true },
+ { type: "pagehide",
+ title: "iframe content #2",
+ persisted: true },
+ { type: "pageshow",
+ title: "dummy page, no iframe",
+ persisted: true } ],
+ });
+
+ // Go back once more, and again verify that the iframe shows the
+ // second page loaded in it.
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "dummy page, no iframe",
+ persisted: true },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe content #2" },
+ { type: "pageshow",
+ persisted: true,
+ title: "iframe parent" } ],
+ });
+
+ verifyIframeInnerHtml("You made it");
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" messagemanagergroup="test" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug303267.html b/docshell/test/chrome/bug303267.html
new file mode 100644
index 0000000000..21b9f30311
--- /dev/null
+++ b/docshell/test/chrome/bug303267.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+ <title>
+ bug303267.html
+ </title>
+ </head>
+<body onpageshow="showpageshowcount()">
+<script>
+var pageshowcount = 0;
+function showpageshowcount() {
+ pageshowcount++;
+ var div1 = document.getElementById("div1");
+ while (div1.firstChild) {
+ div1.firstChild.remove();
+ }
+ div1.appendChild(document.createTextNode(
+ "pageshowcount: " + pageshowcount));
+}
+</script>
+<div id="div1">
+ </div>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug303267_window.xhtml b/docshell/test/chrome/bug303267_window.xhtml
new file mode 100644
index 0000000000..f985b4da59
--- /dev/null
+++ b/docshell/test/chrome/bug303267_window.xhtml
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTests, 0);"
+ title="bug 303267 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ ////
+ // Bug 303267: When a page is displayed from the bfcache, the script globals should
+ // remain intact from the page's initial load.
+ //
+ async function runTests()
+ {
+ // Load an initial test page which should be saved in the bfcache.
+ var navData = {
+ uri: getHttpUrl("bug303267.html"),
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: "bug303267.html"} ],
+ };
+ await promisePageNavigation(navData);
+
+ // Save the HTML of the test page for later comparison.
+ var originalHTML = await getInnerHTMLById("div1");
+
+ // Load a second test page. The first test page's pagehide event should
+ // have the .persisted property set to true, indicating that it was
+ // stored in the bfcache.
+ navData = {
+ uri: "data:text/html,<html><head><title>page2</title></head>" +
+ "<body>bug303267, page2</body></html>",
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "bug303267.html",
+ persisted: true},
+ {type: "pageshow",
+ title: "page2"} ],
+ };
+ await promisePageNavigation(navData);
+
+ // Go back. Verify that the pageshow event for the original test page
+ // had a .persisted property of true, indicating that it came from the
+ // bfcache.
+ navData = {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "page2"},
+ {type: "pageshow",
+ title: "bug303267.html",
+ persisted: true} ],
+ };
+ await promisePageNavigation(navData);
+
+ // After going back, if showpagecount() could access a global variable
+ // and change the test div's innerHTML, then we pass. Otherwise, it
+ // threw an exception and the following test will fail.
+ var newHTML = await getInnerHTMLById("div1");
+ isnot(originalHTML,
+ newHTML, "HTML not updated on pageshow; javascript broken?");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ////
+ // Return the innerHTML of a particular element in the content document.
+ //
+ function getInnerHTMLById(id) {
+ return SpecialPowers.spawn(TestWindow.getBrowser(), [id], (id) => {
+ return content.document.getElementById(id).innerHTML;
+ });
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug311007_window.xhtml b/docshell/test/chrome/bug311007_window.xhtml
new file mode 100644
index 0000000000..13ae5e16e3
--- /dev/null
+++ b/docshell/test/chrome/bug311007_window.xhtml
@@ -0,0 +1,204 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="311007Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="startup();"
+ title="bug 311007 test">
+
+ <script src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js"></script>
+ <script type="application/javascript"><![CDATA[
+ // `content` is the id of the browser element used for the test.
+ /* global content */
+/*
+ Regression test for bug 283733 and bug 307027.
+
+ Bug 283733
+ "accessing a relative anchor in a secure page removes the
+ locked icon and yellow background UI"
+
+ Bug 307027
+ "Going back from secure page to error page does not clear yellow bar"
+
+ And enhancements:
+
+ Bug 478927
+ onLocationChange should notify whether or not loading an error page.
+
+ */
+
+const kDNSErrorURI = "https://example/err.html";
+const kSecureURI =
+ "https://example.com/tests/docshell/test/navigation/blank.html";
+
+/*
+ Step 1: load a network error page. <err.html> Not Secure
+ Step 2: load a secure page. <blank.html> Secure
+ Step 3: a secure page + hashchange. <blank.html#foo> Secure (bug 283733)
+ Step 4: go back to the error page. <err.html> Not Secure (bug 307027)
+ */
+
+var gListener = null;
+
+function WebProgressListener() {
+ this._callback = null;
+}
+
+WebProgressListener.prototype = {
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+
+ onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
+ setTimeout(this._callback, 0, aWebProgress, aRequest, aLocation, aFlags);
+ },
+
+ set callback(aVal) {
+ this._callback = aVal;
+ }
+};
+
+function startup() {
+ gListener = new WebProgressListener();
+
+ document.getElementById("content")
+ .webProgress
+ .addProgressListener(gListener,
+ Ci.nsIWebProgress
+ .NOTIFY_LOCATION);
+
+ setTimeout(step1A, 0);
+}
+
+/******************************************************************************
+ * Step 1: Load an error page, and confirm UA knows it's insecure.
+ ******************************************************************************/
+
+function step1A() {
+ gListener.callback = step1B;
+ content.location = kDNSErrorURI;
+}
+
+function step1B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kDNSErrorURI, "Error page's URI (1)");
+
+ ok(!(aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (1)");
+
+ ok((aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is an error page.");
+
+ ok(!(document.getElementById("content")
+ .browsingContext
+ .secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is not a secure page (1)");
+
+ /* Go to step 2. */
+ setTimeout(step2A, 0);
+}
+
+/******************************************************************************
+ * Step 2: Load a HTTPS page, and confirm it's secure.
+ ******************************************************************************/
+
+function step2A() {
+ gListener.callback = step2B;
+ content.location = kSecureURI;
+}
+
+function step2B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kSecureURI, "A URI on HTTPS (2)");
+
+ ok(!(aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (2)");
+
+ ok(!(aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is not an error page.");
+
+ ok((document.getElementById("content")
+ .browsingContext
+ .secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is a secure page (2)");
+
+ /* Go to step 3. */
+ setTimeout(step3A, 0);
+}
+
+/*****************************************************************************
+ * Step 3: Trigger hashchange within a secure page, and confirm UA knows
+ * it's secure. (Bug 283733)
+ *****************************************************************************/
+
+function step3A() {
+ gListener.callback = step3B;
+ content.location += "#foo";
+}
+
+function step3B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kSecureURI + "#foo", "hashchange on HTTPS (3)");
+
+ ok((aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "We are in the same document as before (3)");
+
+ ok(!(aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is not an error page.");
+
+ ok((document.getElementById("content")
+ .browsingContext
+ .secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is a secure page (3)");
+
+ /* Go to step 4. */
+ setTimeout(step4A, 0);
+}
+
+/*****************************************************************************
+ * Step 4: Go back from a secure page to an error page, and confirm UA knows
+ * it's not secure. (Bug 307027)
+ *****************************************************************************/
+
+function step4A() {
+ gListener.callback = step4B;
+ content.history.go(-2);
+}
+
+function step4B(aWebProgress, aRequest, aLocation, aFlags) {
+ is(aLocation.spec, kDNSErrorURI, "Go back to the error URI (4)");
+
+ ok(!(aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_SAME_DOCUMENT),
+ "DocShell loaded a document (4)");
+
+ ok((aFlags & Ci.nsIWebProgressListener
+ .LOCATION_CHANGE_ERROR_PAGE),
+ "This page is an error page.");
+
+ ok(!(document.getElementById("content")
+ .browsingContext
+ .secureBrowserUI.state &
+ Ci.nsIWebProgressListener.STATE_IS_SECURE),
+ "This is not a secure page (4)");
+
+ /* End. */
+ document.getElementById("content")
+ .webProgress.removeProgressListener(gListener);
+ gListener = null;
+ finish();
+}
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug321671_window.xhtml b/docshell/test/chrome/bug321671_window.xhtml
new file mode 100644
index 0000000000..e8fb9fbc06
--- /dev/null
+++ b/docshell/test/chrome/bug321671_window.xhtml
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="321671Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTest, 0);"
+ title="bug 321671 test">
+
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ // Maximum number of entries in the bfcache for this session history.
+ // This number is hardcoded in docshell code. In the test, we'll
+ // navigate through enough pages so that we hit one that's been
+ // evicted from the bfcache because it's farther from the current
+ // page than this number.
+ const MAX_BFCACHE_PAGES = 3;
+
+ ////
+ // Bug 321671: Scroll position should be retained when moving backwards and
+ // forwards through pages when bfcache is enabled.
+ //
+ async function runTest()
+ {
+ // Variable to hold the scroll positions of the test pages.
+ var scrollPositions = [];
+
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load enough test pages that so the first one is evicted from the
+ // bfcache, scroll down on each page, and save the
+ // current scroll position before continuing. Verify that each
+ // page we're navigating away from is initially put into the bfcache.
+ for (var i = 0; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ let eventsToListenFor = ["pageshow"];
+ let expectedEvents = [ { type: "pageshow",
+ title: "bug321671 page" + (i + 1) } ];
+ if (i > 0) {
+ eventsToListenFor.push("pagehide");
+ expectedEvents.unshift({ type: "pagehide",
+ persisted: true,
+ title: "bug321671 page" + i });
+ }
+ await promisePageNavigation( {
+ uri: "data:text/html,<html><head><title>bug321671 page" + (i + 1) +
+ "</title></head>" +
+ "<body><table border='1' width='300' height='1000'>" +
+ "<tbody><tr><td>" +
+ " page " + (i + 1) + ": foobar foobar foobar foobar " +
+ "</td></tr></tbody></table> " +
+ "</body></html>",
+ eventsToListenFor,
+ expectedEvents,
+ } );
+
+ let { initialScrollY, scrollY } = await SpecialPowers.spawn(TestWindow.getBrowser(), [i], (i) => {
+ let initialScrollY = content.scrollY;
+ content.scrollByLines(10 + (2 * i));
+ return { initialScrollY, scrollY: content.scrollY };
+ });
+ is(initialScrollY, 0,
+ "Page initially has non-zero scrollY position");
+ ok(scrollY > 0,
+ "Page has zero scrollY position after scrolling");
+ scrollPositions[i] = scrollY;
+ }
+
+ // Go back to the first page, one page at a time. For each 'back'
+ // action, verify that its vertical scroll position is restored
+ // correctly. Verify that the last page in the sequence
+ // does not come from the bfcache. Again verify that all pages
+ // that we navigate away from are initially
+ // stored in the bfcache.
+ for (i = MAX_BFCACHE_PAGES + 1; i > 0; i--) {
+ await promisePageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug321671 page" + (i+1),
+ persisted: true },
+ { type: "pageshow",
+ title: "bug321671 page" + i,
+ persisted: i > 1 } ],
+ } );
+
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.scrollY;
+ }), scrollPositions[i-1],
+ "Scroll position not restored while going back!");
+ }
+
+ // Traverse history forward now, and verify scroll position is still
+ // restored. Similar to the backward traversal, verify that all
+ // but the last page in the sequence comes from the bfcache. Also
+ // verify that all of the pages get stored in the bfcache when we
+ // navigate away from them.
+ for (i = 1; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ await promisePageNavigation( {
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ persisted: true,
+ title: "bug321671 page" + i },
+ { type: "pageshow",
+ persisted: i < MAX_BFCACHE_PAGES + 1,
+ title: "bug321671 page" + (i + 1) } ],
+ } );
+
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.scrollY;
+ }), scrollPositions[i],
+ "Scroll position not restored while going forward!");
+ }
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug360511_case1.html b/docshell/test/chrome/bug360511_case1.html
new file mode 100644
index 0000000000..cca043bb66
--- /dev/null
+++ b/docshell/test/chrome/bug360511_case1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>
+ bug360511 case 1
+ </title>
+ </head>
+<body style="height: 100%">
+<a id="link1" href="#bottom">jump to bottom</a>
+<div id="div1" style="height: 200%; border: thin solid black;">
+ hello large div
+ </div>
+ <a name="bottom">here's the bottom of the page</a>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug360511_case2.html b/docshell/test/chrome/bug360511_case2.html
new file mode 100644
index 0000000000..217f47724e
--- /dev/null
+++ b/docshell/test/chrome/bug360511_case2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+ <title>
+ bug360511 case 2
+ </title>
+ </head>
+<body style="height: 100%">
+<a id="link1" href="#bottom">jump to bottom</a>
+<div id="div1" style="height: 200%; border: thin solid black;">
+ hello large div
+ </div>
+ <a name="bottom">here's the bottom of the page</a>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug360511_window.xhtml b/docshell/test/chrome/bug360511_window.xhtml
new file mode 100644
index 0000000000..3a22b081a1
--- /dev/null
+++ b/docshell/test/chrome/bug360511_window.xhtml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="360511Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTest, 0);"
+ title="bug 360511 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ function getScrollY()
+ {
+ return SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.scrollY;
+ });
+ }
+ function getLocation()
+ {
+ return SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.location.href;
+ });
+ }
+
+ ////
+ // Bug 360511: Fragment uri's in session history should be restored correctly
+ // upon back navigation.
+ //
+ async function runTest()
+ {
+ // Case 1: load a page containing a fragment link; the page should be
+ // stored in the bfcache.
+ // Case 2: load a page containing a fragment link; the page should NOT
+ // be stored in the bfcache.
+ for (var i = 1; i < 3; i++)
+ {
+ var url = "bug360511_case" + i + ".html";
+ await promisePageNavigation( {
+ uri: getHttpUrl(url),
+ preventBFCache: i != 1
+ } );
+
+ // Store the original url for later comparison.
+ var originalUrl = TestWindow.getBrowser().currentURI.spec;
+ var originalDocLocation = await getLocation();
+
+ // Verify we're at the top of the page.
+ is(await getScrollY(), 0, "Page initially has a non-zero scrollY property");
+
+ // Click the on the fragment link in the browser, and use setTimeout
+ // to give the event a chance to be processed.
+ await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ var event = content.document.createEvent('MouseEvent');
+ event.initMouseEvent("click", true, true, content, 0,
+ 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ content.document.getElementById("link1").dispatchEvent(event);
+ });
+ await promiseNextPaint();
+
+ // Verify we're no longer at the top of the page.
+ await promiseTrue(async function() {
+ return await getScrollY() > 0;
+ }, 20);
+
+ // Store the fragment url for later comparison.
+ var fragmentUrl = TestWindow.getBrowser().currentURI.spec;
+ let fragDocLocation = await getLocation();
+
+ // Now navigate to any other page
+ var expectedPageTitle = "bug360511 case " + i;
+ await promisePageNavigation( {
+ uri: getHttpUrl("generic.html"),
+ eventsToListenFor: ["pagehide", "pageshow"],
+ expectedEvents: [ {type: "pagehide", title: expectedPageTitle,
+ persisted: i == 1},
+ {type: "pageshow"} ],
+ } );
+
+ // Go back
+ await promisePageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: expectedPageTitle,
+ persisted: i == 1} ],
+ } );
+
+ // Verify the current url is the fragment url
+ is(TestWindow.getBrowser().currentURI.spec, fragmentUrl,
+ "current url is not the previous fragment url");
+ is(await getLocation(), fragDocLocation,
+ "document.location is not the previous fragment url");
+
+ // Go back again. Since we're just going from a fragment url to
+ // parent url, no pageshow event is fired, so don't wait for any
+ // events. Rather, just wait for the page's scrollY property to
+ // change.
+ var originalScrollY = await getScrollY();
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: []
+ } );
+ await promiseTrue(
+ async function() {
+ return (await getScrollY() != originalScrollY);
+ }, 20);
+
+ // Verify the current url is the original url without fragment
+ is(TestWindow.getBrowser().currentURI.spec, originalUrl,
+ "current url is not the original url");
+ is(await getLocation(), originalDocLocation,
+ "document.location is not the original url");
+ }
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug364461_window.xhtml b/docshell/test/chrome/bug364461_window.xhtml
new file mode 100644
index 0000000000..d64a7b9e23
--- /dev/null
+++ b/docshell/test/chrome/bug364461_window.xhtml
@@ -0,0 +1,253 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="364461Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="runTest();"
+ title="364461 test">
+
+ <script src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ var gBrowser;
+
+ async function runTest() {
+ gBrowser = document.getElementById("content");
+
+ // Tests 1 + 2:
+ // Back/forward between two simple documents. Bfcache will be used.
+
+ var test1Doc = "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>test1</body></html>";
+
+ await promisePageNavigation({
+ uri: test1Doc,
+ eventsToListenFor: ["load", "pageshow"],
+ expectedEvents: [{type: "load", title: "test1"},
+ {type: "pageshow", title: "test1", persisted: false}],
+ });
+
+ var test2Doc = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ await promisePageNavigation({
+ uri: test2Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test1", persisted: true},
+ {type: "load", title: "test2"},
+ {type: "pageshow", title: "test2", persisted: false}],
+ });
+
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test2", persisted: true},
+ {type: "pageshow", title: "test1", persisted: true}],
+ });
+
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test1", persisted: true},
+ {type: "pageshow", title: "test2", persisted: true}],
+ });
+
+ // Tests 3 + 4:
+ // Back/forward between a two-level deep iframed document and a simple
+ // document. Bfcache will be used and events should be dispatched to
+ // all frames.
+
+ var test3Doc = "data:text/html,<html><head><title>test3</title>" +
+ "</head><body>" +
+ "<iframe src='data:text/html," +
+ "<html><head><title>test3-nested1</title></head>" +
+ "<body>test3-nested1" +
+ "<iframe src=\"data:text/html," +
+ "<html><head><title>test3-nested2</title></head>" +
+ "<body>test3-nested2</body></html>\">" +
+ "</iframe>" +
+ "</body></html>'>" +
+ "</iframe>" +
+ "</body></html>";
+
+ await promisePageNavigation({
+ uri: test3Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test2", persisted: true},
+ {type: "load", title: "test3-nested2"},
+ {type: "pageshow", title: "test3-nested2", persisted: false},
+ {type: "load", title: "test3-nested1"},
+ {type: "pageshow", title: "test3-nested1", persisted: false},
+ {type: "load", title: "test3"},
+ {type: "pageshow", title: "test3", persisted: false}],
+ });
+
+ var test4Doc = "data:text/html,<html><head><title>test4</title></head>" +
+ "<body>test4</body></html>";
+
+ await promisePageNavigation({
+ uri: test4Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test3", persisted: true},
+ {type: "pagehide", title: "test3-nested1", persisted: true},
+ {type: "pagehide", title: "test3-nested2", persisted: true},
+ {type: "load", title: "test4"},
+ {type: "pageshow", title: "test4", persisted: false}],
+ });
+
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test4", persisted: true},
+ {type: "pageshow", title: "test3-nested2", persisted: true},
+ {type: "pageshow", title: "test3-nested1", persisted: true},
+ {type: "pageshow", title: "test3", persisted: true}],
+ });
+
+ // This is where the two nested pagehide are not dispatched in bug 364461
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test3", persisted: true},
+ {type: "pagehide", title: "test3-nested1", persisted: true},
+ {type: "pagehide", title: "test3-nested2", persisted: true},
+ {type: "pageshow", title: "test4", persisted: true}],
+ });
+
+ // Tests 5 + 6:
+ // Back/forward between a document containing an unload handler and a
+ // a simple document. Bfcache won't be used for the first one (see
+ // http://developer.mozilla.org/en/docs/Using_Firefox_1.5_caching).
+
+ var test5Doc = "data:text/html,<html><head><title>test5</title></head>" +
+ "<body onunload='while(false) { /* nop */ }'>" +
+ "test5</body></html>";
+
+ await promisePageNavigation({
+ uri: test5Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test4", persisted: true},
+ {type: "load", title: "test5"},
+ {type: "pageshow", title: "test5", persisted: false}],
+ });
+
+ var test6Doc = "data:text/html,<html><head><title>test6</title></head>" +
+ "<body>test6</body></html>";
+
+ await promisePageNavigation({
+ uri: test6Doc,
+ eventsToListenFor: ["load", "unload", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test5", persisted: false},
+ {type: "unload", title: "test5"},
+ {type: "load", title: "test6"},
+ {type: "pageshow", title: "test6", persisted: false}],
+ });
+
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test6", persisted: true},
+ {type: "load", title: "test5"},
+ {type: "pageshow", title: "test5", persisted: false}],
+ });
+
+ await promisePageNavigation({
+ forward: true,
+ eventsToListenFor: ["unload", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test5", persisted: false},
+ {type: "unload", title: "test5"},
+ {type: "pageshow", title: "test6", persisted: true}],
+ });
+
+ // Test 7:
+ // Testcase from https://bugzilla.mozilla.org/show_bug.cgi?id=384977#c10
+ // Check that navigation is not blocked after a document is restored
+ // from bfcache
+
+ var test7Doc = "data:text/html,<html><head><title>test7</title>" +
+ "</head><body>" +
+ "<iframe src='data:text/html," +
+ "<html><head><title>test7-nested1</title></head>" +
+ "<body>test7-nested1<br/>" +
+ "<a href=\"data:text/plain,aaa\" target=\"_top\">" +
+ "Click me, hit back, click me again</a>" +
+ "</body></html>'>" +
+ "</iframe>" +
+ "</body></html>";
+
+ await promisePageNavigation({
+ uri: test7Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test6", persisted: true},
+ {type: "load", title: "test7-nested1"},
+ {type: "pageshow", title: "test7-nested1", persisted: false},
+ {type: "load", title: "test7"},
+ {type: "pageshow", title: "test7", persisted: false}],
+ });
+
+ // Simulates a click on the link inside the iframe
+ function clickIframeLink() {
+ SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ var iframe = content.document.getElementsByTagName("iframe")[0];
+ var w = iframe.contentWindow;
+ var d = iframe.contentDocument;
+
+ var evt = d.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, w,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ d.getElementsByTagName("a")[0].dispatchEvent(evt);
+ });
+ }
+
+ let clicked = promisePageNavigation({
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test7", persisted: true},
+ {type: "pagehide", title: "test7-nested1", persisted: true},
+ {type: "load"},
+ {type: "pageshow", persisted: false}],
+ waitForEventsOnly: true,
+ });
+ clickIframeLink();
+ await clicked;
+
+ is(gBrowser.currentURI.spec, "data:text/plain,aaa",
+ "Navigation is blocked when clicking link");
+
+ await promisePageNavigation({
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", persisted: true},
+ {type: "pageshow", title: "test7-nested1", persisted: true},
+ {type: "pageshow", title: "test7", persisted: true}],
+ });
+
+ clicked = promisePageNavigation({
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [{type: "pagehide", title: "test7", persisted: true},
+ {type: "pagehide", title: "test7-nested1", persisted: true},
+ {type: "load"},
+ {type: "pageshow", persisted: false}],
+ waitForEventsOnly: true,
+ });
+ clickIframeLink();
+ await clicked;
+
+ is(gBrowser.currentURI.spec, "data:text/plain,aaa",
+ "Navigation is blocked when clicking link");
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug396519_window.xhtml b/docshell/test/chrome/bug396519_window.xhtml
new file mode 100644
index 0000000000..5cbc6f5a41
--- /dev/null
+++ b/docshell/test/chrome/bug396519_window.xhtml
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="396519Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="runTest();"
+ title="396519 test">
+
+ <script src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ var gTestCount = 0;
+
+ async function navigateAndTest(params, expected) {
+ await promisePageNavigation(params);
+ ++gTestCount;
+ await doTest(expected);
+ }
+
+ async function doTest(expected) {
+ function check(testCount, expected) {
+ let history;
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ history = this.browsingContext.sessionHistory;
+ } else {
+ history = this.content.browsingContext.childSessionHistory.legacySHistory;
+ }
+ if (history.count == expected.length) {
+ for (let i = 0; i < history.count; i++) {
+ var shEntry = history.getEntryAtIndex(i).
+ QueryInterface(Ci.nsISHEntry);
+ is(shEntry.isInBFCache, expected[i], `BFCache for shentry[${i}], test ${testCount}`);
+ }
+
+ // Make sure none of the SHEntries share bfcache entries with one
+ // another.
+ for (let i = 0; i < history.count; i++) {
+ for (let j = 0; j < history.count; j++) {
+ if (j == i)
+ continue;
+
+ let shentry1 = history.getEntryAtIndex(i)
+ .QueryInterface(Ci.nsISHEntry);
+ let shentry2 = history.getEntryAtIndex(j)
+ .QueryInterface(Ci.nsISHEntry);
+ ok(!shentry1.sharesDocumentWith(shentry2),
+ 'Test ' + testCount + ': shentry[' + i + "] shouldn't " +
+ "share document with shentry[" + j + ']');
+ }
+ }
+ }
+ else {
+ is(history.count, expected.length, "Wrong history length in test "+testCount);
+ }
+ }
+
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ check.call(TestWindow.getBrowser(), gTestCount, expected);
+ } else {
+ await SpecialPowers.spawn(TestWindow.getBrowser(), [gTestCount, expected], check);
+ }
+ }
+
+ async function runTest() {
+ // Tests 1 + 2:
+ // Back/forward between two simple documents. Bfcache will be used.
+
+ var test1Doc = "data:text/html,<html><head><title>test1</title></head>" +
+ "<body>test1</body></html>";
+
+ await navigateAndTest({
+ uri: test1Doc,
+ }, [false]);
+
+ var test2Doc = test1Doc.replace(/1/,"2");
+
+ await navigateAndTest({
+ uri: test2Doc,
+ }, [true, false]);
+
+ await navigateAndTest({
+ uri: test1Doc,
+ }, [true, true, false]);
+
+ await navigateAndTest({
+ uri: test2Doc,
+ }, [true, true, true, false]);
+
+ await navigateAndTest({
+ uri: test1Doc,
+ }, [false, true, true, true, false]);
+
+ await navigateAndTest({
+ uri: test2Doc,
+ }, [false, false, true, true, true, false]);
+
+ await navigateAndTest({
+ back: true,
+ }, [false, false, true, true, false, true]);
+
+ await navigateAndTest({
+ forward: true,
+ }, [false, false, true, true, true, false]);
+
+ await navigateAndTest({
+ gotoIndex: 1,
+ }, [false, false, true, true, true, false]);
+
+ await navigateAndTest({
+ back: true,
+ }, [false, true, true, true, false, false]);
+
+ await navigateAndTest({
+ gotoIndex: 5,
+ }, [false, false, true, true, false, false]);
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug396649_window.xhtml b/docshell/test/chrome/bug396649_window.xhtml
new file mode 100644
index 0000000000..16a243bc74
--- /dev/null
+++ b/docshell/test/chrome/bug396649_window.xhtml
@@ -0,0 +1,119 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="396649Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest, 0);"
+ title="bug 396649 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ // Maximum number of entries in the bfcache for this session history.
+ // This number is hardcoded in docshell code. In the test, we'll
+ // navigate through enough pages so that we hit one that's been
+ // evicted from the bfcache because it's farther from the current
+ // page than this number.
+ const MAX_BFCACHE_PAGES = 3;
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug 396649: Content
+ // viewers should be evicted from bfcache when going back if more
+ // than MAX_BFCACHE_PAGES from the current index.
+ //
+ function* testIterator()
+ {
+ // Make sure bfcache is on.
+ enableBFCache(true);
+
+ // Load enough pages so that the first loaded is eviced from
+ // the bfcache, since it is greater the MAX_BFCACHE_PAGES from
+ // the current position in the session history. Verify all
+ // of the pages are initially stored in the bfcache when
+ // they're unloaded.
+ for (var i = 0; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ let eventsToListenFor = ["pageshow"];
+ let expectedEvents = [ { type: "pageshow",
+ title: "bug396649 page" + i } ];
+ if (i > 0) {
+ eventsToListenFor.push("pagehide");
+ expectedEvents.unshift({ type: "pagehide",
+ title: "bug396649 page" + (i-1) });
+ }
+ doPageNavigation( {
+ uri: "data:text/html,<!DOCTYPE html><html>" +
+ "<head><title>bug396649 page" + i +
+ "</title></head>" +
+ "<body>" +
+ "test page " + i +
+ "</body></html>",
+ eventsToListenFor,
+ expectedEvents,
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ // Go back to the first page, one page at a time. The first
+ // MAX_BFCACHE_PAGES pages loaded via back should come from the bfcache,
+ // the last should not, since it should have been evicted during the
+ // previous navigation sequence. Verify all pages are initially stored
+ // in the bfcache when they're unloaded.
+ for (i = MAX_BFCACHE_PAGES + 1; i > 0; i--) {
+ doPageNavigation( {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug396649 page" + i,
+ persisted: true },
+ { type: "pageshow",
+ title: "bug396649 page" + (i - 1),
+ persisted: i > 1 } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ // Traverse history forward now. Again, the first MAX_BFCACHE_PAGES
+ // pages should come from the bfcache, the last should not,
+ // since it should have been evicted during the backwards
+ // traversal above. Verify all pages are initially stored
+ // in the bfcache when they're unloaded.
+ for (i = 1; i <= MAX_BFCACHE_PAGES + 1; i++) {
+ doPageNavigation( {
+ forward: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "bug396649 page" + (i-1),
+ persisted: true },
+ { type: "pageshow",
+ title: "bug396649 page" + i,
+ persisted: i < MAX_BFCACHE_PAGES + 1 } ],
+ onNavComplete: nextTest
+ } );
+ yield undefined;
+ }
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug449778_window.xhtml b/docshell/test/chrome/bug449778_window.xhtml
new file mode 100644
index 0000000000..1bbb8d4b2b
--- /dev/null
+++ b/docshell/test/chrome/bug449778_window.xhtml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 449778" onload="doTheTest()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox id="parent">
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ /* globals SimpleTest, is */
+ var imports = [ "SimpleTest", "is" ];
+ for (var name of imports) {
+ window[name] = window.arguments[0][name];
+ }
+
+ function $(id) {
+ return document.getElementById(id);
+ }
+
+ function addBrowser(parent, id, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ b.setAttribute("type", "content");
+ b.setAttribute("id", id);
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ $(parent).appendChild(b);
+ }
+ addBrowser("parent", "f1", 300, 200);
+ addBrowser("parent", "f2", 300, 200);
+
+ /** Test for Bug 449778 **/
+ var doc1 = "data:text/html,<html><body>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
+ var doc3 = "data:text/html,<html><body>This is a <script>var evt = document.createEvent('Events'); evt.initEvent('testEvt', true, true); document.dispatchEvent(evt);</script>third test</body></html>";
+
+
+ $("f1").setAttribute("src", doc1);
+ $("f2").setAttribute("src", doc2);
+
+ function doTheTest() {
+ var strs = { "f1": "", "f2" : "" };
+ function attachListener(node, type) {
+ var listener = function(e) {
+ if (strs[node.id]) strs[node.id] += " ";
+ strs[node.id] += node.id + ".page" + type;
+ }
+ node.addEventListener("page" + type, listener);
+
+ listener.detach = function() {
+ node.removeEventListener("page" + type, listener);
+ }
+ return listener;
+ }
+
+ var l1 = attachListener($("f1"), "show");
+ var l2 = attachListener($("f1"), "hide");
+ var l3 = attachListener($("f2"), "show");
+ var l4 = attachListener($("f2"), "hide");
+
+ $("f1").swapDocShells($("f2"));
+
+ is(strs.f1, "f1.pagehide f1.pageshow",
+ "Expected hide then show on first loaded page");
+ is(strs.f2, "f2.pagehide f2.pageshow",
+ "Expected hide then show on second loaded page");
+
+ function listener2() {
+ $("f2").removeEventListener("testEvt", listener2);
+
+ strs = { "f1": "", "f2" : "" };
+
+ $("f1").swapDocShells($("f2"));
+ is(strs.f1, "f1.pagehide",
+ "Expected hide on already-loaded page, then nothing");
+ is(strs.f2, "f2.pageshow f2.pagehide f2.pageshow",
+ "Expected show on still-loading page, then hide on it, then show " +
+ "on already-loaded page");
+
+ strs = { "f1": "", "f2" : "" };
+
+ $("f1").addEventListener("pageshow", listener3);
+ }
+
+ function listener3() {
+ $("f1").removeEventListener("pageshow", listener3);
+
+ is(strs.f1, "f1.pageshow",
+ "Expected show as our page finishes loading");
+ is(strs.f2, "", "Expected no more events here.");
+
+ l1.detach();
+ l2.detach();
+ l3.detach();
+ l4.detach();
+
+ window.close();
+ SimpleTest.finish();
+ }
+
+ $("f2").addEventListener("testEvt", listener2, false, true);
+ $("f2").setAttribute("src", doc3);
+ }
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug449780_window.xhtml b/docshell/test/chrome/bug449780_window.xhtml
new file mode 100644
index 0000000000..3b0096d2e9
--- /dev/null
+++ b/docshell/test/chrome/bug449780_window.xhtml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 449780" onload="setTimeout(doTheTest, 0);"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <hbox id="parent">
+ </hbox>
+
+ <!-- test code goes here -->
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ function addBrowser(parent, width, height) {
+ var b =
+ document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser");
+ b.setAttribute("type", "content");
+ b.setAttribute("id", "content");
+ b.setAttribute("width", width);
+ b.setAttribute("height", height);
+ b.setAttribute("remote", SpecialPowers.Services.appinfo.sessionHistoryInParent);
+ document.getElementById("parent").appendChild(b);
+ return b;
+ }
+
+ let f1 = addBrowser("parent", 300, 200);
+
+ /** Test for Bug 449780 **/
+ var doc1 = "data:text/html,<html><body>This is a test</body></html>";
+ var doc2 = "data:text/html,<html><body>This is a second test</body></html>";
+
+ async function doTheTest() {
+ await promisePageNavigation({
+ uri: doc1,
+ });
+ let { origDOM, modifiedDOM } = await SpecialPowers.spawn(f1, [], () => {
+ var origDOM = content.document.documentElement.innerHTML;
+ content.document.body.textContent = "Modified";
+ var modifiedDOM = content.document.documentElement.innerHTML;
+ isnot(origDOM, modifiedDOM, "DOM should be different");
+ return { origDOM, modifiedDOM };
+ });
+
+ await promisePageNavigation({
+ uri: doc2,
+ });
+
+ await promisePageNavigation({
+ back: true,
+ });
+
+ await SpecialPowers.spawn(f1, [modifiedDOM], (modifiedDOM) => {
+ is(content.document.documentElement.innerHTML, modifiedDOM, "Should have been bfcached");
+ });
+
+ await promisePageNavigation({
+ forward: true,
+ });
+
+ f1.removeAttribute("id");
+ let f2 = addBrowser("parent", 300, 200);
+
+ // Make sure there's a document or the swap will fail.
+ await promisePageNavigation({
+ uri: "about:blank",
+ });
+
+ f1.swapDocShells(f2);
+
+ await promisePageNavigation({
+ back: true,
+ });
+
+ await SpecialPowers.spawn(f2, [origDOM], (origDOM) => {
+ is(content.document.documentElement.innerHTML, origDOM, "Should not have been bfcached");
+ });
+
+ finish();
+ }
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/bug454235-subframe.xhtml b/docshell/test/chrome/bug454235-subframe.xhtml
new file mode 100644
index 0000000000..a8b6178e65
--- /dev/null
+++ b/docshell/test/chrome/bug454235-subframe.xhtml
@@ -0,0 +1,7 @@
+<window title="Mozilla Bug 454235 SubFrame"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <deck flex="1">
+ <browser id="topBrowser" src="about:mozilla"/>
+ <browser id="burriedBrowser" src="about:mozilla"/>
+ </deck>
+</window>
diff --git a/docshell/test/chrome/bug582176_window.xhtml b/docshell/test/chrome/bug582176_window.xhtml
new file mode 100644
index 0000000000..f468d17b8b
--- /dev/null
+++ b/docshell/test/chrome/bug582176_window.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="runTest();"
+ title="bug 582176 test">
+
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ ////
+ // Bug 582176.
+ //
+ async function runTest()
+ {
+ enableBFCache(true);
+
+ var notificationCount = 0;
+
+ let onGlobalCreation = () => {
+ ++notificationCount;
+ };
+
+ await promisePageNavigation({
+ uri: "http://mochi.test:8888/chrome/docshell/test/chrome/582176_dummy.html",
+ onGlobalCreation,
+ });
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ let testVar = content.testVar;
+ content.testVar = 1;
+ return testVar;
+ }), undefined,
+ "variable unexpectedly there already");
+ is(notificationCount, 1, "Should notify on first navigation");
+
+ await promisePageNavigation({
+ uri: "http://mochi.test:8888/chrome/docshell/test/chrome/582176_dummy.html?2",
+ onGlobalCreation,
+ });
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.testVar;
+ }), undefined,
+ "variable should no longer be there");
+ is(notificationCount, 2, "Should notify on second navigation");
+
+ await promisePageNavigation({
+ back: true,
+ });
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.testVar;
+ }), 1,
+ "variable should still be there");
+ is(notificationCount, 2, "Should not notify on back navigation");
+
+ await promisePageNavigation({
+ uri: "http://mochi.test:8888/chrome/docshell/test/chrome/582176_xml.xml",
+ onGlobalCreation,
+ });
+ is(await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return content.document.body.textContent;
+ }), "xslt result",
+ "Transform performed successfully");
+ is(notificationCount, 3, "Should notify only once on XSLT navigation");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug608669.xhtml b/docshell/test/chrome/bug608669.xhtml
new file mode 100644
index 0000000000..993f24051c
--- /dev/null
+++ b/docshell/test/chrome/bug608669.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<window title="Mozilla Bug 608669 - Blank page"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="notifyOpener();">
+ <description flex="1" value="This window is intentionally left blank"/>
+ <script type="application/javascript">
+ function notifyOpener() {
+ if (opener) {
+ opener.postMessage("load", "*");
+ }
+ }
+ </script>
+</window>
diff --git a/docshell/test/chrome/bug662200_window.xhtml b/docshell/test/chrome/bug662200_window.xhtml
new file mode 100644
index 0000000000..7c6f656f26
--- /dev/null
+++ b/docshell/test/chrome/bug662200_window.xhtml
@@ -0,0 +1,119 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="303267Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTest, 0);"
+ title="bug 662200 test">
+
+ <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ Services.prefs.setBoolPref("browser.navigation.requireUserInteraction", false);
+
+ ////
+ // Bug 662200
+ //
+ async function runTest()
+ {
+ // Load the first test page
+ var navData = {
+ uri: getHttpUrl("662200a.html"),
+ eventsToListenFor: ["pageshow"],
+ expectedEvents: [ {type: "pageshow", title: "A"} ],
+ };
+ await promisePageNavigation(navData);
+
+ // Load the second test page.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "A"},
+ {type: "pageshow",
+ title: "B"} ],
+ }
+ let clicked = promisePageEvents(navData);
+ SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ var link = content.document.getElementById("link");
+ var event = content.document.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, content,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ });
+ await clicked;
+
+ // Load the third test page.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "B"},
+ {type: "pageshow",
+ title: "C"} ],
+ };
+ clicked = promisePageEvents(navData);
+ SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ var link = content.document.getElementById("link");
+ var event = content.document.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, content,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ });
+ await clicked;
+
+ // Go back.
+ navData = {
+ back: true,
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "C"},
+ {type: "pageshow",
+ title: "B"} ],
+ };
+ await promisePageNavigation(navData);
+
+ // Reload.
+ navData = {
+ eventsToListenFor: ["pageshow", "pagehide"],
+ expectedEvents: [ {type: "pagehide",
+ title: "B"},
+ {type: "pageshow",
+ title: "B"} ],
+ };
+ // Asking the docshell harness to reload for us will call reload on
+ // nsDocShell which has different behavior than the reload on nsSHistory
+ // so we call reloadCurrentEntry() (which is equivalent to reload(0) and
+ // visible from JS) explicitly here.
+ let reloaded = promisePageEvents(navData);
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ TestWindow.getBrowser().browsingContext.sessionHistory.reloadCurrentEntry();
+ } else {
+ SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory.legacySHistory.reloadCurrentEntry();
+ });
+ }
+ await reloaded;
+
+ // After this sequence of events, we should be able to go back and forward
+ is(TestWindow.getBrowser().canGoBack, true, "Should be able to go back!");
+ is(TestWindow.getBrowser().canGoForward, true, "Should be able to go forward!");
+ let requestedIndex;
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ requestedIndex = TestWindow.getBrowser().browsingContext.sessionHistory.requestedIndex;
+ } else {
+ requestedIndex = await SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ return docShell.sessionHistory.legacySHistory.requestedIndex;
+ })
+ }
+ is(requestedIndex, -1, "Requested index should be cleared!");
+
+ Services.prefs.clearUserPref("browser.navigation.requireUserInteraction");
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug690056_window.xhtml b/docshell/test/chrome/bug690056_window.xhtml
new file mode 100644
index 0000000000..a48e14ce8f
--- /dev/null
+++ b/docshell/test/chrome/bug690056_window.xhtml
@@ -0,0 +1,171 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="690056Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest, 0);"
+ title="bug 6500056 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ var tests = testIterator();
+
+ function nextTest() {
+ tests.next();
+ }
+
+ // Makes sure that we fire the visibilitychange events
+ function* testIterator() {
+ // Enable bfcache
+ enableBFCache(8);
+
+ // Load something for a start
+ doPageNavigation({
+ uri: 'data:text/html,<title>initial load</title>',
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now load a new page
+ doPageNavigation({
+ uri: 'data:text/html,<title>new load</title>',
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ // No visibilitychange events fired for initial pageload
+ { type: "pageshow",
+ title: "new load",
+ persisted: false }, // false on initial load
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now go back
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "new load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "initial load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // And forward
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "new load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ waitForPageEvents({
+ eventsToListenFor: [ "visibilitychange" ],
+ expectedEvents: [ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "hidden",
+ hidden: true },
+ ],
+ onNavComplete: nextTest
+ });
+
+ // Now flip our docshell to not active
+ TestWindow.getBrowser().docShellIsActive = false;
+ yield undefined;
+
+ // And navigate back; there should be no visibility state transitions
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "new load",
+ persisted: true },
+ { type: "pageshow",
+ title: "initial load",
+ persisted: true },
+ ],
+ unexpectedEvents: [ "visibilitychange" ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ waitForPageEvents({
+ eventsToListenFor: [ "visibilitychange" ],
+ expectedEvents: [ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "visible",
+ hidden: false },
+ ],
+ onNavComplete: nextTest
+ });
+
+ // Now set the docshell active again
+ TestWindow.getBrowser().docShellIsActive = true;
+ yield undefined;
+
+ // And forward
+ doPageNavigation({
+ forward: true,
+ eventsToListenFor: [ "pageshow", "pagehide", "visibilitychange" ],
+ expectedEvents: [ { type: "pagehide",
+ title: "initial load",
+ persisted: true },
+ { type: "visibilitychange",
+ title: "initial load",
+ visibilityState: "hidden",
+ hidden: true },
+ { type: "visibilitychange",
+ title: "new load",
+ visibilityState: "visible",
+ hidden: false },
+ { type: "pageshow",
+ title: "new load",
+ persisted: true },
+ ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/bug846906.html b/docshell/test/chrome/bug846906.html
new file mode 100644
index 0000000000..a289417ea8
--- /dev/null
+++ b/docshell/test/chrome/bug846906.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <title>
+ </title>
+ </head>
+ <body>
+ <div id="div1" style="width:1024px; height:768px; border:none;">
+ </div>
+ </body>
+</html>
diff --git a/docshell/test/chrome/bug89419.sjs b/docshell/test/chrome/bug89419.sjs
new file mode 100644
index 0000000000..7172690a9a
--- /dev/null
+++ b/docshell/test/chrome/bug89419.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response) {
+ var redirectstate = "/docshell/test/chrome/bug89419.sjs";
+ response.setStatusLine("1.1", 302, "Found");
+ if (getState(redirectstate) == "") {
+ response.setHeader("Location", "red.png", false);
+ setState(redirectstate, "red");
+ } else {
+ response.setHeader("Location", "blue.png", false);
+ setState(redirectstate, "");
+ }
+ response.setHeader("Cache-Control", "no-cache", false);
+}
diff --git a/docshell/test/chrome/bug89419_window.xhtml b/docshell/test/chrome/bug89419_window.xhtml
new file mode 100644
index 0000000000..12b9dec650
--- /dev/null
+++ b/docshell/test/chrome/bug89419_window.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="89419Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(runTests, 0);"
+ title="bug 89419 test">
+
+ <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <script type="application/javascript"><![CDATA[
+ ////
+ // A visited link should have the :visited style applied
+ // to it when displayed on a page which was fetched from
+ // the bfcache.
+ //
+ async function runTests() {
+ // Disable rcwn to make cache behavior deterministic.
+ var {SpecialPowers} = window.arguments[0];
+ await SpecialPowers.pushPrefEnv({"set":[["network.http.rcwn.enabled", false]]});
+
+ // Load a test page containing an image referring to the sjs that returns
+ // a different redirect every time it's loaded.
+ await new Promise(resolve => {
+ doPageNavigation({
+ uri: getHttpUrl("89419.html"),
+ onNavComplete: resolve,
+ preventBFCache: true,
+ });
+ })
+
+ var first = await snapshotWindow(TestWindow.getWindow());
+
+ await new Promise(resolve => {
+ doPageNavigation({
+ uri: "about:blank",
+ onNavComplete: resolve,
+ });
+ });
+
+ var second = await snapshotWindow(TestWindow.getWindow());
+ function snapshotsEqual(snap1, snap2) {
+ return compareSnapshots(snap1, snap2, true)[0];
+ }
+ ok(!snapshotsEqual(first, second), "about:blank should not be the same as the image web page");
+
+ await new Promise(resolve => {
+ doPageNavigation({
+ back: true,
+ onNavComplete: resolve,
+ });
+ });
+
+ var third = await snapshotWindow(TestWindow.getWindow());
+ ok(!snapshotsEqual(third, second), "going back should not be the same as about:blank");
+ ok(snapshotsEqual(first, third), "going back should be the same as the initial load");
+
+ // Tell the framework the test is finished.
+ finish();
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>
diff --git a/docshell/test/chrome/bug909218.html b/docshell/test/chrome/bug909218.html
new file mode 100644
index 0000000000..a11fa6000d
--- /dev/null
+++ b/docshell/test/chrome/bug909218.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <link rel="stylesheet" type="text/css" href="http://mochi.test:8888/tests/SimpleTest/test.css">
+ <script src="bug909218.js"></script>
+</head>
+<body>
+ <img src="http://mochi.test:8888/tests/docshell/test/chrome/red.png">
+ <!-- an iframe so we can check these too get the correct flags -->
+ <iframe src="generic.html"/>
+</body>
+</html>
diff --git a/docshell/test/chrome/bug909218.js b/docshell/test/chrome/bug909218.js
new file mode 100644
index 0000000000..2222480cd3
--- /dev/null
+++ b/docshell/test/chrome/bug909218.js
@@ -0,0 +1,2 @@
+// This file exists just to ensure that we load it with the correct flags.
+dump("bug909218.js loaded\n");
diff --git a/docshell/test/chrome/bug92598_window.xhtml b/docshell/test/chrome/bug92598_window.xhtml
new file mode 100644
index 0000000000..5a10ff250a
--- /dev/null
+++ b/docshell/test/chrome/bug92598_window.xhtml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="92598Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="onLoad();"
+ title="92598 test">
+
+ <script src="chrome://mochikit/content/chrome-harness.js" />
+ <script type="application/javascript" src="docshell_helpers.js" />
+ <script type="application/javascript"><![CDATA[
+ var gBrowser;
+ var gTestsIterator;
+
+ function onLoad() {
+ gBrowser = document.getElementById("content");
+ gTestsIterator = testsIterator();
+ nextTest();
+ }
+
+ function nextTest() {
+ gTestsIterator.next();
+ }
+
+ function* testsIterator() {
+ // Load a page with a no-cache header, followed by a simple page
+ // On pagehide, first page should report it is not being persisted
+ var test1DocURI = "http://mochi.test:8888/chrome/docshell/test/chrome/92598_nostore.html";
+
+ doPageNavigation({
+ uri: test1DocURI,
+ eventsToListenFor: ["load", "pageshow"],
+ expectedEvents: [ { type: "load",
+ title: "test1" },
+ { type: "pageshow",
+ title: "test1",
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ var test2Doc = "data:text/html,<html><head><title>test2</title></head>" +
+ "<body>test2</body></html>";
+
+ doPageNavigation({
+ uri: test2Doc,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test1",
+ persisted: false },
+ { type: "load",
+ title: "test2" },
+ { type: "pageshow",
+ title: "test2",
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ // Now go back in history. First page should not have been cached.
+ // Check persisted property to confirm
+ doPageNavigation({
+ back: true,
+ eventsToListenFor: ["load", "pageshow", "pagehide"],
+ expectedEvents: [ { type: "pagehide",
+ title: "test2",
+ persisted: true },
+ { type: "load",
+ title: "test1" },
+ { type: "pageshow",
+ title: "test1",
+ persisted: false } ],
+ onNavComplete: nextTest
+ });
+ yield undefined;
+
+ finish();
+ }
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" remote="true" />
+</window>
diff --git a/docshell/test/chrome/chrome.ini b/docshell/test/chrome/chrome.ini
new file mode 100644
index 0000000000..2d126b84b7
--- /dev/null
+++ b/docshell/test/chrome/chrome.ini
@@ -0,0 +1,105 @@
+[DEFAULT]
+skip-if = os == 'android'
+support-files =
+ 662200a.html
+ 662200b.html
+ 662200c.html
+ 89419.html
+ bug113934_window.xhtml
+ bug215405_window.xhtml
+ bug293235.html
+ bug293235_p2.html
+ bug293235_window.xhtml
+ bug294258_testcase.html
+ bug294258_window.xhtml
+ bug298622_window.xhtml
+ bug301397_1.html
+ bug301397_2.html
+ bug301397_3.html
+ bug301397_4.html
+ bug301397_window.xhtml
+ bug303267.html
+ bug303267_window.xhtml
+ bug311007_window.xhtml
+ bug321671_window.xhtml
+ bug360511_case1.html
+ bug360511_case2.html
+ bug360511_window.xhtml
+ bug364461_window.xhtml
+ bug396519_window.xhtml
+ bug396649_window.xhtml
+ bug449778_window.xhtml
+ bug449780_window.xhtml
+ bug454235-subframe.xhtml
+ bug608669.xhtml
+ bug662200_window.xhtml
+ bug690056_window.xhtml
+ bug846906.html
+ bug89419_window.xhtml
+ bug909218.html
+ bug909218.js
+ docshell_helpers.js
+ DocShellHelpers.sys.mjs
+ file_viewsource_forbidden_in_iframe.html
+ generic.html
+ mozFrameType_window.xhtml
+ test_docRedirect.sjs
+
+[test_allowContentRetargeting.html]
+[test_bug112564.xhtml]
+support-files =
+ bug112564_window.xhtml
+ 112564_nocache.html
+ 112564_nocache.html^headers^
+[test_bug113934.xhtml]
+[test_bug215405.xhtml]
+[test_bug293235.xhtml]
+skip-if = true # bug 1393441
+[test_bug294258.xhtml]
+[test_bug298622.xhtml]
+[test_bug301397.xhtml]
+skip-if = (os == 'win' && processor == 'aarch64') # bug 1533819
+[test_bug303267.xhtml]
+[test_bug311007.xhtml]
+[test_bug321671.xhtml]
+[test_bug360511.xhtml]
+skip-if = (os == 'win' && processor == 'x86')
+[test_bug364461.xhtml]
+skip-if = (os == 'win' && processor == 'aarch64') # bug 1533814
+[test_bug396519.xhtml]
+[test_bug396649.xhtml]
+[test_bug428288.html]
+[test_bug449778.xhtml]
+[test_bug449780.xhtml]
+[test_bug453650.xhtml]
+[test_bug454235.xhtml]
+[test_bug456980.xhtml]
+[test_bug565388.xhtml]
+skip-if = true # Bug 1026815,Bug 1546159
+[test_bug582176.xhtml]
+support-files =
+ 582176_dummy.html
+ 582176_xml.xml
+ 582176_xslt.xsl
+ bug582176_window.xhtml
+[test_bug608669.xhtml]
+[test_bug662200.xhtml]
+[test_bug690056.xhtml]
+[test_bug789773.xhtml]
+[test_bug846906.xhtml]
+[test_bug89419.xhtml]
+[test_bug909218.html]
+[test_bug92598.xhtml]
+support-files =
+ 92598_nostore.html
+ 92598_nostore.html^headers^
+ bug92598_window.xhtml
+[test_open_and_immediately_close_opener.html]
+# This bug only manifests in the non-e10s window open codepath. The test
+# should be updated to make sure it still opens a new window in the parent
+# process if and when we start running chrome mochitests with e10s enabled.
+skip-if = e10s
+[test_mozFrameType.xhtml]
+[test_viewsource_forbidden_in_iframe.xhtml]
+skip-if = true # bug 1019315
+[test_docRedirect.xhtml]
diff --git a/docshell/test/chrome/docshell_helpers.js b/docshell/test/chrome/docshell_helpers.js
new file mode 100644
index 0000000000..facd627b45
--- /dev/null
+++ b/docshell/test/chrome/docshell_helpers.js
@@ -0,0 +1,758 @@
+if (!window.opener && window.arguments) {
+ window.opener = window.arguments[0];
+}
+/**
+ * Import common SimpleTest methods so that they're usable in this window.
+ */
+/* globals SimpleTest, is, isnot, ok, onerror, todo, todo_is, todo_isnot */
+var imports = [
+ "SimpleTest",
+ "is",
+ "isnot",
+ "ok",
+ "onerror",
+ "todo",
+ "todo_is",
+ "todo_isnot",
+];
+for (var name of imports) {
+ window[name] = window.opener.wrappedJSObject[name];
+}
+const { BrowserTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/BrowserTestUtils.sys.mjs"
+);
+
+const ACTOR_MODULE_URI =
+ "chrome://mochitests/content/chrome/docshell/test/chrome/DocShellHelpers.sys.mjs";
+const { DocShellHelpersParent } = ChromeUtils.importESModule(ACTOR_MODULE_URI);
+// Some functions assume chrome-harness.js has been loaded.
+/* import-globals-from ../../../testing/mochitest/chrome-harness.js */
+
+/**
+ * Define global constants and variables.
+ */
+const NAV_NONE = 0;
+const NAV_BACK = 1;
+const NAV_FORWARD = 2;
+const NAV_GOTOINDEX = 3;
+const NAV_URI = 4;
+const NAV_RELOAD = 5;
+
+var gExpectedEvents; // an array of events which are expected to
+// be triggered by this navigation
+var gUnexpectedEvents; // an array of event names which are NOT expected
+// to be triggered by this navigation
+var gFinalEvent; // true if the last expected event has fired
+var gUrisNotInBFCache = []; // an array of uri's which shouldn't be stored
+// in the bfcache
+var gNavType = NAV_NONE; // defines the most recent navigation type
+// executed by doPageNavigation
+var gOrigMaxTotalViewers = undefined; // original value of max_total_viewers, // to be restored at end of test
+
+var gExtractedPath = null; // used to cache file path for extracting files from a .jar file
+
+/**
+ * The doPageNavigation() function performs page navigations asynchronously,
+ * listens for specified events, and compares actual events with a list of
+ * expected events. When all expected events have occurred, an optional
+ * callback can be notified. The parameter passed to this function is an
+ * object with the following properties:
+ *
+ * uri: if !undefined, the browser will navigate to this uri
+ *
+ * back: if true, the browser will execute goBack()
+ *
+ * forward: if true, the browser will execute goForward()
+ *
+ * gotoIndex: if a number, the browser will execute gotoIndex() with
+ * the number as index
+ *
+ * reload: if true, the browser will execute reload()
+ *
+ * eventsToListenFor: an array containing one or more of the following event
+ * types to listen for: "pageshow", "pagehide", "onload",
+ * "onunload". If this property is undefined, only a
+ * single "pageshow" events will be listened for. If this
+ * property is explicitly empty, [], then no events will
+ * be listened for.
+ *
+ * expectedEvents: an array of one or more expectedEvent objects,
+ * corresponding to the events which are expected to be
+ * fired for this navigation. Each object has the
+ * following properties:
+ *
+ * type: one of the event type strings
+ * title (optional): the title of the window the
+ * event belongs to
+ * persisted (optional): the event's expected
+ * .persisted attribute
+ *
+ * This function will verify that events with the
+ * specified properties are fired in the same order as
+ * specified in the array. If .title or .persisted
+ * properties for an expectedEvent are undefined, those
+ * properties will not be verified for that particular
+ * event.
+ *
+ * This property is ignored if eventsToListenFor is
+ * undefined or [].
+ *
+ * preventBFCache: if true, an RTCPeerConnection will be added to the loaded
+ * page to prevent it from being bfcached. This property
+ * has no effect when eventsToListenFor is [].
+ *
+ * onNavComplete: a callback which is notified after all expected events
+ * have occurred, or after a timeout has elapsed. This
+ * callback is not notified if eventsToListenFor is [].
+ * onGlobalCreation: a callback which is notified when a DOMWindow is created
+ * (implemented by observing
+ * "content-document-global-created")
+ *
+ * There must be an expectedEvent object for each event of the types in
+ * eventsToListenFor which is triggered by this navigation. For example, if
+ * eventsToListenFor = [ "pagehide", "pageshow" ], then expectedEvents
+ * must contain an object for each pagehide and pageshow event which occurs as
+ * a result of this navigation.
+ */
+// eslint-disable-next-line complexity
+function doPageNavigation(params) {
+ // Parse the parameters.
+ let back = params.back ? params.back : false;
+ let forward = params.forward ? params.forward : false;
+ let gotoIndex = params.gotoIndex ? params.gotoIndex : false;
+ let reload = params.reload ? params.reload : false;
+ let uri = params.uri ? params.uri : false;
+ let eventsToListenFor =
+ typeof params.eventsToListenFor != "undefined"
+ ? params.eventsToListenFor
+ : ["pageshow"];
+ gExpectedEvents =
+ typeof params.eventsToListenFor == "undefined" || !eventsToListenFor.length
+ ? undefined
+ : params.expectedEvents;
+ gUnexpectedEvents =
+ typeof params.eventsToListenFor == "undefined" || !eventsToListenFor.length
+ ? undefined
+ : params.unexpectedEvents;
+ let preventBFCache =
+ typeof [params.preventBFCache] == "undefined"
+ ? false
+ : params.preventBFCache;
+ let waitOnly =
+ typeof params.waitForEventsOnly == "boolean" && params.waitForEventsOnly;
+
+ // Do some sanity checking on arguments.
+ let navigation = ["back", "forward", "gotoIndex", "reload", "uri"].filter(k =>
+ params.hasOwnProperty(k)
+ );
+ if (navigation.length > 1) {
+ throw new Error(`Can't specify both ${navigation[0]} and ${navigation[1]}`);
+ } else if (!navigation.length && !waitOnly) {
+ throw new Error(
+ "Must specify back or forward or gotoIndex or reload or uri"
+ );
+ }
+ if (params.onNavComplete && !eventsToListenFor.length) {
+ throw new Error("Can't use onNavComplete when eventsToListenFor == []");
+ }
+ if (params.preventBFCache && !eventsToListenFor.length) {
+ throw new Error("Can't use preventBFCache when eventsToListenFor == []");
+ }
+ if (params.preventBFCache && waitOnly) {
+ throw new Error("Can't prevent bfcaching when only waiting for events");
+ }
+ if (waitOnly && typeof params.onNavComplete == "undefined") {
+ throw new Error(
+ "Must specify onNavComplete when specifying waitForEventsOnly"
+ );
+ }
+ if (waitOnly && navigation.length) {
+ throw new Error(
+ "Can't specify a navigation type when using waitForEventsOnly"
+ );
+ }
+ for (let anEventType of eventsToListenFor) {
+ let eventFound = false;
+ if (anEventType == "pageshow" && !gExpectedEvents) {
+ eventFound = true;
+ }
+ if (gExpectedEvents) {
+ for (let anExpectedEvent of gExpectedEvents) {
+ if (anExpectedEvent.type == anEventType) {
+ eventFound = true;
+ }
+ }
+ }
+ if (gUnexpectedEvents) {
+ for (let anExpectedEventType of gUnexpectedEvents) {
+ if (anExpectedEventType == anEventType) {
+ eventFound = true;
+ }
+ }
+ }
+ if (!eventFound) {
+ throw new Error(
+ `Event type ${anEventType} is specified in ` +
+ "eventsToListenFor, but not in expectedEvents"
+ );
+ }
+ }
+
+ // If the test explicitly sets .eventsToListenFor to [], don't wait for any
+ // events.
+ gFinalEvent = !eventsToListenFor.length;
+
+ // Add observers as needed.
+ let observers = new Map();
+ if (params.hasOwnProperty("onGlobalCreation")) {
+ observers.set("content-document-global-created", params.onGlobalCreation);
+ }
+
+ // Add an event listener for each type of event in the .eventsToListenFor
+ // property of the input parameters, and add an observer for all the topics
+ // in the observers map.
+ let cleanup;
+ let useActor = TestWindow.getBrowser().isRemoteBrowser;
+ if (useActor) {
+ ChromeUtils.registerWindowActor("DocShellHelpers", {
+ parent: {
+ esModuleURI: ACTOR_MODULE_URI,
+ },
+ child: {
+ esModuleURI: ACTOR_MODULE_URI,
+ events: {
+ pageshow: { createActor: true, capture: true },
+ pagehide: { createActor: true, capture: true },
+ load: { createActor: true, capture: true },
+ unload: { createActor: true, capture: true },
+ visibilitychange: { createActor: true, capture: true },
+ },
+ observers: observers.keys(),
+ },
+ allFrames: true,
+ });
+ DocShellHelpersParent.eventsToListenFor = eventsToListenFor;
+ DocShellHelpersParent.observers = observers;
+
+ cleanup = () => {
+ DocShellHelpersParent.eventsToListenFor = null;
+ DocShellHelpersParent.observers = null;
+ ChromeUtils.unregisterWindowActor("DocShellHelpers");
+ };
+ } else {
+ for (let eventType of eventsToListenFor) {
+ dump("TEST: registering a listener for " + eventType + " events\n");
+ TestWindow.getBrowser().addEventListener(
+ eventType,
+ pageEventListener,
+ true
+ );
+ }
+ if (observers.size > 0) {
+ let observer = (_, topic) => {
+ observers.get(topic).call();
+ };
+ for (let topic of observers.keys()) {
+ Services.obs.addObserver(observer, topic);
+ }
+
+ // We only need to do cleanup for the observer, the event listeners will
+ // go away with the window.
+ cleanup = () => {
+ for (let topic of observers.keys()) {
+ Services.obs.removeObserver(observer, topic);
+ }
+ };
+ }
+ }
+
+ if (cleanup) {
+ // Register a cleanup function on domwindowclosed, to avoid contaminating
+ // other tests if we bail out early because of an error.
+ Services.ww.registerNotification(function windowClosed(
+ subject,
+ topic,
+ data
+ ) {
+ if (topic == "domwindowclosed" && subject == window) {
+ Services.ww.unregisterNotification(windowClosed);
+ cleanup();
+ }
+ });
+ }
+
+ // Perform the specified navigation.
+ if (back) {
+ gNavType = NAV_BACK;
+ TestWindow.getBrowser().goBack();
+ } else if (forward) {
+ gNavType = NAV_FORWARD;
+ TestWindow.getBrowser().goForward();
+ } else if (typeof gotoIndex == "number") {
+ gNavType = NAV_GOTOINDEX;
+ TestWindow.getBrowser().gotoIndex(gotoIndex);
+ } else if (uri) {
+ gNavType = NAV_URI;
+ BrowserTestUtils.loadURI(TestWindow.getBrowser(), uri);
+ } else if (reload) {
+ gNavType = NAV_RELOAD;
+ TestWindow.getBrowser().reload();
+ } else if (waitOnly) {
+ gNavType = NAV_NONE;
+ } else {
+ throw new Error("No valid navigation type passed to doPageNavigation!");
+ }
+
+ // If we're listening for events and there is an .onNavComplete callback,
+ // wait for all events to occur, and then call doPageNavigation_complete().
+ if (eventsToListenFor.length && params.onNavComplete) {
+ waitForTrue(
+ function() {
+ return gFinalEvent;
+ },
+ function() {
+ doPageNavigation_complete(
+ eventsToListenFor,
+ params.onNavComplete,
+ preventBFCache,
+ useActor,
+ cleanup
+ );
+ }
+ );
+ } else if (cleanup) {
+ cleanup();
+ }
+}
+
+/**
+ * Finish doPageNavigation(), by removing event listeners, adding an unload
+ * handler if appropriate, and calling the onNavComplete callback. This
+ * function is called after all the expected events for this navigation have
+ * occurred.
+ */
+function doPageNavigation_complete(
+ eventsToListenFor,
+ onNavComplete,
+ preventBFCache,
+ useActor,
+ cleanup
+) {
+ if (useActor) {
+ if (preventBFCache) {
+ let actor = TestWindow.getBrowser().browsingContext.currentWindowGlobal.getActor(
+ "DocShellHelpers"
+ );
+ actor.sendAsyncMessage("docshell_helpers:preventBFCache");
+ }
+ } else {
+ // Unregister our event listeners.
+ dump("TEST: removing event listeners\n");
+ for (let eventType of eventsToListenFor) {
+ TestWindow.getBrowser().removeEventListener(
+ eventType,
+ pageEventListener,
+ true
+ );
+ }
+
+ // If the .preventBFCache property was set, add an RTCPeerConnection to
+ // prevent the page from being bfcached.
+ if (preventBFCache) {
+ let win = TestWindow.getWindow();
+ win.blockBFCache = new win.RTCPeerConnection();
+ }
+ }
+
+ if (cleanup) {
+ cleanup();
+ }
+
+ let uri = TestWindow.getBrowser().currentURI.spec;
+ if (preventBFCache) {
+ // Save the current uri in an array of uri's which shouldn't be
+ // stored in the bfcache, for later verification.
+ if (!(uri in gUrisNotInBFCache)) {
+ gUrisNotInBFCache.push(uri);
+ }
+ } else if (gNavType == NAV_URI) {
+ // If we're navigating to a uri and .preventBFCache was not
+ // specified, splice it out of gUrisNotInBFCache if it's there.
+ gUrisNotInBFCache.forEach(function(element, index, array) {
+ if (element == uri) {
+ array.splice(index, 1);
+ }
+ }, this);
+ }
+
+ // Notify the callback now that we're done.
+ onNavComplete.call();
+}
+
+function promisePageNavigation(params) {
+ if (params.hasOwnProperty("onNavComplete")) {
+ throw new Error(
+ "Can't use a onNavComplete completion callback with promisePageNavigation."
+ );
+ }
+ return new Promise(resolve => {
+ params.onNavComplete = resolve;
+ doPageNavigation(params);
+ });
+}
+
+/**
+ * Allows a test to wait for page navigation events, and notify a
+ * callback when they've all been received. This works exactly the
+ * same as doPageNavigation(), except that no navigation is initiated.
+ */
+function waitForPageEvents(params) {
+ params.waitForEventsOnly = true;
+ doPageNavigation(params);
+}
+
+function promisePageEvents(params) {
+ if (params.hasOwnProperty("onNavComplete")) {
+ throw new Error(
+ "Can't use a onNavComplete completion callback with promisePageEvents."
+ );
+ }
+ return new Promise(resolve => {
+ params.waitForEventsOnly = true;
+ params.onNavComplete = resolve;
+ doPageNavigation(params);
+ });
+}
+
+/**
+ * The event listener which listens for expectedEvents.
+ */
+function pageEventListener(
+ event,
+ originalTargetIsHTMLDocument = HTMLDocument.isInstance(event.originalTarget)
+) {
+ try {
+ dump(
+ "TEST: eventListener received a " +
+ event.type +
+ " event for page " +
+ event.originalTarget.title +
+ ", persisted=" +
+ event.persisted +
+ "\n"
+ );
+ } catch (e) {
+ // Ignore any exception.
+ }
+
+ // If this page shouldn't be in the bfcache because it was previously
+ // loaded with .preventBFCache, make sure that its pageshow event
+ // has .persisted = false, even if the test doesn't explicitly test
+ // for .persisted.
+ if (
+ event.type == "pageshow" &&
+ (gNavType == NAV_BACK ||
+ gNavType == NAV_FORWARD ||
+ gNavType == NAV_GOTOINDEX)
+ ) {
+ let uri = TestWindow.getBrowser().currentURI.spec;
+ if (uri in gUrisNotInBFCache) {
+ ok(
+ !event.persisted,
+ "pageshow event has .persisted = false, even " +
+ "though it was loaded with .preventBFCache previously\n"
+ );
+ }
+ }
+
+ if (typeof gUnexpectedEvents != "undefined") {
+ is(
+ gUnexpectedEvents.indexOf(event.type),
+ -1,
+ "Should not get unexpected event " + event.type
+ );
+ }
+
+ // If no expected events were specified, mark the final event as having been
+ // triggered when a pageshow event is fired; this will allow
+ // doPageNavigation() to return.
+ if (typeof gExpectedEvents == "undefined" && event.type == "pageshow") {
+ waitForNextPaint(function() {
+ gFinalEvent = true;
+ });
+ return;
+ }
+
+ // If there are explicitly no expected events, but we receive one, it's an
+ // error.
+ if (!gExpectedEvents.length) {
+ ok(false, "Unexpected event (" + event.type + ") occurred");
+ return;
+ }
+
+ // Grab the next expected event, and compare its attributes against the
+ // actual event.
+ let expected = gExpectedEvents.shift();
+
+ is(
+ event.type,
+ expected.type,
+ "A " +
+ expected.type +
+ " event was expected, but a " +
+ event.type +
+ " event occurred"
+ );
+
+ if (typeof expected.title != "undefined") {
+ ok(
+ originalTargetIsHTMLDocument,
+ "originalTarget for last " + event.type + " event not an HTMLDocument"
+ );
+ is(
+ event.originalTarget.title,
+ expected.title,
+ "A " +
+ event.type +
+ " event was expected for page " +
+ expected.title +
+ ", but was fired for page " +
+ event.originalTarget.title
+ );
+ }
+
+ if (typeof expected.persisted != "undefined") {
+ is(
+ event.persisted,
+ expected.persisted,
+ "The persisted property of the " +
+ event.type +
+ " event on page " +
+ event.originalTarget.location +
+ " had an unexpected value"
+ );
+ }
+
+ if ("visibilityState" in expected) {
+ is(
+ event.originalTarget.visibilityState,
+ expected.visibilityState,
+ "The visibilityState property of the document on page " +
+ event.originalTarget.location +
+ " had an unexpected value"
+ );
+ }
+
+ if ("hidden" in expected) {
+ is(
+ event.originalTarget.hidden,
+ expected.hidden,
+ "The hidden property of the document on page " +
+ event.originalTarget.location +
+ " had an unexpected value"
+ );
+ }
+
+ // If we're out of expected events, let doPageNavigation() return.
+ if (!gExpectedEvents.length) {
+ waitForNextPaint(function() {
+ gFinalEvent = true;
+ });
+ }
+}
+
+DocShellHelpersParent.eventListener = pageEventListener;
+
+/**
+ * End a test.
+ */
+function finish() {
+ // Work around bug 467960.
+ let historyPurged;
+ if (SpecialPowers.Services.appinfo.sessionHistoryInParent) {
+ let history = TestWindow.getBrowser().browsingContext?.sessionHistory;
+ history.purgeHistory(history.count);
+ historyPurged = Promise.resolve();
+ } else {
+ historyPurged = SpecialPowers.spawn(TestWindow.getBrowser(), [], () => {
+ let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory
+ .legacySHistory;
+ history.purgeHistory(history.count);
+ });
+ }
+
+ // If the test changed the value of max_total_viewers via a call to
+ // enableBFCache(), then restore it now.
+ if (typeof gOrigMaxTotalViewers != "undefined") {
+ Services.prefs.setIntPref(
+ "browser.sessionhistory.max_total_viewers",
+ gOrigMaxTotalViewers
+ );
+ }
+
+ // Close the test window and signal the framework that the test is done.
+ let opener = window.opener;
+ let SimpleTest = opener.wrappedJSObject.SimpleTest;
+
+ // Wait for the window to be closed before finishing the test
+ Services.ww.registerNotification(function observer(subject, topic, data) {
+ if (topic == "domwindowclosed") {
+ Services.ww.unregisterNotification(observer);
+ SimpleTest.waitForFocus(SimpleTest.finish, opener);
+ }
+ });
+
+ historyPurged.then(_ => {
+ window.close();
+ });
+}
+
+/**
+ * Helper function which waits until another function returns true, or until a
+ * timeout occurs, and then notifies a callback.
+ *
+ * Parameters:
+ *
+ * fn: a function which is evaluated repeatedly, and when it turns true,
+ * the onWaitComplete callback is notified.
+ *
+ * onWaitComplete: a callback which will be notified when fn() returns
+ * true, or when a timeout occurs.
+ *
+ * timeout: a timeout, in seconds or ms, after which waitForTrue() will
+ * fail an assertion and then return, even if the fn function never
+ * returns true. If timeout is undefined, waitForTrue() will never
+ * time out.
+ */
+function waitForTrue(fn, onWaitComplete, timeout) {
+ promiseTrue(fn, timeout).then(() => {
+ onWaitComplete.call();
+ });
+}
+
+function promiseTrue(fn, timeout) {
+ if (typeof timeout != "undefined") {
+ // If timeoutWait is less than 500, assume it represents seconds, and
+ // convert to ms.
+ if (timeout < 500) {
+ timeout *= 1000;
+ }
+ }
+
+ // Loop until the test function returns true, or until a timeout occurs,
+ // if a timeout is defined.
+ let intervalid, timeoutid;
+ let condition = new Promise(resolve => {
+ intervalid = setInterval(async () => {
+ if (await fn.call()) {
+ resolve();
+ }
+ }, 20);
+ });
+ if (typeof timeout != "undefined") {
+ condition = Promise.race([
+ condition,
+ new Promise((_, reject) => {
+ timeoutid = setTimeout(() => {
+ reject();
+ }, timeout);
+ }),
+ ]);
+ }
+ return condition
+ .finally(() => {
+ clearInterval(intervalid);
+ })
+ .then(() => {
+ clearTimeout(timeoutid);
+ });
+}
+
+function waitForNextPaint(cb) {
+ requestAnimationFrame(_ => requestAnimationFrame(cb));
+}
+
+function promiseNextPaint() {
+ return new Promise(resolve => {
+ waitForNextPaint(resolve);
+ });
+}
+
+/**
+ * Enable or disable the bfcache.
+ *
+ * Parameters:
+ *
+ * enable: if true, set max_total_viewers to -1 (the default); if false, set
+ * to 0 (disabled), if a number, set it to that specific number
+ */
+function enableBFCache(enable) {
+ // If this is the first time the test called enableBFCache(),
+ // store the original value of max_total_viewers, so it can
+ // be restored at the end of the test.
+ if (typeof gOrigMaxTotalViewers == "undefined") {
+ gOrigMaxTotalViewers = Services.prefs.getIntPref(
+ "browser.sessionhistory.max_total_viewers"
+ );
+ }
+
+ if (typeof enable == "boolean") {
+ if (enable) {
+ Services.prefs.setIntPref("browser.sessionhistory.max_total_viewers", -1);
+ } else {
+ Services.prefs.setIntPref("browser.sessionhistory.max_total_viewers", 0);
+ }
+ } else if (typeof enable == "number") {
+ Services.prefs.setIntPref(
+ "browser.sessionhistory.max_total_viewers",
+ enable
+ );
+ }
+}
+
+/*
+ * get http root for local tests. Use a single extractJarToTmp instead of
+ * extracting for each test.
+ * Returns a file://path if we have a .jar file
+ */
+function getHttpRoot() {
+ var location = window.location.href;
+ location = getRootDirectory(location);
+ var jar = getJar(location);
+ if (jar != null) {
+ if (gExtractedPath == null) {
+ var resolved = extractJarToTmp(jar);
+ gExtractedPath = resolved.path;
+ }
+ } else {
+ return null;
+ }
+ return "file://" + gExtractedPath + "/";
+}
+
+/**
+ * Returns the full HTTP url for a file in the mochitest docshell test
+ * directory.
+ */
+function getHttpUrl(filename) {
+ var root = getHttpRoot();
+ if (root == null) {
+ root = "http://mochi.test:8888/chrome/docshell/test/chrome/";
+ }
+ return root + filename;
+}
+
+/**
+ * A convenience object with methods that return the current test window,
+ * browser, and document.
+ */
+var TestWindow = {};
+TestWindow.getWindow = function() {
+ return document.getElementById("content").contentWindow;
+};
+TestWindow.getBrowser = function() {
+ return document.getElementById("content");
+};
+TestWindow.getDocument = function() {
+ return document.getElementById("content").contentDocument;
+};
diff --git a/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html b/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html
new file mode 100644
index 0000000000..fdecbbdfe1
--- /dev/null
+++ b/docshell/test/chrome/file_viewsource_forbidden_in_iframe.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Test ifranes for view-source forbidden in iframe tests</title>
+</head>
+<body>
+ <iframe id="testIframe"></iframe>
+ <iframe id="refIframe"></iframe>
+</body>
+</html>
diff --git a/docshell/test/chrome/gen_template.pl b/docshell/test/chrome/gen_template.pl
new file mode 100644
index 0000000000..109d6161cd
--- /dev/null
+++ b/docshell/test/chrome/gen_template.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+
+# This script makes docshell test case templates. It takes one argument:
+#
+# -b: a bugnumber
+#
+# For example, this command:
+#
+# perl gen_template.pl -b 303267
+#
+# Writes test case template files test_bug303267.xhtml and bug303267_window.xhtml
+# to the current directory.
+
+use FindBin;
+use Getopt::Long;
+GetOptions("b=i"=> \$bug_number);
+
+$template = "$FindBin::RealBin/test.template.txt";
+
+open(IN,$template) or die("Failed to open input file for reading.");
+open(OUT, ">>test_bug" . $bug_number . ".xhtml") or die("Failed to open output file for appending.");
+while((defined(IN)) && ($line = <IN>)) {
+ $line =~ s/{BUGNUMBER}/$bug_number/g;
+ print OUT $line;
+}
+close(IN);
+close(OUT);
+
+$template = "$FindBin::RealBin/window.template.txt";
+
+open(IN,$template) or die("Failed to open input file for reading.");
+open(OUT, ">>bug" . $bug_number . "_window.xhtml") or die("Failed to open output file for appending.");
+while((defined(IN)) && ($line = <IN>)) {
+ $line =~ s/{BUGNUMBER}/$bug_number/g;
+ print OUT $line;
+}
+close(IN);
+close(OUT);
+
diff --git a/docshell/test/chrome/generic.html b/docshell/test/chrome/generic.html
new file mode 100644
index 0000000000..569a78c05a
--- /dev/null
+++ b/docshell/test/chrome/generic.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+ <title>
+ generic page
+ </title>
+ </head>
+<body>
+<div id="div1" style="height: 1000px; border: thin solid black;">
+ A generic page which can be used any time a test needs to load an arbitrary page via http.
+ </div>
+</body>
+</html>
diff --git a/docshell/test/chrome/mozFrameType_window.xhtml b/docshell/test/chrome/mozFrameType_window.xhtml
new file mode 100644
index 0000000000..e5d0126d22
--- /dev/null
+++ b/docshell/test/chrome/mozFrameType_window.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<window title="Test mozFrameType attribute"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTests();">
+
+ <html:iframe id="normalFrame"/>
+ <html:iframe id="typeContentFrame" mozframetype="content"/>
+
+ <script type="application/javascript"><![CDATA[
+ function runTests() {
+ let opener = window.arguments[0];
+ let SimpleTest = opener.SimpleTest;
+
+ function getDocShellType(frame) {
+ return frame.contentWindow.docShell.itemType;
+ }
+
+ var normalFrame = document.getElementById("normalFrame");
+ var typeContentFrame = document.getElementById("typeContentFrame");
+
+ SimpleTest.is(getDocShellType(normalFrame), Ci.nsIDocShellTreeItem.typeChrome,
+ "normal iframe in chrome document is typeChrome");
+ SimpleTest.is(getDocShellType(typeContentFrame), Ci.nsIDocShellTreeItem.typeContent,
+ "iframe with mozFrameType='content' in chrome document is typeContent");
+
+ SimpleTest.executeSoon(function () {
+ // First focus the parent window and then close this one.
+ SimpleTest.waitForFocus(function() {
+ let ww = SpecialPowers.Services.ww;
+ ww.registerNotification(function windowObs(subject, topic, data) {
+ if (topic == "domwindowclosed") {
+ ww.unregisterNotification(windowObs);
+
+ // Don't start the next test synchronously!
+ SimpleTest.executeSoon(function() {
+ SimpleTest.finish();
+ });
+ }
+ });
+
+ window.close();
+ }, opener);
+ });
+ }
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/red.png b/docshell/test/chrome/red.png
new file mode 100644
index 0000000000..aa9ce25263
--- /dev/null
+++ b/docshell/test/chrome/red.png
Binary files differ
diff --git a/docshell/test/chrome/test.template.txt b/docshell/test/chrome/test.template.txt
new file mode 100644
index 0000000000..b7dd5e5c23
--- /dev/null
+++ b/docshell/test/chrome/test.template.txt
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}.xul
+-->
+<window title="Mozilla Bug {BUGNUMBER}"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <title>Test for Bug {BUGNUMBER}</title>
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}">
+ Mozilla Bug {BUGNUMBER}</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug {BUGNUMBER} **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug{BUGNUMBER}_window.xul", "bug{BUGNUMBER}",
+ "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_allowContentRetargeting.html b/docshell/test/chrome/test_allowContentRetargeting.html
new file mode 100644
index 0000000000..b6b830138f
--- /dev/null
+++ b/docshell/test/chrome/test_allowContentRetargeting.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runNextTest);
+
+var TEST_URL = "http://mochi.test:8888/tests/docshell/test/chrome/allowContentRetargeting.sjs";
+
+function runNextTest() {
+ var test = tests.shift();
+ if (!test) {
+ SimpleTest.finish();
+ return;
+ }
+ test();
+}
+
+var tests = [
+
+ // Set allowContentRetargeting = false, load a downloadable URL, verify the
+ // downloadable stops loading.
+ function basic() {
+ var iframe = insertIframe();
+ iframe.contentWindow.docShell.allowContentRetargeting = false;
+ loadIframe(iframe);
+ },
+
+ // Set allowContentRetargeting = false on parent docshell, load a downloadable
+ // URL, verify the downloadable stops loading.
+ function inherit() {
+ var docshell = window.docShell;
+ docshell.allowContentRetargeting = false;
+ loadIframe(insertIframe());
+ },
+];
+
+function insertIframe() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ return iframe;
+}
+
+function loadIframe(iframe) {
+ iframe.setAttribute("src", TEST_URL);
+ iframe.contentWindow.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+}
+
+var progressListener = {
+ onStateChange(webProgress, req, flags, status) {
+ if (!(flags & Ci.nsIWebProgressListener.STATE_STOP))
+ return;
+ is(Components.isSuccessCode(status), false,
+ "Downloadable should have failed to load");
+ document.querySelector("iframe").remove();
+ runNextTest();
+ },
+
+ QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),
+};
+
+ </script>
+</head>
+<body>
+<p id="display">
+</p>
+</body>
+</html>
diff --git a/docshell/test/chrome/test_bug112564.xhtml b/docshell/test/chrome/test_bug112564.xhtml
new file mode 100644
index 0000000000..33fd187eb2
--- /dev/null
+++ b/docshell/test/chrome/test_bug112564.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=112564
+-->
+<window title="Mozilla Bug 112564"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=112564">Mozilla Bug 112564</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 112564 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug112564_window.xhtml", "bug112564",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug113934.xhtml b/docshell/test/chrome/test_bug113934.xhtml
new file mode 100644
index 0000000000..99b8ae253c
--- /dev/null
+++ b/docshell/test/chrome/test_bug113934.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=113934
+-->
+<window title="Mozilla Bug 113934"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=113934"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.openDialog("bug113934_window.xhtml?content", "bug113934",
+ "chrome,width=800,height=800,noopener", window);
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug215405.xhtml b/docshell/test/chrome/test_bug215405.xhtml
new file mode 100644
index 0000000000..e40d1d046a
--- /dev/null
+++ b/docshell/test/chrome/test_bug215405.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=215405
+-->
+<window title="Mozilla Bug 215405"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=215405">Mozilla Bug 215405</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 215405 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug215405_window.xhtml", "bug215405",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug293235.xhtml b/docshell/test/chrome/test_bug293235.xhtml
new file mode 100644
index 0000000000..5b0f03f1e9
--- /dev/null
+++ b/docshell/test/chrome/test_bug293235.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=293235.xul
+-->
+<window title="Mozilla Bug 293235"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=293235">
+ Mozilla Bug 293235</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 293235 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug293235_window.xhtml", "bug293235",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug294258.xhtml b/docshell/test/chrome/test_bug294258.xhtml
new file mode 100644
index 0000000000..97588b6ab2
--- /dev/null
+++ b/docshell/test/chrome/test_bug294258.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=294258.xul
+-->
+<window title="Mozilla Bug 294258"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=294258">
+ Mozilla Bug 294258</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 294258 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug294258_window.xhtml", "bug294258",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug298622.xhtml b/docshell/test/chrome/test_bug298622.xhtml
new file mode 100644
index 0000000000..56eae4df37
--- /dev/null
+++ b/docshell/test/chrome/test_bug298622.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=298622.xul
+-->
+<window title="Mozilla Bug 298622"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=298622">
+ Mozilla Bug 298622</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 298622 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug298622_window.xhtml", "bug298622",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug301397.xhtml b/docshell/test/chrome/test_bug301397.xhtml
new file mode 100644
index 0000000000..9bcd2f5212
--- /dev/null
+++ b/docshell/test/chrome/test_bug301397.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=301397.xul
+-->
+<window title="Mozilla Bug 301397"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=301397">
+ Mozilla Bug 301397</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 301397 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug301397_window.xhtml", "bug301397",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug303267.xhtml b/docshell/test/chrome/test_bug303267.xhtml
new file mode 100644
index 0000000000..105abff0d9
--- /dev/null
+++ b/docshell/test/chrome/test_bug303267.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=303267.xul
+-->
+<window title="Mozilla Bug 303267"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=303267">Mozilla Bug 303267</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+SimpleTest.expectAssertions(0, 1);
+
+/** Test for Bug 303267 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug303267_window.xhtml", "bug303267",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug311007.xhtml b/docshell/test/chrome/test_bug311007.xhtml
new file mode 100644
index 0000000000..b4f13e6d9d
--- /dev/null
+++ b/docshell/test/chrome/test_bug311007.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=311007.xul
+-->
+<window title="Mozilla Bug 311007"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=311007">
+ Mozilla Bug 311007</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 311007 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug311007_window.xhtml", "bug311007",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug321671.xhtml b/docshell/test/chrome/test_bug321671.xhtml
new file mode 100644
index 0000000000..aa1712bf1f
--- /dev/null
+++ b/docshell/test/chrome/test_bug321671.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=321671.xul
+-->
+<window title="Mozilla Bug 321671"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=321671">
+ Mozilla Bug 321671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 321671 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug321671_window.xhtml", "bug321671",
+ "chrome,width=600,height=600,scrollbars,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug360511.xhtml b/docshell/test/chrome/test_bug360511.xhtml
new file mode 100644
index 0000000000..cbbadcdd45
--- /dev/null
+++ b/docshell/test/chrome/test_bug360511.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=360511.xul
+-->
+<window title="Mozilla Bug 360511"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
+ </script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=360511">
+ Mozilla Bug 360511</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 360511 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug360511_window.xhtml", "bug360511",
+ "chrome,scrollbars,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug364461.xhtml b/docshell/test/chrome/test_bug364461.xhtml
new file mode 100644
index 0000000000..c753f7825b
--- /dev/null
+++ b/docshell/test/chrome/test_bug364461.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=364461
+-->
+<window title="Mozilla Bug 364461"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=364461">Mozilla Bug 364461</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 364461 **/
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({
+ "set":[["security.data_uri.block_toplevel_data_uri_navigations", false]]
+}, runTests);
+
+function runTests() {
+ window.openDialog("bug364461_window.xhtml", "bug364461",
+ "chrome,width=600,height=600,noopener", window);
+}
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug396519.xhtml b/docshell/test/chrome/test_bug396519.xhtml
new file mode 100644
index 0000000000..a6faea79ae
--- /dev/null
+++ b/docshell/test/chrome/test_bug396519.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396519
+-->
+<window title="Mozilla Bug 396519"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=396519"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for Bug 396519 **/
+
+ SimpleTest.waitForExplicitFinish();
+ window.openDialog("bug396519_window.xhtml", "bug396519",
+ "chrome,width=600,height=600,noopener", window);
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug396649.xhtml b/docshell/test/chrome/test_bug396649.xhtml
new file mode 100644
index 0000000000..eda8e924da
--- /dev/null
+++ b/docshell/test/chrome/test_bug396649.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396649.xul
+-->
+<window title="Mozilla Bug 396649"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script type="application/javascript"
+ src=
+ "chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
+ </script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=396649">
+ Mozilla Bug 396649</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 396649 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug396649_window.xhtml", "bug396649",
+ "chrome,width=600,height=600,scrollbars,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug428288.html b/docshell/test/chrome/test_bug428288.html
new file mode 100644
index 0000000000..29b90c677d
--- /dev/null
+++ b/docshell/test/chrome/test_bug428288.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=428288
+-->
+<head>
+ <title>Test for Bug 428288</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428288">Mozilla Bug 428288</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name="target"></iframe>
+ <a id="crashy" target="target" href="about:blank">crash me</a>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 428288 **/
+
+function makeClick() {
+ var event = document.createEvent("MouseEvents");
+ event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ document.getElementById("crashy").dispatchEvent(event);
+ return true;
+}
+
+ok(makeClick(), "Crashes if bug 428288 is present");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/docshell/test/chrome/test_bug449778.xhtml b/docshell/test/chrome/test_bug449778.xhtml
new file mode 100644
index 0000000000..67e17164ea
--- /dev/null
+++ b/docshell/test/chrome/test_bug449778.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=449778
+-->
+<window title="Mozilla Bug 449778"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=449778"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.openDialog("bug449778_window.xhtml", "bug449778",
+ "chrome,width=800,height=800,noopener", window);
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug449780.xhtml b/docshell/test/chrome/test_bug449780.xhtml
new file mode 100644
index 0000000000..43ed3ce25d
--- /dev/null
+++ b/docshell/test/chrome/test_bug449780.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=449780
+-->
+<window title="Mozilla Bug 449780"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=449780"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.openDialog("bug449780_window.xhtml", "bug449780",
+ "chrome,width=800,height=800,noopener", window);
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug453650.xhtml b/docshell/test/chrome/test_bug453650.xhtml
new file mode 100644
index 0000000000..2865200478
--- /dev/null
+++ b/docshell/test/chrome/test_bug453650.xhtml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=453650
+-->
+<window title="Mozilla Bug 453650"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 453650 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var iter = runTests();
+ nextTest();
+
+ function* runTests() {
+ var iframe = document.createXULElement("iframe");
+ iframe.style.width = "300px";
+ iframe.style.height = "300px";
+ iframe.setAttribute("src", "data:text/html,<h1 id='h'>hello</h1>");
+
+ document.documentElement.appendChild(iframe);
+ yield whenLoaded(iframe);
+ info("iframe loaded");
+
+ var h1 = iframe.contentDocument.getElementById("h");
+ let myCallback = function() { h1.style.width = "400px"; };
+ info("Calling waitForInterruptibleReflow");
+ yield waitForInterruptibleReflow(iframe.docShell, myCallback);
+ info("got past top-level waitForInterruptibleReflow");
+
+ myCallback = function() { h1.style.width = "300px"; };
+ info("Calling waitForReflow");
+ waitForReflow(iframe.docShell, myCallback);
+ info("got past top-level waitForReflow");
+ yield is(300, h1.offsetWidth, "h1 has correct width");
+
+ SimpleTest.finish();
+ }
+
+ function waitForInterruptibleReflow(docShell,
+ callbackThatShouldTriggerReflow) {
+ waitForReflow(docShell, callbackThatShouldTriggerReflow, true);
+ }
+
+ function waitForReflow(docShell, callbackThatShouldTriggerReflow,
+ interruptible = false) {
+ info("Entering waitForReflow");
+ function done() {
+ info("Entering done (inside of waitForReflow)");
+
+ docShell.removeWeakReflowObserver(observer);
+ SimpleTest.executeSoon(nextTest);
+ }
+
+ var observer = {
+ reflow (start, end) {
+ info("Entering observer.reflow");
+ if (interruptible) {
+ ok(false, "expected interruptible reflow");
+ } else {
+ ok(true, "observed uninterruptible reflow");
+ }
+
+ info("times: " + start + ", " + end);
+ ok(start <= end, "reflow start time lower than end time");
+ done();
+ },
+
+ reflowInterruptible (start, end) {
+ info("Entering observer.reflowInterruptible");
+ if (!interruptible) {
+ ok(false, "expected uninterruptible reflow");
+ } else {
+ ok(true, "observed interruptible reflow");
+ }
+
+ info("times: " + start + ", " + end);
+ ok(start <= end, "reflow start time lower than end time");
+ done();
+ },
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIReflowObserver",
+ "nsISupportsWeakReference",
+ ]),
+ };
+
+ info("waitForReflow is adding a reflow observer");
+ docShell.addWeakReflowObserver(observer);
+ callbackThatShouldTriggerReflow();
+ }
+
+ function whenLoaded(iframe) {
+ info("entering whenLoaded");
+ iframe.addEventListener("load", function() {
+ SimpleTest.executeSoon(nextTest);
+ }, { once: true });
+ }
+
+ function nextTest() {
+ info("entering nextTest");
+ iter.next();
+ }
+
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=453650"
+ target="_blank">Mozilla Bug 453650</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug454235.xhtml b/docshell/test/chrome/test_bug454235.xhtml
new file mode 100644
index 0000000000..ed6dc57c41
--- /dev/null
+++ b/docshell/test/chrome/test_bug454235.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=454235
+-->
+<window title="Mozilla Bug 454235"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=454235"
+ target="_blank">Mozilla Bug 454235</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+ /** Test for Bug 454235 **/
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(doTest);
+
+function doTest() {
+ var hiddenBrowser = document.getElementById("hiddenBrowser");
+
+ hiddenBrowser.contentWindow.focus();
+ ok(!hiddenBrowser.contentDocument.hasFocus(), "hidden browser is unfocusable");
+
+ SimpleTest.finish();
+}
+
+
+
+ ]]></script>
+ <box flex="1" style="visibility: hidden; border:5px black solid">
+ <browser style="border:5px blue solid" id="hiddenBrowser" src="bug454235-subframe.xhtml"/>
+ </box>
+</window>
diff --git a/docshell/test/chrome/test_bug456980.xhtml b/docshell/test/chrome/test_bug456980.xhtml
new file mode 100644
index 0000000000..d1741209c6
--- /dev/null
+++ b/docshell/test/chrome/test_bug456980.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=456980
+-->
+<window title="Mozilla Bug 456980"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=456980"
+ target="_blank">Mozilla Bug 396519</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ window.openDialog("bug113934_window.xhtml?chrome", "bug456980",
+ "chrome,width=800,height=800,noopener", window);
+ });
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug565388.xhtml b/docshell/test/chrome/test_bug565388.xhtml
new file mode 100644
index 0000000000..7919176cba
--- /dev/null
+++ b/docshell/test/chrome/test_bug565388.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=565388
+-->
+<window title="Mozilla Bug 565388"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 565388 **/
+ SimpleTest.waitForExplicitFinish();
+
+function test() {
+ var progressListener = {
+ add(docShell, callback) {
+ this.callback = callback;
+ this.docShell = docShell;
+ docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
+ },
+
+ finish() {
+ this.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ removeProgressListener(this);
+ this.callback();
+ },
+
+ onStateChange (webProgress, req, flags, status) {
+ if (req.name.startsWith("data:application/vnd.mozilla.xul")) {
+ if (flags & Ci.nsIWebProgressListener.STATE_STOP)
+ this.finish();
+ }
+ },
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+ }
+
+ var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
+ .getService(Ci.nsIPrincipal);
+ var webNav = SpecialPowers.Services.appShell.createWindowlessBrowser(true);
+ var docShell = webNav.docShell;
+ docShell.createAboutBlankContentViewer(systemPrincipal, systemPrincipal);
+ var win = docShell.contentViewer.DOMDocument.defaultView;
+
+ progressListener.add(docShell, function(){
+ is(win.document.documentURI, "data:application/xhtml+xml;charset=utf-8,<window/>");
+ webNav.close();
+ SimpleTest.finish();
+ });
+
+ win.location = "data:application/xhtml+xml;charset=utf-8,<window/>";
+}
+
+addLoadEvent(function onLoad() {
+ test();
+});
+
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=565388"
+ target="_blank">Mozilla Bug 565388</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug582176.xhtml b/docshell/test/chrome/test_bug582176.xhtml
new file mode 100644
index 0000000000..718a500cdc
--- /dev/null
+++ b/docshell/test/chrome/test_bug582176.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=582176.xul
+-->
+<window title="Mozilla Bug 582176"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=582176">
+ Mozilla Bug 582176</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 582176 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug582176_window.xhtml", "bug582176",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug608669.xhtml b/docshell/test/chrome/test_bug608669.xhtml
new file mode 100644
index 0000000000..182c307766
--- /dev/null
+++ b/docshell/test/chrome/test_bug608669.xhtml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=608669
+-->
+<window title="Mozilla Bug 608669"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=608669"
+ target="_blank">Mozilla Bug 608669</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+
+/** Test for Bug 608669 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(nextTest);
+
+let gen = doTest();
+
+function nextTest() {
+ gen.next();
+}
+
+let chromeWindow = window.browsingContext.topChromeWindow;
+
+function* doTest() {
+ var notificationCount = 0;
+ var observer = {
+ observe(aSubject, aTopic, aData) {
+ is(aTopic, "chrome-document-global-created",
+ "correct topic");
+ is(aData, "null",
+ "correct data");
+ notificationCount++;
+ }
+ };
+
+ var os = SpecialPowers.Services.obs;
+ os.addObserver(observer, "chrome-document-global-created");
+ os.addObserver(observer, "content-document-global-created");
+
+ is(notificationCount, 0, "initial count");
+
+ // create a new window
+ var testWin = chromeWindow.open("", "bug 608669", "chrome,width=600,height=600");
+ testWin.x = "y";
+ is(notificationCount, 1, "after created window");
+
+ // Try loading in the window
+ testWin.location = "bug608669.xhtml";
+ chromeWindow.onmessage = nextTest;
+ yield undefined;
+ is(notificationCount, 1, "after first load");
+ is(testWin.x, "y", "reused window");
+
+ // Try loading again in the window
+ testWin.location = "bug608669.xhtml?x";
+ chromeWindow.onmessage = nextTest;
+ yield undefined;
+ is(notificationCount, 2, "after second load");
+ is("x" in testWin, false, "didn't reuse window");
+
+ chromeWindow.onmessage = null;
+
+ testWin.close();
+
+ os.removeObserver(observer, "chrome-document-global-created");
+ os.removeObserver(observer, "content-document-global-created");
+ SimpleTest.finish();
+}
+
+ ]]></script>
+</window>
diff --git a/docshell/test/chrome/test_bug662200.xhtml b/docshell/test/chrome/test_bug662200.xhtml
new file mode 100644
index 0000000000..5af4e200e2
--- /dev/null
+++ b/docshell/test/chrome/test_bug662200.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=662200.xul
+-->
+<window title="Mozilla Bug 662200"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=662200">
+ Mozilla Bug 662200</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 662200 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug662200_window.xhtml", "bug662200",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug690056.xhtml b/docshell/test/chrome/test_bug690056.xhtml
new file mode 100644
index 0000000000..f1b330a3da
--- /dev/null
+++ b/docshell/test/chrome/test_bug690056.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690056
+-->
+<window title="Mozilla Bug 690056"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=690056"
+ target="_blank">Mozilla Bug 690056</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug690056_window.xhtml", "bug690056",
+ "chrome,width=600,height=600,noopener", window);
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/test_bug789773.xhtml b/docshell/test/chrome/test_bug789773.xhtml
new file mode 100644
index 0000000000..0f4a67fc10
--- /dev/null
+++ b/docshell/test/chrome/test_bug789773.xhtml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=789773
+-->
+<window title="Mozilla Bug 789773"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=789773"
+ target="_blank">Mozilla Bug 789773</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /* Test for Bug 789773.
+ *
+ * See comment 50 for the situation we're testing against here.
+ *
+ * Note that the failure mode of this test is to hang, and hang the browser on quit.
+ * This is an unfortunate occurance, but that's why we're testing it.
+ */
+ SimpleTest.waitForExplicitFinish();
+
+ const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+
+ var calledListenerForBrowserChromeURL = false;
+ var testProgressListener = {
+ START_DOC: Ci.nsIWebProgressListener.STATE_START | Ci.nsIWebProgressListener.STATE_IS_DOCUMENT,
+ onStateChange(wp, req, stateFlags, status) {
+ let browserChromeFileName = AppConstants.BROWSER_CHROME_URL.split("/").reverse()[0];
+ if (req.name.includes(browserChromeFileName)) {
+ wp.DOMWindow; // Force the lazy creation of a DOM window.
+ calledListenerForBrowserChromeURL = true;
+ }
+ if (req.name.includes("mozilla.html") && (stateFlags & Ci.nsIWebProgressListener.STATE_STOP))
+ finishTest();
+ },
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+ }
+
+ // Add our progress listener
+ var webProgress = Cc['@mozilla.org/docloaderservice;1'].getService(Ci.nsIWebProgress);
+ webProgress.addProgressListener(testProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
+
+ // Open the window.
+ var popup = window.open("about:mozilla", "_blank", "width=640,height=400");
+
+ // Wait for the window to load.
+ function finishTest() {
+ webProgress.removeProgressListener(testProgressListener);
+ ok(true, "Loaded the popup window without spinning forever in the event loop!");
+ ok(calledListenerForBrowserChromeURL, "Should have called the progress listener for browser.xhtml");
+ popup.close();
+ SimpleTest.finish();
+ }
+
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/test_bug846906.xhtml b/docshell/test/chrome/test_bug846906.xhtml
new file mode 100644
index 0000000000..0fdf0e5079
--- /dev/null
+++ b/docshell/test/chrome/test_bug846906.xhtml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=846906
+-->
+<window title="Mozilla Bug 846906"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+
+ /** Test for Bug 846906 **/
+ SimpleTest.waitForExplicitFinish();
+
+ var appShellService = SpecialPowers.Services.appShell;
+ ok(appShellService, "Should be able to get app shell service");
+
+ var windowlessBrowser = appShellService.createWindowlessBrowser();
+ ok(windowlessBrowser, "Should be able to create windowless browser");
+
+ ok(windowlessBrowser instanceof Ci.nsIWindowlessBrowser,
+ "Windowless browser should implement nsIWindowlessBrowser");
+
+ var webNavigation = windowlessBrowser.QueryInterface(Ci.nsIWebNavigation);
+ ok(webNavigation, "Windowless browser should implement nsIWebNavigation");
+
+ var interfaceRequestor = windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor);
+ ok(interfaceRequestor, "Should be able to query interface requestor interface");
+
+ var docShell = windowlessBrowser.docShell;
+ ok(docShell, "Should be able to get doc shell interface");
+
+ var document = webNavigation.document;
+ ok(document, "Should be able to get document");
+
+ var iframe = document.createXULElement("iframe");
+ ok(iframe, "Should be able to create iframe");
+
+ iframe.onload = function () {
+ ok(true, "Should receive initial onload event");
+
+ iframe.onload = function () {
+ ok(true, "Should receive onload event");
+
+ var contentDocument = iframe.contentDocument;
+ ok(contentDocument, "Should be able to get content document");
+
+ var div = contentDocument.getElementById("div1");
+ ok(div, "Should be able to get element by id");
+
+ var rect = div.getBoundingClientRect();
+ ok(rect, "Should be able to get bounding client rect");
+
+ // xxx: can we do better than hardcoding these values here?
+ is(rect.width, 1024);
+ is(rect.height, 768);
+
+ windowlessBrowser.close();
+
+ // Once the browser is closed, nsIWebNavigation and
+ // nsIInterfaceRequestor methods should no longer be accessible.
+ try {
+ windowlessBrowser.getInterface(Ci.nsIDocShell);
+ ok(false);
+ } catch (e) {
+ is(e.result, Cr.NS_ERROR_NULL_POINTER);
+ }
+
+ try {
+ windowlessBrowser.document;
+ ok(false);
+ } catch (e) {
+ is(e.result, Cr.NS_ERROR_NULL_POINTER);
+ }
+
+ SimpleTest.finish();
+ };
+ iframe.setAttribute("src", "http://mochi.test:8888/chrome/docshell/test/chrome/bug846906.html");
+ };
+ document.documentElement.appendChild(iframe);
+
+ ]]>
+ </script>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=846906"
+ target="_blank">Mozilla Bug 846906</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_bug89419.xhtml b/docshell/test/chrome/test_bug89419.xhtml
new file mode 100644
index 0000000000..6a00080aa6
--- /dev/null
+++ b/docshell/test/chrome/test_bug89419.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=89419.xul
+-->
+<window title="Mozilla Bug 89419"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=89419">
+ Mozilla Bug 89419</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 89419 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug89419_window.xhtml", "bug89419",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_bug909218.html b/docshell/test/chrome/test_bug909218.html
new file mode 100644
index 0000000000..bcbcc176eb
--- /dev/null
+++ b/docshell/test/chrome/test_bug909218.html
@@ -0,0 +1,117 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+
+// The default flags we will stick on the docShell - every request made by the
+// docShell should include those flags.
+const TEST_FLAGS = Ci.nsIRequest.LOAD_ANONYMOUS |
+ Ci.nsIRequest.LOAD_BYPASS_CACHE |
+ Ci.nsIRequest.INHIBIT_CACHING;
+
+var TEST_URL = "http://mochi.test:8888/chrome/docshell/test/chrome/bug909218.html";
+
+// These are the requests we expect to see loading TEST_URL into our iframe.
+
+// The test entry-point. The basic outline is:
+// * Create an iframe and set defaultLoadFlags on its docShell.
+// * Add a web progress listener to observe each request as the iframe is
+// loaded, and check that each request has the flags we specified.
+// * Load our test URL into the iframe and wait for the load to complete.
+function test() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ var docShell = iframe.contentWindow.docShell;
+ // Add our progress listener - when it notices the top-level document is
+ // complete, the test will end.
+ RequestWatcher.init(docShell, SimpleTest.finish);
+ // Set the flags we care about, then load our test URL.
+ docShell.defaultLoadFlags = TEST_FLAGS;
+ iframe.setAttribute("src", TEST_URL);
+}
+
+// an nsIWebProgressListener that checks all requests made by the docShell
+// have the flags we expect.
+var RequestWatcher = {
+ init(docShell, callback) {
+ this.callback = callback;
+ this.docShell = docShell;
+ docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
+ Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+ // These are the requests we expect to see - initialize each to have a
+ // count of zero.
+ this.requestCounts = {};
+ for (var url of [
+ TEST_URL,
+ // content loaded by the above test html.
+ "http://mochi.test:8888/chrome/docshell/test/chrome/bug909218.js",
+ "http://mochi.test:8888/tests/SimpleTest/test.css",
+ "http://mochi.test:8888/tests/docshell/test/chrome/red.png",
+ // the content of an iframe in the test html.
+ "http://mochi.test:8888/chrome/docshell/test/chrome/generic.html",
+ ]) {
+ this.requestCounts[url] = 0;
+ }
+ },
+
+ // Finalize the test after we detect a completed load. We check we saw the
+ // correct requests and make a callback to exit.
+ finalize() {
+ ok(Object.keys(this.requestCounts).length, "we expected some requests");
+ for (var url in this.requestCounts) {
+ var count = this.requestCounts[url];
+ // As we are looking at all request states, we expect more than 1 for
+ // each URL - 0 or 1 would imply something went wrong - >1 just means
+ // multiple states for each request were recorded, which we don't care
+ // about (we do care they all have the correct flags though - but we
+ // do that in onStateChange)
+ ok(count > 1, url + " saw " + count + " requests");
+ }
+ this.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ removeProgressListener(this);
+ this.callback();
+ },
+
+ onStateChange(webProgress, req, flags, status) {
+ // We are checking requests - if there isn't one, ignore it.
+ if (!req) {
+ return;
+ }
+ // We will usually see requests for 'about:document-onload-blocker' not
+ // have the flag, so we just ignore them.
+ // We also see, eg, resource://gre-resources/loading-image.png, so
+ // skip resource:// URLs too.
+ // We may also see, eg, chrome://global/skin/icons/chevron.svg, so
+ // skip chrome:// URLs too.
+ if (req.name.startsWith("about:") || req.name.startsWith("resource:") ||
+ req.name.startsWith("chrome:") || req.name.startsWith("documentchannel:")) {
+ return;
+ }
+ is(req.loadFlags & TEST_FLAGS, TEST_FLAGS, "request " + req.name + " has the expected flags");
+ this.requestCounts[req.name] += 1;
+ var stopFlags = Ci.nsIWebProgressListener.STATE_STOP |
+ Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+ if (req.name == TEST_URL && (flags & stopFlags) == stopFlags) {
+ this.finalize();
+ }
+ },
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+};
+
+</script>
+</head>
+</html>
diff --git a/docshell/test/chrome/test_bug92598.xhtml b/docshell/test/chrome/test_bug92598.xhtml
new file mode 100644
index 0000000000..9c3a46866a
--- /dev/null
+++ b/docshell/test/chrome/test_bug92598.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=92598
+-->
+<window title="Mozilla Bug 92598"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=92598">Mozilla Bug 92598</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 92598 **/
+
+SimpleTest.waitForExplicitFinish();
+window.openDialog("bug92598_window.xhtml", "bug92598",
+ "chrome,width=600,height=600,noopener", window);
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_docRedirect.sjs b/docshell/test/chrome/test_docRedirect.sjs
new file mode 100644
index 0000000000..4050eb06d7
--- /dev/null
+++ b/docshell/test/chrome/test_docRedirect.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ response.setHeader("Location", "http://example.org/");
+ response.write("Hello world!");
+}
diff --git a/docshell/test/chrome/test_docRedirect.xhtml b/docshell/test/chrome/test_docRedirect.xhtml
new file mode 100644
index 0000000000..1688d9823e
--- /dev/null
+++ b/docshell/test/chrome/test_docRedirect.xhtml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1342989
+-->
+<window title="Mozilla Bug 1342989"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ const WEB_PROGRESS_LISTENER_FLAGS =
+ Object.keys(Ci.nsIWebProgressListener).filter(
+ propName => propName.startsWith("STATE_")
+ );
+
+ function bitFlagsToNames(flags, knownNames, intf) {
+ return knownNames.map( (F) => {
+ return (flags & intf[F]) ? F : undefined;
+ }).filter( (s) => !!s );
+ }
+
+ var progressListener = {
+ add(docShell, callback) {
+ this.callback = callback;
+ this.docShell = docShell;
+ docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
+ },
+
+ finish(success) {
+ this.docShell.
+ QueryInterface(Ci.nsIInterfaceRequestor).
+ getInterface(Ci.nsIWebProgress).
+ removeProgressListener(this);
+ this.callback(success);
+ },
+
+ onStateChange (webProgress, req, flags, status) {
+ if (!(flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) &&
+ !(flags & Ci.nsIWebProgressListener.STATE_IS_REDIRECTED_DOCUMENT))
+ return;
+
+ var channel = req.QueryInterface(Ci.nsIChannel);
+
+ if (flags & Ci.nsIWebProgressListener.STATE_IS_REDIRECTED_DOCUMENT) {
+ SimpleTest.is(channel.URI.host, "example.org",
+ "Should be redirected to example.org (see test_docRedirect.sjs)");
+ this.finish(true);
+ }
+
+ // Fail in case we didn't receive document redirection event.
+ if (flags & Ci.nsIWebProgressListener.STATE_STOP)
+ this.finish(false);
+ },
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+ }
+
+ var webNav = SpecialPowers.Services.appShell.createWindowlessBrowser(true);
+ let docShell = webNav.docShell;
+ let system = Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal);
+ docShell.createAboutBlankContentViewer(system, system);
+
+ progressListener.add(docShell, function(success) {
+ webNav.close();
+ SimpleTest.is(success, true, "Received document redirect event");
+ SimpleTest.finish();
+ });
+
+ var win = docShell.contentViewer.DOMDocument.defaultView;
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ win.location = "http://example.com/chrome/docshell/test/chrome/test_docRedirect.sjs"
+
+ ]]>
+ </script>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1342989"
+ target="_blank">Mozilla Bug 1342989</a>
+ </body>
+</window>
diff --git a/docshell/test/chrome/test_mozFrameType.xhtml b/docshell/test/chrome/test_mozFrameType.xhtml
new file mode 100644
index 0000000000..6e8bfd8f85
--- /dev/null
+++ b/docshell/test/chrome/test_mozFrameType.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=769771
+-->
+<window title="Test mozFrameType attribute"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 769771 **/
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function () {
+ window.openDialog("mozFrameType_window.xhtml", "mozFrameType",
+ "chrome,width=600,height=600,noopener", window);
+});
+
+]]>
+</script>
+
+</window>
diff --git a/docshell/test/chrome/test_open_and_immediately_close_opener.html b/docshell/test/chrome/test_open_and_immediately_close_opener.html
new file mode 100644
index 0000000000..bb5f6f054d
--- /dev/null
+++ b/docshell/test/chrome/test_open_and_immediately_close_opener.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for Bug 1702678</title>
+ <meta charset="utf-8">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1702678">Mozilla Bug 1702678</a>
+
+<script type="application/javascript">
+"use strict";
+
+const HTML = `
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script>
+ // We need to queue a promise reaction job whilch will close the window
+ // during the nested event loop spun up by the window opening code.
+ Promise.resolve().then(() => {
+ window.close();
+ });
+ window.open("data:text/html,Hello");
+ <\/script>
+</head>
+</html>
+`;
+
+add_task(async function() {
+ // This bug only manifests when opening tabs in new windows.
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.link.open_newwindow", 2]],
+ });
+
+ // Create a window in a new BrowsingContextGroup so that it will be the last
+ // window in the group when it closes, and the group will be destroyed.
+ window.open(`data:text/html,${encodeURIComponent(HTML)}`, "", "noopener");
+
+ // Make a few trips through the event loop to ensure we've had a chance to
+ // open and close the relevant windows.
+ for (let i = 0; i < 10; i++) {
+ await new Promise(resolve => setTimeout(resolve, 0));
+ }
+
+ ok(true, "We didn't crash");
+});
+</script>
+
+</body>
+</html>
+
diff --git a/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xhtml b/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xhtml
new file mode 100644
index 0000000000..0cc45c7821
--- /dev/null
+++ b/docshell/test/chrome/test_viewsource_forbidden_in_iframe.xhtml
@@ -0,0 +1,159 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin/global.css"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=624883
+-->
+<window title="Mozilla Bug 624883"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=624883"
+ target="_blank">Mozilla Bug 624883</a>
+ </body>
+
+ <!-- test code goes here -->
+ <iframe type="content" onload="startTest()" src="file_viewsource_forbidden_in_iframe.html"></iframe>
+
+ <script type="application/javascript">
+ <![CDATA[
+
+ SimpleTest.waitForExplicitFinish();
+
+ // We create a promise that will resolve with the error message
+ // on a network error page load and reject on any other load.
+ function createNetworkErrorMessagePromise(frame) {
+ return new Promise(function(resolve, reject) {
+
+ // Error pages do not fire "load" events, so use a progressListener.
+ var originalDocumentURI = frame.contentDocument.documentURI;
+ var progressListener = {
+ onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
+ // Make sure nothing other than an error page is loaded.
+ if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) {
+ reject("location change was not to an error page");
+ }
+ },
+
+ onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
+ // Wait until the documentURI changes (from about:blank) this should
+ // be the error page URI.
+ var documentURI = frame.contentDocument.documentURI;
+ if (documentURI == originalDocumentURI) {
+ return;
+ }
+
+ aWebProgress.removeProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_ALL);
+ var matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI);
+ if (!matchArray) {
+ reject("no network error message found in URI")
+ return;
+ }
+
+ var errorMsg = matchArray[1];
+ resolve(decodeURIComponent(errorMsg));
+ },
+
+ QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
+ "nsISupportsWeakReference"])
+ };
+
+ frame.contentWindow.docShell
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebProgress)
+ .addProgressListener(progressListener,
+ Ci.nsIWebProgress.NOTIFY_LOCATION |
+ Ci.nsIWebProgress.NOTIFY_STATE_REQUEST);
+ });
+ }
+
+ function startTest() {
+ // Get a reference message that we know will be an unknown protocol message,
+ // so we can use it for comparisons in the test cases.
+ var refIframe = window[0].document.getElementById("refIframe");
+ var refErrorPromise = createNetworkErrorMessagePromise(refIframe);
+
+ refErrorPromise.then(
+ function(msg) {
+ window.refErrorMsg = msg;
+ var testIframe = window[0].document.getElementById("testIframe");
+
+ // Run test cases on load of "about:blank", so that the URI always changes
+ // and we can detect this in our Promise.
+ testIframe.onload = runNextTestCase;
+ testIframe.src = "about:blank";
+ },
+ function(reason) {
+ ok(false, "Could not get reference error message", reason);
+ SimpleTest.finish();
+ })
+ .catch(function(e) {
+ ok(false, "Unexpected exception thrown getting reference error message", e);
+ });
+
+ refIframe.src = "wibble://example.com";
+ }
+
+ function runTestCase(testCase) {
+ var testIframe = window[0].document.getElementById("testIframe");
+ var expectedErrorMsg = window.refErrorMsg.replace("wibble", testCase.expectedProtocolList);
+
+ var testErrorPromise = createNetworkErrorMessagePromise(testIframe);
+ testErrorPromise.then(
+ function(actualErrorMsg) {
+ is(actualErrorMsg, expectedErrorMsg, testCase.desc);
+ testIframe.src = "about:blank";
+ },
+ function(reason) {
+ ok(false, testCase.desc, reason);
+ testIframe.src = "about:blank";
+ })
+ .catch(function(e) {
+ ok(false, testCase.desc + " - unexpected exception thrown", e);
+ });
+
+ testIframe.src = testCase.protocols + "://example.com/!/";
+ }
+
+ var testCaseIndex = -1;
+ let testCases = [
+ {
+ desc: "Test 1: view-source should not be allowed in an iframe",
+ protocols: "view-source:http",
+ expectedProtocolList: "view-source, http"
+ },
+ {
+ desc: "Test 2: jar:view-source should not be allowed in an iframe",
+ protocols: "jar:view-source:http",
+ expectedProtocolList: "jar, view-source, http"
+ },
+ {
+ desc: "Test 3: if invalid protocol first should report before view-source",
+ protocols: "wibble:view-source:http",
+ // Nothing after the invalid protocol gets set as a proper nested URI,
+ // so the list stops there.
+ expectedProtocolList: "wibble"
+ },
+ {
+ desc: "Test 4: if view-source first should report before invalid protocol",
+ protocols: "view-source:wibble:http",
+ expectedProtocolList: "view-source, wibble"
+ }
+ ];
+
+ function runNextTestCase() {
+ ++testCaseIndex;
+ if (testCaseIndex == testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ runTestCase(testCases[testCaseIndex]);
+ }
+
+ ]]>
+ </script>
+</window>
diff --git a/docshell/test/chrome/window.template.txt b/docshell/test/chrome/window.template.txt
new file mode 100644
index 0000000000..4c520dc075
--- /dev/null
+++ b/docshell/test/chrome/window.template.txt
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="{BUGNUMBER}Test"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="600"
+ height="600"
+ onload="setTimeout(nextTest,0);"
+ title="bug {BUGNUMBER} test">
+
+ <script type="application/javascript"
+ src="docshell_helpers.js">
+ </script>
+
+ <script type="application/javascript"><![CDATA[
+
+ // Define the generator-iterator for the tests.
+ var tests = testIterator();
+
+ ////
+ // Execute the next test in the generator function.
+ //
+ function nextTest() {
+ tests.next();
+ }
+
+ ////
+ // Generator function for test steps for bug {BUGNUMBER}:
+ // Description goes here.
+ //
+ function testIterator()
+ {
+ // Test steps go here. See bug303267_window.xhtml for an example.
+
+ // Tell the framework the test is finished. Include the final 'yield'
+ // statement to prevent a StopIteration exception from being thrown.
+ finish();
+ yield undefined;
+ }
+
+ ]]></script>
+
+ <browser type="content" primary="true" flex="1" id="content" src="about:blank"/>
+</window>