Bug 1357589: Part 1 - Use the correct default remote type for content-created tabs/windows. r=mconley r?mystor
When creating new windows/tabs from the content process, we currently choose
the default remote type based on the referrer URI, rather than the actual
remote type of the opener. While this generally works, it fails when opening
windows from URLs (particularly in iframes) which are opened in process types
other than their default process type, since the initial about:blank load gets
redirected to a new process before the child process has a chance to load its
actual target URI.
Using the actual remote type of the child opening the window fixes this
problem for URLs which are capable of being loaded into the child's process
type.
MozReview-Commit-ID: ClxVGxu52Lf
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5236,18 +5236,18 @@ var TabsProgressListener = {
function nsBrowserAccess() { }
nsBrowserAccess.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]),
_openURIInNewTab(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
aIsExternal, aForceNotRemote = false,
aUserContextId = Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID,
- aOpener = null, aTriggeringPrincipal = null,
- aNextTabParentId = 0, aName = "") {
+ aOpenerWindow = null, aOpenerBrowser = null,
+ aTriggeringPrincipal = null, aNextTabParentId = 0, aName = "") {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
if (window.toolbar.visible)
win = window;
else {
win = RecentWindow.getMostRecentBrowserWindow({private: aIsPrivate});
needToFocusWin = true;
@@ -5269,17 +5269,18 @@ nsBrowserAccess.prototype = {
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
triggeringPrincipal: aTriggeringPrincipal,
referrerURI: aReferrer,
referrerPolicy: aReferrerPolicy,
userContextId: aUserContextId,
fromExternal: aIsExternal,
inBackground: loadInBackground,
forceNotRemote: aForceNotRemote,
- opener: aOpener,
+ opener: aOpenerWindow,
+ openerBrowser: aOpenerBrowser,
nextTabParentId: aNextTabParentId,
name: aName,
});
let browser = win.gBrowser.getBrowserForTab(tab);
if (needToFocusWin || (!loadInBackground && aIsExternal))
win.focus();
@@ -5349,17 +5350,17 @@ nsBrowserAccess.prototype = {
let forceNotRemote = !!aOpener;
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,
- openerWindow, aTriggeringPrincipal);
+ openerWindow, null, aTriggeringPrincipal);
if (browser)
newWindow = browser.contentWindow;
break;
default : // OPEN_CURRENTWINDOW or an illegal value
newWindow = window.content;
if (aURI) {
let loadflags = isExternal ?
Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
@@ -5391,17 +5392,17 @@ nsBrowserAccess.prototype = {
? aParams.openerOriginAttributes.userContextId
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID
let referrer = aParams.referrer ? makeURI(aParams.referrer) : null;
let browser = this._openURIInNewTab(aURI, referrer,
aParams.referrerPolicy,
aParams.isPrivate,
isExternal, false,
- userContextId, null,
+ userContextId, null, aParams.opener,
aParams.triggeringPrincipal,
aNextTabParentId, aName);
if (browser)
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
return null;
},
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1609,16 +1609,17 @@
var aSkipAnimation;
var aForceNotRemote;
var aPreferredRemoteType;
var aNoReferrer;
var aUserContextId;
var aSameProcessAsFrameLoader;
var aOriginPrincipal;
var aOpener;
+ var aOpenerBrowser;
var aIsPrerendered;
var aCreateLazyBrowser;
var aNextTabParentId;
var aFocusUrlBar;
var aName;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@@ -1636,16 +1637,17 @@
aSkipAnimation = params.skipAnimation;
aForceNotRemote = params.forceNotRemote;
aPreferredRemoteType = params.preferredRemoteType;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aSameProcessAsFrameLoader = params.sameProcessAsFrameLoader;
aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
+ aOpenerBrowser = params.openerBrowser;
aIsPrerendered = params.isPrerendered;
aCreateLazyBrowser = params.createLazyBrowser;
aNextTabParentId = params.nextTabParentId;
aFocusUrlBar = params.focusUrlBar;
aName = params.name;
}
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
@@ -1667,16 +1669,17 @@
forceNotRemote: aForceNotRemote,
createLazyBrowser: aCreateLazyBrowser,
preferredRemoteType: aPreferredRemoteType,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
opener: aOpener,
+ openerBrowser: aOpenerBrowser,
isPrerendered: aIsPrerendered,
nextTabParentId: aNextTabParentId,
focusUrlBar: aFocusUrlBar,
name: aName });
if (!bgLoad)
this.selectedTab = tab;
return tab;
@@ -2103,17 +2106,17 @@
aParams.remoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
}
if (aParams.remoteType) {
b.setAttribute("remoteType", aParams.remoteType);
b.setAttribute("remote", "true");
}
- if (aParams.opener) {
+ if (aParams.openerWindow) {
if (aParams.remoteType) {
throw new Error("Cannot set opener window on a remote browser!");
}
b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener);
}
if (!aParams.isPreloadBrowser && this.hasAttribute("autocompletepopup")) {
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
@@ -2124,16 +2127,19 @@
if (this.hasAttribute("datetimepicker")) {
b.setAttribute("datetimepicker", this.getAttribute("datetimepicker"));
}
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
if (aParams.nextTabParentId) {
+ if (!aParams.remoteType) {
+ throw new Error("Cannot have nextTabParentId without a remoteType");
+ }
// Gecko is going to read this attribute and use it.
b.setAttribute("nextTabParentId", aParams.nextTabParentId.toString());
}
if (aParams.sameProcessAsFrameLoader) {
b.sameProcessAsFrameLoader = aParams.sameProcessAsFrameLoader;
}
@@ -2406,16 +2412,17 @@
var aPreferredRemoteType;
var aNoReferrer;
var aUserContextId;
var aEventDetail;
var aSameProcessAsFrameLoader;
var aOriginPrincipal;
var aDisallowInheritPrincipal;
var aOpener;
+ var aOpenerBrowser;
var aIsPrerendered;
var aCreateLazyBrowser;
var aSkipBackgroundNotify;
var aNextTabParentId;
var aNoInitialLabel;
var aFocusUrlBar;
var aName;
if (arguments.length == 2 &&
@@ -2437,16 +2444,17 @@
aPreferredRemoteType = params.preferredRemoteType;
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aEventDetail = params.eventDetail;
aSameProcessAsFrameLoader = params.sameProcessAsFrameLoader;
aOriginPrincipal = params.originPrincipal;
aDisallowInheritPrincipal = params.disallowInheritPrincipal;
aOpener = params.opener;
+ aOpenerBrowser = params.openerBrowser;
aIsPrerendered = params.isPrerendered;
aCreateLazyBrowser = params.createLazyBrowser;
aSkipBackgroundNotify = params.skipBackgroundNotify;
aNextTabParentId = params.nextTabParentId;
aNoInitialLabel = params.noInitialLabel;
aFocusUrlBar = params.focusUrlBar;
aName = params.name;
}
@@ -2532,16 +2540,22 @@
t.owner = aOwner;
var position = this.tabs.length - 1;
t._tPos = position;
this.tabContainer._setPositionalAttributes();
this.tabContainer.updateVisibility();
+ // If we don't have a preferred remote type, and we have a remote
+ // opener, use the opener's remote type.
+ if (!aPreferredRemoteType && aOpenerBrowser) {
+ aPreferredRemoteType = aOpenerBrowser.remoteType;
+ }
+
// If URI is about:blank and we don't have a preferred remote type,
// then we need to use the referrer, if we have one, to get the
// correct remote type for the new tab.
if (uriIsAboutBlank && !aPreferredRemoteType && aReferrerURI) {
aPreferredRemoteType =
E10SUtils.getRemoteTypeForURI(aReferrerURI.spec,
gMultiProcessBrowser);
}
@@ -2568,17 +2582,17 @@
}
if (!b) {
// No preloaded browser found, create one.
b = this._createBrowser({ remoteType,
uriIsAboutBlank,
userContextId: aUserContextId,
sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
- opener: aOpener,
+ openerWindow: aOpener,
isPrerendered: aIsPrerendered,
nextTabParentId: aNextTabParentId,
name: aName });
}
t.linkedBrowser = b;
if (aFocusUrlBar) {
--- a/dom/base/nsOpenURIInFrameParams.cpp
+++ b/dom/base/nsOpenURIInFrameParams.cpp
@@ -3,20 +3,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsOpenURIInFrameParams.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/ToJSValue.h"
-NS_IMPL_ISUPPORTS(nsOpenURIInFrameParams, nsIOpenURIInFrameParams)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsOpenURIInFrameParams)
+ NS_INTERFACE_MAP_ENTRY(nsIOpenURIInFrameParams)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION(nsOpenURIInFrameParams, mOpener)
-nsOpenURIInFrameParams::nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsOpenURIInFrameParams)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsOpenURIInFrameParams)
+
+nsOpenURIInFrameParams::nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes,
+ nsIFrameLoaderOwner* aOpener)
: mOpenerOriginAttributes(aOriginAttributes)
+ , mOpener(aOpener)
{
}
nsOpenURIInFrameParams::~nsOpenURIInFrameParams() {
}
NS_IMETHODIMP
nsOpenURIInFrameParams::GetReferrer(nsAString& aReferrer)
@@ -51,15 +61,23 @@ NS_IMETHODIMP
nsOpenURIInFrameParams::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
{
NS_ENSURE_TRUE(aTriggeringPrincipal, NS_ERROR_INVALID_ARG);
mTriggeringPrincipal = aTriggeringPrincipal;
return NS_OK;
}
NS_IMETHODIMP
+nsOpenURIInFrameParams::GetOpener(nsIFrameLoaderOwner** aOpener)
+{
+ nsCOMPtr<nsIFrameLoaderOwner> owner = mOpener;
+ owner.forget(aOpener);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsOpenURIInFrameParams::GetOpenerOriginAttributes(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue)
{
bool ok = ToJSValue(aCx, mOpenerOriginAttributes, aValue);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
return NS_OK;
}
--- a/dom/base/nsOpenURIInFrameParams.h
+++ b/dom/base/nsOpenURIInFrameParams.h
@@ -1,29 +1,34 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/BasePrincipal.h"
+#include "nsCycleCollectionParticipant.h"
#include "nsIBrowserDOMWindow.h"
+#include "nsIFrameLoader.h"
#include "nsString.h"
namespace mozilla {
class OriginAttributes;
}
class nsOpenURIInFrameParams final : public nsIOpenURIInFrameParams
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(nsOpenURIInFrameParams)
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIOPENURIINFRAMEPARAMS
- explicit nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes);
+ explicit nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes,
+ nsIFrameLoaderOwner* aOpener);
private:
~nsOpenURIInFrameParams();
mozilla::OriginAttributes mOpenerOriginAttributes;
+ nsCOMPtr<nsIFrameLoaderOwner> mOpener;
nsString mReferrer;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
};
--- a/dom/interfaces/base/nsIBrowserDOMWindow.idl
+++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl
@@ -13,16 +13,20 @@ interface nsIPrincipal;
[scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)]
interface nsIOpenURIInFrameParams : nsISupports
{
attribute DOMString referrer;
readonly attribute boolean isPrivate;
attribute nsIPrincipal triggeringPrincipal;
+ // The browser or frame element in the parent process which holds the
+ // opener window in the content process. May be null.
+ readonly attribute nsIFrameLoaderOwner opener;
+
[implicit_jscontext]
readonly attribute jsval openerOriginAttributes;
};
[scriptable, uuid(9d17f3dd-672b-451e-afd2-b1115df780d5)]
/**
* The C++ source has access to the browser script source through
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1102,42 +1102,44 @@ ContentParent::CreateBrowser(const TabCo
uint64_t aNextTabParentId)
{
AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
if (!sCanLaunchSubprocesses) {
return nullptr;
}
+ nsAutoString remoteType;
+ if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
+ remoteType)) {
+ remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
+ }
+
if (aNextTabParentId) {
if (TabParent* parent =
sNextTabParents.GetAndRemove(aNextTabParentId).valueOr(nullptr)) {
MOZ_ASSERT(!parent->GetOwnerElement(),
"Shouldn't have an owner elemnt before");
+ MOZ_ASSERT(remoteType == static_cast<ContentParent*>(parent->Manager())->GetRemoteType(),
+ "Browser remote type must match tab parent remote type");
parent->SetOwnerElement(aFrameElement);
return parent;
}
}
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
bool isInContentProcess = !XRE_IsParentProcess();
TabId tabId(nsContentUtils::GenerateTabId());
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
TabId openerTabId;
if (docShell) {
openerTabId = TabParent::GetTabIdFrom(docShell);
}
- nsAutoString remoteType;
- if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
- remoteType)) {
- remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
- }
-
RefPtr<nsIContentParent> constructorSender;
if (isInContentProcess) {
MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
constructorSender = CreateContentBridgeParent(aContext, initialPriority,
openerTabId, tabId);
} else {
if (aOpenerContentParent) {
constructorSender = aOpenerContentParent;
@@ -4538,18 +4540,23 @@ ContentParent::CommonCreateWindow(PBrows
}
if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
if (NS_WARN_IF(!browserDOMWin)) {
aResult = NS_ERROR_ABORT;
return IPC_OK();
}
+ nsCOMPtr<nsIFrameLoaderOwner> opener;
+ if (frame) {
+ opener = do_QueryInterface(frame);
+ }
+
nsCOMPtr<nsIOpenURIInFrameParams> params =
- new nsOpenURIInFrameParams(openerOriginAttributes);
+ new nsOpenURIInFrameParams(openerOriginAttributes, opener);
params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
params->SetTriggeringPrincipal(aTriggeringPrincipal);
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
aResult = browserDOMWin->OpenURIInFrame(aURIToLoad, params, openLocation,
nsIBrowserDOMWindow::OPEN_NEW,
aNextTabParentId, aName,