зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
cec7ed92f4
Коммит
f9eea2d135
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче