Bug 749187 - Ensure new tabs and windows opened in private browsing mode have docshells set accordingly; r=gavin a=lsblakk
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 26 Apr 2012 14:35:19 -0400
changeset 95840 ce3cc54fe3bbc33cf1c8cd7e080aeed7e6cc192f
parent 95839 0433b21faf608bfea43e98ed14e09a5f654b92e8
child 95841 9620de534159e6d6575ca482fbc2053186022f4d
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, lsblakk
bugs749187
milestone14.0a2
Bug 749187 - Ensure new tabs and windows opened in private browsing mode have docshells set accordingly; r=gavin a=lsblakk
browser/base/content/browser.js
browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8780,27 +8780,29 @@ let gPrivateBrowsingUI = {
   },
 
   /**
    * These accessors are used to support per-window Private Browsing mode.
    * For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
    * and the setter should only be used in tests.
    */
   get privateWindow() {
-    return window.getInterface(Ci.nsIWebNavigation)
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
                  .QueryInterface(Ci.nsIDocShellTreeItem)
                  .treeOwner
                  .QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIXULWindow)
                  .docShell.QueryInterface(Ci.nsILoadContext)
                  .usePrivateBrowsing;
   },
 
   set privateWindow(val) {
-    return window.getInterface(Ci.nsIWebNavigation)
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
                  .QueryInterface(Ci.nsIDocShellTreeItem)
                  .treeOwner
                  .QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIXULWindow)
                  .docShell.QueryInterface(Ci.nsILoadContext)
                  .usePrivateBrowsing = val;
   }
 };
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -90,16 +90,17 @@ const STATE_RESTORE_FINISHED = 3;
 function PrivateBrowsingService() {
   this._obs = Cc["@mozilla.org/observer-service;1"].
               getService(Ci.nsIObserverService);
   this._obs.addObserver(this, "profile-after-change", true);
   this._obs.addObserver(this, "quit-application-granted", true);
   this._obs.addObserver(this, "private-browsing", true);
   this._obs.addObserver(this, "command-line-startup", true);
   this._obs.addObserver(this, "sessionstore-browser-state-restored", true);
+  this._obs.addObserver(this, "domwindowopened", true);
 
   // List of nsIXULWindows we are going to be closing during the transition
   this._windowsToClose = [];
 }
 
 PrivateBrowsingService.prototype = {
   // Preferences Service
   get _prefs() {
@@ -143,16 +144,27 @@ PrivateBrowsingService.prototype = {
 
   _unload: function PBS__destroy() {
     // Force an exit from the private browsing mode on shutdown
     this._quitting = true;
     if (this._inPrivateBrowsing)
       this.privateBrowsingEnabled = false;
   },
 
+  _setPerWindowPBFlag: function PBS__setPerWindowPBFlag(aWindow, aFlag) {
+    aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+           .getInterface(Ci.nsIWebNavigation)
+           .QueryInterface(Ci.nsIDocShellTreeItem)
+           .treeOwner
+           .QueryInterface(Ci.nsIInterfaceRequestor)
+           .getInterface(Ci.nsIXULWindow)
+           .docShell.QueryInterface(Ci.nsILoadContext)
+           .usePrivateBrowsing = aFlag;
+  },
+
   _onBeforePrivateBrowsingModeChange: function PBS__onBeforePrivateBrowsingModeChange() {
     // nothing needs to be done here if we're enabling at startup
     if (!this._autoStarted) {
       let ss = Cc["@mozilla.org/browser/sessionstore;1"].
                getService(Ci.nsISessionStore);
       let blankState = JSON.stringify({
         "windows": [{
           "tabs": [{
@@ -213,33 +225,25 @@ PrivateBrowsingService.prototype = {
           browserWindow.getInterface(Ci.nsIWebNavigation)
                        .QueryInterface(Ci.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIXULWindow)
                        .docShell.contentViewer.resetCloseWindow();
         }
       }
-
-      if (!this._quitting) {
-        var windowsEnum = Services.wm.getEnumerator("navigator:browser");
-        while (windowsEnum.hasMoreElements()) {
-          var window = windowsEnum.getNext();
-          window.getInterface(Ci.nsIWebNavigation)
-                .QueryInterface(Ci.nsIDocShellTreeItem)
-                .treeOwner
-                .QueryInterface(Ci.nsIInterfaceRequestor)
-                .getInterface(Ci.nsIXULWindow)
-                .docShell.QueryInterface(Ci.nsILoadContext)
-                .usePrivateBrowsing = this._inPrivateBrowsing;
-        }
-      }
     }
     else
       this._saveSession = false;
+
+    var windowsEnum = Services.wm.getEnumerator("navigator:browser");
+    while (windowsEnum.hasMoreElements()) {
+      var window = windowsEnum.getNext();
+      this._setPerWindowPBFlag(window, this._inPrivateBrowsing);
+    }
   },
 
   _onAfterPrivateBrowsingModeChange: function PBS__onAfterPrivateBrowsingModeChange() {
     // nothing to do here if we're enabling at startup or the current session is being
     // used
     if (!this._autoStarted && this._saveSession) {
       let ss = Cc["@mozilla.org/browser/sessionstore;1"].
                getService(Ci.nsISessionStore);
@@ -468,16 +472,28 @@ PrivateBrowsingService.prototype = {
         }
         break;
       case "sessionstore-browser-state-restored":
         if (this._currentStatus == STATE_WAITING_FOR_RESTORE) {
           this._currentStatus = STATE_RESTORE_FINISHED;
           this._notifyIfTransitionComplete();
         }
         break;
+      case "domwindowopened":
+        let aWindow = aSubject;
+        let self = this;
+        aWindow.addEventListener("load", function PBS__onWindowLoad(aEvent) {
+          aWindow.removeEventListener("load", arguments.callee);
+          if (aWindow.document
+                     .documentElement
+                     .getAttribute("windowtype") == "navigator:browser") {
+            self._setPerWindowPBFlag(aWindow, self._inPrivateBrowsing);
+          }
+        }, false);
+        break;
     }
   },
 
   // nsICommandLineHandler
 
   handle: function PBS_handle(aCmdLine) {
     if (aCmdLine.handleFlag("private", false))
       aCmdLine.preventDefault = true; // It has already been handled
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
@@ -35,71 +35,101 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // This test makes sure that the gPrivateBrowsingUI object, the Private Browsing
 // menu item and its XUL <command> element work correctly.
 
 function test() {
   // initialization
+  waitForExplicitFinish();
   gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
   let observerData;
   function observer(aSubject, aTopic, aData) {
     if (aTopic == "private-browsing")
       observerData = aData;
   }
   Services.obs.addObserver(observer, "private-browsing", false);
   let pbMenuItem = document.getElementById("privateBrowsingItem");
   // add a new blank tab to ensure the title can be meaningfully compared later
   gBrowser.selectedTab = gBrowser.addTab();
   let originalTitle = document.title;
 
+  function testNewWindow(aCallback, expected) {
+    Services.obs.addObserver(function observer1(aSubject, aTopic, aData) {
+      aSubject.addEventListener("load", function() {
+        aSubject.removeEventListener("load", arguments.callee);
+        executeSoon(function() {
+          let ui = aSubject.gPrivateBrowsingUI;
+          is(ui.privateBrowsingEnabled, expected, "The privateBrowsingEnabled property on the new window is set correctly");
+          is(ui.privateWindow, expected, "The privateWindow property on the new window is set correctly");
+
+          Services.obs.addObserver(function observer2(aSubject, aTopic, aData) {
+            aCallback();
+            Services.obs.removeObserver(observer2, "domwindowclosed");
+          }, "domwindowclosed", false);
+          aSubject.close();
+        });
+        Services.obs.removeObserver(observer1, "domwindowopened");
+      }, false);
+    }, "domwindowopened", false);
+    OpenBrowserWindow();
+  }
+
   // test the gPrivateBrowsingUI object
   ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
   is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
   is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   ok(pbMenuItem, "The Private Browsing menu item exists");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
-  gPrivateBrowsingUI.toggleMode();
-  is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
-  is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
-  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
-  // check to see if the Private Browsing mode was activated successfully
-  is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
-  is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
-  gPrivateBrowsingUI.toggleMode()
-  is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
-  is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
-  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
-  // check to see if the Private Browsing mode was deactivated successfully
-  is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
-  is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
+  testNewWindow(function() {
+    gPrivateBrowsingUI.toggleMode();
+    is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
+    is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
+    is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
+    // check to see if the Private Browsing mode was activated successfully
+    is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
+    is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
+    testNewWindow(function() {
+      gPrivateBrowsingUI.toggleMode()
+      is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
+      is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
+      is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
+      // check to see if the Private Browsing mode was deactivated successfully
+      is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
+      is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
+
+      testNewWindow(function() {
+        // These are tests for the privateWindow setter.  Note that the setter should
+        // not be used anywhere else for now!
+        gPrivateBrowsingUI.privateWindow = true;
+        is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+        gPrivateBrowsingUI.privateWindow = false;
+        is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
 
-  // These are tests for the privateWindow setter.  Note that the setter should
-  // not be used anywhere else for now!
-  gPrivateBrowsingUI.privateWindow = true;
-  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
-  gPrivateBrowsingUI.privateWindow = false;
-  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+        // now, test using the <command> object
+        let cmd = document.getElementById("Tools:PrivateBrowsing");
+        isnot(cmd, null, "XUL command object for the private browsing service exists");
+        var func = new Function("", cmd.getAttribute("oncommand"));
+        func.call(cmd);
+        // check to see if the Private Browsing mode was activated successfully
+        is(observerData, "enter", "Private Browsing mode was activated using the command object");
+        // check to see that the window title has been changed correctly
+        isnot(document.title, originalTitle, "Private browsing mode has correctly changed the title");
+        func.call(cmd);
+        // check to see if the Private Browsing mode was deactivated successfully
+        is(observerData, "exit", "Private Browsing mode was deactivated using the command object");
+        // check to see that the window title has been restored correctly
+        is(document.title, originalTitle, "Private browsing mode has correctly restored the title");
 
-  // now, test using the <command> object
-  let cmd = document.getElementById("Tools:PrivateBrowsing");
-  isnot(cmd, null, "XUL command object for the private browsing service exists");
-  var func = new Function("", cmd.getAttribute("oncommand"));
-  func.call(cmd);
-  // check to see if the Private Browsing mode was activated successfully
-  is(observerData, "enter", "Private Browsing mode was activated using the command object");
-  // check to see that the window title has been changed correctly
-  isnot(document.title, originalTitle, "Private browsing mode has correctly changed the title");
-  func.call(cmd);
-  // check to see if the Private Browsing mode was deactivated successfully
-  is(observerData, "exit", "Private Browsing mode was deactivated using the command object");
-  // check to see that the window title has been restored correctly
-  is(document.title, originalTitle, "Private browsing mode has correctly restored the title");
+        // cleanup
+        gBrowser.removeCurrentTab();
+        Services.obs.removeObserver(observer, "private-browsing");
+        gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
 
-  // cleanup
-  gBrowser.removeCurrentTab();
-  Services.obs.removeObserver(observer, "private-browsing");
-  gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
+        finish();
+      }, false);
+    }, true);
+  }, false);
 }