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

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

@ -1503,6 +1503,7 @@
var aUserContextId; var aUserContextId;
var aRelatedBrowser; var aRelatedBrowser;
var aOriginPrincipal; var aOriginPrincipal;
var aOpener;
if (arguments.length == 2 && if (arguments.length == 2 &&
typeof arguments[1] == "object" && typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) { !(arguments[1] instanceof Ci.nsIURI)) {
@ -1522,6 +1523,7 @@
aUserContextId = params.userContextId; aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser; aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal; aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
} }
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground : var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
@ -1542,7 +1544,8 @@
noReferrer: aNoReferrer, noReferrer: aNoReferrer,
userContextId: aUserContextId, userContextId: aUserContextId,
originPrincipal: aOriginPrincipal, originPrincipal: aOriginPrincipal,
relatedBrowser: aRelatedBrowser }); relatedBrowser: aRelatedBrowser,
opener: aOpener });
if (!bgLoad) if (!bgLoad)
this.selectedTab = tab; this.selectedTab = tab;
@ -1655,11 +1658,27 @@
<method name="updateBrowserRemoteness"> <method name="updateBrowserRemoteness">
<parameter name="aBrowser"/> <parameter name="aBrowser"/>
<parameter name="aShouldBeRemote"/> <parameter name="aShouldBeRemote"/>
<parameter name="aOpener"/>
<body> <body>
<![CDATA[ <![CDATA[
let isRemote = aBrowser.getAttribute("remote") == "true"; 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; return false;
}
let tab = this.getTabForBrowser(aBrowser); let tab = this.getTabForBrowser(aBrowser);
let evt = document.createEvent("Events"); let evt = document.createEvent("Events");
@ -1700,6 +1719,10 @@
// turns this normal property into a field. // turns this normal property into a field.
aBrowser.relatedBrowser = relatedBrowser; 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); parent.appendChild(aBrowser);
aBrowser.userTypedValue = oldUserTypedValue; aBrowser.userTypedValue = oldUserTypedValue;
@ -1881,6 +1904,13 @@
b.setAttribute("remote", "true"); 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) { if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
b.setAttribute("showresizer", "true"); b.setAttribute("showresizer", "true");
} }
@ -1981,7 +2011,8 @@
remote: remote, remote: remote,
uriIsAboutBlank: uriIsAboutBlank, uriIsAboutBlank: uriIsAboutBlank,
userContextId: aParams.userContextId, userContextId: aParams.userContextId,
relatedBrowser: aParams.relatedBrowser}); relatedBrowser: aParams.relatedBrowser,
opener: aParams.opener});
} }
let notificationbox = this.getNotificationBox(browser); let notificationbox = this.getNotificationBox(browser);
@ -2057,6 +2088,7 @@
var aEventDetail; var aEventDetail;
var aRelatedBrowser; var aRelatedBrowser;
var aOriginPrincipal; var aOriginPrincipal;
var aOpener;
if (arguments.length == 2 && if (arguments.length == 2 &&
typeof arguments[1] == "object" && typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) { !(arguments[1] instanceof Ci.nsIURI)) {
@ -2077,6 +2109,7 @@
aEventDetail = params.eventDetail; aEventDetail = params.eventDetail;
aRelatedBrowser = params.relatedBrowser; aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal; aOriginPrincipal = params.originPrincipal;
aOpener = params.opener;
} }
// if we're adding tabs, we're past interrupt mode, ditch the owner // if we're adding tabs, we're past interrupt mode, ditch the owner
@ -2144,7 +2177,8 @@
let browserParams = { let browserParams = {
forceNotRemote: aForceNotRemote, forceNotRemote: aForceNotRemote,
userContextId: aUserContextId, userContextId: aUserContextId,
relatedBrowser: aRelatedBrowser relatedBrowser: aRelatedBrowser,
opener: aOpener,
}; };
let { usingPreloadedContent } = this._linkBrowserToTab(t, aURI, browserParams); let { usingPreloadedContent } = this._linkBrowserToTab(t, aURI, browserParams);
let b = t.linkedBrowser; let b = t.linkedBrowser;

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

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

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

@ -252,6 +252,8 @@
#include "mozilla/StyleSheet.h" #include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h" #include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/SVGSVGElement.h" #include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/DocLoadingTimelineMarker.h" #include "mozilla/DocLoadingTimelineMarker.h"
#include "nsISpeculativeConnect.h" #include "nsISpeculativeConnect.h"
@ -1362,6 +1364,10 @@ nsIDocument::~nsIDocument()
mNodeInfoManager->DropDocumentReference(); mNodeInfoManager->DropDocumentReference();
} }
if (mDocGroup) {
mDocGroup->RemoveDocument(this);
}
UnlinkOriginalDocumentIfStatic(); UnlinkOriginalDocumentIfStatic();
} }
@ -2848,6 +2854,36 @@ nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
} }
} }
mNodeInfoManager->SetDocumentPrincipal(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 NS_IMETHODIMP
@ -4254,6 +4290,23 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
mScopeObject = do_GetWeakReference(aGlobal); mScopeObject = do_GetWeakReference(aGlobal);
if (aGlobal) { if (aGlobal) {
mHasHadScriptHandlingObject = true; 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; mScriptGlobalObject = aScriptGlobalObject;
if (aScriptGlobalObject) { if (aScriptGlobalObject) {
mHasHadScriptHandlingObject = true;
mHasHadDefaultView = true;
// Go back to using the docshell for the layout history state // Go back to using the docshell for the layout history state
mLayoutHistoryState = nullptr; mLayoutHistoryState = nullptr;
mScopeObject = do_GetWeakReference(aScriptGlobalObject); SetScopeObject(aScriptGlobalObject);
mHasHadDefaultView = true;
#ifdef DEBUG #ifdef DEBUG
if (!mWillReparent) { if (!mWillReparent) {
// We really shouldn't have a wrapper here but if we do we need to make sure // 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, mScriptGlobalObject == aScriptObject,
"Wrong script object!"); "Wrong script object!");
if (aScriptObject) { if (aScriptObject) {
mScopeObject = do_GetWeakReference(aScriptObject); SetScopeObject(aScriptObject);
mHasHadScriptHandlingObject = true;
mHasHadDefaultView = false; mHasHadDefaultView = false;
} }
} }

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

@ -81,6 +81,7 @@
#include "nsAboutProtocolUtils.h" #include "nsAboutProtocolUtils.h"
#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE #include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
#include "PostMessageEvent.h" #include "PostMessageEvent.h"
#include "DocGroup.h"
// Interfaces Needed // Interfaces Needed
#include "nsIFrame.h" #include "nsIFrame.h"
@ -1226,9 +1227,10 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mCleanedUp(false), mCleanedUp(false),
mDialogAbuseCount(0), mDialogAbuseCount(0),
mAreDialogsEnabled(true), mAreDialogsEnabled(true),
mCanSkipCCGeneration(0), #ifdef DEBUG
mStaticConstellation(0), mIsValidatingTabGroup(false),
mConstellation(NullCString()) #endif
mCanSkipCCGeneration(0)
{ {
AssertIsOnMainThread(); AssertIsOnMainThread();
@ -1262,11 +1264,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
// |this| is an outer window. Outer windows start out frozen and // |this| is an outer window. Outer windows start out frozen and
// remain frozen until they get an inner window. // remain frozen until they get an inner window.
MOZ_ASSERT(IsFrozen()); 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 // 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 // Outer windows are always supposed to call CleanUp before letting themselves
// be destroyed. And while CleanUp generally seems to be intended to clean up // 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 // outers, we've historically called it for both. Changing this would probably
@ -2856,6 +2858,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext); nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
aDocument->SetScriptGlobalObject(newInnerWindow); aDocument->SetScriptGlobalObject(newInnerWindow);
MOZ_ASSERT(newInnerWindow->mTabGroup,
"We must have a TabGroup cached at this point");
if (!aState) { if (!aState) {
if (reUseInnerWindow) { if (reUseInnerWindow) {
@ -3032,11 +3036,8 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
mDocShell = aDocShell; // Weak Reference mDocShell = aDocShell; // Weak Reference
// Copy over the static constellation from our new parent. nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetParent(); MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup || mTabGroup == Cast(parentWindow)->mTabGroup);
if (parentWindow) {
mStaticConstellation = Cast(parentWindow)->mStaticConstellation;
}
NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!"); NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
@ -3141,19 +3142,24 @@ nsGlobalWindow::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
{ {
FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener)); FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
nsWeakPtr opener = do_GetWeakReference(aOpener);
if (opener == mOpener) {
return;
}
NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled, NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
"aOriginalOpener is true, but not first call to " "aOriginalOpener is true, but not first call to "
"SetOpenerWindow!"); "SetOpenerWindow!");
NS_ASSERTION(aOpener || !aOriginalOpener, NS_ASSERTION(aOpener || !aOriginalOpener,
"Shouldn't set mHadOriginalOpener if aOpener is null"); "Shouldn't set mHadOriginalOpener if aOpener is null");
mOpener = do_GetWeakReference(aOpener); mOpener = opener.forget();
NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!"); NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!");
// Copy over the static constellation from our new opener // Check that the js visible opener matches!
if (aOpener) { nsPIDOMWindowOuter* contentOpener = GetSanitizedOpener(aOpener);
mStaticConstellation = Cast(aOpener)->mStaticConstellation; MOZ_RELEASE_ASSERT(!contentOpener || !mTabGroup ||
} mTabGroup == Cast(contentOpener)->mTabGroup);
if (aOriginalOpener) { if (aOriginalOpener) {
MOZ_ASSERT(!mHadOriginalOpener, MOZ_ASSERT(!mHadOriginalOpener,
@ -4726,26 +4732,13 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult)
} }
nsPIDOMWindowOuter* nsPIDOMWindowOuter*
nsGlobalWindow::GetOpenerWindowOuter() nsGlobalWindow::GetSanitizedOpener(nsPIDOMWindowOuter* aOpener)
{ {
MOZ_RELEASE_ASSERT(IsOuterWindow()); if (!aOpener) {
nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
if (!opener) {
return nullptr; return nullptr;
} }
nsGlobalWindow* win = nsGlobalWindow::Cast(opener); nsGlobalWindow* win = nsGlobalWindow::Cast(aOpener);
// 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;
}
// First, ensure that we're not handing back a chrome window to content: // First, ensure that we're not handing back a chrome window to content:
if (win->IsChromeWindow()) { if (win->IsChromeWindow()) {
@ -4755,7 +4748,7 @@ nsGlobalWindow::GetOpenerWindowOuter()
// We don't want to reveal the opener if the opener is a mail window, // 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). // 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. // 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) { if (openerDocShell) {
nsCOMPtr<nsIDocShellTreeItem> openerRootItem; nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
@ -4765,7 +4758,7 @@ nsGlobalWindow::GetOpenerWindowOuter()
uint32_t appType; uint32_t appType;
nsresult rv = openerRootDocShell->GetAppType(&appType); nsresult rv = openerRootDocShell->GetAppType(&appType);
if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) { if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
return opener; return aOpener;
} }
} }
} }
@ -4773,6 +4766,30 @@ nsGlobalWindow::GetOpenerWindowOuter()
return nullptr; 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* nsPIDOMWindowOuter*
nsGlobalWindow::GetOpenerWindow(ErrorResult& aError) nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
{ {
@ -4797,11 +4814,9 @@ nsGlobalWindow::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
already_AddRefed<nsPIDOMWindowOuter> already_AddRefed<nsPIDOMWindowOuter>
nsGlobalWindow::GetOpener() nsGlobalWindow::GetOpener()
{ {
FORWARD_TO_INNER(GetOpener, (), nullptr); FORWARD_TO_OUTER(GetOpener, (), nullptr);
ErrorResult dummy; nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindowOuter();
nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(dummy);
dummy.SuppressException();
return opener.forget(); 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(mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -13640,6 +13656,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
} }
tmp->DisconnectAndClearGroupMessageManagers(); tmp->DisconnectAndClearGroupMessageManagers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers) NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
// QueryInterface implementation for nsGlobalChromeWindow // QueryInterface implementation for nsGlobalChromeWindow
@ -14110,6 +14127,24 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
return messageManager; 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 // nsGlobalModalWindow implementation
// QueryInterface implementation for nsGlobalModalWindow // QueryInterface implementation for nsGlobalModalWindow
@ -14593,44 +14628,105 @@ nsGlobalWindow::CheckForDPIChange()
} }
} }
void mozilla::dom::TabGroup*
nsGlobalWindow::GetConstellation(nsACString& aConstellation) 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 #ifdef DEBUG
RefPtr<nsGlobalWindow> outer = GetOuterWindowInternal(); // Ensure that we don't recurse forever
MOZ_ASSERT(outer, "We should have an outer window"); if (!mIsValidatingTabGroup) {
RefPtr<nsGlobalWindow> top = outer->GetTopInternal(); mIsValidatingTabGroup = true;
RefPtr<nsPIDOMWindowOuter> opener = outer->GetOpener(); // We only need to do this check if we aren't in the chrome tab group
MOZ_ASSERT(!top || (top->mStaticConstellation == if (GetDocShell()->ItemType() == nsIDocShellTreeItem::typeChrome) {
outer->mStaticConstellation)); MOZ_ASSERT(mTabGroup == TabGroup::GetChromeTabGroup());
MOZ_ASSERT(!opener || (Cast(opener)->mStaticConstellation == } else {
outer->mStaticConstellation)); // 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 #endif
if (mConstellation.IsVoid()) { return mTabGroup;
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();
}
}
}
// Get the static constellation from the outer window object. mozilla::dom::TabGroup*
mConstellation.AppendPrintf("^%llu", GetOuterWindowInternal()->mStaticConstellation); 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( nsGlobalWindow::TemporarilyDisableDialogs::TemporarilyDisableDialogs(

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

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

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

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

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

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

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

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

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

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

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

@ -36,6 +36,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement) nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAudioChannels) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAudioChannels)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 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(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAudioChannels) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAudioChannels)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -153,6 +155,15 @@ nsGenericHTMLFrameElement::EnsureFrameLoader()
if (mIsPrerendered) { if (mIsPrerendered) {
mFrameLoader->SetIsPrerendered(); 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 nsresult
@ -212,6 +223,13 @@ nsGenericHTMLFrameElement::GetParentApplication(mozIApplication** aApplication)
return NS_OK; return NS_OK;
} }
void
nsGenericHTMLFrameElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv)
{
MOZ_ASSERT(!mFrameLoader);
mOpenerWindow = nsPIDOMWindowOuter::From(aWindow);
}
void void
nsGenericHTMLFrameElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner, nsGenericHTMLFrameElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner,
ErrorResult& rv) ErrorResult& rv)

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

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

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

@ -9,6 +9,7 @@ interface nsIBrowserDOMWindow;
interface nsIDOMElement; interface nsIDOMElement;
interface nsIDOMEvent; interface nsIDOMEvent;
interface nsIMessageBroadcaster; interface nsIMessageBroadcaster;
interface mozIDOMWindowProxy;
[scriptable, uuid(78bdcb41-1efa-409f-aaba-70842213f80f)] [scriptable, uuid(78bdcb41-1efa-409f-aaba-70842213f80f)]
interface nsIDOMChromeWindow : nsISupports interface nsIDOMChromeWindow : nsISupports
@ -63,4 +64,18 @@ interface nsIDOMChromeWindow : nsISupports
* doesn't support this. * doesn't support this.
*/ */
void beginWindowMove(in nsIDOMEvent mouseDownEvent, [optional] in nsIDOMElement panel); 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); 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 // Unfortunately we don't get a window unless we've shown the frame. That's
// pretty bogus; see bug 763602. // pretty bogus; see bug 763602.
newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame, newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame,

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

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

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

@ -128,12 +128,6 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
return rv; return rv;
} }
if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
d->SetScriptHandlingObject(sgo);
} else if (aEventObject){
d->SetScopeObject(aEventObject);
}
if (isHTML) { if (isHTML) {
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d); nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?"); NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
@ -147,6 +141,14 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
doc->SetPrincipal(aPrincipal); doc->SetPrincipal(aPrincipal);
doc->SetBaseURI(aBaseURI); 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, // XMLDocuments and documents "created in memory" get to be UTF-8 by default,
// unlike the legacy HTML mess // unlike the legacy HTML mess
doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8")); doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8"));

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

@ -803,7 +803,6 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID
nsIScriptGlobalObject* sgo = nsIScriptGlobalObject* sgo =
source->GetScriptHandlingObject(hasHadScriptObject); source->GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(sgo || !hasHadScriptObject); NS_ENSURE_STATE(sgo || !hasHadScriptObject);
mDocument->SetScriptHandlingObject(sgo);
mCurrentNode = mDocument; mCurrentNode = mDocument;
mNodeInfoManager = mDocument->NodeInfoManager(); mNodeInfoManager = mDocument->NodeInfoManager();
@ -811,6 +810,10 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, int32_t aNsID
// Reset and set up the document // Reset and set up the document
URIUtils::ResetWithSource(mDocument, aSourceDocument); 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 // Set the charset
if (!mOutputFormat.mEncoding.IsEmpty()) { if (!mOutputFormat.mEncoding.IsEmpty()) {
nsAutoCString canonicalCharset; nsAutoCString canonicalCharset;

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

@ -95,6 +95,7 @@
#include "nsIController.h" #include "nsIController.h"
#include "nsQueryObject.h" #include "nsQueryObject.h"
#include <algorithm> #include <algorithm>
#include "nsIDOMChromeWindow.h"
// The XUL doc interface // The XUL doc interface
#include "nsIDOMXULDocument.h" #include "nsIDOMXULDocument.h"
@ -191,6 +192,8 @@ nsXULElement::nsXULSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{ {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoader"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mFrameLoader");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIFrameLoader*, 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* nsINode::nsSlots*
@ -1585,6 +1588,30 @@ nsXULElement::LoadSrc()
slots->mFrameLoader = nsFrameLoader::Create(this, false); slots->mFrameLoader = nsFrameLoader::Create(this, false);
NS_ENSURE_TRUE(slots->mFrameLoader, NS_OK); 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, (new AsyncEventDispatcher(this,
NS_LITERAL_STRING("XULFrameLoaderCreated"), NS_LITERAL_STRING("XULFrameLoaderCreated"),
/* aBubbles */ true))->RunDOMEventWhenSafe(); /* aBubbles */ true))->RunDOMEventWhenSafe();
@ -1628,6 +1655,15 @@ nsXULElement::GetParentApplication(mozIApplication** aApplication)
return NS_OK; 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 nsresult
nsXULElement::SetIsPrerendered() nsXULElement::SetIsPrerendered()
{ {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -42,6 +42,7 @@ protected:
int32_t aInitialWidth, int32_t aInitialHeight, int32_t aInitialWidth, int32_t aInitialHeight,
bool aIsHiddenWindow, bool aIsHiddenWindow,
nsITabParent *aOpeningTab, nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpenerWindow,
nsWebShellWindow **aResult); nsWebShellWindow **aResult);
uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask); 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 // 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. // 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, return browserDOMWin->OpenURI(nullptr, aParent, openLocation,
nsIBrowserDOMWindow::OPEN_NEW, aReturn); nsIBrowserDOMWindow::OPEN_NEW, aReturn);
} }

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

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

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

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

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

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

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

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

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

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

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

@ -1920,29 +1920,30 @@ NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus)
// top-level function to create a new window // top-level function to create a new window
NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags, NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab, nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval) nsIXULWindow **_retval)
{ {
NS_ENSURE_ARG_POINTER(_retval); NS_ENSURE_ARG_POINTER(_retval);
if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
return CreateNewChromeWindow(aChromeFlags, aOpeningTab, _retval); return CreateNewChromeWindow(aChromeFlags, aOpeningTab, aOpener, _retval);
return CreateNewContentWindow(aChromeFlags, aOpeningTab, _retval); return CreateNewContentWindow(aChromeFlags, aOpeningTab, aOpener, _retval);
} }
NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags, NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab, nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval) nsIXULWindow **_retval)
{ {
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
// Just do a normal create of a window and return. // Just do a normal create of a window and return.
nsCOMPtr<nsIXULWindow> newWindow; nsCOMPtr<nsIXULWindow> newWindow;
appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags, appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
nsIAppShellService::SIZE_TO_CONTENT, nsIAppShellService::SIZE_TO_CONTENT,
nsIAppShellService::SIZE_TO_CONTENT, nsIAppShellService::SIZE_TO_CONTENT,
aOpeningTab, aOpeningTab, aOpener,
getter_AddRefs(newWindow)); getter_AddRefs(newWindow));
NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); 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, NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
nsITabParent *aOpeningTab, nsITabParent *aOpeningTab,
mozIDOMWindowProxy *aOpener,
nsIXULWindow **_retval) nsIXULWindow **_retval)
{ {
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
@ -1985,9 +1987,12 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
nsCOMPtr<nsIXULWindow> newWindow; nsCOMPtr<nsIXULWindow> newWindow;
{ {
AutoNoJSAPI nojsapi; 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, appShell->CreateTopLevelWindow(this, uri,
aChromeFlags, 615, 480, aChromeFlags, 615, 480,
aOpeningTab, aOpeningTab, nullptr,
getter_AddRefs(newWindow)); getter_AddRefs(newWindow));
NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
} }
@ -1997,6 +2002,17 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
(static_cast<nsIXULWindow*> (static_cast<nsIXULWindow*>
(newWindow)); (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(); xulWin->LockUntilChromeLoad();
{ {

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

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