Bug 1235822 - Focus window for beforeunload dialog so it is seen when shutting down. r=dao
authorKestrel <kestrel@vmail.me>
Thu, 17 Nov 2016 10:52:50 +0100
changeset 323043 51357859be9ef65ddc3f33f088e77e5aae0fa153
parent 323042 89236ec592e1cb7eee96c4757d4cf6e61faabce5
child 323044 0f869d4c93ef11e91cb2190e5fed03404d21fdf4
push id30967
push userphilringnalda@gmail.com
push dateFri, 18 Nov 2016 03:21:38 +0000
treeherdermozilla-central@8e476f8bd52d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs1235822
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1235822 - Focus window for beforeunload dialog so it is seen when shutting down. r=dao
browser/base/content/tabbrowser.xml
toolkit/components/startup/tests/browser/browser_bug511456.js
toolkit/components/startup/tests/browser/head.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -5008,16 +5008,24 @@
           // If this is a same-process modal dialog, then we're given its DOM
           // window as the event's target. For remote dialogs, we're given the
           // browser, but that's in the originalTarget and not the target,
           // because it's across the tabbrowser's XBL boundary.
           let tabForEvent = targetIsWindow ?
                             this._getTabForContentWindow(event.target.top) :
                             this.getTabForBrowser(event.originalTarget);
 
+          // Focus window for beforeunload dialog so it is seen but don't
+          // steal focus from other applications.
+          if (event.detail &&
+              event.detail.tabPrompt &&
+              event.detail.inPermitUnload &&
+              Services.focus.activeWindow)
+            window.focus();
+
           // Don't need to act if the tab is already selected:
           if (tabForEvent.selected)
             return;
 
           // We always switch tabs for beforeunload tab-modal prompts.
           if (event.detail &&
               event.detail.tabPrompt &&
               !event.detail.inPermitUnload) {
--- a/toolkit/components/startup/tests/browser/browser_bug511456.js
+++ b/toolkit/components/startup/tests/browser/browser_bug511456.js
@@ -7,29 +7,31 @@
 const TEST_URL = "http://example.com/browser/toolkit/components/startup/tests/browser/beforeunload.html";
 
 SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
 
 function test() {
   waitForExplicitFinish();
   ignoreAllUncaughtExceptions();
 
+  // Create foreground window
   let win2 = window.openDialog(location, "", "chrome,all,dialog=no", "about:blank");
   win2.addEventListener("load", function onLoad() {
     win2.removeEventListener("load", onLoad);
 
-    gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
-    let browser = gBrowser.selectedBrowser;
+    // Create background test tab
+    let browser = gBrowser.addTab(TEST_URL).linkedBrowser;
 
     whenBrowserLoaded(browser, function() {
       let seenDialog = false;
 
       // Cancel the prompt the first time.
       waitForOnBeforeUnloadDialog(browser, (btnLeave, btnStay) => {
-        seenDialog = true;
+        seenDialog = Services.focus.activeWindow == window &&
+                     gBrowser.selectedBrowser == browser;
         btnStay.click();
       });
 
       let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
                          getService(Ci.nsIAppStartup);
       appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);
       ok(seenDialog, "Should have seen a prompt dialog");
       ok(!win2.closed, "Shouldn't have closed the additional window");
--- a/toolkit/components/startup/tests/browser/head.js
+++ b/toolkit/components/startup/tests/browser/head.js
@@ -19,16 +19,16 @@ function waitForOnBeforeUnloadDialog(bro
     if (Cu.isCrossProcessWrapper(event.target)) {
       // This event fires in both the content and chrome processes. We
       // want to ignore the one in the content process.
       return;
     }
 
     browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true);
 
-    executeSoon(() => {
+    SimpleTest.waitForCondition(() => Services.focus.activeWindow == browser.ownerGlobal, function() {
       let stack = browser.parentNode;
       let dialogs = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
       let {button0, button1} = dialogs[0].ui;
       callback(button0, button1);
-    });
+    }, "Waited too long for window with dialog to focus");
   }, true);
 }