Bug 1114299 - Be more strict about which window chromeFlags we compute from content. r=smaug

We don't ever want to accept "private", "non-private", "remote" or "non-remote" from the
content process. We only let the parent decide when to open those types of windows.
This commit is contained in:
Mike Conley 2015-07-10 11:40:19 -04:00
parent ac8df6815f
commit caba121b6c
5 changed files with 56 additions and 40 deletions

View File

@ -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

View File

@ -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,

View File

@ -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)))

View File

@ -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;
}
}
}

View File

@ -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);