Bug 1303196 - Part 7: Updates to apply correctly after noopener changes, r=smaug

MozReview-Commit-ID: 25Ew2PLpP5c
This commit is contained in:
Michael Layzell 2016-10-27 12:37:44 -04:00
parent 0f986f1b54
commit de29c95ed2
14 changed files with 78 additions and 47 deletions

View File

@ -4943,7 +4943,7 @@ nsBrowserAccess.prototype = {
return browser;
},
openURI: function (aURI, aOpener, aWhere, aContext) {
openURI: function (aURI, aOpener, aWhere, aFlags) {
// This function should only ever be called if we're opening a URI
// from a non-remote browser window (via nsContentTreeOwner).
if (aOpener && Cu.isCrossProcessWrapper(aOpener)) {
@ -4953,7 +4953,7 @@ nsBrowserAccess.prototype = {
}
var newWindow = null;
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
if (aOpener && isExternal) {
Cu.reportError("nsBrowserAccess.openURI did not expect an opener to be " +
@ -5007,10 +5007,11 @@ nsBrowserAccess.prototype = {
let userContextId = aOpener && aOpener.document
? aOpener.document.nodePrincipal.originAttributes.userContextId
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
isPrivate, isExternal,
forceNotRemote, userContextId,
aOpener);
openerWindow);
if (browser)
newWindow = browser.contentWindow;
break;
@ -5032,13 +5033,13 @@ nsBrowserAccess.prototype = {
return newWindow;
},
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aContext) {
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags) {
if (aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB) {
dump("Error: openURIInFrame can only open in new tabs");
return null;
}
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
var isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
var userContextId = aParams.openerOriginAttributes &&
("userContextId" in aParams.openerOriginAttributes)

View File

@ -231,8 +231,8 @@ function tunnelToInnerBrowser(outer, inner) {
// that support openers, window features, etc. didn't seem callable from JS and / or
// this event doesn't give enough info to use them.
browserWindow.browserDOMWindow
.openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
Ci.nsIBrowserDOMWindow.OPEN_NEWTAB);
.openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
Ci.nsIBrowserDOMWindow.OPEN_NEW);
},
stop() {

View File

@ -8,6 +8,7 @@
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsHostObjectProtocolHandler.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/URIUtils.h"

View File

@ -256,6 +256,7 @@ BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
mozIDOMWindowProxy** aReturnWindow)
{
*aReturnWindow = nullptr;
@ -283,9 +284,11 @@ BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow,
aURI->GetSpec(spec);
}
ErrorResult res;
popupFrameElement->PresetOpenerWindow(aOpenerWindow, res);
MOZ_ASSERT(!res.Failed());
if (!aForceNoOpener) {
ErrorResult res;
popupFrameElement->PresetOpenerWindow(aOpenerWindow, res);
MOZ_ASSERT(!res.Failed());
}
OpenWindowResult opened =
DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,

View File

@ -118,6 +118,7 @@ public:
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
mozIDOMWindowProxy** aReturnWindow);
private:

View File

@ -62,17 +62,29 @@ interface nsIBrowserDOMWindow : nsISupports
const short OPEN_SWITCHTAB = 4;
/**
* Values for openURI's aContext parameter. These affect the behavior of
* OPEN_DEFAULTWINDOW.
* Values for openURI's aFlags parameter. This is a bitflags field.
*
* The 0x1 bit decides the behavior of OPEN_DEFAULTWINDOW, and the 0x4 bit
* controls whether or not to set the window.opener property on the newly
* opened window.
*
* NOTE: The 0x2 bit is ignored for backwards compatibility with addons, as
* OPEN_NEW used to have the value 2. The values 0 and 2 are treated
* the same way internally.
*/
/**
* external link (load request from another application, xremote, etc).
*/
const short OPEN_EXTERNAL = 1;
/**
* internal open new window
*/
const short OPEN_NEW = 2;
const long OPEN_NEW = 0x0;
/**
* external link (load request from another application, xremote, etc).
*/
const long OPEN_EXTERNAL = 0x1;
/**
* Don't set the window.opener property on the window which is being opened
*/
const long OPEN_NO_OPENER = 0x4;
/**
* Load a URI
@ -82,13 +94,14 @@ interface nsIBrowserDOMWindow : nsISupports
* happened in will be returned.
* @param aWhere see possible values described above.
* @param aOpener window requesting the open (can be null).
* @param aContext the context in which the URI is being opened. This
* is used only when aWhere == OPEN_DEFAULTWINDOW.
* @param aFlags flags which control the behavior of the load. The
* OPEN_EXTERNAL/OPEN_NEW flag is only used when
* aWhere == OPEN_DEFAULTWINDOW.
* @return the window into which the URI was opened.
*/
mozIDOMWindowProxy
openURI(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
in short aWhere, in short aContext);
in short aWhere, in long aFlags);
/**
* As above, but return the nsIFrameLoaderOwner for the new window.
@ -96,7 +109,7 @@ interface nsIBrowserDOMWindow : nsISupports
// See bug 537428
*/
nsIFrameLoaderOwner openURIInFrame(in nsIURI aURI, in nsIOpenURIInFrameParams params,
in short aWhere, in short aContext);
in short aWhere, in long aFlags);
/**
* @param aWindow the window to test.

View File

@ -662,13 +662,14 @@ ContentChild::ProvideWindow(mozIDOMWindowProxy* aParent,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
bool* aWindowIsNew,
mozIDOMWindowProxy** aReturn)
{
return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
aCalledFromJS, aPositionSpecified,
aSizeSpecified, aURI, aName, aFeatures,
aWindowIsNew, aReturn);
aForceNoOpener, aWindowIsNew, aReturn);
}
nsresult
@ -682,6 +683,7 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
bool* aWindowIsNew,
mozIDOMWindowProxy** aReturn)
{
@ -831,7 +833,7 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
// they can poke at the document and cause the nsDocument to be created before
// the openerwindow
nsCOMPtr<mozIDOMWindowProxy> windowProxy = do_GetInterface(newChild->WebNavigation());
if (windowProxy && aParent) {
if (!aForceNoOpener && windowProxy && aParent) {
nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(windowProxy);
nsPIDOMWindowOuter* parent = nsPIDOMWindowOuter::From(aParent);
outer->SetOpenerWindow(parent, *aWindowIsNew);

View File

@ -88,6 +88,7 @@ public:
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
bool* aWindowIsNew,
mozIDOMWindowProxy** aReturn);

View File

@ -1169,8 +1169,8 @@ TabChild::ProvideWindow(mozIDOMWindowProxy* aParent,
bool aCalledFromJS,
bool aPositionSpecified, bool aSizeSpecified,
nsIURI* aURI, const nsAString& aName,
const nsACString& aFeatures, bool* aWindowIsNew,
mozIDOMWindowProxy** aReturn)
const nsACString& aFeatures, bool aForceNoOpener,
bool* aWindowIsNew, mozIDOMWindowProxy** aReturn)
{
*aReturn = nullptr;
@ -1212,6 +1212,7 @@ TabChild::ProvideWindow(mozIDOMWindowProxy* aParent,
aURI,
aName,
aFeatures,
aForceNoOpener,
aWindowIsNew,
aReturn);
}

View File

@ -883,8 +883,8 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
rv = provider->ProvideWindow(aParent, chromeFlags, aCalledFromJS,
sizeSpec.PositionSpecified(),
sizeSpec.SizeSpecified(),
uriToLoad, name, features, &windowIsNew,
getter_AddRefs(newWindow));
uriToLoad, name, features, aForceNoOpener,
&windowIsNew, getter_AddRefs(newWindow));
if (NS_SUCCEEDED(rv)) {
GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
@ -998,8 +998,9 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
}
mozIDOMWindowProxy* openerWindow = aForceNoOpener ? nullptr : aParent;
rv = CreateChromeWindow(features, parentChrome, chromeFlags, contextFlags,
nullptr, aParent, getter_AddRefs(newChrome));
nullptr, openerWindow, getter_AddRefs(newChrome));
} else {
rv = mWindowCreator->CreateChromeWindow(parentChrome, chromeFlags,
@ -1012,7 +1013,7 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
if (xulBrowserWin) {
nsPIDOMWindowOuter* openerWindow = aForceNoOpener ? nullptr : parentWindow;
nsPIDOMWindowOuter* openerWindow = aForceNoOpener ? nullptr : parentWindow.get();
xulBrowserWin->ForceInitialBrowserNonRemote(openerWindow);
}
}
@ -2147,7 +2148,7 @@ nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
if (piOpenedWindow) {
if (!aForceNoOpener) {
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
} else if (aParent) {
} else if (aParent && aParent != piOpenedWindow) {
MOZ_ASSERT(nsGlobalWindow::Cast(piOpenedWindow)->TabGroup() !=
nsGlobalWindow::Cast(aParent)->TabGroup(),
"If we're forcing no opener, they should be in different tab groups");

View File

@ -98,5 +98,6 @@ interface nsIWindowProvider : nsISupports
in nsIURI aURI,
in AString aName,
in AUTF8String aFeatures,
in boolean aForceNoOpener,
out boolean aWindowIsNew);
};

View File

@ -3230,8 +3230,8 @@ function nsBrowserAccess() {
nsBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
_getBrowser: function _getBrowser(aURI, aOpener, aWhere, aContext) {
let isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
_getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags) {
let isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
if (isExternal && aURI && aURI.schemeIs("chrome"))
return null;
@ -3239,12 +3239,10 @@ nsBrowserAccess.prototype = {
Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
switch (aContext) {
case Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL:
aWhere = Services.prefs.getIntPref("browser.link.open_external");
break;
default: // OPEN_NEW or an illegal value
aWhere = Services.prefs.getIntPref("browser.link.open_newwindow");
if (isExternal) {
aWhere = Services.prefs.getIntPref("browser.link.open_external");
} else {
aWhere = Services.prefs.getIntPref("browser.link.open_newwindow");
}
}
@ -3292,12 +3290,13 @@ nsBrowserAccess.prototype = {
}
}
let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
// BrowserApp.addTab calls loadURIWithFlags with the appropriate params
let tab = BrowserApp.addTab(aURI ? aURI.spec : "about:blank", { flags: loadflags,
referrerURI: referrer,
external: isExternal,
parentId: parentId,
opener: aOpener,
opener: openerWindow,
selected: true,
isPrivate: isPrivate,
pinned: pinned });
@ -3314,13 +3313,13 @@ nsBrowserAccess.prototype = {
return browser;
},
openURI: function browser_openURI(aURI, aOpener, aWhere, aContext) {
let browser = this._getBrowser(aURI, aOpener, aWhere, aContext);
openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags) {
let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags);
return browser ? browser.contentWindow : null;
},
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aContext) {
let browser = this._getBrowser(aURI, null, aWhere, aContext);
openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags) {
let browser = this._getBrowser(aURI, null, aWhere, aFlags);
return browser ? browser.QueryInterface(Ci.nsIFrameLoaderOwner) : null;
},

View File

@ -141,7 +141,7 @@ nsWebHandlerApp.prototype = {
// openURI
browserDOMWin.openURI(uriToSend,
null, // no window.opener
null, // no window.opener
Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
Ci.nsIBrowserDOMWindow.OPEN_NEW);

View File

@ -781,6 +781,7 @@ nsContentTreeOwner::ProvideWindow(mozIDOMWindowProxy* aParent,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool aForceNoOpener,
bool* aWindowIsNew,
mozIDOMWindowProxy** aReturn)
{
@ -814,7 +815,7 @@ nsContentTreeOwner::ProvideWindow(mozIDOMWindowProxy* aParent,
BrowserElementParent::OpenWindowResult opened =
BrowserElementParent::OpenWindowInProcess(parent, aURI, aName,
aFeatures, aReturn);
aFeatures, aForceNoOpener, aReturn);
// If OpenWindowInProcess handled the open (by opening it or blocking the
// popup), tell our caller not to proceed trying to create a new window
@ -873,13 +874,19 @@ nsContentTreeOwner::ProvideWindow(mozIDOMWindowProxy* aParent,
{
dom::AutoNoJSAPI nojsapi;
uint32_t flags = nsIBrowserDOMWindow::OPEN_NEW;
if (aForceNoOpener) {
flags |= nsIBrowserDOMWindow::OPEN_NO_OPENER;
}
// Get a new rendering area from the browserDOMWin. We don't want
// to be starting any loads here, so get it with a null URI.
//
// This method handles setting the opener for us, so we don't need to set it
// ourselves.
return browserDOMWin->OpenURI(nullptr, aParent, openLocation,
nsIBrowserDOMWindow::OPEN_NEW, aReturn);
return browserDOMWin->OpenURI(nullptr, aParent,
openLocation,
flags, aReturn);
}
}