summaryrefslogtreecommitdiffstats
path: root/docshell/test/browser/browser_onbeforeunload_navigation.js
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/test/browser/browser_onbeforeunload_navigation.js')
-rw-r--r--docshell/test/browser/browser_onbeforeunload_navigation.js165
1 files changed, 165 insertions, 0 deletions
diff --git a/docshell/test/browser/browser_onbeforeunload_navigation.js b/docshell/test/browser/browser_onbeforeunload_navigation.js
new file mode 100644
index 0000000000..23dc3b528e
--- /dev/null
+++ b/docshell/test/browser/browser_onbeforeunload_navigation.js
@@ -0,0 +1,165 @@
+"use strict";
+
+const TEST_PAGE =
+ "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
+const TARGETED_PAGE =
+ "data:text/html," +
+ encodeURIComponent("<body>Shouldn't be seeing this</body>");
+
+const { PromptTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/PromptTestUtils.sys.mjs"
+);
+
+var loadStarted = false;
+var tabStateListener = {
+ resolveLoad: null,
+ expectLoad: null,
+
+ onStateChange(webprogress, request, flags, status) {
+ const WPL = Ci.nsIWebProgressListener;
+ if (flags & WPL.STATE_IS_WINDOW) {
+ if (flags & WPL.STATE_START) {
+ loadStarted = true;
+ } else if (flags & WPL.STATE_STOP) {
+ let url = request.QueryInterface(Ci.nsIChannel).URI.spec;
+ is(url, this.expectLoad, "Should only see expected document loads");
+ if (url == this.expectLoad) {
+ this.resolveLoad();
+ }
+ }
+ }
+ },
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIWebProgressListener",
+ "nsISupportsWeakReference",
+ ]),
+};
+
+function promiseLoaded(url, callback) {
+ if (tabStateListener.expectLoad) {
+ throw new Error("Can't wait for multiple loads at once");
+ }
+ tabStateListener.expectLoad = url;
+ return new Promise(resolve => {
+ tabStateListener.resolveLoad = resolve;
+ if (callback) {
+ callback();
+ }
+ }).then(() => {
+ tabStateListener.expectLoad = null;
+ tabStateListener.resolveLoad = null;
+ });
+}
+
+function promiseStayOnPagePrompt(browser, acceptNavigation) {
+ return PromptTestUtils.handleNextPrompt(
+ browser,
+ { modalType: Services.prompt.MODAL_TYPE_CONTENT, promptType: "confirmEx" },
+ { buttonNumClick: acceptNavigation ? 0 : 1 }
+ );
+}
+
+add_task(async function test() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["dom.require_user_interaction_for_beforeunload", false]],
+ });
+
+ let testTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_PAGE,
+ false,
+ true
+ );
+ let browser = testTab.linkedBrowser;
+ browser.addProgressListener(
+ tabStateListener,
+ Ci.nsIWebProgress.NOTIFY_STATE_WINDOW
+ );
+
+ const NUM_TESTS = 7;
+ await SpecialPowers.spawn(browser, [NUM_TESTS], testCount => {
+ let { testFns } = this.content.wrappedJSObject;
+ Assert.equal(
+ testFns.length,
+ testCount,
+ "Should have the correct number of test functions"
+ );
+ });
+
+ for (let allowNavigation of [false, true]) {
+ for (let i = 0; i < NUM_TESTS; i++) {
+ info(
+ `Running test ${i} with navigation ${
+ allowNavigation ? "allowed" : "forbidden"
+ }`
+ );
+
+ if (allowNavigation) {
+ // If we're allowing navigations, we need to re-load the test
+ // page after each test, since the tests will each navigate away
+ // from it.
+ await promiseLoaded(TEST_PAGE, () => {
+ browser.loadURI(Services.io.newURI(TEST_PAGE), {
+ triggeringPrincipal: document.nodePrincipal,
+ });
+ });
+ }
+
+ let promptPromise = promiseStayOnPagePrompt(browser, allowNavigation);
+ let loadPromise;
+ if (allowNavigation) {
+ loadPromise = promiseLoaded(TARGETED_PAGE);
+ }
+
+ let winID = await SpecialPowers.spawn(
+ browser,
+ [i, TARGETED_PAGE],
+ (testIdx, url) => {
+ let { testFns } = this.content.wrappedJSObject;
+ this.content.onbeforeunload = testFns[testIdx];
+ this.content.location = url;
+ return this.content.windowGlobalChild.innerWindowId;
+ }
+ );
+
+ await promptPromise;
+ await loadPromise;
+
+ if (allowNavigation) {
+ await SpecialPowers.spawn(
+ browser,
+ [TARGETED_PAGE, winID],
+ (url, winID) => {
+ this.content.onbeforeunload = null;
+ Assert.equal(
+ this.content.location.href,
+ url,
+ "Page should have navigated to the correct URL"
+ );
+ Assert.notEqual(
+ this.content.windowGlobalChild.innerWindowId,
+ winID,
+ "Page should have a new inner window"
+ );
+ }
+ );
+ } else {
+ await SpecialPowers.spawn(browser, [TEST_PAGE, winID], (url, winID) => {
+ this.content.onbeforeunload = null;
+ Assert.equal(
+ this.content.location.href,
+ url,
+ "Page should have the same URL"
+ );
+ Assert.equal(
+ this.content.windowGlobalChild.innerWindowId,
+ winID,
+ "Page should have the same inner window"
+ );
+ });
+ }
+ }
+ }
+
+ gBrowser.removeTab(testTab);
+});