summaryrefslogtreecommitdiffstats
path: root/docshell/test/browser
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /docshell/test/browser
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'docshell/test/browser')
-rw-r--r--docshell/test/browser/browser.ini93
-rw-r--r--docshell/test/browser/browser_bug1206879.js31
-rw-r--r--docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js35
-rw-r--r--docshell/test/browser/browser_bug134911.js41
-rw-r--r--docshell/test/browser/browser_bug234628-1.js18
-rw-r--r--docshell/test/browser/browser_bug234628-10.js18
-rw-r--r--docshell/test/browser/browser_bug234628-11.js18
-rw-r--r--docshell/test/browser/browser_bug234628-2.js18
-rw-r--r--docshell/test/browser/browser_bug234628-3.js18
-rw-r--r--docshell/test/browser/browser_bug234628-4.js18
-rw-r--r--docshell/test/browser/browser_bug234628-5.js18
-rw-r--r--docshell/test/browser/browser_bug234628-6.js18
-rw-r--r--docshell/test/browser/browser_bug234628-7.js18
-rw-r--r--docshell/test/browser/browser_bug234628-8.js11
-rw-r--r--docshell/test/browser/browser_bug234628-9.js11
-rw-r--r--docshell/test/browser/browser_bug349769.js47
-rw-r--r--docshell/test/browser/browser_bug388121-1.js15
-rw-r--r--docshell/test/browser/browser_bug388121-2.js58
-rw-r--r--docshell/test/browser/browser_bug420605.js122
-rw-r--r--docshell/test/browser/browser_bug422543.js116
-rw-r--r--docshell/test/browser/browser_bug441169.js37
-rw-r--r--docshell/test/browser/browser_bug503832.js87
-rw-r--r--docshell/test/browser/browser_bug554155.js26
-rw-r--r--docshell/test/browser/browser_bug655270.js60
-rw-r--r--docshell/test/browser/browser_bug655273.js30
-rw-r--r--docshell/test/browser/browser_bug670318.js70
-rw-r--r--docshell/test/browser/browser_bug673467.js51
-rw-r--r--docshell/test/browser/browser_bug852909.js23
-rw-r--r--docshell/test/browser/browser_bug92473.js54
-rw-r--r--docshell/test/browser/browser_loadDisallowInherit.js65
-rw-r--r--docshell/test/browser/browser_loadURI.js34
-rw-r--r--docshell/test/browser/browser_multiple_pushState.js15
-rw-r--r--docshell/test/browser/browser_onbeforeunload_navigation.js176
-rw-r--r--docshell/test/browser/browser_search_notification.js51
-rw-r--r--docshell/test/browser/browser_tab_touch_events.js49
-rw-r--r--docshell/test/browser/browser_timelineMarkers-01.js32
-rw-r--r--docshell/test/browser/browser_timelineMarkers-02.js15
-rw-r--r--docshell/test/browser/browser_timelineMarkers-03.js8
-rw-r--r--docshell/test/browser/browser_timelineMarkers-04.js8
-rw-r--r--docshell/test/browser/browser_timelineMarkers-05.js15
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-02.js133
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-03.js91
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-04.js88
-rw-r--r--docshell/test/browser/browser_timelineMarkers-frame-05.js117
-rw-r--r--docshell/test/browser/browser_ua_emulation.js36
-rw-r--r--docshell/test/browser/browser_uriFixupAlternateRedirects.js24
-rw-r--r--docshell/test/browser/browser_uriFixupIntegration.js51
-rw-r--r--docshell/test/browser/favicon_bug655270.icobin0 -> 1406 bytes
-rw-r--r--docshell/test/browser/file_bug1046022.html50
-rw-r--r--docshell/test/browser/file_bug1206879.html9
-rw-r--r--docshell/test/browser/file_bug234628-1-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-1.html17
-rw-r--r--docshell/test/browser/file_bug234628-10-child.xhtml4
-rw-r--r--docshell/test/browser/file_bug234628-10.html17
-rw-r--r--docshell/test/browser/file_bug234628-11-child.xhtml4
-rw-r--r--docshell/test/browser/file_bug234628-11-child.xhtml^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-11.html17
-rw-r--r--docshell/test/browser/file_bug234628-2-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-2.html17
-rw-r--r--docshell/test/browser/file_bug234628-3-child.html13
-rw-r--r--docshell/test/browser/file_bug234628-3.html18
-rw-r--r--docshell/test/browser/file_bug234628-4-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-4.html18
-rw-r--r--docshell/test/browser/file_bug234628-5-child.htmlbin0 -> 498 bytes
-rw-r--r--docshell/test/browser/file_bug234628-5.html18
-rw-r--r--docshell/test/browser/file_bug234628-6-child.htmlbin0 -> 540 bytes
-rw-r--r--docshell/test/browser/file_bug234628-6-child.html^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-6.html18
-rw-r--r--docshell/test/browser/file_bug234628-7-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-7-child.html^headers^1
-rw-r--r--docshell/test/browser/file_bug234628-7.html18
-rw-r--r--docshell/test/browser/file_bug234628-8-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-8.html17
-rw-r--r--docshell/test/browser/file_bug234628-9-child.html12
-rw-r--r--docshell/test/browser/file_bug234628-9.htmlbin0 -> 740 bytes
-rw-r--r--docshell/test/browser/file_bug420605.html31
-rw-r--r--docshell/test/browser/file_bug422543_script.js98
-rw-r--r--docshell/test/browser/file_bug503832.html35
-rw-r--r--docshell/test/browser/file_bug655270.html11
-rw-r--r--docshell/test/browser/file_bug670318.html23
-rw-r--r--docshell/test/browser/file_bug852909.pdfbin0 -> 1568 bytes
-rw-r--r--docshell/test/browser/file_bug852909.pngbin0 -> 94 bytes
-rw-r--r--docshell/test/browser/file_multiple_pushState.html14
-rw-r--r--docshell/test/browser/frame-head.js113
-rw-r--r--docshell/test/browser/head.js99
-rw-r--r--docshell/test/browser/print_postdata.sjs22
-rw-r--r--docshell/test/browser/redirect_to_example.sjs4
-rw-r--r--docshell/test/browser/test-form_sjis.html24
-rw-r--r--docshell/test/browser/timelineMarkers-04.html55
89 files changed, 3047 insertions, 0 deletions
diff --git a/docshell/test/browser/browser.ini b/docshell/test/browser/browser.ini
new file mode 100644
index 000000000..9211092a4
--- /dev/null
+++ b/docshell/test/browser/browser.ini
@@ -0,0 +1,93 @@
+[DEFAULT]
+support-files =
+ favicon_bug655270.ico
+ file_bug234628-1-child.html
+ file_bug234628-1.html
+ file_bug234628-10-child.xhtml
+ file_bug234628-10.html
+ file_bug234628-11-child.xhtml
+ file_bug234628-11-child.xhtml^headers^
+ file_bug234628-11.html
+ file_bug234628-2-child.html
+ file_bug234628-2.html
+ file_bug234628-3-child.html
+ file_bug234628-3.html
+ file_bug234628-4-child.html
+ file_bug234628-4.html
+ file_bug234628-5-child.html
+ file_bug234628-5.html
+ file_bug234628-6-child.html
+ file_bug234628-6-child.html^headers^
+ file_bug234628-6.html
+ file_bug234628-7-child.html
+ file_bug234628-7-child.html^headers^
+ file_bug234628-7.html
+ file_bug234628-8-child.html
+ file_bug234628-8.html
+ file_bug234628-9-child.html
+ file_bug234628-9.html
+ file_bug420605.html
+ file_bug422543_script.js
+ file_bug503832.html
+ file_bug655270.html
+ file_bug670318.html
+ file_bug852909.pdf
+ file_bug852909.png
+ file_bug1046022.html
+ file_bug1206879.html
+ file_multiple_pushState.html
+ print_postdata.sjs
+ test-form_sjis.html
+ timelineMarkers-04.html
+ browser_timelineMarkers-frame-02.js
+ browser_timelineMarkers-frame-03.js
+ browser_timelineMarkers-frame-04.js
+ browser_timelineMarkers-frame-05.js
+ head.js
+ frame-head.js
+
+[browser_bug1206879.js]
+[browser_bug1309900_crossProcessHistoryNavigation.js]
+[browser_bug134911.js]
+[browser_bug234628-1.js]
+[browser_bug234628-10.js]
+[browser_bug234628-11.js]
+[browser_bug234628-2.js]
+[browser_bug234628-3.js]
+[browser_bug234628-4.js]
+[browser_bug234628-5.js]
+[browser_bug234628-6.js]
+[browser_bug234628-7.js]
+[browser_bug234628-8.js]
+[browser_bug234628-9.js]
+[browser_bug349769.js]
+[browser_bug388121-1.js]
+[browser_bug388121-2.js]
+[browser_bug420605.js]
+[browser_bug422543.js]
+[browser_bug441169.js]
+[browser_bug503832.js]
+[browser_bug554155.js]
+[browser_bug655270.js]
+[browser_bug655273.js]
+[browser_bug670318.js]
+[browser_bug673467.js]
+[browser_bug852909.js]
+[browser_bug92473.js]
+[browser_uriFixupIntegration.js]
+[browser_uriFixupAlternateRedirects.js]
+support-files =
+ redirect_to_example.sjs
+[browser_loadDisallowInherit.js]
+[browser_loadURI.js]
+[browser_multiple_pushState.js]
+[browser_onbeforeunload_navigation.js]
+[browser_search_notification.js]
+[browser_tab_touch_events.js]
+[browser_timelineMarkers-01.js]
+[browser_timelineMarkers-02.js]
+skip-if = true # Bug 1220415
+[browser_timelineMarkers-03.js]
+[browser_timelineMarkers-04.js]
+[browser_timelineMarkers-05.js]
+[browser_ua_emulation.js]
diff --git a/docshell/test/browser/browser_bug1206879.js b/docshell/test/browser/browser_bug1206879.js
new file mode 100644
index 000000000..1276f6428
--- /dev/null
+++ b/docshell/test/browser/browser_bug1206879.js
@@ -0,0 +1,31 @@
+add_task(function*() {
+ let url = getRootDirectory(gTestPath) + "file_bug1206879.html";
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, true);
+
+ let numLocationChanges = 0;
+
+ let listener = {
+ onLocationChange: function(browser, wp, request, uri, flags) {
+ if (browser != tab.linkedBrowser) {
+ return;
+ }
+ info("onLocationChange: " + uri.spec);
+ numLocationChanges++;
+ this.resolve();
+ }
+ };
+ let locationPromise = new Promise((resolve, reject) => {
+ listener.resolve = resolve;
+ gBrowser.addTabsProgressListener(listener);
+ });
+ yield ContentTask.spawn(tab.linkedBrowser, {}, function() {
+ content.frames[0].history.pushState(null, null, "foo");
+ });
+
+ yield locationPromise;
+
+ gBrowser.removeTab(tab);
+ gBrowser.removeTabsProgressListener(listener);
+ is(numLocationChanges, 1,
+ "pushState with a different URI should cause a LocationChange event.");
+});
diff --git a/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
new file mode 100644
index 000000000..a4b4645e8
--- /dev/null
+++ b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+add_task(function* runTests() {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:about");
+
+ registerCleanupFunction(function* () {
+ gBrowser.removeTab(tab);
+ });
+
+ let browser = tab.linkedBrowser;
+
+ browser.loadURI("about:accounts");
+ let href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "about:accounts", "Check about:accounts loaded");
+
+ // Using a dummy onunload listener to disable the bfcache as that can prevent
+ // the test browser load detection mechanism from working.
+ browser.loadURI("data:text/html,<body%20onunload=''><iframe></iframe></body>");
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
+ "Check data URL loaded");
+
+ browser.goBack();
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "about:accounts", "Check we've gone back to about:accounts");
+
+ browser.goForward();
+ href = yield BrowserTestUtils.browserLoaded(browser);
+ is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
+ "Check we've gone forward to data URL");
+});
diff --git a/docshell/test/browser/browser_bug134911.js b/docshell/test/browser/browser_bug134911.js
new file mode 100644
index 000000000..aa54cfd1a
--- /dev/null
+++ b/docshell/test/browser/browser_bug134911.js
@@ -0,0 +1,41 @@
+const TEXT = {
+ /* The test text decoded correctly as Shift_JIS */
+ rightText: "\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059",
+
+ enteredText1: "The quick brown fox jumps over the lazy dog",
+ enteredText2: "\u03BE\u03B5\u03C3\u03BA\u03B5\u03C0\u03AC\u03B6\u03C9\u0020\u03C4\u1F74\u03BD\u0020\u03C8\u03C5\u03C7\u03BF\u03C6\u03B8\u03CC\u03C1\u03B1\u0020\u03B2\u03B4\u03B5\u03BB\u03C5\u03B3\u03BC\u03AF\u03B1",
+};
+
+function test() {
+ waitForExplicitFinish();
+
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
+}
+
+function afterOpen() {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
+ content.document.getElementById("testtextarea").value = TEXT.enteredText1;
+ content.document.getElementById("testinput").value = TEXT.enteredText2;
+ }).then(() => {
+ /* Force the page encoding to Shift_JIS */
+ BrowserSetForcedCharacterSet("Shift_JIS");
+ });
+}
+
+function afterChangeCharset() {
+ ContentTask.spawn(gBrowser.selectedBrowser, TEXT, function(TEXT) {
+ is(content.document.getElementById("testpar").innerHTML, TEXT.rightText,
+ "encoding successfully changed");
+ is(content.document.getElementById("testtextarea").value, TEXT.enteredText1,
+ "text preserved in <textarea>");
+ is(content.document.getElementById("testinput").value, TEXT.enteredText2,
+ "text preserved in <input>");
+ }).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug234628-1.js b/docshell/test/browser/browser_bug234628-1.js
new file mode 100644
index 000000000..bfb4d3708
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-1.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-1.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 85, "Child doc should be windows-1252 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 85, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-10.js b/docshell/test/browser/browser_bug234628-10.js
new file mode 100644
index 000000000..7dbe805c4
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-10.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-10.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 151, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 151, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 71, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-11.js b/docshell/test/browser/browser_bug234628-11.js
new file mode 100644
index 000000000..fc597f5c0
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-11.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-11.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 193, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 193, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-2.js b/docshell/test/browser/browser_bug234628-2.js
new file mode 100644
index 000000000..638e223c0
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-2.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-2.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 129, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u00E2\u201A\u00AC'), 78, "Child doc should be windows-1252 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 129, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 78, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-3.js b/docshell/test/browser/browser_bug234628-3.js
new file mode 100644
index 000000000..51aca7ec8
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-3.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-3.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 118, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 73, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 118, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 73, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-4.js b/docshell/test/browser/browser_bug234628-4.js
new file mode 100644
index 000000000..fe7f1545f
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-4.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-4.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 132, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 132, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 79, "Child doc should decode as utf-8 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-8", "Child doc should report UTF-8 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-5.js b/docshell/test/browser/browser_bug234628-5.js
new file mode 100644
index 000000000..a37f14b8d
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-5.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-5.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 146, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should be utf-16 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 146, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 87, "Child doc should decode as utf-16 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-16LE", "Child doc should report UTF-16LE subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-6.js b/docshell/test/browser/browser_bug234628-6.js
new file mode 100644
index 000000000..7d2d92531
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-6.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-6.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 190, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should be utf-16 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 190, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 109, "Child doc should decode as utf-16 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "UTF-16BE", "Child doc should report UTF-16 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-7.js b/docshell/test/browser/browser_bug234628-7.js
new file mode 100644
index 000000000..0bafd67e7
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-7.js
@@ -0,0 +1,18 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-7.html", afterOpen, "windows-1251", afterChangeCharset);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 188, "Parent doc should be windows-1252 initially");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 107, "Child doc should be utf-8 initially");
+}
+
+function afterChangeCharset() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 188, "Parent doc should decode as windows-1251 subsequently");
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0432\u201A\u00AC'), 107, "Child doc should decode as windows-1251 subsequently");
+
+ is(content.document.characterSet, "windows-1251", "Parent doc should report windows-1251 subsequently");
+ is(content.frames[0].document.characterSet, "windows-1251", "Child doc should report windows-1251 subsequently");
+}
diff --git a/docshell/test/browser/browser_bug234628-8.js b/docshell/test/browser/browser_bug234628-8.js
new file mode 100644
index 000000000..40a0c6946
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-8.js
@@ -0,0 +1,11 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-8.html", afterOpen);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u0402'), 156, "Parent doc should be windows-1251");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u0402'), 99, "Child doc should be windows-1251");
+}
+
diff --git a/docshell/test/browser/browser_bug234628-9.js b/docshell/test/browser/browser_bug234628-9.js
new file mode 100644
index 000000000..72da65e80
--- /dev/null
+++ b/docshell/test/browser/browser_bug234628-9.js
@@ -0,0 +1,11 @@
+function test() {
+ var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ runCharsetTest(rootDir + "file_bug234628-9.html", afterOpen);
+}
+
+function afterOpen() {
+ is(content.document.documentElement.textContent.indexOf('\u20AC'), 145, "Parent doc should be UTF-16");
+
+ is(content.frames[0].document.documentElement.textContent.indexOf('\u20AC'), 96, "Child doc should be windows-1252");
+}
+
diff --git a/docshell/test/browser/browser_bug349769.js b/docshell/test/browser/browser_bug349769.js
new file mode 100644
index 000000000..76d4e0f28
--- /dev/null
+++ b/docshell/test/browser/browser_bug349769.js
@@ -0,0 +1,47 @@
+add_task(function* test() {
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+ const uris = [undefined, "about:blank"];
+
+ function checkContentProcess(uri) {
+ yield ContentTask.spawn(newBrowser, uri, function* (uri) {
+ var prin = content.document.nodePrincipal;
+ Assert.notEqual(prin, null, "Loaded principal must not be null when adding " + uri);
+ Assert.notEqual(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(Ci.nsIScriptSecurityManager);
+ Assert.equal(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+ });
+ }
+
+ for (var uri of uris) {
+ yield BrowserTestUtils.withNewTab({ gBrowser }, function* (newBrowser) {
+ yield BrowserTestUtils.loadURI(newBrowser, uri);
+
+ var prin = newBrowser.contentPrincipal;
+ isnot(prin, null, "Forced principal must not be null when loading " + uri);
+ isnot(prin, undefined,
+ "Forced principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Forced principal must not be system when loading " + uri);
+
+ // Belt-and-suspenders e10s check: make sure that the same checks hold
+ // true in the content process.
+ checkContentProcess(uri);
+
+ yield BrowserTestUtils.browserLoaded(newBrowser);
+
+ prin = newBrowser.contentPrincipal;
+ isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+ isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+
+ // Belt-and-suspenders e10s check: make sure that the same checks hold
+ // true in the content process.
+ checkContentProcess(uri);
+ });
+ }
+});
+
diff --git a/docshell/test/browser/browser_bug388121-1.js b/docshell/test/browser/browser_bug388121-1.js
new file mode 100644
index 000000000..7da617594
--- /dev/null
+++ b/docshell/test/browser/browser_bug388121-1.js
@@ -0,0 +1,15 @@
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (newBrowser) {
+ yield ContentTask.spawn(newBrowser, null, function* () {
+ var prin = content.document.nodePrincipal;
+ Assert.notEqual(prin, null, "Loaded principal must not be null");
+ Assert.notEqual(prin, undefined, "Loaded principal must not be undefined");
+
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
+ .getService(Ci.nsIScriptSecurityManager);
+ Assert.equal(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system");
+ });
+ });
+});
+
diff --git a/docshell/test/browser/browser_bug388121-2.js b/docshell/test/browser/browser_bug388121-2.js
new file mode 100644
index 000000000..6c050d971
--- /dev/null
+++ b/docshell/test/browser/browser_bug388121-2.js
@@ -0,0 +1,58 @@
+function test() {
+ waitForExplicitFinish();
+
+ var w;
+ const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
+ var iteration = 1;
+ const uris = ["", "about:blank"];
+ var uri;
+ var origDoc;
+
+ function testLoad() {
+ if (w.document == origDoc) {
+ // Go back to polling
+ setTimeout(testLoad, 10);
+ return;
+ }
+ var prin = w.document.nodePrincipal;
+ isnot(prin, null, "Loaded principal must not be null when adding " + uri);
+ isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Loaded principal must not be system when loading " + uri);
+ w.close();
+
+ if (iteration == uris.length) {
+ finish();
+ } else {
+ ++iteration;
+ doTest();
+ }
+ }
+
+ function doTest() {
+ uri = uris[iteration - 1];
+ w = window.open(uri, "_blank", "width=10,height=10");
+ var prin = w.document.nodePrincipal;
+ if (!uri) {
+ uri = undefined;
+ }
+ isnot(prin, null, "Forced principal must not be null when loading " + uri);
+ isnot(prin, undefined,
+ "Forced principal must not be undefined when loading " + uri);
+ is(secMan.isSystemPrincipal(prin), false,
+ "Forced principal must not be system when loading " + uri);
+ if (uri == undefined) {
+ // No actual load here, so just move along.
+ w.close();
+ ++iteration;
+ doTest();
+ } else {
+ origDoc = w.document;
+ // Need to poll, because load listeners on the content window won't
+ // survive the load.
+ setTimeout(testLoad, 10);
+ }
+ }
+
+ doTest();
+}
diff --git a/docshell/test/browser/browser_bug420605.js b/docshell/test/browser/browser_bug420605.js
new file mode 100644
index 000000000..f07d45e93
--- /dev/null
+++ b/docshell/test/browser/browser_bug420605.js
@@ -0,0 +1,122 @@
+/* Test for Bug 420605
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=420605
+ */
+
+function test() {
+ waitForExplicitFinish();
+
+ var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html";
+ var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html#firefox";
+
+ var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
+ .getService(Ci.nsINavHistoryService);
+
+ /* Queries nsINavHistoryService and returns a single history entry
+ * for a given URI */
+ function getNavHistoryEntry(aURI) {
+ var options = historyService.getNewQueryOptions();
+ options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+ options.maxResults = 1;
+
+ var query = historyService.getNewQuery();
+ query.uri = aURI;
+
+ var result = historyService.executeQuery(query, options);
+ result.root.containerOpen = true;
+
+ if (!result.root.childCount) {
+ return null;
+ }
+ return result.root.getChild(0);
+ }
+
+ // We'll save the favicon URL of the orignal page here and check that the
+ // page with a hash has the same favicon.
+ var originalFavicon;
+
+ // Control flow in this test is a bit complicated.
+ //
+ // When the page loads, onPageLoad (the DOMContentLoaded handler) and
+ // historyObserver::onPageChanged are both called, in some order. Once
+ // they've both run, we click a fragment link in the content page
+ // (clickLinkIfReady), which should trigger another onPageChanged event,
+ // this time for the fragment's URL.
+
+ var _clickLinkTimes = 0;
+ function clickLinkIfReady() {
+ _clickLinkTimes++;
+ if (_clickLinkTimes == 2) {
+ BrowserTestUtils.synthesizeMouseAtCenter('#firefox-link', {},
+ gBrowser.selectedBrowser);
+ }
+ }
+
+ /* Global history observer that triggers for the two test URLs above. */
+ var historyObserver = {
+ onBeginUpdateBatch: function() {},
+ onEndUpdateBatch: function() {},
+ onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
+ aTransitionType, _added) {},
+ onTitleChanged: function(aURI, aPageTitle) {},
+ onDeleteURI: function(aURI) {},
+ onClearHistory: function() {},
+ onPageChanged: function(aURI, aWhat, aValue) {
+ if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
+ return;
+ }
+ aURI = aURI.spec;
+ switch (aURI) {
+ case pageurl:
+ ok(aValue, "Favicon value is not null for page without fragment.");
+ originalFavicon = aValue;
+
+ // Now that the favicon has loaded, click on fragment link.
+ // This should trigger the |case fragmenturl| below.
+ clickLinkIfReady();
+
+ return;
+ case fragmenturl:
+ // If the fragment URL's favicon isn't set, this branch won't
+ // be called and the test will time out.
+
+ is(aValue, originalFavicon, "New favicon should be same as original favicon.");
+
+ // Let's explicitly check that we can get the favicon
+ // from nsINavHistoryService now.
+ let info = getNavHistoryEntry(makeURI(aURI));
+ ok(info, "There must be a history entry for the fragment.");
+ ok(info.icon, "The history entry must have an associated favicon.");
+ historyService.removeObserver(historyObserver, false);
+ gBrowser.removeCurrentTab();
+ finish();
+ }
+ },
+ onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsINavHistoryObserver) ||
+ iid.equals(Ci.nsISupports)) {
+ return this;
+ }
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ };
+ historyService.addObserver(historyObserver, false);
+
+ function onPageLoad() {
+ gBrowser.selectedBrowser
+ .removeEventListener("DOMContentLoaded", arguments.callee, true);
+ clickLinkIfReady();
+ }
+
+ // Make sure neither of the test pages haven't been loaded before.
+ var info = getNavHistoryEntry(makeURI(pageurl));
+ ok(!info, "The test page must not have been visited already.");
+ info = getNavHistoryEntry(makeURI(fragmenturl));
+ ok(!info, "The fragment test page must not have been visited already.");
+
+ // Now open the test page in a new tab.
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener(
+ "DOMContentLoaded", onPageLoad, true);
+ content.location = pageurl;
+}
diff --git a/docshell/test/browser/browser_bug422543.js b/docshell/test/browser/browser_bug422543.js
new file mode 100644
index 000000000..0655a17b7
--- /dev/null
+++ b/docshell/test/browser/browser_bug422543.js
@@ -0,0 +1,116 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(function* runTests() {
+ yield setup();
+ let browser = gBrowser.selectedBrowser;
+ // Now that we're set up, initialize our frame script.
+ yield checkListeners("initial", "listeners initialized");
+
+ // Check if all history listeners are always notified.
+ info("# part 1");
+ yield whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
+ yield checkListeners("newentry", "shistory has a new entry");
+ ok(browser.canGoBack, "we can go back");
+
+ yield whenPageShown(browser, () => browser.goBack());
+ yield checkListeners("goback", "back to the first shentry");
+ ok(browser.canGoForward, "we can go forward");
+
+ yield whenPageShown(browser, () => browser.goForward());
+ yield checkListeners("goforward", "forward to the second shentry");
+
+ yield whenPageShown(browser, () => browser.reload());
+ yield checkListeners("reload", "current shentry reloaded");
+
+ yield whenPageShown(browser, () => browser.gotoIndex(0));
+ yield checkListeners("gotoindex", "back to the first index");
+
+ // Check nsISHistoryInternal.notifyOnHistoryReload
+ info("# part 2");
+ ok((yield notifyReload()), "reloading has not been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let the first listener cancel the reload action.
+ info("# part 3");
+ yield resetListeners();
+ yield setListenerRetval(0, false);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let both listeners cancel the reload action.
+ info("# part 4");
+ yield resetListeners();
+ yield setListenerRetval(1, false);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+
+ // Let the second listener cancel the reload action.
+ info("# part 5");
+ yield resetListeners();
+ yield setListenerRetval(0, true);
+ ok(!(yield notifyReload()), "reloading has been canceled");
+ yield checkListeners("reload", "saw the reload notification");
+});
+
+function listenOnce(message, arg = {}) {
+ return new Promise(resolve => {
+ let mm = gBrowser.selectedBrowser.messageManager;
+ mm.addMessageListener(message + ":return", function listener(msg) {
+ mm.removeMessageListener(message + ":return", listener);
+ resolve(msg.data);
+ });
+
+ mm.sendAsyncMessage(message, arg);
+ });
+}
+
+function checkListeners(aLast, aMessage) {
+ return listenOnce("bug422543:getListenerStatus").then((listenerStatuses) => {
+ is(listenerStatuses[0], aLast, aMessage);
+ is(listenerStatuses[1], aLast, aMessage);
+ });
+}
+
+function resetListeners() {
+ return listenOnce("bug422543:resetListeners");
+}
+
+function notifyReload() {
+ return listenOnce("bug422543:notifyReload").then(({ rval }) => {
+ return rval;
+ });
+}
+
+function setListenerRetval(num, val) {
+ return listenOnce("bug422543:setRetval", { num, val });
+}
+
+function setup() {
+ return BrowserTestUtils.openNewForegroundTab(gBrowser,
+ "http://mochi.test:8888")
+ .then(function (tab) {
+ let browser = tab.linkedBrowser;
+ registerCleanupFunction(function* () {
+ yield listenOnce("bug422543:cleanup");
+ gBrowser.removeTab(tab);
+ });
+
+ browser.messageManager
+ .loadFrameScript(getRootDirectory(gTestPath) + "file_bug422543_script.js", false);
+ });
+}
+
+function whenPageShown(aBrowser, aNavigation) {
+ let listener = ContentTask.spawn(aBrowser, null, function () {
+ return new Promise(resolve => {
+ addEventListener("pageshow", function onLoad() {
+ removeEventListener("pageshow", onLoad, true);
+ resolve();
+ }, true);
+ });
+ });
+
+ aNavigation();
+ return listener;
+}
diff --git a/docshell/test/browser/browser_bug441169.js b/docshell/test/browser/browser_bug441169.js
new file mode 100644
index 000000000..015115793
--- /dev/null
+++ b/docshell/test/browser/browser_bug441169.js
@@ -0,0 +1,37 @@
+/* Make sure that netError won't allow HTML injection through badcert parameters. See bug 441169. */
+var newBrowser
+
+function task() {
+ let resolve;
+ let promise = new Promise(r => { resolve = r; });
+
+ addEventListener("DOMContentLoaded", checkPage, false);
+
+ function checkPage(event) {
+ if (event.target != content.document) {
+ return;
+ }
+ removeEventListener("DOMContentLoaded", checkPage, false);
+
+ is(content.document.getElementById("test_span"), null, "Error message should not be parsed as HTML, and hence shouldn't include the 'test_span' element.");
+ resolve();
+ }
+
+ var chromeURL = "about:neterror?e=nssBadCert&u=https%3A//test.kuix.de/&c=UTF-8&d=This%20sentence%20should%20not%20be%20parsed%20to%20include%20a%20%3Cspan%20id=%22test_span%22%3Enamed%3C/span%3E%20span%20tag.%0A%0AThe%20certificate%20is%20only%20valid%20for%20%3Ca%20id=%22cert_domain_link%22%20title=%22kuix.de%22%3Ekuix.de%3C/a%3E%0A%0A(Error%20code%3A%20ssl_error_bad_cert_domain)";
+ content.location = chromeURL;
+
+ return promise;
+}
+
+function test() {
+ waitForExplicitFinish();
+
+ var newTab = gBrowser.addTab();
+ gBrowser.selectedTab = newTab;
+ newBrowser = gBrowser.getBrowserForTab(newTab);
+
+ ContentTask.spawn(newBrowser, null, task).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug503832.js b/docshell/test/browser/browser_bug503832.js
new file mode 100644
index 000000000..66904cbae
--- /dev/null
+++ b/docshell/test/browser/browser_bug503832.js
@@ -0,0 +1,87 @@
+/* Test for Bug 503832
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=503832
+ */
+
+add_task(function* () {
+ var pagetitle = "Page Title for Bug 503832";
+ var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html";
+ var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug503832.html#firefox";
+
+ var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
+ .getService(Ci.nsINavHistoryService);
+
+ let fragmentPromise = new Promise(resolve => {
+ /* Global history observer that triggers for the two test URLs above. */
+ var historyObserver = {
+ onBeginUpdateBatch: function() {},
+ onEndUpdateBatch: function() {},
+ onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
+ aTransitionType, _added) {},
+ onTitleChanged: function(aURI, aPageTitle) {
+ aURI = aURI.spec;
+ switch (aURI) {
+ case pageurl:
+ is(aPageTitle, pagetitle, "Correct page title for " + aURI);
+ return;
+ case fragmenturl:
+ is(aPageTitle, pagetitle, "Correct page title for " + aURI);
+ // If titles for fragment URLs aren't set, this code
+ // branch won't be called and the test will timeout,
+ // resulting in a failure
+ historyService.removeObserver(historyObserver, false);
+ resolve();
+ }
+ },
+ onDeleteURI: function(aURI) {},
+ onClearHistory: function() {},
+ onPageChanged: function(aURI, aWhat, aValue) {},
+ onDeleteVisits: function () {},
+ QueryInterface: function(iid) {
+ if (iid.equals(Ci.nsINavHistoryObserver) ||
+ iid.equals(Ci.nsISupports)) {
+ return this;
+ }
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ };
+
+ historyService.addObserver(historyObserver, false);
+ });
+
+ /* Queries nsINavHistoryService and returns a single history entry
+ * for a given URI */
+ function getNavHistoryEntry(aURI) {
+ var options = historyService.getNewQueryOptions();
+ options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
+ options.maxResults = 1;
+
+ var query = historyService.getNewQuery();
+ query.uri = aURI;
+
+ var result = historyService.executeQuery(query, options);
+ result.root.containerOpen = true;
+
+ if (!result.root.childCount) {
+ return null;
+ }
+ var node = result.root.getChild(0);
+ result.root.containerOpen = false;
+ return node;
+ }
+
+ // Make sure neither of the test pages haven't been loaded before.
+ var info = getNavHistoryEntry(makeURI(pageurl));
+ ok(!info, "The test page must not have been visited already.");
+ info = getNavHistoryEntry(makeURI(fragmenturl));
+ ok(!info, "The fragment test page must not have been visited already.");
+
+ // Now open the test page in a new tab
+ yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageurl);
+
+ // Now that the page is loaded, click on fragment link
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#firefox-link", {},
+ gBrowser.selectedBrowser);
+ yield fragmentPromise;
+
+ gBrowser.removeCurrentTab();
+});
diff --git a/docshell/test/browser/browser_bug554155.js b/docshell/test/browser/browser_bug554155.js
new file mode 100644
index 000000000..efc74a1c1
--- /dev/null
+++ b/docshell/test/browser/browser_bug554155.js
@@ -0,0 +1,26 @@
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" }, function* (browser) {
+ let numLocationChanges = 0;
+
+ let listener = {
+ onLocationChange: function(browser, webProgress, request, uri, flags) {
+ info("location change: " + (uri && uri.spec));
+ numLocationChanges++;
+ }
+ };
+
+ gBrowser.addTabsProgressListener(listener);
+
+ yield ContentTask.spawn(browser, null, function() {
+ // pushState to a new URL (http://example.com/foo"). This should trigger
+ // exactly one LocationChange event.
+ content.history.pushState(null, null, "foo");
+ });
+
+ yield Promise.resolve();
+
+ gBrowser.removeTabsProgressListener(listener);
+ is(numLocationChanges, 1,
+ "pushState should cause exactly one LocationChange event.");
+ });
+});
diff --git a/docshell/test/browser/browser_bug655270.js b/docshell/test/browser/browser_bug655270.js
new file mode 100644
index 000000000..275245df8
--- /dev/null
+++ b/docshell/test/browser/browser_bug655270.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test for Bug 655273
+ *
+ * Call pushState and then make sure that the favicon service associates our
+ * old favicon with the new URI.
+ */
+
+function test() {
+ const testDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+ const origURL = testDir + "file_bug655270.html";
+ const newURL = origURL + '?new_page';
+
+ const faviconURL = testDir + "favicon_bug655270.ico";
+
+ waitForExplicitFinish();
+
+ let tab = gBrowser.addTab(origURL);
+
+ // The page at origURL has a <link rel='icon'>, so we should get a call into
+ // our observer below when it loads. Once we verify that we have the right
+ // favicon URI, we call pushState, which should trigger another onPageChange
+ // event, this time for the URI after pushState.
+
+ let observer = {
+ onPageChanged: function(aURI, aWhat, aValue) {
+ if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
+ return;
+
+ if (aURI.spec == origURL) {
+ is(aValue, faviconURL, 'FaviconURL for original URI');
+ // Ignore the promise returned here and wait for the next
+ // onPageChanged notification.
+ ContentTask.spawn(tab.linkedBrowser, null, function() {
+ content.history.pushState('', '', '?new_page');
+ });
+ }
+
+ if (aURI.spec == newURL) {
+ is(aValue, faviconURL, 'FaviconURL for new URI');
+ gBrowser.removeTab(tab);
+ PlacesUtils.history.removeObserver(this);
+ finish();
+ }
+ },
+
+ onBeginUpdateBatch: function() { },
+ onEndUpdateBatch: function() { },
+ onVisit: function() { },
+ onTitleChanged: function() { },
+ onDeleteURI: function() { },
+ onClearHistory: function() { },
+ onDeleteVisits: function() { },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
+ };
+
+ PlacesUtils.history.addObserver(observer, false);
+}
diff --git a/docshell/test/browser/browser_bug655273.js b/docshell/test/browser/browser_bug655273.js
new file mode 100644
index 000000000..3acb6ddd5
--- /dev/null
+++ b/docshell/test/browser/browser_bug655273.js
@@ -0,0 +1,30 @@
+/* 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/. */
+
+/**
+ * Test for Bug 655273. Make sure that after changing the URI via
+ * history.pushState, the resulting SHEntry has the same title as our old
+ * SHEntry.
+ **/
+
+add_task(function* test() {
+ waitForExplicitFinish();
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, function* () {
+ let cw = content;
+ let oldTitle = cw.document.title;
+ ok(oldTitle, 'Content window should initially have a title.');
+ cw.history.pushState('', '', 'new_page');
+
+ let shistory = cw.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ is(shistory.getEntryAtIndex(shistory.index, false).title,
+ oldTitle, 'SHEntry title after pushstate.');
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_bug670318.js b/docshell/test/browser/browser_bug670318.js
new file mode 100644
index 000000000..a73639cab
--- /dev/null
+++ b/docshell/test/browser/browser_bug670318.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Test for Bug 670318
+ *
+ * When LoadEntry() is called on a browser that has multiple duplicate history
+ * entries, history.index can end up out of range (>= history.count).
+ */
+
+const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
+
+add_task(function* test() {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
+ function* (browser) {
+ yield ContentTask.spawn(browser, URL, function* (URL) {
+ let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+ let count = 0;
+
+ let testDone = {};
+ testDone.promise = new Promise(resolve => { testDone.resolve = resolve; });
+
+ let listener = {
+ OnHistoryNewEntry: function (aNewURI) {
+ if (aNewURI.spec == URL && 5 == ++count) {
+ addEventListener("load", function onLoad() {
+ removeEventListener("load", onLoad, true);
+
+ Assert.ok(history.index < history.count, "history.index is valid");
+ testDone.resolve();
+ }, true);
+
+ history.removeSHistoryListener(listener);
+ delete content._testListener;
+ content.setTimeout(() => { content.location.reload(); }, 0);
+ }
+
+ return true;
+ },
+
+ OnHistoryReload: () => true,
+ OnHistoryGoBack: () => true,
+ OnHistoryGoForward: () => true,
+ OnHistoryGotoIndex: () => true,
+ OnHistoryPurge: () => true,
+ OnHistoryReplaceEntry: () => {
+ // The initial load of about:blank causes a transient entry to be
+ // created, so our first navigation to a real page is a replace
+ // instead of a new entry.
+ ++count;
+ return true;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+ Ci.nsISupportsWeakReference])
+ };
+
+ history.addSHistoryListener(listener);
+ // Since listener implements nsISupportsWeakReference, we are
+ // responsible for keeping it alive so that the GC doesn't clear
+ // it before the test completes. We do this by anchoring the listener
+ // to the content global window, and clearing it just before the test
+ // completes.
+ content._testListener = listener;
+ content.location = URL;
+
+ yield testDone.promise;
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_bug673467.js b/docshell/test/browser/browser_bug673467.js
new file mode 100644
index 000000000..10139a48c
--- /dev/null
+++ b/docshell/test/browser/browser_bug673467.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test for bug 673467. In a new tab, load a page which inserts a new iframe
+// before the load and then sets its location during the load. This should
+// create just one SHEntry.
+
+var doc = "data:text/html,<html><body onload='load()'>" +
+ "<script>" +
+ " var iframe = document.createElement('iframe');" +
+ " iframe.id = 'iframe';" +
+ " document.documentElement.appendChild(iframe);" +
+ " function load() {" +
+ " iframe.src = 'data:text/html,Hello!';" +
+ " }" +
+ "</script>" +
+ "</body></html>"
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.addTab(doc);
+ let tabBrowser = tab.linkedBrowser;
+
+ BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
+ return ContentTask.spawn(tab.linkedBrowser, null, () => {
+ return new Promise(resolve => {
+ // The main page has loaded. Now wait for the iframe to load.
+ let iframe = content.document.getElementById('iframe');
+ iframe.addEventListener('load', function listener(aEvent) {
+
+ // Wait for the iframe to load the new document, not about:blank.
+ if (!iframe.src)
+ return;
+
+ iframe.removeEventListener('load', listener, true);
+ let shistory = content
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .sessionHistory;
+
+ Assert.equal(shistory.count, 1, "shistory count should be 1.");
+ resolve();
+ }, true);
+ });
+ });
+ }).then(() => {
+ gBrowser.removeTab(tab);
+ finish();
+ });
+}
diff --git a/docshell/test/browser/browser_bug852909.js b/docshell/test/browser/browser_bug852909.js
new file mode 100644
index 000000000..5e2374c43
--- /dev/null
+++ b/docshell/test/browser/browser_bug852909.js
@@ -0,0 +1,23 @@
+var rootDir = "http://mochi.test:8888/browser/docshell/test/browser/";
+
+function test() {
+ waitForExplicitFinish();
+
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.png");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(image);
+}
+
+function image(event) {
+ ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for images.");
+
+ gBrowser.removeCurrentTab();
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug852909.pdf");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(pdf);
+}
+
+function pdf(event) {
+ ok(!gBrowser.selectedTab.mayEnableCharacterEncodingMenu, "Docshell should say the menu should be disabled for PDF.js.");
+
+ gBrowser.removeCurrentTab();
+ finish();
+}
diff --git a/docshell/test/browser/browser_bug92473.js b/docshell/test/browser/browser_bug92473.js
new file mode 100644
index 000000000..d1c4aebdb
--- /dev/null
+++ b/docshell/test/browser/browser_bug92473.js
@@ -0,0 +1,54 @@
+/* The test text as octets for reference
+ * %83%86%83%6a%83%52%81%5b%83%68%82%cd%81%41%82%b7%82%d7%82%c4%82%cc%95%b6%8e%9a%82%c9%8c%c5%97%4c%82%cc%94%d4%8d%86%82%f0%95%74%97%5e%82%b5%82%dc%82%b7
+ */
+
+function testContent(text) {
+ return ContentTask.spawn(gBrowser.selectedBrowser, text, text => {
+ Assert.equal(content.document.getElementById("testpar").innerHTML, text,
+ "<p> contains expected text");
+ Assert.equal(content.document.getElementById("testtextarea").innerHTML, text,
+ "<textarea> contains expected text");
+ Assert.equal(content.document.getElementById("testinput").value, text,
+ "<input> contains expected text");
+ });
+}
+
+function afterOpen() {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ /* The test text decoded incorrectly as Windows-1251. This is the "right" wrong
+ text; anything else is unexpected. */
+ const wrongText="\u0453\u2020\u0453\u006A\u0453\u0052\u0403\u005B\u0453\u0068\u201A\u041D\u0403\u0041\u201A\u00B7\u201A\u0427\u201A\u0414\u201A\u041C\u2022\u00B6\u040B\u0459\u201A\u0419\u040A\u0415\u2014\u004C\u201A\u041C\u201D\u0424\u040C\u2020\u201A\u0440\u2022\u0074\u2014\u005E\u201A\u00B5\u201A\u042C\u201A\u00B7";
+
+ /* Test that the content on load is the expected wrong decoding */
+ testContent(wrongText).then(() => {
+ BrowserSetForcedCharacterSet("Shift_JIS");
+ });
+}
+
+function afterChangeCharset() {
+ /* The test text decoded correctly as Shift_JIS */
+ const rightText="\u30E6\u30CB\u30B3\u30FC\u30C9\u306F\u3001\u3059\u3079\u3066\u306E\u6587\u5B57\u306B\u56FA\u6709\u306E\u756A\u53F7\u3092\u4ED8\u4E0E\u3057\u307E\u3059";
+
+ /* test that the content is decoded correctly */
+ testContent(rightText).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+
+ // Get the local directory. This needs to be a file: URI because chrome: URIs
+ // are always UTF-8 (bug 617339) and we are testing decoding from other
+ // charsets.
+ var jar = getJar(getRootDirectory(gTestPath));
+ var dir = jar ?
+ extractJarToTmp(jar) :
+ getChromeDir(getResolvedURI(gTestPath));
+ var rootDir = Services.io.newFileURI(dir).spec;
+
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "test-form_sjis.html");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpen);
+}
diff --git a/docshell/test/browser/browser_loadDisallowInherit.js b/docshell/test/browser/browser_loadDisallowInherit.js
new file mode 100644
index 000000000..71789890f
--- /dev/null
+++ b/docshell/test/browser/browser_loadDisallowInherit.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ registerCleanupFunction(function () {
+ gBrowser.removeTab(tab);
+ });
+
+ let browser = gBrowser.getBrowserForTab(tab);
+
+ function loadURL(url, flags, func) {
+ browser.addEventListener("load", function loadListener(e) {
+ if (browser.currentURI.spec != url)
+ return;
+ browser.removeEventListener(e.type, loadListener, true);
+ func();
+ }, true);
+ browser.loadURIWithFlags(url, flags, null, null, null);
+ }
+
+ // Load a normal http URL
+ function testURL(url, func) {
+ loadURL("http://example.com/", 0, function () {
+ let pagePrincipal = browser.contentPrincipal;
+ ok(pagePrincipal, "got principal for http:// page");
+
+ // Now load the URL normally
+ loadURL(url, 0, function () {
+ ok(browser.contentPrincipal.equals(pagePrincipal), url + " should inherit principal");
+
+ // Now load the URL and disallow inheriting the principal
+ let webNav = Components.interfaces.nsIWebNavigation;
+ loadURL(url, webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, function () {
+ let newPrincipal = browser.contentPrincipal;
+ ok(newPrincipal, "got inner principal");
+ ok(!newPrincipal.equals(pagePrincipal),
+ url + " should not inherit principal when loaded with DISALLOW_INHERIT_OWNER");
+
+ func();
+ });
+ });
+ });
+ }
+
+ let urls = [
+ "data:text/html,<body>hi",
+ // We used to test javascript: here as well, but now that we no longer run
+ // javascript: in a sandbox, we end up not running it at all in the
+ // DISALLOW_INHERIT_OWNER case, so never actually do a load for it at all.
+ ];
+
+ function nextTest() {
+ let url = urls.shift();
+ if (url)
+ testURL(url, nextTest);
+ else
+ finish();
+ }
+
+ nextTest();
+}
+
diff --git a/docshell/test/browser/browser_loadURI.js b/docshell/test/browser/browser_loadURI.js
new file mode 100644
index 000000000..a68e1c2de
--- /dev/null
+++ b/docshell/test/browser/browser_loadURI.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+const gPostData = "postdata=true";
+
+function test() {
+ waitForExplicitFinish();
+
+ let tab = gBrowser.selectedTab = gBrowser.addTab();
+ registerCleanupFunction(function () {
+ gBrowser.removeTab(tab);
+ });
+
+ var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
+ createInstance(Ci.nsIStringInputStream);
+ dataStream.data = gPostData;
+
+ var postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
+ createInstance(Ci.nsIMIMEInputStream);
+ postStream.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ postStream.addContentLength = true;
+ postStream.setData(dataStream);
+
+ tab.linkedBrowser.loadURIWithFlags("http://mochi.test:8888/browser/docshell/test/browser/print_postdata.sjs", 0, null, null, postStream);
+ BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(() => {
+ ContentTask.spawn(tab.linkedBrowser, gPostData, function(postData) {
+ var bodyText = content.document.body.textContent;
+ is(bodyText, postData, "post data was submitted correctly");
+ }).then(() => { finish(); });
+ });
+}
diff --git a/docshell/test/browser/browser_multiple_pushState.js b/docshell/test/browser/browser_multiple_pushState.js
new file mode 100644
index 000000000..5c2f5aef4
--- /dev/null
+++ b/docshell/test/browser/browser_multiple_pushState.js
@@ -0,0 +1,15 @@
+add_task(function* test_multiple_pushState() {
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: "http://example.org/browser/docshell/test/browser/file_multiple_pushState.html",
+ }, function* (browser) {
+ const kExpected = "http://example.org/bar/ABC/DEF?key=baz";
+
+ let contentLocation = yield ContentTask.spawn(browser, null, function* () {
+ return content.document.location.href;
+ });
+
+ is(contentLocation, kExpected);
+ is(browser.documentURI.spec, kExpected);
+ });
+});
diff --git a/docshell/test/browser/browser_onbeforeunload_navigation.js b/docshell/test/browser/browser_onbeforeunload_navigation.js
new file mode 100644
index 000000000..d2feb69d4
--- /dev/null
+++ b/docshell/test/browser/browser_onbeforeunload_navigation.js
@@ -0,0 +1,176 @@
+var contentWindow;
+var originalLocation;
+var currentTest = -1;
+var stayingOnPage = true;
+
+var TEST_PAGE = "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
+var TARGETED_PAGE = "data:text/html," + encodeURIComponent("<body>Shouldn't be seeing this</body>");
+
+SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
+
+var loadExpected = TEST_PAGE;
+var testTab;
+var testsLength;
+
+var loadStarted = false;
+var tabStateListener = {
+ onStateChange: function(webprogress, request, stateFlags, status) {
+ let startDocumentFlags = Ci.nsIWebProgressListener.STATE_START |
+ Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
+ if ((stateFlags & startDocumentFlags) == startDocumentFlags) {
+ loadStarted = true;
+ }
+ },
+ onStatusChange: () => {},
+ onLocationChange: () => {},
+ onSecurityChange: () => {},
+ onProgressChange: () => {},
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener])
+};
+
+function onTabLoaded(event) {
+ info("A document loaded in a tab!");
+ let loadedPage = event.target.location.href;
+ if (loadedPage == "about:blank" ||
+ event.originalTarget != testTab.linkedBrowser.contentDocument) {
+ return;
+ }
+
+ if (!loadExpected) {
+ ok(false, "Expected no page loads, but loaded " + loadedPage + " instead!");
+ return;
+ }
+
+ if (!testsLength) {
+ testsLength = testTab.linkedBrowser.contentWindow.wrappedJSObject.testFns.length;
+ }
+
+ is(loadedPage, loadExpected, "Loaded the expected page");
+ if (contentWindow) {
+ is(contentWindow.document, event.target, "Same doc");
+ }
+ if (onAfterPageLoad) {
+ onAfterPageLoad();
+ }
+}
+
+function onAfterTargetedPageLoad() {
+ ok(!stayingOnPage, "We should only fire if we're expecting to let the onbeforeunload dialog proceed to the new location");
+ is(testTab.linkedBrowser.currentURI.spec, TARGETED_PAGE, "Should have loaded the expected new page");
+
+ runNextTest();
+}
+
+function onTabModalDialogLoaded(node) {
+ let content = testTab.linkedBrowser.contentWindow;
+ ok(!loadStarted, "No load should be started.");
+ info(content.location.href);
+ is(content, contentWindow, "Window should be the same still.");
+ is(content.location.href, originalLocation, "Page should not have changed.");
+ is(content.mySuperSpecialMark, 42, "Page should not have refreshed.");
+
+ ok(!content.dialogWasInvoked, "Dialog should only be invoked once per test.");
+ content.dialogWasInvoked = true;
+
+
+ // Now listen for the dialog going away again...
+ let observer = new MutationObserver(function(muts) {
+ if (!node.parentNode) {
+ info("Dialog is gone");
+ observer.disconnect();
+ observer = null;
+ // If we're staying on the page, run the next test from here
+ if (stayingOnPage) {
+ // Evil, but necessary: without this delay, we manage to still break our
+ // own onbeforeunload code, because we'll basically cause a new load to be
+ // started while processing the destruction of the dialog for the old one.
+ executeSoon(runNextTest);
+ }
+ // if we accepted a page load in the dialog, the next test will get started
+ // by the load handler for that page loading
+ }
+ });
+ observer.observe(node.parentNode, {childList: true});
+
+ // If we're going to let the page load, set us up to listen for that happening:
+ if (!stayingOnPage) {
+ loadExpected = TARGETED_PAGE;
+ onAfterPageLoad = onAfterTargetedPageLoad;
+ }
+
+ let button = stayingOnPage ? node.ui.button1 : node.ui.button0;
+ // ... and then actually make the dialog go away
+ info("Clicking button: " + button.label);
+ EventUtils.synthesizeMouseAtCenter(button, {});
+}
+
+// Listen for the dialog being created
+Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
+
+function runNextTest() {
+ currentTest++;
+ if (currentTest >= testsLength) {
+ if (!stayingOnPage) {
+ finish();
+ return;
+ }
+ // Run the same tests again, but this time let the navigation happen:
+ stayingOnPage = false;
+ // Remove onbeforeunload handler, or this load will trigger the dialog...
+ contentWindow.onbeforeunload = null;
+ currentTest = 0;
+ }
+
+
+ if (!stayingOnPage) {
+ // Right now we're on the data: page. Null contentWindow out to
+ // avoid CPOW errors when contentWindow is no longer the correct
+ // outer window proxy object.
+ contentWindow = null;
+
+ onAfterPageLoad = runCurrentTest;
+ loadExpected = TEST_PAGE;
+ testTab.linkedBrowser.loadURI(TEST_PAGE);
+ } else {
+ runCurrentTest();
+ }
+}
+
+function runCurrentTest() {
+ // Reset things so we're sure the previous tests failings don't influence this one:
+ contentWindow = testTab.linkedBrowser.contentWindow;
+ contentWindow.mySuperSpecialMark = 42;
+ contentWindow.dialogWasInvoked = false;
+ originalLocation = contentWindow.location.href;
+ // And run this test:
+ info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
+ contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
+ loadStarted = false;
+ testTab.linkedBrowser.loadURI(TARGETED_PAGE);
+}
+
+var onAfterPageLoad = runNextTest;
+
+function test() {
+ waitForExplicitFinish();
+ gBrowser.addProgressListener(tabStateListener);
+
+ testTab = gBrowser.selectedTab = gBrowser.addTab();
+ testTab.linkedBrowser.addEventListener("load", onTabLoaded, true);
+ testTab.linkedBrowser.loadURI(TEST_PAGE);
+}
+
+registerCleanupFunction(function() {
+ // Remove the handler, or closing this tab will prove tricky:
+ if (contentWindow) {
+ try {
+ contentWindow.onbeforeunload = null;
+ } catch (ex) {}
+ }
+ contentWindow = null;
+ testTab.linkedBrowser.removeEventListener("load", onTabLoaded, true);
+ Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
+ gBrowser.removeProgressListener(tabStateListener);
+ gBrowser.removeTab(testTab);
+});
+
diff --git a/docshell/test/browser/browser_search_notification.js b/docshell/test/browser/browser_search_notification.js
new file mode 100644
index 000000000..b0a4571e5
--- /dev/null
+++ b/docshell/test/browser/browser_search_notification.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ waitForExplicitFinish();
+
+ const kSearchEngineID = "test_urifixup_search_engine";
+ const kSearchEngineURL = "http://localhost/?search={searchTerms}";
+ Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+ let oldDefaultEngine = Services.search.defaultEngine;
+ Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+ let selectedName = Services.search.defaultEngine.name;
+ is(selectedName, kSearchEngineID, "Check fake search engine is selected");
+
+ registerCleanupFunction(function() {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ });
+
+ let tab = gBrowser.addTab();
+ gBrowser.selectedTab = tab;
+
+ function observer(subject, topic, data) {
+ Services.obs.removeObserver(observer, "keyword-search");
+ is(topic, "keyword-search", "Got keyword-search notification");
+
+ let engine = Services.search.defaultEngine;
+ ok(engine, "Have default search engine.");
+ is(engine, subject, "Notification subject is engine.");
+ is("firefox health report", data, "Notification data is search term.");
+
+ executeSoon(function cleanup() {
+ gBrowser.removeTab(tab);
+ finish();
+ });
+ }
+
+ Services.obs.addObserver(observer, "keyword-search", false);
+
+ gURLBar.value = "firefox health report";
+ gURLBar.handleCommand();
+}
+
diff --git a/docshell/test/browser/browser_tab_touch_events.js b/docshell/test/browser/browser_tab_touch_events.js
new file mode 100644
index 000000000..615983f61
--- /dev/null
+++ b/docshell/test/browser/browser_tab_touch_events.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(function*() {
+ const URI = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
+
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URI }, function* (browser) {
+ yield ContentTask.spawn(browser, null, test_body);
+ });
+});
+
+function* test_body() {
+ let docshell = docShell;
+
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_NONE,
+ "touchEventsOverride flag should be initially set to NONE");
+
+ docshell.touchEventsOverride = Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED;
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "touchEventsOverride flag should be changed to DISABLED");
+
+ let frameWin = content.document.querySelector("#test-iframe").contentWindow;
+ docshell = frameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "touchEventsOverride flag should be passed on to frames.");
+
+ let newFrame = content.document.createElement("iframe");
+ content.document.body.appendChild(newFrame);
+
+ let newFrameWin = newFrame.contentWindow;
+ docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "Newly created frames should use the new touchEventsOverride flag");
+
+ newFrameWin.location.reload();
+ yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
+
+ docshell = newFrameWin.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ is(docshell.touchEventsOverride, Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
+ "New touchEventsOverride flag should persist across reloads");
+}
diff --git a/docshell/test/browser/browser_timelineMarkers-01.js b/docshell/test/browser/browser_timelineMarkers-01.js
new file mode 100644
index 000000000..59eeb57db
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-01.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell has the right profile timeline API
+
+const URL = "data:text/html;charset=utf-8,Test page";
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, function() {
+ ok("recordProfileTimelineMarkers" in docShell,
+ "The recordProfileTimelineMarkers attribute exists");
+ ok("popProfileTimelineMarkers" in docShell,
+ "The popProfileTimelineMarkers function exists");
+ ok(docShell.recordProfileTimelineMarkers === false,
+ "recordProfileTimelineMarkers is false by default");
+ ok(docShell.popProfileTimelineMarkers().length === 0,
+ "There are no markers by default");
+
+ docShell.recordProfileTimelineMarkers = true;
+ ok(docShell.recordProfileTimelineMarkers === true,
+ "recordProfileTimelineMarkers can be set to true");
+
+ docShell.recordProfileTimelineMarkers = false;
+ ok(docShell.recordProfileTimelineMarkers === false,
+ "recordProfileTimelineMarkers can be set to false");
+ });
+ });
+});
diff --git a/docshell/test/browser/browser_timelineMarkers-02.js b/docshell/test/browser/browser_timelineMarkers-02.js
new file mode 100644
index 000000000..34142760e
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-02.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = '<!DOCTYPE html><style>' +
+ 'body {margin:0; padding: 0;} ' +
+ 'div {width:100px;height:100px;background:red;} ' +
+ '.resize-change-color {width:50px;height:50px;background:blue;} ' +
+ '.change-color {width:50px;height:50px;background:yellow;} ' +
+ '.add-class {}' +
+ '</style><div></div>';
+URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-02.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-03.js b/docshell/test/browser/browser_timelineMarkers-03.js
new file mode 100644
index 000000000..b104367c1
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-03.js
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = "data:text/html;charset=utf-8,<p>Test page</p>";
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-03.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-04.js b/docshell/test/browser/browser_timelineMarkers-04.js
new file mode 100644
index 000000000..fdee867e7
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-04.js
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const URL = "http://mochi.test:8888/browser/docshell/test/browser/timelineMarkers-04.html";
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-04.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-05.js b/docshell/test/browser/browser_timelineMarkers-05.js
new file mode 100644
index 000000000..0130c58d9
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-05.js
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var URL = '<!DOCTYPE html><style>' +
+ 'body {margin:0; padding: 0;} ' +
+ 'div {width:100px;height:100px;background:red;} ' +
+ '.resize-change-color {width:50px;height:50px;background:blue;} ' +
+ '.change-color {width:50px;height:50px;background:yellow;} ' +
+ '.add-class {}' +
+ '</style><div></div>';
+URL = "data:text/html;charset=utf8," + encodeURIComponent(URL);
+
+var test = makeTimelineTest("browser_timelineMarkers-frame-05.js", URL);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-02.js b/docshell/test/browser/browser_timelineMarkers-frame-02.js
new file mode 100644
index 000000000..83750395d
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-02.js
@@ -0,0 +1,133 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right markers when
+// restyles, reflows and paints occur
+
+function rectangleContains(rect, x, y, width, height) {
+ return rect.x <= x && rect.y <= y && rect.width >= width &&
+ rect.height >= height;
+}
+
+function sanitizeMarkers(list) {
+ // These markers are currently gathered from all docshells, which may
+ // interfere with this test.
+ return list.filter(e => e.name != "Worker" && e.name != "MinorGC");
+}
+
+var TESTS = [{
+ desc: "Changing the width of the test element",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "resize-change-color");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ console.log(markers);
+ info(JSON.stringify(markers.filter(m => m.name == "Paint")));
+ ok(markers.some(m => m.name == "Reflow"), "markers includes Reflow");
+ ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
+ for (let marker of markers.filter(m => m.name == "Paint")) {
+ // This change should generate at least one rectangle.
+ ok(marker.rectangles.length >= 1, "marker has one rectangle");
+ // One of the rectangles should contain the div.
+ ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100)));
+ }
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "Changing the test element's background color",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "change-color");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
+ ok(markers.some(m => m.name == "Paint"), "markers includes Paint");
+ for (let marker of markers.filter(m => m.name == "Paint")) {
+ // This change should generate at least one rectangle.
+ ok(marker.rectangles.length >= 1, "marker has one rectangle");
+ // One of the rectangles should contain the div.
+ ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50)));
+ }
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "Changing the test element's classname",
+ searchFor: "Paint",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ div.setAttribute("class", "change-color add-class");
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ ok(markers.length > 0, "markers were returned");
+ ok(!markers.some(m => m.name == "Reflow"), "markers doesn't include Reflow");
+ ok(!markers.some(m => m.name == "Paint"), "markers doesn't include Paint");
+ ok(markers.some(m => m.name == "Styles"), "markers includes Restyle");
+ }
+}, {
+ desc: "sync console.time/timeEnd",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ content.console.time("FOOBAR");
+ content.console.timeEnd("FOOBAR");
+ let markers = docShell.popProfileTimelineMarkers();
+ is(markers.length, 1, "Got one marker");
+ is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker");
+ is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail");
+ content.console.time("FOO");
+ content.setTimeout(() => {
+ content.console.time("BAR");
+ content.setTimeout(() => {
+ content.console.timeEnd("FOO");
+ content.console.timeEnd("BAR");
+ }, 100);
+ }, 100);
+ },
+ check: function(markers) {
+ markers = sanitizeMarkers(markers);
+ is(markers.length, 2, "Got 2 markers");
+ is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker");
+ is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail");
+ is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker");
+ is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail");
+ }
+}, {
+ desc: "Timestamps created by console.timeStamp()",
+ searchFor: "Timestamp",
+ setup: function(docshell) {
+ content.console.timeStamp("rock");
+ let markers = docShell.popProfileTimelineMarkers();
+ is(markers.length, 1, "Got one marker");
+ is(markers[0].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[0].causeName, "rock", "Got Timestamp label value");
+ content.console.timeStamp("paper");
+ content.console.timeStamp("scissors");
+ content.console.timeStamp();
+ content.console.timeStamp(undefined);
+ },
+ check: function (markers) {
+ markers = sanitizeMarkers(markers);
+ is(markers.length, 4, "Got 4 markers");
+ is(markers[0].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[0].causeName, "paper", "Got Timestamp label value");
+ is(markers[1].name, "TimeStamp", "Got Timestamp marker");
+ is(markers[1].causeName, "scissors", "Got Timestamp label value");
+ is(markers[2].name, "TimeStamp", "Got empty Timestamp marker when no argument given");
+ is(markers[2].causeName, void 0, "Got empty Timestamp label value");
+ is(markers[3].name, "TimeStamp", "Got empty Timestamp marker when argument is undefined");
+ is(markers[3].causeName, void 0, "Got empty Timestamp label value");
+ markers.forEach(m => is(m.end, m.start,
+ "All Timestamp markers should have identical start/end times"));
+ }
+}];
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-03.js b/docshell/test/browser/browser_timelineMarkers-frame-03.js
new file mode 100644
index 000000000..cf5f150ad
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-03.js
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right
+// markers for DOM events.
+
+var TESTS = [{
+ desc: "Event dispatch with single handler",
+ searchFor: 'DOMEvent',
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ true);
+ content.document.body.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ is(markers[0].type, "dog", "Got dog event name");
+ is(markers[0].eventPhase, 2, "Got phase 2");
+ }
+}, {
+ desc: "Event dispatch with a second handler",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ false);
+ content.document.body.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 2, "Got 2 markers");
+ }
+}, {
+ desc: "Event targeted at child",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let child = content.document.body.firstElementChild;
+ child.addEventListener("dog", function(e) { });
+ child.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 2, "Got 2 markers");
+ is(markers[0].eventPhase, 1, "Got phase 1 marker");
+ is(markers[1].eventPhase, 2, "Got phase 2 marker");
+ }
+}, {
+ desc: "Event dispatch on a new document",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let doc = content.document.implementation.createHTMLDocument("doc");
+ let p = doc.createElement("p");
+ p.innerHTML = "inside";
+ doc.body.appendChild(p);
+
+ p.addEventListener("zebra", function(e) {console.log("hi");});
+ p.dispatchEvent(new content.Event("zebra"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ }
+}, {
+ desc: "Event dispatch on window",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == 'DOMEvent').length >= 2;
+ },
+ setup: function(docShell) {
+ let doc = content.window.addEventListener("aardvark", function(e) {
+ console.log("I like ants!");
+ });
+
+ content.window.dispatchEvent(new content.Event("aardvark"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == 'DOMEvent');
+ is(markers.length, 1, "Got 1 marker");
+ }
+}];
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-04.js b/docshell/test/browser/browser_timelineMarkers-frame-04.js
new file mode 100644
index 000000000..427312993
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-04.js
@@ -0,0 +1,88 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the docShell profile timeline API returns the right
+// markers for XMLHttpRequest events.
+
+var TESTS = [{
+ desc: "Event dispatch from XMLHttpRequest",
+ searchFor: function(markers) {
+ return markers.filter(m => m.name == "DOMEvent").length >= 5;
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("dog"));
+ },
+ check: function(markers) {
+ let domMarkers = markers.filter(m => m.name == "DOMEvent");
+ // One subtlety here is that we have five events: the event we
+ // inject in "setup", plus the four state transition events. The
+ // first state transition is reported synchronously and so should
+ // show up as a nested marker.
+ is(domMarkers.length, 5, "Got 5 markers");
+
+ // We should see some Javascript markers, and they should have a
+ // cause.
+ let jsMarkers = markers.filter(m => m.name == "Javascript" && m.causeName);
+ ok(jsMarkers.length > 0, "Got some Javascript markers");
+ is(jsMarkers[0].stack.functionDisplayName, "do_xhr",
+ "Javascript marker has entry point name");
+ }
+}];
+
+if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
+ TESTS.push({
+ desc: "Async stack trace on Javascript marker",
+ searchFor: (markers) => {
+ return markers.some(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("promisetest"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ ok(markers.length > 0, "Found a Javascript marker");
+
+ let frame = markers[0].stack;
+ ok(frame.asyncParent !== null, "Parent frame has async parent");
+ is(frame.asyncParent.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ let asyncFrame = frame.asyncParent;
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted')
+ asyncFrame = asyncFrame.parent;
+ is(asyncFrame.functionDisplayName, "do_promise",
+ "Async parent has correct function name");
+ }
+ }, {
+ desc: "Async stack trace on Javascript marker with script",
+ searchFor: (markers) => {
+ return markers.some(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ },
+ setup: function(docShell) {
+ content.dispatchEvent(new content.Event("promisescript"));
+ },
+ check: function(markers) {
+ markers = markers.filter(m => (m.name == "Javascript" &&
+ m.causeName == "promise callback"));
+ ok(markers.length > 0, "Found a Javascript marker");
+
+ let frame = markers[0].stack;
+ ok(frame.asyncParent !== null, "Parent frame has async parent");
+ is(frame.asyncParent.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ let asyncFrame = frame.asyncParent;
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted')
+ asyncFrame = asyncFrame.parent;
+ is(asyncFrame.functionDisplayName, "do_promise_script",
+ "Async parent has correct function name");
+ }
+ });
+}
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_timelineMarkers-frame-05.js b/docshell/test/browser/browser_timelineMarkers-frame-05.js
new file mode 100644
index 000000000..713f0e560
--- /dev/null
+++ b/docshell/test/browser/browser_timelineMarkers-frame-05.js
@@ -0,0 +1,117 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function forceSyncReflow(div) {
+ div.setAttribute('class', 'resize-change-color');
+ // Force a reflow.
+ return div.offsetWidth;
+}
+
+function testSendingEvent() {
+ content.document.body.dispatchEvent(new content.Event("dog"));
+}
+
+function testConsoleTime() {
+ content.console.time("cats");
+}
+
+function testConsoleTimeEnd() {
+ content.console.timeEnd("cats");
+}
+
+function makePromise() {
+ let resolver;
+ new Promise(function(resolve, reject) {
+ testConsoleTime();
+ resolver = resolve;
+ }).then(function(val) {
+ testConsoleTimeEnd();
+ });
+ return resolver;
+}
+
+function resolvePromise(resolver) {
+ resolver(23);
+}
+
+var TESTS = [{
+ desc: "Stack trace on sync reflow",
+ searchFor: "Reflow",
+ setup: function(docShell) {
+ let div = content.document.querySelector("div");
+ forceSyncReflow(div);
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "Reflow");
+ ok(markers.length > 0, "Reflow marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "forceSyncReflow");
+ }
+}, {
+ desc: "Stack trace on DOM event",
+ searchFor: "DOMEvent",
+ setup: function(docShell) {
+ content.document.body.addEventListener("dog",
+ function(e) { console.log("hi"); },
+ true);
+ testSendingEvent();
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "DOMEvent");
+ ok(markers.length > 0, "DOMEvent marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testSendingEvent",
+ "testSendingEvent is on the stack");
+ }
+}, {
+ desc: "Stack trace on console event",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ testConsoleTime();
+ testConsoleTimeEnd();
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "ConsoleTime");
+ ok(markers.length > 0, "ConsoleTime marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testConsoleTime",
+ "testConsoleTime is on the stack");
+ ok(markers[0].endStack.functionDisplayName == "testConsoleTimeEnd",
+ "testConsoleTimeEnd is on the stack");
+ }
+}];
+
+if (Services.prefs.getBoolPref("javascript.options.asyncstack")) {
+ TESTS.push({
+ desc: "Async stack trace on Promise",
+ searchFor: "ConsoleTime",
+ setup: function(docShell) {
+ let resolver = makePromise();
+ resolvePromise(resolver);
+ },
+ check: function(markers) {
+ markers = markers.filter(m => m.name == "ConsoleTime");
+ ok(markers.length > 0, "Promise marker includes stack");
+ ok(markers[0].stack.functionDisplayName == "testConsoleTime",
+ "testConsoleTime is on the stack");
+ let frame = markers[0].endStack;
+ ok(frame.functionDisplayName == "testConsoleTimeEnd",
+ "testConsoleTimeEnd is on the stack");
+
+ frame = frame.parent;
+ ok(frame.functionDisplayName == "makePromise/<",
+ "makePromise/< is on the stack");
+ let asyncFrame = frame.asyncParent;
+ ok(asyncFrame !== null, "Frame has async parent");
+ is(asyncFrame.asyncCause, "promise callback",
+ "Async parent has correct cause");
+ // Skip over self-hosted parts of our Promise implementation.
+ while (asyncFrame.source === 'self-hosted') {
+ asyncFrame = asyncFrame.parent;
+ }
+ is(asyncFrame.functionDisplayName, "makePromise",
+ "Async parent has correct function name");
+ }
+ });
+}
+
+timelineContentTest(TESTS);
diff --git a/docshell/test/browser/browser_ua_emulation.js b/docshell/test/browser/browser_ua_emulation.js
new file mode 100644
index 000000000..94a602d4b
--- /dev/null
+++ b/docshell/test/browser/browser_ua_emulation.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const URL = "data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>";
+
+// Test that the docShell UA emulation works
+function* contentTask() {
+ let docshell = docShell;
+ is(docshell.customUserAgent, "", "There should initially be no customUserAgent");
+
+ docshell.customUserAgent = "foo";
+ is(content.navigator.userAgent, "foo", "The user agent should be changed to foo");
+
+ let frameWin = content.document.querySelector("#test-iframe").contentWindow;
+ is(frameWin.navigator.userAgent, "foo", "The UA should be passed on to frames.");
+
+ let newFrame = content.document.createElement("iframe");
+ content.document.body.appendChild(newFrame);
+
+ let newFrameWin = newFrame.contentWindow;
+ is(newFrameWin.navigator.userAgent, "foo", "Newly created frames should use the new UA");
+
+ newFrameWin.location.reload();
+ yield ContentTaskUtils.waitForEvent(newFrameWin, "load");
+
+ is(newFrameWin.navigator.userAgent, "foo", "New UA should persist across reloads");
+}
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab({ gBrowser, url: URL },
+ function* (browser) {
+ yield ContentTask.spawn(browser, null, contentTask);
+ });
+});
diff --git a/docshell/test/browser/browser_uriFixupAlternateRedirects.js b/docshell/test/browser/browser_uriFixupAlternateRedirects.js
new file mode 100644
index 000000000..f5a00a2df
--- /dev/null
+++ b/docshell/test/browser/browser_uriFixupAlternateRedirects.js
@@ -0,0 +1,24 @@
+"use strict";
+
+const REDIRECTURL = "http://www.example.com/browser/docshell/test/browser/redirect_to_example.sjs"
+
+add_task(function* () {
+ let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+ gURLBar.value = REDIRECTURL;
+ gURLBar.select();
+ let errorPageLoaded = BrowserTestUtils.waitForErrorPage(tab.linkedBrowser);
+ EventUtils.sendKey("return");
+ yield errorPageLoaded;
+ let [contentURL, originalURL] = yield ContentTask.spawn(tab.linkedBrowser, null, () => {
+ return [
+ content.document.documentURI,
+ content.document.mozDocumentURIIfNotForErrorPages.spec,
+ ];
+ });
+ info("Page that loaded: " + contentURL);
+ ok(contentURL.startsWith("about:neterror?"), "Should be on an error page");
+ originalURL = new URL(originalURL);
+ is(originalURL.host, "example", "Should be an error for http://example, not http://www.example.com/");
+
+ yield BrowserTestUtils.removeTab(tab);
+});
diff --git a/docshell/test/browser/browser_uriFixupIntegration.js b/docshell/test/browser/browser_uriFixupIntegration.js
new file mode 100644
index 000000000..e041e1f67
--- /dev/null
+++ b/docshell/test/browser/browser_uriFixupIntegration.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const kSearchEngineID = "browser_urifixup_search_engine";
+const kSearchEngineURL = "http://example.com/?search={searchTerms}";
+
+add_task(function* setup() {
+ // Add a new fake search engine.
+ Services.search.addEngineWithDetails(kSearchEngineID, "", "", "", "get",
+ kSearchEngineURL);
+
+ let oldDefaultEngine = Services.search.defaultEngine;
+ Services.search.defaultEngine = Services.search.getEngineByName(kSearchEngineID);
+
+ // Remove the fake engine when done.
+ registerCleanupFunction(() => {
+ if (oldDefaultEngine) {
+ Services.search.defaultEngine = oldDefaultEngine;
+ }
+
+ let engine = Services.search.getEngineByName(kSearchEngineID);
+ if (engine) {
+ Services.search.removeEngine(engine);
+ }
+ });
+});
+
+add_task(function* test() {
+ for (let searchParams of ["foo bar", "brokenprotocol:somethingelse"]) {
+ // Add a new blank tab.
+ gBrowser.selectedTab = gBrowser.addTab("about:blank");
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ // Enter search terms and start a search.
+ gURLBar.value = searchParams;
+ gURLBar.focus();
+ EventUtils.synthesizeKey("VK_RETURN", {});
+ yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ // Check that we arrived at the correct URL.
+ let escapedParams = encodeURIComponent(searchParams).replace("%20", "+");
+ let expectedURL = kSearchEngineURL.replace("{searchTerms}", escapedParams);
+ is(gBrowser.selectedBrowser.currentURI.spec, expectedURL,
+ "New tab should have loaded with expected url.");
+
+ // Cleanup.
+ gBrowser.removeCurrentTab();
+ }
+});
diff --git a/docshell/test/browser/favicon_bug655270.ico b/docshell/test/browser/favicon_bug655270.ico
new file mode 100644
index 000000000..d44438903
--- /dev/null
+++ b/docshell/test/browser/favicon_bug655270.ico
Binary files differ
diff --git a/docshell/test/browser/file_bug1046022.html b/docshell/test/browser/file_bug1046022.html
new file mode 100644
index 000000000..2de68cb43
--- /dev/null
+++ b/docshell/test/browser/file_bug1046022.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Bug 1046022 - test navigating inside onbeforeunload</title>
+ </head>
+ <body>
+ Waiting for onbeforeunload to hit...
+ </body>
+
+ <script>
+var testFns = [
+ function(e) {
+ e.target.location.href = 'otherpage-href-set.html';
+ return "stop";
+ },
+ function(e) {
+ e.target.location.reload();
+ return "stop";
+ },
+ function(e) {
+ e.target.location.replace('otherpage-location-replaced.html');
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = "otherpage.html";
+ e.target.body.appendChild(link);
+ link.click();
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = "otherpage.html";
+ link.setAttribute("target", "_blank");
+ e.target.body.appendChild(link);
+ link.click();
+ return "stop";
+ },
+ function(e) {
+ var link = e.target.createElement('a');
+ link.href = e.target.location.href;
+ e.target.body.appendChild(link);
+ link.setAttribute("target", "somearbitrarywindow");
+ link.click();
+ return "stop";
+ },
+];
+ </script>
+</html>
diff --git a/docshell/test/browser/file_bug1206879.html b/docshell/test/browser/file_bug1206879.html
new file mode 100644
index 000000000..5313902a9
--- /dev/null
+++ b/docshell/test/browser/file_bug1206879.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test page for bug 1206879</title>
+ </head>
+ <body>
+ <iframe src="http://example.com/"></iframe>
+ </body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-1-child.html b/docshell/test/browser/file_bug234628-1-child.html
new file mode 100644
index 000000000..c36197ac4
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-1-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-1.html b/docshell/test/browser/file_bug234628-1.html
new file mode 100644
index 000000000..11c523ccd
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<h1>No encoding declaration in parent or child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-1-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-10-child.xhtml b/docshell/test/browser/file_bug234628-10-child.xhtml
new file mode 100644
index 000000000..cccf6f2bc
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-10-child.xhtml
@@ -0,0 +1,4 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>XML child with no encoding declaration</title></head>
+<body><p>Euro sign if decoded as UTF-8: €</p></body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-10.html b/docshell/test/browser/file_bug234628-10.html
new file mode 100644
index 000000000..78b8f0035
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-10.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in HTML parent or XHTML child</title>
+</head>
+<body>
+<h1>No encoding declaration in HTML parent or XHTML child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-10-child.xhtml"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-11-child.xhtml b/docshell/test/browser/file_bug234628-11-child.xhtml
new file mode 100644
index 000000000..11ef668b0
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11-child.xhtml
@@ -0,0 +1,4 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title></head>
+<body><p>Euro sign if decoded as UTF-8: €</p></body>
+</html>
diff --git a/docshell/test/browser/file_bug234628-11-child.xhtml^headers^ b/docshell/test/browser/file_bug234628-11-child.xhtml^headers^
new file mode 100644
index 000000000..30fb30405
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11-child.xhtml^headers^
@@ -0,0 +1 @@
+Content-Type: application/xhtml+xml; charset=utf-8
diff --git a/docshell/test/browser/file_bug234628-11.html b/docshell/test/browser/file_bug234628-11.html
new file mode 100644
index 000000000..21c5b733e
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-11.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in HTML parent and HTTP declaration in XHTML child</title>
+</head>
+<body>
+<h1>No encoding declaration in HTML parent and HTTP declaration in XHTML child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-11-child.xhtml"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-2-child.html b/docshell/test/browser/file_bug234628-2-child.html
new file mode 100644
index 000000000..0acd2e0b2
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-2-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-2.html b/docshell/test/browser/file_bug234628-2.html
new file mode 100644
index 000000000..a87d29e12
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-2.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>No encoding declaration in parent or child</title>
+</head>
+<body>
+<h1>No encoding declaration in parent or child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-2-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-3-child.html b/docshell/test/browser/file_bug234628-3-child.html
new file mode 100644
index 000000000..a6ad83231
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-3-child.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-3.html b/docshell/test/browser/file_bug234628-3.html
new file mode 100644
index 000000000..8caab6040
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-3.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and child</title>
+</head>
+<body>
+<h1>meta declaration in parent and child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-3-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-4-child.html b/docshell/test/browser/file_bug234628-4-child.html
new file mode 100644
index 000000000..f0e7c2c05
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-4-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOM in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-4.html b/docshell/test/browser/file_bug234628-4.html
new file mode 100644
index 000000000..013757901
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-4.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOM in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOM in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-4-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-5-child.html b/docshell/test/browser/file_bug234628-5-child.html
new file mode 100644
index 000000000..a650552f6
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-5-child.html
Binary files differ
diff --git a/docshell/test/browser/file_bug234628-5.html b/docshell/test/browser/file_bug234628-5.html
new file mode 100644
index 000000000..987e6420b
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-5.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and UTF-16 BOM in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and UTF-16 BOM in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-5-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-6-child.html b/docshell/test/browser/file_bug234628-6-child.html
new file mode 100644
index 000000000..52c37f259
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6-child.html
Binary files differ
diff --git a/docshell/test/browser/file_bug234628-6-child.html^headers^ b/docshell/test/browser/file_bug234628-6-child.html^headers^
new file mode 100644
index 000000000..bfdcf487f
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6-child.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=utf-16be
diff --git a/docshell/test/browser/file_bug234628-6.html b/docshell/test/browser/file_bug234628-6.html
new file mode 100644
index 000000000..9d7fc580c
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-6.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOMless UTF-16 with HTTP charset in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-6-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-7-child.html b/docshell/test/browser/file_bug234628-7-child.html
new file mode 100644
index 000000000..c761ace10
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as UTF-8: €</p>
+<p>a with diaeresis if decoded as UTF-8: ä</p>
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-7-child.html^headers^ b/docshell/test/browser/file_bug234628-7-child.html^headers^
new file mode 100644
index 000000000..2d1c08b9e
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7-child.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=utf-8
diff --git a/docshell/test/browser/file_bug234628-7.html b/docshell/test/browser/file_bug234628-7.html
new file mode 100644
index 000000000..7cb506096
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-7.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1252">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and BOMless UTF-8 with HTTP charset in child</h1>
+
+<p>Euro sign if decoded as Windows-1252: </p>
+<p>a with diaeresis if decoded as Windows-1252: </p>
+
+<iframe src="file_bug234628-7-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-8-child.html b/docshell/test/browser/file_bug234628-8-child.html
new file mode 100644
index 000000000..254e0fb2b
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-8-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and no declaration in child</title>
+</head>
+<body>
+<p>Capital dje if decoded as Windows-1251: </p>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-8.html b/docshell/test/browser/file_bug234628-8.html
new file mode 100644
index 000000000..b44e91801
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-8.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="windows-1251">
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>meta declaration in parent and no declaration in child</title>
+</head>
+<body>
+<h1>meta declaration in parent and no declaration in child</h1>
+
+<p>Capital dje if decoded as Windows-1251: </p>
+
+<iframe src="file_bug234628-8-child.html"></iframe>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-9-child.html b/docshell/test/browser/file_bug234628-9-child.html
new file mode 100644
index 000000000..a86b14d7e
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-9-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>UTF-16 with BOM in parent and no declaration in child</title>
+</head>
+<body>
+<p>Euro sign if decoded as Windows-1251: </p>
+
+</body>
+</html>
+
diff --git a/docshell/test/browser/file_bug234628-9.html b/docshell/test/browser/file_bug234628-9.html
new file mode 100644
index 000000000..8a469da3a
--- /dev/null
+++ b/docshell/test/browser/file_bug234628-9.html
Binary files differ
diff --git a/docshell/test/browser/file_bug420605.html b/docshell/test/browser/file_bug420605.html
new file mode 100644
index 000000000..8424b92f8
--- /dev/null
+++ b/docshell/test/browser/file_bug420605.html
@@ -0,0 +1,31 @@
+<head>
+<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="/>
+ <title>Page Title for Bug 420605</title>
+</head>
+<body>
+ <h1>Fragment links</h1>
+
+ <p>This page has a bunch of fragment links to sections below:</p>
+
+ <ul>
+ <li><a id="firefox-link" href="#firefox">Firefox</a></li>
+ <li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
+ <li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
+ </ul>
+
+ <p>And here are the sections:</p>
+
+ <h2 id="firefox">Firefox</h2>
+
+ <p>Firefox is a browser.</p>
+
+ <h2 id="thunderbird">Thunderbird</h2>
+
+ <p>Thunderbird is an email client</p>
+
+ <h2 id="seamonkey">Seamonkey</h2>
+
+ <p>Seamonkey is the all-in-one application.</p>
+
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug422543_script.js b/docshell/test/browser/file_bug422543_script.js
new file mode 100644
index 000000000..cd69df1ec
--- /dev/null
+++ b/docshell/test/browser/file_bug422543_script.js
@@ -0,0 +1,98 @@
+const { utils: Cu, interfaces: Ci } = Components;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function SHistoryListener() {
+}
+
+SHistoryListener.prototype = {
+ retval: true,
+ last: "initial",
+
+ OnHistoryNewEntry: function (aNewURI) {
+ this.last = "newentry";
+ },
+
+ OnHistoryGoBack: function (aBackURI) {
+ this.last = "goback";
+ return this.retval;
+ },
+
+ OnHistoryGoForward: function (aForwardURI) {
+ this.last = "goforward";
+ return this.retval;
+ },
+
+ OnHistoryGotoIndex: function (aIndex, aGotoURI) {
+ this.last = "gotoindex";
+ return this.retval;
+ },
+
+ OnHistoryPurge: function (aNumEntries) {
+ this.last = "purge";
+ return this.retval;
+ },
+
+ OnHistoryReload: function (aReloadURI, aReloadFlags) {
+ this.last = "reload";
+ return this.retval;
+ },
+
+ OnHistoryReplaceEntry: function (aIndex) {},
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
+ Ci.nsISupportsWeakReference])
+};
+
+let testAPI = {
+ shistory: null,
+ listeners: [ new SHistoryListener(),
+ new SHistoryListener() ],
+
+ init() {
+ this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+ for (let listener of this.listeners) {
+ this.shistory.addSHistoryListener(listener);
+ }
+ },
+
+ cleanup() {
+ for (let listener of this.listeners) {
+ this.shistory.removeSHistoryListener(listener);
+ }
+ this.shistory = null;
+ sendAsyncMessage("bug422543:cleanup:return", {});
+ },
+
+ getListenerStatus() {
+ sendAsyncMessage("bug422543:getListenerStatus:return",
+ this.listeners.map(l => l.last));
+ },
+
+ resetListeners() {
+ for (let listener of this.listeners) {
+ listener.last = "initial";
+ }
+
+ sendAsyncMessage("bug422543:resetListeners:return", {});
+ },
+
+ notifyReload() {
+ let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
+ let rval =
+ internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
+ sendAsyncMessage("bug422543:notifyReload:return", { rval });
+ },
+
+ setRetval({ num, val }) {
+ this.listeners[num].retval = val;
+ sendAsyncMessage("bug422543:setRetval:return", {});
+ },
+};
+
+addMessageListener("bug422543:cleanup", () => { testAPI.cleanup(); });
+addMessageListener("bug422543:getListenerStatus", () => { testAPI.getListenerStatus(); });
+addMessageListener("bug422543:notifyReload", () => { testAPI.notifyReload(); });
+addMessageListener("bug422543:resetListeners", () => { testAPI.resetListeners(); });
+addMessageListener("bug422543:setRetval", (msg) => { testAPI.setRetval(msg.data); });
+
+testAPI.init();
diff --git a/docshell/test/browser/file_bug503832.html b/docshell/test/browser/file_bug503832.html
new file mode 100644
index 000000000..338631c8a
--- /dev/null
+++ b/docshell/test/browser/file_bug503832.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test page for https://bugzilla.mozilla.org/show_bug.cgi?id=503832
+-->
+<head>
+ <title>Page Title for Bug 503832</title>
+</head>
+<body>
+ <h1>Fragment links</h1>
+
+ <p>This page has a bunch of fragment links to sections below:</p>
+
+ <ul>
+ <li><a id="firefox-link" href="#firefox">Firefox</a></li>
+ <li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
+ <li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
+ </ul>
+
+ <p>And here are the sections:</p>
+
+ <h2 id="firefox">Firefox</h2>
+
+ <p>Firefox is a browser.</p>
+
+ <h2 id="thunderbird">Thunderbird</h2>
+
+ <p>Thunderbird is an email client</p>
+
+ <h2 id="seamonkey">Seamonkey</h2>
+
+ <p>Seamonkey is the all-in-one application.</p>
+
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug655270.html b/docshell/test/browser/file_bug655270.html
new file mode 100644
index 000000000..0c08d982b
--- /dev/null
+++ b/docshell/test/browser/file_bug655270.html
@@ -0,0 +1,11 @@
+<html>
+
+<head>
+ <link rel='icon' href='favicon_bug655270.ico'>
+</head>
+
+<body>
+Nothing to see here...
+</body>
+
+</html>
diff --git a/docshell/test/browser/file_bug670318.html b/docshell/test/browser/file_bug670318.html
new file mode 100644
index 000000000..4cd9b454a
--- /dev/null
+++ b/docshell/test/browser/file_bug670318.html
@@ -0,0 +1,23 @@
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<script>
+function load() {
+ function next() {
+ if (count < 5)
+ iframe.src = 'data:text/html;charset=utf-8,iframe ' + (++count);
+ }
+
+ var count = 0;
+ var iframe = document.createElement('iframe');
+ iframe.onload = function () { setTimeout(next, 0) };
+ document.body.appendChild(iframe);
+
+ setTimeout(next, 0);
+}
+</script>
+</head>
+
+<body onload="load()">
+Testcase
+</body>
+</html>
diff --git a/docshell/test/browser/file_bug852909.pdf b/docshell/test/browser/file_bug852909.pdf
new file mode 100644
index 000000000..89066463f
--- /dev/null
+++ b/docshell/test/browser/file_bug852909.pdf
Binary files differ
diff --git a/docshell/test/browser/file_bug852909.png b/docshell/test/browser/file_bug852909.png
new file mode 100644
index 000000000..c7510d388
--- /dev/null
+++ b/docshell/test/browser/file_bug852909.png
Binary files differ
diff --git a/docshell/test/browser/file_multiple_pushState.html b/docshell/test/browser/file_multiple_pushState.html
new file mode 100644
index 000000000..c58a1a71b
--- /dev/null
+++ b/docshell/test/browser/file_multiple_pushState.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test multiple calls to history.pushState</title>
+ </head>
+ <body>
+ <h1>Ohai</h1>
+ </body>
+ <script type="text/javascript">
+ window.history.pushState({}, "", "/bar/ABC?key=baz");
+ window.history.pushState({}, "", "/bar/ABC/DEF?key=baz");
+ </script>
+</html>
diff --git a/docshell/test/browser/frame-head.js b/docshell/test/browser/frame-head.js
new file mode 100644
index 000000000..5cb3b1513
--- /dev/null
+++ b/docshell/test/browser/frame-head.js
@@ -0,0 +1,113 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Functions that are automatically loaded as frame scripts for
+// timeline tests.
+
+var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
+var { Promise } = Cu.import('resource://gre/modules/Promise.jsm', {});
+
+Cu.import("resource://gre/modules/Timer.jsm");
+
+// Functions that look like mochitest functions but forward to the
+// browser process.
+
+this.ok = function(value, message) {
+ sendAsyncMessage("browser:test:ok", {
+ value: !!value,
+ message: message});
+}
+
+this.is = function(v1, v2, message) {
+ ok(v1 == v2, message);
+}
+
+this.info = function(message) {
+ sendAsyncMessage("browser:test:info", {message: message});
+}
+
+this.finish = function() {
+ sendAsyncMessage("browser:test:finish");
+}
+
+/* Start a task that runs some timeline tests in the ordinary way.
+ *
+ * @param array tests
+ * The tests to run. This is an array where each element
+ * is of the form { desc, searchFor, setup, check }.
+ *
+ * desc is the test description, a string.
+ * searchFor is a string or a function
+ * If a string, then when a marker with this name is
+ * found, marker-reading is stopped.
+ * If a function, then the accumulated marker array is
+ * passed to it, and marker reading stops when it returns
+ * true.
+ * setup is a function that takes the docshell as an argument.
+ * It should start the test.
+ * check is a function that takes an array of markers
+ * as an argument and checks the results of the test.
+ */
+this.timelineContentTest = function(tests) {
+ Task.spawn(function*() {
+ let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+
+ info("Start recording");
+ docShell.recordProfileTimelineMarkers = true;
+
+ for (let {desc, searchFor, setup, check} of tests) {
+
+ info("Running test: " + desc);
+
+ info("Flushing the previous markers if any");
+ docShell.popProfileTimelineMarkers();
+
+ info("Running the test setup function");
+ let onMarkers = timelineWaitForMarkers(docShell, searchFor);
+ setup(docShell);
+ info("Waiting for new markers on the docShell");
+ let markers = yield onMarkers;
+
+ // Cycle collection markers are non-deterministic, and none of these tests
+ // expect them to show up.
+ markers = markers.filter(m => m.name.indexOf("nsCycleCollector") === -1);
+
+ info("Running the test check function");
+ check(markers);
+ }
+
+ info("Stop recording");
+ docShell.recordProfileTimelineMarkers = false;
+ finish();
+ });
+}
+
+function timelineWaitForMarkers(docshell, searchFor) {
+ if (typeof(searchFor) == "string") {
+ let searchForString = searchFor;
+ let f = function (markers) {
+ return markers.some(m => m.name == searchForString);
+ };
+ searchFor = f;
+ }
+
+ return new Promise(function(resolve, reject) {
+ let waitIterationCount = 0;
+ let maxWaitIterationCount = 10; // Wait for 2sec maximum
+ let markers = [];
+
+ setTimeout(function timeoutHandler() {
+ let newMarkers = docshell.popProfileTimelineMarkers();
+ markers = [...markers, ...newMarkers];
+ if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
+ resolve(markers);
+ } else {
+ setTimeout(timeoutHandler, 200);
+ waitIterationCount++;
+ }
+ }, 200);
+ });
+}
diff --git a/docshell/test/browser/head.js b/docshell/test/browser/head.js
new file mode 100644
index 000000000..24ca8f45b
--- /dev/null
+++ b/docshell/test/browser/head.js
@@ -0,0 +1,99 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* Helper function for timeline tests. Returns an async task that is
+ * suitable for use as a particular timeline test.
+ * @param string frameScriptName
+ * Base name of the frame script file.
+ * @param string url
+ * URL to load.
+ */
+function makeTimelineTest(frameScriptName, url) {
+ info("in timelineTest");
+ return Task.async(function*() {
+ info("in in timelineTest");
+ waitForExplicitFinish();
+
+ yield timelineTestOpenUrl(url);
+
+ const here = "chrome://mochitests/content/browser/docshell/test/browser/";
+
+ let mm = gBrowser.selectedBrowser.messageManager;
+ mm.loadFrameScript(here + "frame-head.js", false);
+ mm.loadFrameScript(here + frameScriptName, false);
+
+ // Set up some listeners so that timeline tests running in the
+ // content process can forward their results to the main process.
+ mm.addMessageListener("browser:test:ok", function(message) {
+ ok(message.data.value, message.data.message);
+ });
+ mm.addMessageListener("browser:test:info", function(message) {
+ info(message.data.message);
+ });
+ mm.addMessageListener("browser:test:finish", function(ignore) {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ });
+}
+
+/* Open a URL for a timeline test. */
+function timelineTestOpenUrl(url) {
+ window.focus();
+
+ let tabSwitchPromise = new Promise((resolve, reject) => {
+ window.gBrowser.addEventListener("TabSwitchDone", function listener() {
+ window.gBrowser.removeEventListener("TabSwitchDone", listener);
+ resolve();
+ });
+ });
+
+ let loadPromise = new Promise(function(resolve, reject) {
+ let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
+ let linkedBrowser = tab.linkedBrowser;
+
+ linkedBrowser.addEventListener("load", function onload() {
+ linkedBrowser.removeEventListener("load", onload, true);
+ resolve(tab);
+ }, true);
+ });
+
+ return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
+}
+
+/**
+ * Helper function for charset tests. It loads |url| in a new tab,
+ * runs |check1| in a ContentTask when the page is ready, switches the
+ * charset to |charset|, and then runs |check2| in a ContentTask when
+ * the page has finished reloading.
+ *
+ * |charset| and |check2| can be omitted, in which case the test
+ * finishes when |check1| completes.
+ */
+function runCharsetTest(url, check1, charset, check2) {
+ waitForExplicitFinish();
+
+ BrowserTestUtils.openNewForegroundTab(gBrowser, url, true).then(afterOpen);
+
+ function afterOpen() {
+ if (charset) {
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterChangeCharset);
+
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
+ BrowserSetForcedCharacterSet(charset);
+ });
+ } else {
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check1).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ }
+ }
+
+ function afterChangeCharset() {
+ ContentTask.spawn(gBrowser.selectedBrowser, null, check2).then(() => {
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ }
+}
diff --git a/docshell/test/browser/print_postdata.sjs b/docshell/test/browser/print_postdata.sjs
new file mode 100644
index 000000000..4175a2480
--- /dev/null
+++ b/docshell/test/browser/print_postdata.sjs
@@ -0,0 +1,22 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/plain", false);
+ if (request.method == "GET") {
+ response.write(request.queryString);
+ } else {
+ var body = new BinaryInputStream(request.bodyInputStream);
+
+ var avail;
+ var bytes = [];
+
+ while ((avail = body.available()) > 0)
+ Array.prototype.push.apply(bytes, body.readByteArray(avail));
+
+ var data = String.fromCharCode.apply(null, bytes);
+ response.bodyOutputStream.write(data, data.length);
+ }
+}
diff --git a/docshell/test/browser/redirect_to_example.sjs b/docshell/test/browser/redirect_to_example.sjs
new file mode 100644
index 000000000..eef5e49f4
--- /dev/null
+++ b/docshell/test/browser/redirect_to_example.sjs
@@ -0,0 +1,4 @@
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 302, "Moved Permanently");
+ response.setHeader("Location", "http://example");
+}
diff --git a/docshell/test/browser/test-form_sjis.html b/docshell/test/browser/test-form_sjis.html
new file mode 100644
index 000000000..91c375dee
--- /dev/null
+++ b/docshell/test/browser/test-form_sjis.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/REC-html401-19991224/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1251">
+ <title>Shift_JIS in body and text area</title>
+ </head>
+ <body>
+ <h1>Incorrect meta charset</h1>
+ <h2>This page is encoded in Shift_JIS, but has an incorrect meta charset
+ claiming that it is windows-1251</h2>
+ <p id="testpar">jR[h́AׂĂ̕ɌŗL̔ԍt^܂</p>
+ <form>
+ <p>
+ <textarea id="testtextarea" rows=6 cols=60>jR[h́AׂĂ̕ɌŗL̔ԍt^܂</textarea>
+ <input id="testinput" type="text" size=60 value="jR[h́AׂĂ̕ɌŗL̔ԍt^܂">
+ </p>
+ </form>
+ <h2>Expected text on load:</h2>
+ <p>&#x453;&#x2020;&#x453;&#x6A;&#x453;&#x52;&#x403;&#x5B;&#x453;&#x68;&#x201A;&#x41D;&#x403;&#x41;&#x201A;&#xB7;&#x201A;&#x427;&#x201A;&#x414;&#x201A;&#x41C;&#x2022;&#xB6;&#x40B;&#x459;&#x201A;&#x419;&#x40A;&#x415;&#x2014;&#x4C;&#x201A;&#x41C;&#x201D;&#x424;&#x40C;&#x2020;&#x201A;&#x440;&#x2022;&#x74;&#x2014;&#x5E;&#x201A;&#xB5;&#x201A;&#x42C;&#x201A;&#xB7;</p>
+ <h2>Expected text on resetting the encoding to Shift_JIS:</h2>
+ <p>&#x30E6;&#x30CB;&#x30B3;&#x30FC;&#x30C9;&#x306F;&#x3001;&#x3059;&#x3079;&#x3066;&#x306E;&#x6587;&#x5B57;&#x306B;&#x56FA;&#x6709;&#x306E;&#x756A;&#x53F7;&#x3092;&#x4ED8;&#x4E0E;&#x3057;&#x307E;&#x3059;</p>
+ </body>
+</html>
diff --git a/docshell/test/browser/timelineMarkers-04.html b/docshell/test/browser/timelineMarkers-04.html
new file mode 100644
index 000000000..829998387
--- /dev/null
+++ b/docshell/test/browser/timelineMarkers-04.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8"></meta>
+ <title>markers test</title>
+</head>
+<body>
+
+ <p>Test page</p>
+
+ <script>
+ function do_xhr() {
+ const theURL = "timelineMarkers-04.html";
+
+ xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ dump("ReadyState = " + xhr.readyState + "\n");
+ };
+ xhr.open("get", theURL, true);
+ xhr.send();
+ }
+
+ window.addEventListener("dog", do_xhr, true);
+
+ function do_promise() {
+ new Promise(function(resolve, reject) {
+ console.time("Bob");
+ window.setTimeout(function() {
+ resolve(23);
+ }, 10);
+ }).then(function (val) {
+ console.timeEnd("Bob");
+ });
+ }
+
+ window.addEventListener("promisetest", do_promise, true);
+
+ var globalResolver;
+ function do_promise_script() {
+ new Promise(function(resolve, reject) {
+ console.time("Bob");
+ globalResolver = resolve;
+ window.setTimeout("globalResolver(23);", 10);
+ }).then(function (val) {
+ console.timeEnd("Bob");
+ });
+ }
+
+ window.addEventListener("promisescript", do_promise_script, true);
+
+ </script>
+
+</body>
+</html>
+