Bug 332195 - part 6: make an exception for beforeunload events while tabview is open, r=mconley
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 26 Oct 2015 14:17:16 +0100
changeset 302981 31033f04e561f64b6bb2a86e065d5b226616cfe4
parent 302980 a60f220db385060583af460764abd87cd628c01e
child 302982 18427d3815fc527f9c334a20aca678f03952691b
push idunknown
push userunknown
push dateunknown
reviewersmconley
bugs332195
milestone44.0a1
Bug 332195 - part 6: make an exception for beforeunload events while tabview is open, r=mconley
browser/base/content/tabbrowser.xml
browser/modules/RemotePrompt.jsm
toolkit/components/prompts/src/nsPrompter.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4341,17 +4341,21 @@
           let tabForEvent = targetIsWindow ?
                             this._getTabForContentWindow(event.target.top) :
                             this.getTabForBrowser(event.originalTarget);
 
           // Don't need to act if the tab is already selected:
           if (tabForEvent.selected)
             return;
 
+          // If this is a tabprompt, and we're not in tabview/panorama with
+          // the prompt being a beforeunload one, we won't switch tabs
+          // (unless this behaviour has been disabled entirely using the pref).
           if (event.detail && event.detail.tabPrompt &&
+              !(event.detail.inPermitUnload && ("TabView" in window) && TabView.isVisible()) &&
               Services.prefs.getBoolPref("browser.tabs.dontfocusfordialogs")) {
             let docPrincipal = targetIsWindow ? event.target.document.nodePrincipal : null;
             // At least one of these should/will be non-null:
             let promptPrincipal = event.detail.promptPrincipal || docPrincipal ||
                                   tabForEvent.linkedBrowser.contentPrincipal;
             // For null principals, we bail immediately and don't show the checkbox:
             if (!promptPrincipal || promptPrincipal.isNullPrincipal) {
               tabForEvent.setAttribute("attention", "true");
--- a/browser/modules/RemotePrompt.jsm
+++ b/browser/modules/RemotePrompt.jsm
@@ -58,17 +58,21 @@ var RemotePrompt = {
       browser.messageManager.removeMessageListener("Prompt:ForceClose", listener);
 
       if (newPrompt) {
         newPrompt.abortPrompt();
       }
     });
 
     try {
-      let eventDetail = {tabPrompt: true, promptPrincipal: args.promptPrincipal};
+      let eventDetail = {
+        tabPrompt: true,
+        promptPrincipal: args.promptPrincipal,
+        inPermitUnload: args.inPermitUnload,
+      };
       PromptUtils.fireDialogEvent(window, "DOMWillOpenModalDialog", browser, eventDetail);
 
       args.promptActive = true;
 
       newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
 
       // TODO since we don't actually open a window, need to check if
       // there's other stuff in nsWindowWatcher::OpenWindowInternal
--- a/toolkit/components/prompts/src/nsPrompter.js
+++ b/toolkit/components/prompts/src/nsPrompter.js
@@ -366,17 +366,20 @@ function openModalWindow(domWin, uri, ar
     // Note that we don't need to fire DOMWillOpenModalDialog and
     // DOMModalDialogClosed events here, wwatcher's OpenWindowInternal
     // will do that. Similarly for enterModalState / leaveModalState.
 
     Services.ww.openWindow(domWin, uri, "_blank", "centerscreen,chrome,modal,titlebar", args);
 }
 
 function openTabPrompt(domWin, tabPrompt, args) {
-    let eventDetail = Cu.cloneInto({tabPrompt: true}, domWin);
+    let docShell = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIDocShell);
+    let inPermitUnload = docShell.contentViewer && docShell.contentViewer.inPermitUnload;
+    let eventDetail = Cu.cloneInto({tabPrompt: true, inPermitUnload}, domWin);
     PromptUtils.fireDialogEvent(domWin, "DOMWillOpenModalDialog", null, eventDetail);
 
     let winUtils = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIDOMWindowUtils);
     winUtils.enterModalState();
 
     // We provide a callback so the prompt can close itself. We don't want to
     // wait for this event loop to return... Otherwise the presence of other
@@ -429,24 +432,24 @@ function openTabPrompt(domWin, tabPrompt
     } finally {
         // If the prompt unexpectedly failed to invoke the callback, do so here.
         if (!callbackInvoked)
             onPromptClose(true);
     }
 }
 
 function openRemotePrompt(domWin, args, tabPrompt) {
-    let messageManager = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIWebNavigation)
-                         .QueryInterface(Ci.nsIDocShell)
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsITabChild)
-                         .messageManager;
+    let docShell = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIDocShell);
+    let messageManager = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
+                                 .getInterface(Ci.nsITabChild)
+                                 .messageManager;
 
-    let eventDetail = Cu.cloneInto({tabPrompt}, domWin);
+    let inPermitUnload = docShell.contentViewer && docShell.contentViewer.inPermitUnload;
+    let eventDetail = Cu.cloneInto({tabPrompt, inPermitUnload}, domWin);
     PromptUtils.fireDialogEvent(domWin, "DOMWillOpenModalDialog", null, eventDetail);
 
     let winUtils = domWin.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIDOMWindowUtils);
     winUtils.enterModalState();
     let closed = false;
 
     // It should be hard or impossible to cause a window to create multiple