diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 50afc84eded1..578d0513582c 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -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) diff --git a/devtools/client/responsive.html/browser/tunnel.js b/devtools/client/responsive.html/browser/tunnel.js index 034b62ae8b18..aeff3d552448 100644 --- a/devtools/client/responsive.html/browser/tunnel.js +++ b/devtools/client/responsive.html/browser/tunnel.js @@ -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() { diff --git a/dom/base/nsHostObjectURI.cpp b/dom/base/nsHostObjectURI.cpp index 43d16ad5d25d..0d505c0efaef 100644 --- a/dom/base/nsHostObjectURI.cpp +++ b/dom/base/nsHostObjectURI.cpp @@ -8,6 +8,7 @@ #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" +#include "nsHostObjectProtocolHandler.h" #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/URIUtils.h" diff --git a/dom/browser-element/BrowserElementParent.cpp b/dom/browser-element/BrowserElementParent.cpp index 63f49b118aaf..fda9348fd1b1 100644 --- a/dom/browser-element/BrowserElementParent.cpp +++ b/dom/browser-element/BrowserElementParent.cpp @@ -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, diff --git a/dom/browser-element/BrowserElementParent.h b/dom/browser-element/BrowserElementParent.h index a5f5a886e98d..428884f97dbe 100644 --- a/dom/browser-element/BrowserElementParent.h +++ b/dom/browser-element/BrowserElementParent.h @@ -118,6 +118,7 @@ public: nsIURI* aURI, const nsAString& aName, const nsACString& aFeatures, + bool aForceNoOpener, mozIDOMWindowProxy** aReturnWindow); private: diff --git a/dom/interfaces/base/nsIBrowserDOMWindow.idl b/dom/interfaces/base/nsIBrowserDOMWindow.idl index 993e6ac0d28f..bc64bf783e64 100644 --- a/dom/interfaces/base/nsIBrowserDOMWindow.idl +++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl @@ -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. diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index f86b63ec0d56..585c5ccdf139 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -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 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); diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 776f884a630b..4838f0387cff 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -88,6 +88,7 @@ public: nsIURI* aURI, const nsAString& aName, const nsACString& aFeatures, + bool aForceNoOpener, bool* aWindowIsNew, mozIDOMWindowProxy** aReturn); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 68be990b0d2d..171f33da139b 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -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); } diff --git a/embedding/components/windowwatcher/nsWindowWatcher.cpp b/embedding/components/windowwatcher/nsWindowWatcher.cpp index 71d10c158d84..0b71b88fc6ce 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -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 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"); diff --git a/embedding/nsIWindowProvider.idl b/embedding/nsIWindowProvider.idl index 03797eb190e9..34c517312f45 100644 --- a/embedding/nsIWindowProvider.idl +++ b/embedding/nsIWindowProvider.idl @@ -98,5 +98,6 @@ interface nsIWindowProvider : nsISupports in nsIURI aURI, in AString aName, in AUTF8String aFeatures, + in boolean aForceNoOpener, out boolean aWindowIsNew); }; diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index b0e9b82d947c..7e2b9f131392 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -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; }, diff --git a/uriloader/exthandler/nsWebHandlerApp.js b/uriloader/exthandler/nsWebHandlerApp.js index 38dbcc870d03..65d600f5517d 100644 --- a/uriloader/exthandler/nsWebHandlerApp.js +++ b/uriloader/exthandler/nsWebHandlerApp.js @@ -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); diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index e0976f3ba44f..d5a537380428 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -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); } }