diff --git a/embedding/browser/webBrowser/nsIWebBrowserChrome.idl b/embedding/browser/webBrowser/nsIWebBrowserChrome.idl index 02882c981013..7904c516818f 100644 --- a/embedding/browser/webBrowser/nsIWebBrowserChrome.idl +++ b/embedding/browser/webBrowser/nsIWebBrowserChrome.idl @@ -63,6 +63,9 @@ interface nsIWebBrowserChrome : nsISupports const unsigned long CHROME_WINDOW_MIN = 0x00004000; const unsigned long CHROME_WINDOW_POPUP = 0x00008000; + // private browsing windows + const unsigned long CHROME_PRIVATE_WINDOW = 0x00010000; + // Prevents new window animations on Mac OS X Lion. Ignored on other // platforms. const unsigned long CHROME_MAC_SUPPRESS_ANIMATION = 0x01000000; diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index f1569d2719de..c855c358a1c9 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -898,17 +898,25 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent, } if (windowIsNew) { - // For top level windows, we want to ensure that the privacy status of the parent - // is propagated to the new child if it is available. - nsCOMPtr parentItem; - GetWindowTreeItem(aParent, getter_AddRefs(parentItem)); - nsCOMPtr parentContext = do_QueryInterface(parentItem); + // See if the caller has requested a private browsing window. + bool isPrivateBrowsingWindow = + !!(chromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW); + // Otherwise, propagate the privacy status of the parent window, if + // available, to the child. + if (!isPrivateBrowsingWindow) { + nsCOMPtr parentItem; + GetWindowTreeItem(aParent, getter_AddRefs(parentItem)); + nsCOMPtr parentContext = do_QueryInterface(parentItem); + if (parentContext) { + isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing(); + } + } nsCOMPtr childRoot; newDocShellItem->GetRootTreeItem(getter_AddRefs(childRoot)); nsCOMPtr childContext = do_QueryInterface(childRoot); - if (parentContext && childContext) { - childContext->SetUsePrivateBrowsing(parentContext->UsePrivateBrowsing()); + if (childContext) { + childContext->SetUsePrivateBrowsing(isPrivateBrowsingWindow); } } @@ -1490,6 +1498,12 @@ uint32_t nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow *aParent, } } + // Determine whether the window is a private browsing window + if (isChrome) { + chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ? + nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0; + } + nsCOMPtr prefBranch; nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, true); diff --git a/embedding/test/Makefile.in b/embedding/test/Makefile.in index 325e89a83441..7842e2f33436 100644 --- a/embedding/test/Makefile.in +++ b/embedding/test/Makefile.in @@ -19,6 +19,7 @@ MOCHITEST_FILES = \ bug449141_page.html \ test_bug499115.html \ test_nsFind.html \ + test_private_window_from_content.html \ test_window_open_units.html \ $(NULL) diff --git a/embedding/test/test_private_window_from_content.html b/embedding/test/test_private_window_from_content.html new file mode 100644 index 000000000000..5f0aa5589585 --- /dev/null +++ b/embedding/test/test_private_window_from_content.html @@ -0,0 +1,8 @@ + + + diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js index 4f17581f6ddc..d1975d5e4158 100644 --- a/testing/specialpowers/content/specialpowersAPI.js +++ b/testing/specialpowers/content/specialpowersAPI.js @@ -11,6 +11,7 @@ var Cu = Components.utils; Components.utils.import("resource://specialpowers/MockFilePicker.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); function SpecialPowersAPI() { this._consoleListeners = []; @@ -1242,4 +1243,8 @@ SpecialPowersAPI.prototype = { getMozFullPath: function(file) { return file.mozFullPath; }, + + isWindowPrivate: function(win) { + return PrivateBrowsingUtils.isWindowPrivate(win); + }, };