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.js176
1 files changed, 176 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 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);
+});
+