Bug 1303196 - Part 2: Connect the DocGroup and TabGroup objects to nsGlobalWindow and nsDocument, ensuring that Opener is set early enough that it is correct, r=smaug

MozReview-Commit-ID: 3rZfLw3dXkF
This commit is contained in:
Michael Layzell 2016-10-07 14:59:59 -04:00
Родитель cec7ed92f4
Коммит f9eea2d135
34 изменённых файлов: 500 добавлений и 139 удалений

Просмотреть файл

@ -4250,10 +4250,10 @@ var XULBrowserWindow = {
return initBrowser.frameLoader.tabParent;
},
forceInitialBrowserNonRemote: function() {
forceInitialBrowserNonRemote: function(aOpener) {
let initBrowser =
document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
gBrowser.updateBrowserRemoteness(initBrowser, false);
gBrowser.updateBrowserRemoteness(initBrowser, false, aOpener);
},
setDefaultStatus: function (status) {
@ -4901,7 +4901,8 @@ nsBrowserAccess.prototype = {
_openURIInNewTab: function(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
aIsExternal, aForceNotRemote=false,
aUserContextId=Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID) {
aUserContextId=Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID,
aOpener=null) {
let win, needToFocusWin;
// try the current window. if we're in a popup, fall back on the most recent browser window
@ -4931,7 +4932,9 @@ nsBrowserAccess.prototype = {
userContextId: aUserContextId,
fromExternal: aIsExternal,
inBackground: loadInBackground,
forceNotRemote: aForceNotRemote});
forceNotRemote: aForceNotRemote,
opener: aOpener,
});
let browser = win.gBrowser.getBrowserForTab(tab);
if (needToFocusWin || (!loadInBackground && aIsExternal))
@ -5006,7 +5009,8 @@ nsBrowserAccess.prototype = {
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
isPrivate, isExternal,
forceNotRemote, userContextId);
forceNotRemote, userContextId,
aOpener);
if (browser)
newWindow = browser.contentWindow;
break;

Просмотреть файл

@ -1503,6 +1503,7 @@
var aUserContextId;
var aRelatedBrowser;
var aOriginPrincipal;
var aOpener;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@ -1522,6 +1523,7 @@
aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
}
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
@ -1542,7 +1544,8 @@
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
relatedBrowser: aRelatedBrowser });
relatedBrowser: aRelatedBrowser,
opener: aOpener });
if (!bgLoad)
this.selectedTab = tab;
@ -1655,11 +1658,27 @@
<method name="updateBrowserRemoteness">
<parameter name="aBrowser"/>
<parameter name="aShouldBeRemote"/>
<parameter name="aOpener"/>
<body>
<![CDATA[
let isRemote = aBrowser.getAttribute("remote") == "true";
if (isRemote == aShouldBeRemote)
// If we are passed an opener, we must be making the browser non-remote, and
// if the browser is _currently_ non-remote, we need the openers to match,
// because it is already too late to change it.
if (aOpener) {
if (aShouldBeRemote) {
throw new Exception("Cannot set an opener on a browser which should be remote!");
}
if (!isRemote && aBrowser.contentWindow.opener != aOpener) {
throw new Exception("Cannot change opener on an already non-remote browser!");
}
}
// Abort if we're not going to change anything
if (isRemote == aShouldBeRemote) {
return false;
}
let tab = this.getTabForBrowser(aBrowser);
let evt = document.createEvent("Events");
@ -1700,6 +1719,10 @@
// turns this normal property into a field.
aBrowser.relatedBrowser = relatedBrowser;
// Set the opener window on the browser, such that when the frame
// loader is created the opener is set correctly.
aBrowser.presetOpenerWindow(aOpener);
parent.appendChild(aBrowser);
aBrowser.userTypedValue = oldUserTypedValue;
@ -1881,6 +1904,13 @@
b.setAttribute("remote", "true");
}
if (aParams.opener) {
if (aParams.remote) {
throw new Exception("Cannot set opener window on a remote browser!");
}
b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener);
}
if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
b.setAttribute("showresizer", "true");
}
@ -1981,7 +2011,8 @@
remote: remote,
uriIsAboutBlank: uriIsAboutBlank,
userContextId: aParams.userContextId,
relatedBrowser: aParams.relatedBrowser});
relatedBrowser: aParams.relatedBrowser,
opener: aParams.opener});
}
let notificationbox = this.getNotificationBox(browser);
@ -2057,6 +2088,7 @@
var aEventDetail;
var aRelatedBrowser;
var aOriginPrincipal;
var aOpener;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@ -2077,6 +2109,7 @@
aEventDetail = params.eventDetail;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
}
// if we're adding tabs, we're past interrupt mode, ditch the owner
@ -2144,7 +2177,8 @@
let browserParams = {
forceNotRemote: aForceNotRemote,
userContextId: aUserContextId,
relatedBrowser: aRelatedBrowser
relatedBrowser: aRelatedBrowser,
opener: aOpener,
};
let { usingPreloadedContent } = this._linkBrowserToTab(t, aURI, browserParams);
let b = t.linkedBrowser;

Просмотреть файл

@ -31,6 +31,7 @@
#include "mozilla/Unused.h"
#include "Navigator.h"
#include "URIUtils.h"
#include "mozilla/dom/DocGroup.h"
#include "nsIContent.h"
#include "nsIContentInlines.h"

Просмотреть файл

@ -252,6 +252,8 @@
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/DocLoadingTimelineMarker.h"
#include "nsISpeculativeConnect.h"
@ -1362,6 +1364,10 @@ nsIDocument::~nsIDocument()
mNodeInfoManager->DropDocumentReference();
}
if (mDocGroup) {
mDocGroup->RemoveDocument(this);
}
UnlinkOriginalDocumentIfStatic();
}
@ -2848,6 +2854,36 @@ nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
}
}
mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
#ifdef DEBUG
// Validate that the docgroup is set correctly by calling its getter and
// triggering its sanity check.
//
// If we're setting the principal to null, we don't want to perform the check,
// as the document is entering an intermediate state where it does not have a
// principal. It will be given another real principal shortly which we will
// check. It's not unsafe to have a document which has a null principal in the
// same docgroup as another document, so this should not be a problem.
if (aNewPrincipal) {
GetDocGroup();
}
#endif
}
mozilla::dom::DocGroup*
nsIDocument::GetDocGroup()
{
#ifdef DEBUG
// Sanity check that we have an up-to-date and accurate docgroup
if (mDocGroup) {
nsAutoCString docGroupKey;
mozilla::dom::DocGroup::GetKey(NodePrincipal(), docGroupKey);
MOZ_ASSERT(mDocGroup->MatchesKey(docGroupKey));
// XXX: Check that the TabGroup is correct as well!
}
#endif
return mDocGroup;
}
NS_IMETHODIMP
@ -4254,6 +4290,23 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
mScopeObject = do_GetWeakReference(aGlobal);
if (aGlobal) {
mHasHadScriptHandlingObject = true;
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
if (window) {
// We want to get the tabgroup unconditionally, such that we can make
// certain that it is cached in the inner window early enough.
mozilla::dom::TabGroup* tabgroup = nsGlobalWindow::Cast(window)->TabGroup();
// We should already have the principal, and now that we have been added to a
// window, we should be able to join a DocGroup!
nsAutoCString docGroupKey;
mozilla::dom::DocGroup::GetKey(NodePrincipal(), docGroupKey);
if (mDocGroup) {
MOZ_RELEASE_ASSERT(mDocGroup->MatchesKey(docGroupKey));
} else {
mDocGroup = tabgroup->AddDocument(docGroupKey, this);
MOZ_ASSERT(mDocGroup);
}
}
}
}
@ -4442,11 +4495,10 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
mScriptGlobalObject = aScriptGlobalObject;
if (aScriptGlobalObject) {
mHasHadScriptHandlingObject = true;
mHasHadDefaultView = true;
// Go back to using the docshell for the layout history state
mLayoutHistoryState = nullptr;
mScopeObject = do_GetWeakReference(aScriptGlobalObject);
SetScopeObject(aScriptGlobalObject);
mHasHadDefaultView = true;
#ifdef DEBUG
if (!mWillReparent) {
// We really shouldn't have a wrapper here but if we do we need to make sure
@ -4583,8 +4635,7 @@ nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
mScriptGlobalObject == aScriptObject,
"Wrong script object!");
if (aScriptObject) {
mScopeObject = do_GetWeakReference(aScriptObject);
mHasHadScriptHandlingObject = true;
SetScopeObject(aScriptObject);
mHasHadDefaultView = false;
}
}

Просмотреть файл

@ -81,6 +81,7 @@
#include "nsAboutProtocolUtils.h"
#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
#include "PostMessageEvent.h"
#include "DocGroup.h"
// Interfaces Needed
#include "nsIFrame.h"
@ -1226,9 +1227,10 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mCleanedUp(false),
mDialogAbuseCount(0),
mAreDialogsEnabled(true),
mCanSkipCCGeneration(0),
mStaticConstellation(0),
mConstellation(NullCString())
#ifdef DEBUG
mIsValidatingTabGroup(false),
#endif
mCanSkipCCGeneration(0)
{
AssertIsOnMainThread();
@ -1262,11 +1264,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
// |this| is an outer window. Outer windows start out frozen and
// remain frozen until they get an inner window.
MOZ_ASSERT(IsFrozen());
// As an outer window, we may be the root of a constellation. This initial
// static constellation may be overridden as this window is given a parent
// window or an opener.
mStaticConstellation = WindowID();
}
// We could have failed the first time through trying
@ -1430,6 +1427,11 @@ nsGlobalWindow::~nsGlobalWindow()
}
}
// We don't have to leave the tab group if we are an inner window.
if (mTabGroup && IsOuterWindow()) {
mTabGroup->Leave(AsOuter());
}
// Outer windows are always supposed to call CleanUp before letting themselves
// be destroyed. And while CleanUp generally seems to be intended to clean up
// outers, we've historically called it for both. Changing this would probably
@ -2856,6 +2858,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
aDocument->SetScriptGlobalObject(newInnerWindow);
MOZ_ASSERT(newInnerWindow->mTabGroup,
"We must have a TabGroup cached at this point");
if (!aState) {
if (reUseInnerWindow) {
@ -3032,11 +3036,8 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
mDocShell = aDocShell; // Weak Reference
// Copy over the static constellation from our new parent.
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetParent();
if (parentWindow) {
mStaticConstellation = Cast(parentWindow)->mStaticConstellation;
}
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup || mTabGroup == Cast(parentWindow)->mTabGroup);
NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
@ -3141,19 +3142,24 @@ nsGlobalWindow::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
{
FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
nsWeakPtr opener = do_GetWeakReference(aOpener);
if (opener == mOpener) {
return;
}
NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
"aOriginalOpener is true, but not first call to "
"SetOpenerWindow!");
NS_ASSERTION(aOpener || !aOriginalOpener,
"Shouldn't set mHadOriginalOpener if aOpener is null");
mOpener = do_GetWeakReference(aOpener);
mOpener = opener.forget();
NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!");
// Copy over the static constellation from our new opener
if (aOpener) {
mStaticConstellation = Cast(aOpener)->mStaticConstellation;
}
// Check that the js visible opener matches!
nsPIDOMWindowOuter* contentOpener = GetSanitizedOpener(aOpener);
MOZ_RELEASE_ASSERT(!contentOpener || !mTabGroup ||
mTabGroup == Cast(contentOpener)->mTabGroup);
if (aOriginalOpener) {
MOZ_ASSERT(!mHadOriginalOpener,
@ -4726,26 +4732,13 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult)
}
nsPIDOMWindowOuter*
nsGlobalWindow::GetOpenerWindowOuter()
nsGlobalWindow::GetSanitizedOpener(nsPIDOMWindowOuter* aOpener)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
if (!opener) {
if (!aOpener) {
return nullptr;
}
nsGlobalWindow* win = nsGlobalWindow::Cast(opener);
// First, check if we were called from a privileged chrome script
if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
// Catch the case where we're chrome but the opener is not...
if (GetPrincipal() == nsContentUtils::GetSystemPrincipal() &&
win->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
return nullptr;
}
return opener;
}
nsGlobalWindow* win = nsGlobalWindow::Cast(aOpener);
// First, ensure that we're not handing back a chrome window to content:
if (win->IsChromeWindow()) {
@ -4755,7 +4748,7 @@ nsGlobalWindow::GetOpenerWindowOuter()
// We don't want to reveal the opener if the opener is a mail window,
// because opener can be used to spoof the contents of a message (bug 105050).
// So, we look in the opener's root docshell to see if it's a mail window.
nsCOMPtr<nsIDocShell> openerDocShell = opener->GetDocShell();
nsCOMPtr<nsIDocShell> openerDocShell = aOpener->GetDocShell();
if (openerDocShell) {
nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
@ -4765,7 +4758,7 @@ nsGlobalWindow::GetOpenerWindowOuter()
uint32_t appType;
nsresult rv = openerRootDocShell->GetAppType(&appType);
if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
return opener;
return aOpener;
}
}
}
@ -4773,6 +4766,30 @@ nsGlobalWindow::GetOpenerWindowOuter()
return nullptr;
}
nsPIDOMWindowOuter*
nsGlobalWindow::GetOpenerWindowOuter()
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
if (!opener) {
return nullptr;
}
// First, check if we were called from a privileged chrome script
if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
// Catch the case where we're chrome but the opener is not...
if (GetPrincipal() == nsContentUtils::GetSystemPrincipal() &&
nsGlobalWindow::Cast(opener)->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
return nullptr;
}
return opener;
}
return GetSanitizedOpener(opener);
}
nsPIDOMWindowOuter*
nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
{
@ -4797,11 +4814,9 @@ nsGlobalWindow::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
already_AddRefed<nsPIDOMWindowOuter>
nsGlobalWindow::GetOpener()
{
FORWARD_TO_INNER(GetOpener, (), nullptr);
FORWARD_TO_OUTER(GetOpener, (), nullptr);
ErrorResult dummy;
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(dummy);
dummy.SuppressException();
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindowOuter();
return opener.forget();
}
@ -13627,6 +13642,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -13640,6 +13656,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
}
tmp->DisconnectAndClearGroupMessageManagers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
// QueryInterface implementation for nsGlobalChromeWindow
@ -14110,6 +14127,24 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
return messageManager;
}
nsresult
nsGlobalChromeWindow::SetOpenerForInitialContentBrowser(mozIDOMWindowProxy* aOpenerWindow)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(!mOpenerForInitialContentBrowser);
mOpenerForInitialContentBrowser = aOpenerWindow;
return NS_OK;
}
nsresult
nsGlobalChromeWindow::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aOpenerWindow)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
// Intentionally forget our own member
mOpenerForInitialContentBrowser.forget(aOpenerWindow);
return NS_OK;
}
// nsGlobalModalWindow implementation
// QueryInterface implementation for nsGlobalModalWindow
@ -14593,44 +14628,105 @@ nsGlobalWindow::CheckForDPIChange()
}
}
void
nsGlobalWindow::GetConstellation(nsACString& aConstellation)
mozilla::dom::TabGroup*
nsGlobalWindow::TabGroupOuter()
{
FORWARD_TO_INNER_VOID(GetConstellation, (aConstellation));
MOZ_RELEASE_ASSERT(IsOuterWindow());
// This method is valid both on inner and outer windows, which is a
// Outer windows lazily join TabGroups when requested. This is usually done
// because a document is getting its NodePrincipal, and asking for the
// TabGroup to determine its DocGroup.
if (!mTabGroup) {
// Get mOpener ourselves, instead of relying on GetOpenerWindowOuter,
// because that way we dodge the LegacyIsCallerChromeOrNativeCode() call
// which we want to return false.
nsCOMPtr<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
nsGlobalWindow* opener = Cast(GetSanitizedOpener(piOpener));
nsGlobalWindow* parent = Cast(GetScriptableParentOrNull());
MOZ_ASSERT(!parent || !opener, "Only one of parent and opener may be provided");
mozilla::dom::TabGroup* toJoin = nullptr;
if (GetDocShell()->ItemType() == nsIDocShellTreeItem::typeChrome) {
toJoin = TabGroup::GetChromeTabGroup();
} else if (opener) {
toJoin = opener->TabGroup();
} else if (parent) {
toJoin = parent->TabGroup();
}
mTabGroup = mozilla::dom::TabGroup::Join(AsOuter(), toJoin);
}
MOZ_ASSERT(mTabGroup);
#ifdef DEBUG
RefPtr<nsGlobalWindow> outer = GetOuterWindowInternal();
MOZ_ASSERT(outer, "We should have an outer window");
RefPtr<nsGlobalWindow> top = outer->GetTopInternal();
RefPtr<nsPIDOMWindowOuter> opener = outer->GetOpener();
MOZ_ASSERT(!top || (top->mStaticConstellation ==
outer->mStaticConstellation));
MOZ_ASSERT(!opener || (Cast(opener)->mStaticConstellation ==
outer->mStaticConstellation));
// Ensure that we don't recurse forever
if (!mIsValidatingTabGroup) {
mIsValidatingTabGroup = true;
// We only need to do this check if we aren't in the chrome tab group
if (GetDocShell()->ItemType() == nsIDocShellTreeItem::typeChrome) {
MOZ_ASSERT(mTabGroup == TabGroup::GetChromeTabGroup());
} else {
// Sanity check that our tabgroup matches our opener or parent.
RefPtr<nsPIDOMWindowOuter> parent = GetScriptableParentOrNull();
MOZ_ASSERT_IF(parent, Cast(parent)->TabGroup() == mTabGroup);
nsCOMPtr<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
nsGlobalWindow* opener = Cast(GetSanitizedOpener(piOpener));
MOZ_ASSERT_IF(opener && opener != this, opener->TabGroup() == mTabGroup);
}
mIsValidatingTabGroup = false;
}
#endif
if (mConstellation.IsVoid()) {
mConstellation.Truncate();
// The dynamic constellation part comes from the eTLD+1 for the principal's URI.
nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
nsCOMPtr<nsIURI> uri;
nsresult rv = principal->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
if (tldService) {
rv = tldService->GetBaseDomain(uri, 0, mConstellation);
if (NS_FAILED(rv)) {
mConstellation.Truncate();
}
}
}
return mTabGroup;
}
// Get the static constellation from the outer window object.
mConstellation.AppendPrintf("^%llu", GetOuterWindowInternal()->mStaticConstellation);
mozilla::dom::TabGroup*
nsGlobalWindow::TabGroupInner()
{
MOZ_RELEASE_ASSERT(IsInnerWindow());
// If we don't have a TabGroup yet, try to get it from the outer window and
// cache it.
if (!mTabGroup) {
nsGlobalWindow* outer = GetOuterWindowInternal();
// This will never be called without either an outer window, or a cached tab group.
// This is because of the following:
// * This method is only called on inner windows
// * This method is called as a document is attached to it's script global
// by the document
// * Inner windows are created in nsGlobalWindow::SetNewDocument, which
// immediately sets a document, which will call this method, causing
// the TabGroup to be cached.
MOZ_RELEASE_ASSERT(outer, "Inner window without outer window has no cached tab group!");
mTabGroup = outer->TabGroup();
}
MOZ_ASSERT(mTabGroup);
aConstellation.Assign(mConstellation);
#ifdef DEBUG
nsGlobalWindow* outer = GetOuterWindowInternal();
MOZ_ASSERT_IF(outer, outer->TabGroup() == mTabGroup);
#endif
return mTabGroup;
}
mozilla::dom::TabGroup*
nsGlobalWindow::TabGroup()
{
if (IsInnerWindow()) {
return TabGroupInner();
}
return TabGroupOuter();
}
mozilla::dom::DocGroup*
nsGlobalWindow::GetDocGroup()
{
nsIDocument* doc = GetExtantDoc();
if (doc) {
return doc->GetDocGroup();
}
return nullptr;
}
nsGlobalWindow::TemporarilyDisableDialogs::TemporarilyDisableDialogs(

Просмотреть файл

@ -86,6 +86,7 @@ class nsIJSID;
class nsIScriptContext;
class nsIScriptTimeoutHandler;
class nsIWebBrowserChrome;
class mozIDOMWindowProxy;
class nsDOMWindowList;
class nsScreen;
@ -106,6 +107,7 @@ struct ChannelPixelLayout;
class Console;
class Crypto;
class CustomElementRegistry;
class DocGroup;
class External;
class Function;
class Gamepad;
@ -121,6 +123,7 @@ struct RequestInit;
class RequestOrUSVString;
class Selection;
class SpeechSynthesis;
class TabGroup;
class U2F;
class VRDisplay;
class VREventObserver;
@ -920,6 +923,9 @@ protected:
// Initializes the mWasOffline member variable
void InitWasOffline();
public:
nsPIDOMWindowOuter*
GetSanitizedOpener(nsPIDOMWindowOuter* aOpener);
nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aError);
@ -1739,9 +1745,12 @@ private:
// IsSecureContext() for the inner window that corresponds to aDocument.
bool ComputeIsSecureContext(nsIDocument* aDocument);
public:
mozilla::dom::TabGroup* TabGroupInner();
mozilla::dom::TabGroup* TabGroupOuter();
void GetConstellation(nsACString& aConstellation);
public:
mozilla::dom::TabGroup* TabGroup();
mozilla::dom::DocGroup* GetDocGroup();
protected:
// These members are only used on outer window objects. Make sure
@ -1946,6 +1955,13 @@ protected:
RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
#endif
RefPtr<mozilla::dom::TabGroup> mTabGroup; // Outer window only
#ifdef DEBUG
// This member is used in the debug only assertions in TabGroup()
// to catch cyclic parent/opener trees and not overflow the stack.
bool mIsValidatingTabGroup;
#endif
// This is the CC generation the last time we called CanSkip.
uint32_t mCanSkipCCGeneration;
@ -1954,9 +1970,6 @@ protected:
nsAutoPtr<mozilla::dom::VREventObserver> mVREventObserver;
uint64_t mStaticConstellation; // Only used on outer windows
nsCString mConstellation; // Only used on inner windows
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class mozilla::dom::PostMessageEvent;
@ -2053,6 +2066,7 @@ public:
// The pointer being set indicates we've set the IsInFullscreenChange
// flag on this pres shell.
nsWeakPtr mFullscreenPresShell;
nsCOMPtr<mozIDOMWindowProxy> mOpenerForInitialContentBrowser;
};
/*

Просмотреть файл

@ -123,6 +123,7 @@ class BoxObject;
class CDATASection;
class Comment;
struct CustomElementDefinition;
class DocGroup;
class DocumentFragment;
class DocumentTimeline;
class DocumentType;
@ -2849,11 +2850,13 @@ public:
mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
virtual void RemoveIntersectionObserver(
mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
virtual void UpdateIntersectionObservations() = 0;
virtual void ScheduleIntersectionObserverNotification() = 0;
virtual void NotifyIntersectionObservers() = 0;
mozilla::dom::DocGroup* GetDocGroup();
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
{
@ -3310,6 +3313,8 @@ protected:
bool mUserHasInteracted;
mozilla::TimeStamp mPageUnloadingEventTimeStamp;
RefPtr<mozilla::dom::DocGroup> mDocGroup;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)

Просмотреть файл

@ -1258,6 +1258,12 @@ nsObjectLoadingContent::GetParentApplication(mozIApplication** aApplication)
return NS_OK;
}
void
nsObjectLoadingContent::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, mozilla::ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_FAILURE);
}
NS_IMETHODIMP
nsObjectLoadingContent::SetIsPrerendered()
{

Просмотреть файл

@ -256,6 +256,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
return mRewrittenYoutubeEmbed;
}
void PresetOpenerWindow(mozIDOMWindowProxy* aOpenerWindow, mozilla::ErrorResult& aRv);
protected:
/**
* Begins loading the object when called

Просмотреть файл

@ -283,6 +283,10 @@ BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow,
aURI->GetSpec(spec);
}
ErrorResult res;
popupFrameElement->PresetOpenerWindow(aOpenerWindow, res);
MOZ_ASSERT(!res.Failed());
OpenWindowResult opened =
DispatchOpenWindowEvent(openerFrameElement, popupFrameElement,
NS_ConvertUTF8toUTF16(spec),

Просмотреть файл

@ -36,6 +36,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAudioChannels)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -47,6 +48,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGenericHTMLFrameElement,
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAudioChannels)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -153,6 +155,15 @@ nsGenericHTMLFrameElement::EnsureFrameLoader()
if (mIsPrerendered) {
mFrameLoader->SetIsPrerendered();
}
if (mOpenerWindow) {
nsCOMPtr<nsIDocShell> docShell;
mFrameLoader->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsPIDOMWindowOuter> outerWindow = docShell->GetWindow();
outerWindow->SetOpenerWindow(nsPIDOMWindowOuter::From(mOpenerWindow), true);
mOpenerWindow = nullptr;
}
}
}
nsresult
@ -212,6 +223,13 @@ nsGenericHTMLFrameElement::GetParentApplication(mozIApplication** aApplication)
return NS_OK;
}
void
nsGenericHTMLFrameElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
{
MOZ_ASSERT(!mFrameLoader);
mOpenerWindow = nsPIDOMWindowOuter::From(aWindow);
}
void
nsGenericHTMLFrameElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner,
ErrorResult& rv)

Просмотреть файл

@ -83,6 +83,9 @@ public:
void SwapFrameLoaders(RefPtr<nsFrameLoader>& aOtherLoader,
mozilla::ErrorResult& rv);
void PresetOpenerWindow(mozIDOMWindowProxy* aOpenerWindow,
mozilla::ErrorResult& aRv);
static bool BrowserFramesEnabled();
/**
@ -107,6 +110,7 @@ protected:
already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
RefPtr<nsFrameLoader> mFrameLoader;
nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow;
/**
* True when the element is created by the parser using the

Просмотреть файл

@ -9,6 +9,7 @@ interface nsIBrowserDOMWindow;
interface nsIDOMElement;
interface nsIDOMEvent;
interface nsIMessageBroadcaster;
interface mozIDOMWindowProxy;
[scriptable, uuid(78bdcb41-1efa-409f-aaba-70842213f80f)]
interface nsIDOMChromeWindow : nsISupports
@ -63,4 +64,18 @@ interface nsIDOMChromeWindow : nsISupports
* doesn't support this.
*/
void beginWindowMove(in nsIDOMEvent mouseDownEvent, [optional] in nsIDOMElement panel);
/**
* These methods provide a way to specify the opener value for the content in
* the window before the content itself is created. This is important in order
* to set the DocGroup of a document, as the opener must be set before the
* document is created.
*
* SetOpenerForInitialContentBrowser is used to set which opener will be used,
* and TakeOpenerForInitialContentBrowser is used by nsXULElement in order to
* take the value set earlier, and null out the value in the
* nsIDOMChromeWindow.
*/
void setOpenerForInitialContentBrowser(in mozIDOMWindowProxy aOpener);
mozIDOMWindowProxy takeOpenerForInitialContentBrowser();
};

Просмотреть файл

@ -826,6 +826,17 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
aTabOpener->mDefaultScale);
}
// Set the opener window for this window before we start loading the document
// inside of it. We have to do this before loading the remote scripts, because
// 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) {
nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(windowProxy);
nsPIDOMWindowOuter* parent = nsPIDOMWindowOuter::From(aParent);
outer->SetOpenerWindow(parent, *aWindowIsNew);
}
// Unfortunately we don't get a window unless we've shown the frame. That's
// pretty bogus; see bug 763602.
newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame,

Просмотреть файл

@ -125,6 +125,9 @@ interface MozFrameLoaderOwner {
[ChromeOnly]
void setIsPrerendered();
[ChromeOnly, Throws]
void presetOpenerWindow(WindowProxy? window);
[ChromeOnly, Throws]
void swapFrameLoaders(XULElement aOtherLoaderOwner);

Просмотреть файл

@ -128,12 +128,6 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
return rv;
}
if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
d->SetScriptHandlingObject(sgo);
} else if (aEventObject){
d->SetScopeObject(aEventObject);
}
if (isHTML) {
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
@ -147,6 +141,14 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
doc->SetPrincipal(aPrincipal);
doc->SetBaseURI(aBaseURI);
// We need to set the script handling object after we set the principal such
// that the doc group is assigned correctly.
if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
d->SetScriptHandlingObject(sgo);
} else if (aEventObject){
d->SetScopeObject(aEventObject);
}
// XMLDocuments and documents "created in memory" get to be UTF-8 by default,
// unlike the legacy HTML mess
doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8"));

Просмотреть файл

@ -803,7 +803,6 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID
nsIScriptGlobalObject* sgo =
source->GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(sgo || !hasHadScriptObject);
mDocument->SetScriptHandlingObject(sgo);
mCurrentNode = mDocument;
mNodeInfoManager = mDocument->NodeInfoManager();
@ -811,6 +810,10 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID
// Reset and set up the document
URIUtils::ResetWithSource(mDocument, aSourceDocument);
// Make sure we set the script handling object after resetting with the
// source, so that we have the right principal.
mDocument->SetScriptHandlingObject(sgo);
// Set the charset
if (!mOutputFormat.mEncoding.IsEmpty()) {
nsAutoCString canonicalCharset;

Просмотреть файл

@ -95,6 +95,7 @@
#include "nsIController.h"
#include "nsQueryObject.h"
#include <algorithm>
#include "nsIDOMChromeWindow.h"
// The XUL doc interface
#include "nsIDOMXULDocument.h"
@ -191,6 +192,8 @@ nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoader");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIFrameLoader*, mFrameLoader));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mOpener");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(mozIDOMWindowProxy*, mOpener));
}
nsINode::nsSlots*
@ -1585,6 +1588,30 @@ nsXULElement::LoadSrc()
slots->mFrameLoader = nsFrameLoader::Create(this, false);
NS_ENSURE_TRUE(slots->mFrameLoader, NS_OK);
nsCOMPtr<nsPIDOMWindowOuter> opener;
if (slots->mOpener) {
opener = nsPIDOMWindowOuter::From(slots->mOpener);
slots->mOpener = nullptr;
} else {
// If we are a content-primary xul-browser, we want to take the opener property!
nsCOMPtr<nsIDOMChromeWindow> chromeWindow = do_QueryInterface(OwnerDoc()->GetWindow());
if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("content-primary"), eIgnoreCase) &&
chromeWindow) {
nsCOMPtr<mozIDOMWindowProxy> wp;
chromeWindow->TakeOpenerForInitialContentBrowser(getter_AddRefs(wp));
opener = nsPIDOMWindowOuter::From(wp);
}
}
if (opener) {
nsCOMPtr<nsIDocShell> docShell;
nsresult rv = slots->mFrameLoader->GetDocShell(getter_AddRefs(docShell));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMWindowOuter> outerWindow = docShell->GetWindow();
outerWindow->SetOpenerWindow(opener, true);
}
(new AsyncEventDispatcher(this,
NS_LITERAL_STRING("XULFrameLoaderCreated"),
/* aBubbles */ true))->RunDOMEventWhenSafe();
@ -1628,6 +1655,15 @@ nsXULElement::GetParentApplication(mozIApplication** aApplication)
return NS_OK;
}
void
nsXULElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
{
nsXULSlots* slots = static_cast<nsXULSlots*>(Slots());
MOZ_ASSERT(!slots->mFrameLoader, "Cannot SetOpenerWindow when a frame loader is present");
slots->mOpener = aWindow;
}
nsresult
nsXULElement::SetIsPrerendered()
{

Просмотреть файл

@ -412,6 +412,7 @@ public:
nsresult GetFrameLoaderXPCOM(nsIFrameLoader** aFrameLoader);
nsresult GetParentApplication(mozIApplication** aApplication);
void PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv);
nsresult SetIsPrerendered();
virtual void RecompileScriptEventListeners() override;
@ -616,6 +617,7 @@ protected:
void Traverse(nsCycleCollectionTraversalCallback &cb);
RefPtr<nsFrameLoader> mFrameLoader;
nsCOMPtr<mozIDOMWindowProxy> mOpener;
};
virtual nsINode::nsSlots* CreateSlots() override;

Просмотреть файл

@ -65,8 +65,10 @@
#include "mozilla/dom/DOMStorage.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/dom/DocGroup.h"
#include "nsIXULWindow.h"
#include "nsIXULBrowserWindow.h"
#include "nsGlobalWindow.h"
#ifdef USEWEAKREFS
#include "nsIWeakReference.h"
@ -483,6 +485,7 @@ nsWindowWatcher::CreateChromeWindow(const nsACString& aFeatures,
uint32_t aChromeFlags,
uint32_t aContextFlags,
nsITabParent* aOpeningTabParent,
mozIDOMWindowProxy* aOpener,
nsIWebBrowserChrome** aResult)
{
nsCOMPtr<nsIWindowCreator2> windowCreator2(do_QueryInterface(mWindowCreator));
@ -501,7 +504,7 @@ nsWindowWatcher::CreateChromeWindow(const nsACString& aFeatures,
nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
nsresult rv =
windowCreator2->CreateChromeWindow2(aParentChrome, aChromeFlags, aContextFlags,
aOpeningTabParent, &cancel,
aOpeningTabParent, aOpener, &cancel,
getter_AddRefs(newWindowChrome));
if (NS_SUCCEEDED(rv) && cancel) {
@ -621,7 +624,7 @@ nsWindowWatcher::OpenWindowWithTabParent(nsITabParent* aOpeningTabParent,
nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
CreateChromeWindow(aFeatures, parentChrome, chromeFlags, contextFlags,
aOpeningTabParent, getter_AddRefs(newWindowChrome));
aOpeningTabParent, nullptr, getter_AddRefs(newWindowChrome));
if (NS_WARN_IF(!newWindowChrome)) {
return NS_ERROR_UNEXPECTED;
@ -996,7 +999,7 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
}
rv = CreateChromeWindow(features, parentChrome, chromeFlags, contextFlags,
nullptr, getter_AddRefs(newChrome));
nullptr, aParent, getter_AddRefs(newChrome));
} else {
rv = mWindowCreator->CreateChromeWindow(parentChrome, chromeFlags,
@ -1009,7 +1012,8 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
if (xulBrowserWin) {
xulBrowserWin->ForceInitialBrowserNonRemote();
nsPIDOMWindowOuter* openerWindow = aForceNoOpener ? nullptr : parentWindow;
xulBrowserWin->ForceInitialBrowserNonRemote(openerWindow);
}
}
/* It might be a chrome nsXULWindow, in which case it won't have
@ -2182,28 +2186,30 @@ nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
*aOpenedWindow = 0;
nsCOMPtr<nsPIDOMWindowOuter> piOpenedWindow = aOpenedItem->GetWindow();
if (piOpenedWindow) {
if (aParent) {
if (!aForceNoOpener) {
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
}
if (!aForceNoOpener) {
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
} else if (aParent) {
MOZ_ASSERT(nsGlobalWindow::Cast(piOpenedWindow)->TabGroup() !=
nsGlobalWindow::Cast(aParent)->TabGroup(),
"If we're forcing no opener, they should be in different tab groups");
}
if (aWindowIsNew) {
if (aWindowIsNew) {
#ifdef DEBUG
// Assert that we're not loading things right now. If we are, when
// that load completes it will clobber whatever principals we set up
// on this new window!
nsCOMPtr<nsIDocumentLoader> docloader = do_QueryInterface(aOpenedItem);
NS_ASSERTION(docloader, "How can we not have a docloader here?");
// Assert that we're not loading things right now. If we are, when
// that load completes it will clobber whatever principals we set up
// on this new window!
nsCOMPtr<nsIDocumentLoader> docloader = do_QueryInterface(aOpenedItem);
NS_ASSERTION(docloader, "How can we not have a docloader here?");
nsCOMPtr<nsIChannel> chan;
docloader->GetDocumentChannel(getter_AddRefs(chan));
NS_ASSERTION(!chan, "Why is there a document channel?");
nsCOMPtr<nsIChannel> chan;
docloader->GetDocumentChannel(getter_AddRefs(chan));
NS_ASSERTION(!chan, "Why is there a document channel?");
#endif
nsCOMPtr<nsIDocument> doc = piOpenedWindow->GetExtantDoc();
if (doc) {
doc->SetIsInitialDocument(true);
}
nsCOMPtr<nsIDocument> doc = piOpenedWindow->GetExtantDoc();
if (doc) {
doc->SetIsInitialDocument(true);
}
}
rv = CallQueryInterface(piOpenedWindow, aOpenedWindow);

Просмотреть файл

@ -130,6 +130,7 @@ private:
uint32_t aChromeFlags,
uint32_t aContextFlags,
nsITabParent* aOpeningTabParent,
mozIDOMWindowProxy* aOpener,
nsIWebBrowserChrome** aResult);
void MaybeDisablePersistence(const nsACString& aFeatures,

Просмотреть файл

@ -20,6 +20,7 @@
interface nsITabParent;
interface nsIURI;
interface nsIWebBrowserChrome;
interface mozIDOMWindowProxy;
[scriptable, uuid(b6c44689-f97e-4f32-a723-29eeddfbdc53)]
@ -42,6 +43,8 @@ interface nsIWindowCreator2 : nsIWindowCreator {
@param contextFlags Flags about the context of the window being created.
@param aOpeningTab The TabParent that is trying to open this new chrome
window. Can be nullptr.
@param aOpener The window which is trying to open this new chrome window.
Can be nullptr
@param cancel Return |true| to reject window creation. If true the
implementation has determined the window should not
be created at all. The caller should not default
@ -52,6 +55,7 @@ interface nsIWindowCreator2 : nsIWindowCreator {
in uint32_t chromeFlags,
in uint32_t contextFlags,
in nsITabParent aOpeningTab,
in mozIDOMWindowProxy aOpener,
out boolean cancel);
/**

Просмотреть файл

@ -244,7 +244,7 @@ function plInit() {
// to this reinitialization on the switch.
if (browserWindow.gMultiProcessBrowser) {
if (!firstPageCanLoadAsRemote())
browserWindow.XULBrowserWindow.forceInitialBrowserNonRemote();
browserWindow.XULBrowserWindow.forceInitialBrowserNonRemote(null);
// Implicit else: initial browser in e10s is remote by default.
}

Просмотреть файл

@ -611,7 +611,7 @@ nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent,
nsIWebBrowserChrome **_retval)
{
bool cancel;
return CreateChromeWindow2(aParent, aChromeFlags, 0, nullptr, &cancel, _retval);
return CreateChromeWindow2(aParent, aChromeFlags, 0, nullptr, nullptr, &cancel, _retval);
}
@ -635,6 +635,7 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
uint32_t aChromeFlags,
uint32_t aContextFlags,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy* aOpener,
bool *aCancel,
nsIWebBrowserChrome **_retval)
{
@ -654,7 +655,7 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work.");
if (xulParent)
xulParent->CreateNewWindow(aChromeFlags, aOpeningTab, getter_AddRefs(newWindow));
xulParent->CreateNewWindow(aChromeFlags, aOpeningTab, aOpener, getter_AddRefs(newWindow));
// And if it fails, don't try again without a parent. It could fail
// intentionally (bug 115969).
} else { // try using basic methods:
@ -671,7 +672,7 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
appShell->CreateTopLevelWindow(0, 0, aChromeFlags,
nsIAppShellService::SIZE_TO_CONTENT,
nsIAppShellService::SIZE_TO_CONTENT,
aOpeningTab,
aOpeningTab, aOpener,
getter_AddRefs(newWindow));
}

Просмотреть файл

@ -135,7 +135,7 @@ nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
if (!aIsPrivate) {
rv = JustCreateTopWindow(nullptr, url,
chromeMask, initialWidth, initialHeight,
true, nullptr, getter_AddRefs(newWindow));
true, nullptr, nullptr, getter_AddRefs(newWindow));
NS_ENSURE_SUCCESS(rv, rv);
mHiddenWindow.swap(newWindow);
@ -145,7 +145,7 @@ nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
rv = JustCreateTopWindow(nullptr, url,
chromeMask, initialWidth, initialHeight,
true, nullptr, getter_AddRefs(newWindow));
true, nullptr, nullptr, getter_AddRefs(newWindow));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocShell> docShell;
@ -190,6 +190,7 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
int32_t aInitialWidth,
int32_t aInitialHeight,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsIXULWindow **aResult)
{
@ -197,12 +198,12 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW);
nsWebShellWindow *newWindow = nullptr;
RefPtr<nsWebShellWindow> newWindow;
rv = JustCreateTopWindow(aParent, aUrl,
aChromeMask, aInitialWidth, aInitialHeight,
false, aOpeningTab, &newWindow); // addrefs
*aResult = newWindow; // transfer ref
false, aOpeningTab, aOpenerWindow,
getter_AddRefs(newWindow));
newWindow.forget(aResult);
if (NS_SUCCEEDED(rv)) {
// the addref resulting from this is the owning addref for this window
@ -626,6 +627,7 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWebShellWindow **aResult)
{
*aResult = nullptr;
@ -739,7 +741,8 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
nsresult rv = window->Initialize(parent, center ? aParent : nullptr,
aUrl, aInitialWidth, aInitialHeight,
aIsHiddenWindow, aOpeningTab, widgetInitData);
aIsHiddenWindow, aOpeningTab,
aOpenerWindow, widgetInitData);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -42,6 +42,7 @@ protected:
int32_t aInitialWidth, int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWebShellWindow **aResult);
uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask);

Просмотреть файл

@ -994,6 +994,9 @@ nsContentTreeOwner::ProvideWindow(mozIDOMWindowProxy* aParent,
// 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);
}

Просмотреть файл

@ -38,6 +38,8 @@ interface nsIAppShellService : nsISupports
* @param aInitialHeight like aInitialWidth, but subtly different.
* @param aOpeningTab The TabParent that requested that this window be opened.
* Can be left null.
* @param aOpenerWindow The Window Proxy which requested that this window be opened.
* Can be left null.
*/
const long SIZE_TO_CONTENT = -1;
nsIXULWindow createTopLevelWindow(in nsIXULWindow aParent,
@ -45,7 +47,8 @@ interface nsIAppShellService : nsISupports
in uint32_t aChromeMask,
in long aInitialWidth,
in long aInitialHeight,
in nsITabParent aOpeningTab);
in nsITabParent aOpeningTab,
in mozIDOMWindowProxy aOpenerWindow);
/**
* This is the constructor for creating an invisible DocShell.

Просмотреть файл

@ -13,6 +13,7 @@ interface nsIDOMElement;
interface nsIInputStream;
interface nsIDocShell;
interface nsITabParent;
interface mozIDOMWindowProxy;
/**
* The nsIXULBrowserWindow supplies the methods that may be called from the
@ -48,7 +49,7 @@ interface nsIXULBrowserWindow : nsISupports
*
*/
nsITabParent forceInitialBrowserRemote();
void forceInitialBrowserNonRemote();
void forceInitialBrowserNonRemote(in mozIDOMWindowProxy openerWindow);
/**
* Determines whether a load should continue.

Просмотреть файл

@ -17,6 +17,7 @@ interface nsIDocShell;
interface nsIDocShellTreeItem;
interface nsIXULBrowserWindow;
interface nsITabParent;
interface mozIDOMWindowProxy;
[scriptable, uuid(d6d7a014-e28d-4c9d-8727-1cf6d870619b)]
interface nsIXULWindow : nsISupports
@ -120,10 +121,12 @@ interface nsIXULWindow : nsISupports
* @param aChromeFlags see nsIWebBrowserChrome
* @param aOpeningTab the TabParent that requested this new window be opened.
* Can be left null.
* @param aOpener The window which is requesting that this new window be opened.
* @return the newly minted window
*/
nsIXULWindow createNewWindow(in int32_t aChromeFlags,
in nsITabParent aOpeningTab);
in nsITabParent aOpeningTab,
in mozIDOMWindowProxy aOpener);
attribute nsIXULBrowserWindow XULBrowserWindow;

Просмотреть файл

@ -113,6 +113,7 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWidgetInitData& widgetInitData)
{
nsresult rv;
@ -209,6 +210,12 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK);
}
if (aOpenerWindow) {
nsPIDOMWindowOuter* window = mDocShell->GetWindow();
MOZ_ASSERT(window);
window->SetOpenerWindow(nsPIDOMWindowOuter::From(aOpenerWindow), true);
}
// Eagerly create an about:blank content viewer with the right principal here,
// rather than letting it happening in the upcoming call to
// SetInitialPrincipalToSubject. This avoids creating the about:blank document

Просмотреть файл

@ -39,6 +39,7 @@ public:
int32_t aInitialWidth, int32_t aInitialHeight,
bool aIsHiddenWindow,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWIndow,
nsWidgetInitData& widgetInitData);
nsresult Toolbar();

Просмотреть файл

@ -1920,29 +1920,30 @@ NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus)
// top-level function to create a new window
NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
return CreateNewChromeWindow(aChromeFlags, aOpeningTab, _retval);
return CreateNewContentWindow(aChromeFlags, aOpeningTab, _retval);
return CreateNewChromeWindow(aChromeFlags, aOpeningTab, aOpener, _retval);
return CreateNewContentWindow(aChromeFlags, aOpeningTab, aOpener, _retval);
}
NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval)
{
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
// Just do a normal create of a window and return.
nsCOMPtr<nsIXULWindow> newWindow;
appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
nsIAppShellService::SIZE_TO_CONTENT,
nsIAppShellService::SIZE_TO_CONTENT,
aOpeningTab,
aOpeningTab, aOpener,
getter_AddRefs(newWindow));
NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
@ -1955,6 +1956,7 @@ NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval)
{
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
@ -1985,9 +1987,12 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
nsCOMPtr<nsIXULWindow> newWindow;
{
AutoNoJSAPI nojsapi;
// We actually want this toplevel window which we are creating to have a
// null opener, as we will be creating the content xul:browser window inside
// of it, so we pass nullptr as our aOpener.
appShell->CreateTopLevelWindow(this, uri,
aChromeFlags, 615, 480,
aOpeningTab,
aOpeningTab, nullptr,
getter_AddRefs(newWindow));
NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
}
@ -1997,6 +2002,17 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
(static_cast<nsIXULWindow*>
(newWindow));
if (aOpener) {
nsCOMPtr<nsIDocShell> docShell;
xulWin->GetDocShell(getter_AddRefs(docShell));
MOZ_ASSERT(docShell);
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
do_QueryInterface(docShell->GetWindow());
MOZ_ASSERT(chromeWindow);
chromeWindow->SetOpenerForInitialContentBrowser(aOpener);
}
xulWin->LockUntilChromeLoad();
{

Просмотреть файл

@ -121,8 +121,8 @@ protected:
NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX,
int32_t aCY);
NS_IMETHOD ExitModalLoop(nsresult aStatus);
NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, mozIDOMWindowProxy* aOpenerWindow, nsIXULWindow **_retval);
NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, mozIDOMWindowProxy* aOpenerWindow, nsIXULWindow **_retval);
NS_IMETHOD GetHasPrimaryContent(bool* aResult);
void EnableParent(bool aEnable);