Bug 1350152 - Don't rely on gBrowser in nsLoginManagerPrompter.js. r=mkaply draft
authorJohann Hofmann <jhofmann@mozilla.com>
Thu, 01 Jun 2017 21:41:11 +0200
changeset 620222 7b6fbc54e4d5992adb071b7f2f0ec08ebe5fe96e
parent 620112 d942ef54fdf726840a698d2ddcaf989d2c00edbc
child 640637 0c2cf9214a99fbc29aa9b1002f4f1f9701903c3e
push id71973
push userbmo:jhofmann@mozilla.com
push dateThu, 03 Aug 2017 08:39:03 +0000
reviewersmkaply
bugs1350152, 1266836
milestone57.0a1
Bug 1350152 - Don't rely on gBrowser in nsLoginManagerPrompter.js. r=mkaply In bug 1266836 we fixed this code to properly work in e10s, but made the mistake of using gBrowser in toolkit code, breaking XUL apps that don't have a gBrowser. This solution implements a different code-path for non-e10s and returns a chrome window for consumers that don't offer a browser. MozReview-Commit-ID: 929ahDenzu5
toolkit/components/passwordmgr/nsLoginManagerPrompter.js
--- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
@@ -803,16 +803,19 @@ LoginManagerPrompter.prototype = {
    *        Login to save or change. For changes, this login should contain the
    *        new password.
    * @param {string} type
    *        This is "password-save" or "password-change" depending on the
    *        original notification type. This is used for telemetry and tests.
    */
   _showLoginCaptureDoorhanger(login, type) {
     let { browser } = this._getNotifyWindow();
+    if (!browser) {
+      return;
+    }
 
     let saveMsgNames = {
       prompt: login.username === "" ? "saveLoginMsgNoUser"
                                     : "saveLoginMsg",
       buttonLabel: "saveLoginButtonAllow.label",
       buttonAccessKey: "saveLoginButtonAllow.accesskey",
       secondaryButtonLabel: "saveLoginButtonDeny.label",
       secondaryButtonAccessKey: "saveLoginButtonDeny.accesskey",
@@ -1415,20 +1418,43 @@ LoginManagerPrompter.prototype = {
     propBag.setProperty("timesUsedIncrement", 1);
     this._pwmgr.modifyLogin(login, propBag);
   },
 
   /**
    * Given a content DOM window, returns the chrome window and browser it's in.
    */
   _getChromeWindow(aWindow) {
+    // Handle non-e10s toolkit consumers.
+    if (!Cu.isCrossProcessWrapper(aWindow)) {
+      let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                             .getInterface(Ci.nsIWebNavigation)
+                             .QueryInterface(Ci.nsIDocShell)
+                             .chromeEventHandler.ownerGlobal;
+      if (!chromeWin) {
+        return null;
+      }
+
+      // gBrowser only exists on some apps, like Firefox.
+      let tabbrowser = chromeWin.gBrowser || chromeWin.getBrowser();
+      // At least serve the chrome window if getBrowser()
+      // or getBrowserForContentWindow() are not supported.
+      if (!tabbrowser || typeof tabbrowser.getBrowserForContentWindow != "function") {
+        return { win: chromeWin };
+      }
+
+      let browser = tabbrowser.getBrowserForContentWindow(aWindow);
+      return { win: chromeWin, browser };
+    }
+
     let windows = Services.wm.getEnumerator(null);
     while (windows.hasMoreElements()) {
       let win = windows.getNext();
-      let browser = win.gBrowser.getBrowserForContentWindow(aWindow);
+      let tabbrowser = win.gBrowser || win.getBrowser();
+      let browser = tabbrowser.getBrowserForContentWindow(aWindow);
       if (browser) {
         return { win, browser };
       }
     }
     return null;
   },
 
   _getNotifyWindow() {