diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 70d5d639177b..46ed81514252 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9837,13 +9837,9 @@ nsDocShell::InternalLoad(nsIURI* aURI, if (aURI) { aURI->GetSpec(spec); } - nsAutoString features; - if (mInPrivateBrowsing) { - features.AssignLiteral("private"); - } rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec), name, // window name - features, + EmptyString(), // Features getter_AddRefs(newWin)); // In some cases the Open call doesn't actually result in a new diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 9a76d2f4b45b..47b6df3751e7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1597,10 +1597,6 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener, nsAutoCString baseURIString; baseURI->GetSpec(baseURIString); - // We can assume that if content is requesting to open a window from a remote - // tab, then we want to enforce that the new window is also a remote tab. - features.AppendLiteral(",remote"); - nsresult rv; if (!SendCreateWindow(newChild, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index cc7d513be3ac..e5c1440886cf 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -622,6 +622,13 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab, // We always expect to open a new window here. If we don't, it's an error. *aWindowIsNew = true; + // The content process should never be in charge of computing whether or + // not a window should be private or remote - the parent will do that. + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME)); + MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)); + if (NS_WARN_IF(IsBrowserOrApp())) return false; @@ -735,9 +742,11 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab, AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad); + const char* features = aFeatures.Length() ? aFeatures.get() : nullptr; + *aResult = pwwatch->OpenWindow2(parent, finalURIString.get(), NS_ConvertUTF16toUTF8(aName).get(), - aFeatures.get(), aCalledFromJS, + features, aCalledFromJS, false, false, this, nullptr, getter_AddRefs(window)); if (NS_WARN_IF(NS_FAILED(*aResult))) diff --git a/embedding/components/windowwatcher/nsWindowWatcher.cpp b/embedding/components/windowwatcher/nsWindowWatcher.cpp index 6dd50b2c73e4..0f96f1ae4ae8 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -562,7 +562,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, // security checks. chromeFlags = CalculateChromeFlags(aParent, features.get(), featuresSpecified, aDialog, uriToLoadIsChrome, - hasChromeParent, openedFromRemoteTab); + hasChromeParent, aCalledFromJS, + openedFromRemoteTab); // If we are opening a window from a remote browser, the resulting window // should also be remote. @@ -1466,8 +1467,8 @@ nsWindowWatcher::URIfromURL(const char* aURL, #define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \ prefBranch->GetBoolPref(feature, &forceEnable); \ - if (forceEnable && !(aDialog && isCallerChrome) && \ - !(isCallerChrome && aHasChromeParent) && !aChromeURL) { \ + if (forceEnable && !(aDialog && !openedFromContentScript) && \ + !(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \ chromeFlags |= flag; \ } else { \ chromeFlags |= \ @@ -1491,26 +1492,30 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, bool aDialog, bool aChromeURL, bool aHasChromeParent, + bool aCalledFromJS, bool aOpenedFromRemoteTab) { + const bool inContentProcess = XRE_IsContentProcess(); uint32_t chromeFlags = 0; - bool isCallerChrome = - nsContentUtils::IsCallerChrome() && !aOpenedFromRemoteTab; - bool onlyPrivateFlag = aFeaturesSpecified && aFeatures && isCallerChrome && - nsCRT::strcasecmp(aFeatures, "private") == 0; - if (!aFeaturesSpecified || !aFeatures || onlyPrivateFlag) { + if (!aFeaturesSpecified || !aFeatures) { chromeFlags = nsIWebBrowserChrome::CHROME_ALL; if (aDialog) { chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | nsIWebBrowserChrome::CHROME_OPENAS_CHROME; } - if (onlyPrivateFlag) { - chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW; + + if (inContentProcess) { + return chromeFlags; } - return chromeFlags; + } else { + chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS; } + bool openedFromContentScript = + aOpenedFromRemoteTab ? aCalledFromJS + : !nsContentUtils::IsCallerChrome(); + /* This function has become complicated since browser windows and dialogs diverged. The difference is, browser windows assume all chrome not explicitly mentioned is off, if the features string @@ -1520,30 +1525,32 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, in the standards-compliant window.(normal)open. */ bool presenceFlag = false; - - chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS; if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) { chromeFlags = nsIWebBrowserChrome::CHROME_ALL; } /* Next, allow explicitly named options to override the initial settings */ - // Determine whether the window is a private browsing window - if (isCallerChrome) { + if (!inContentProcess && !openedFromContentScript) { + // Determine whether the window is a private browsing window chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ? nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0; chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ? nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0; } - // Determine whether the window should have remote tabs. - if (isCallerChrome || aOpenedFromRemoteTab) { - bool remote; - if (BrowserTabsRemoteAutostart()) { - remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag); - } else { - remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag); + if (!inContentProcess) { + // Determine whether the window should have remote tabs. + bool remote = BrowserTabsRemoteAutostart(); + + if (!openedFromContentScript) { + if (remote) { + remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag); + } else { + remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag); + } } + if (remote) { chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW; } @@ -1644,7 +1651,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, if (aParent) { aParent->GetFullScreen(&isFullScreen); } - if (isFullScreen && !isCallerChrome) { + if (isFullScreen && openedFromContentScript) { // If the parent window is in fullscreen & the caller context is content, // dialog feature is disabled. (see bug 803675) disableDialogFeature = true; @@ -1671,7 +1678,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, */ // Check security state for use in determing window dimensions - if (!isCallerChrome || !aHasChromeParent) { + if (openedFromContentScript || !aHasChromeParent) { // If priv check fails (or if we're called from chrome, but the // parent is not a chrome window), set all elements to minimum // reqs., else leave them alone. @@ -2270,12 +2277,19 @@ nsWindowWatcher::GetWindowOpenLocation(nsIDOMWindow* aParent, return nsIBrowserDOMWindow::OPEN_NEWWINDOW; } - if (restrictionPref == 2 && - // Only continue if there are no size/position features and no special - // chrome flags. - (aChromeFlags != nsIWebBrowserChrome::CHROME_ALL || - aPositionSpecified || aSizeSpecified)) { - return nsIBrowserDOMWindow::OPEN_NEWWINDOW; + if (restrictionPref == 2) { + // Only continue if there are no size/position features and no special + // chrome flags - with the exception of the remoteness and private flags, + // which might have been automatically flipped by Gecko. + int32_t uiChromeFlags = aChromeFlags; + uiChromeFlags &= ~(nsIWebBrowserChrome::CHROME_REMOTE_WINDOW | + nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW | + nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW | + nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME); + if (uiChromeFlags != nsIWebBrowserChrome::CHROME_ALL || + aPositionSpecified || aSizeSpecified) { + return nsIBrowserDOMWindow::OPEN_NEWWINDOW; + } } } diff --git a/embedding/components/windowwatcher/nsWindowWatcher.h b/embedding/components/windowwatcher/nsWindowWatcher.h index 04a025058371..a71bfab805fb 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.h +++ b/embedding/components/windowwatcher/nsWindowWatcher.h @@ -96,6 +96,7 @@ protected: bool aDialog, bool aChromeURL, bool aHasChromeParent, + bool aCalledFromJS, bool aOpenedFromRemoteTab); static int32_t WinHasOption(const char* aOptions, const char* aName, int32_t aDefault, bool* aPresenceFlag);