Backed out 2 changesets (bug 1582716, bug 1575051) for gv-junit failures, new exception. CLOSED TREE

Backed out changeset b5aa3ac4483e (bug 1582716)
Backed out changeset c385531b4ee3 (bug 1575051)
This commit is contained in:
Brindusan Cristian 2019-09-24 19:47:00 +03:00
parent 41aaf2b98d
commit 203fbcd6c8
20 changed files with 593 additions and 69 deletions

View File

@ -16,7 +16,6 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Location.h"
#include "mozilla/dom/LocationBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/UserActivationIPCUtils.h"
#include "mozilla/dom/WindowBinding.h"
@ -472,14 +471,8 @@ void BrowsingContext::GetChildren(Children& aChildren) {
//
// See
// https://html.spec.whatwg.org/multipage/browsers.html#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name
BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
RefPtr<BrowsingContext> requestingContext = this;
if (nsCOMPtr<nsIDocShell> caller = do_GetInterface(GetEntryGlobal())) {
if (caller->GetBrowsingContext()) {
requestingContext = caller->GetBrowsingContext();
}
}
BrowsingContext* BrowsingContext::FindWithName(
const nsAString& aName, BrowsingContext& aRequestingContext) {
BrowsingContext* found = nullptr;
if (aName.IsEmpty()) {
// You can't find a browsing context with an empty name.
@ -489,9 +482,9 @@ BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
// a blank name.
found = nullptr;
} else if (IsSpecialName(aName)) {
found = FindWithSpecialName(aName, *requestingContext);
found = FindWithSpecialName(aName, aRequestingContext);
} else if (BrowsingContext* child =
FindWithNameInSubtree(aName, *requestingContext)) {
FindWithNameInSubtree(aName, aRequestingContext)) {
found = child;
} else {
BrowsingContext* current = this;
@ -505,7 +498,7 @@ BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
// contexts in the same browsing context group.
siblings = &mGroup->Toplevels();
} else if (parent->NameEquals(aName) &&
requestingContext->CanAccess(parent) &&
aRequestingContext.CanAccess(parent) &&
parent->IsTargetable()) {
found = parent;
break;
@ -519,7 +512,7 @@ BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
}
if (BrowsingContext* relative =
sibling->FindWithNameInSubtree(aName, *requestingContext)) {
sibling->FindWithNameInSubtree(aName, aRequestingContext)) {
found = relative;
// Breaks the outer loop
parent = nullptr;
@ -533,7 +526,7 @@ BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
// Helpers should perform access control checks, which means that we
// only need to assert that we can access found.
MOZ_DIAGNOSTIC_ASSERT(!found || requestingContext->CanAccess(found));
MOZ_DIAGNOSTIC_ASSERT(!found || aRequestingContext.CanAccess(found));
return found;
}

View File

@ -259,7 +259,8 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
// BrowsingContext::FindWithName(const nsAString&) is equivalent to
// calling nsIDocShellTreeItem::FindItemWithName(aName, nullptr,
// nullptr, false, <return value>).
BrowsingContext* FindWithName(const nsAString& aName);
BrowsingContext* FindWithName(const nsAString& aName,
BrowsingContext& aRequestingContext);
// Find a browsing context in this context's list of
// children. Doesn't consider the special names, '_self', '_parent',

View File

@ -133,19 +133,6 @@ JSObject* BrowsingContextGroup::WrapObject(JSContext* aCx,
return BrowsingContextGroup_Binding::Wrap(aCx, this, aGivenProto);
}
static StaticRefPtr<BrowsingContextGroup> sChromeGroup;
/* static */
BrowsingContextGroup* BrowsingContextGroup::GetChromeGroup() {
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
if (!sChromeGroup && XRE_IsParentProcess()) {
sChromeGroup = new BrowsingContextGroup();
ClearOnShutdown(&sChromeGroup);
}
return sChromeGroup;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BrowsingContextGroup, mContexts,
mToplevels, mSubscribers, mCachedContexts)

View File

@ -108,8 +108,6 @@ class BrowsingContextGroup final : public nsWrapperCache {
}
}
static BrowsingContextGroup* GetChromeGroup();
private:
friend class CanonicalBrowsingContext;

View File

@ -2888,6 +2888,65 @@ static bool ItemIsActive(nsIDocShellTreeItem* aItem) {
return false;
}
NS_IMETHODIMP
nsDocShell::FindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
bool aSkipTabGroup,
nsIDocShellTreeItem** aResult) {
NS_ENSURE_ARG_POINTER(aResult);
// If we don't find one, we return NS_OK and a null result
*aResult = nullptr;
if (aName.IsEmpty()) {
return NS_OK;
}
if (aRequestor) {
// If aRequestor is not null we don't need to check special names, so
// just hand straight off to the search by actual name function.
return DoFindItemWithName(aName, aRequestor, aOriginalRequestor,
aSkipTabGroup, aResult);
} else {
// This is the entry point into the target-finding algorithm. Check
// for special names. This should only be done once, hence the check
// for a null aRequestor.
nsCOMPtr<nsIDocShellTreeItem> foundItem;
if (aName.LowerCaseEqualsLiteral("_self")) {
foundItem = this;
} else if (aName.LowerCaseEqualsLiteral("_blank")) {
// Just return null. Caller must handle creating a new window with
// a blank name himself.
return NS_OK;
} else if (aName.LowerCaseEqualsLiteral("_parent")) {
GetInProcessSameTypeParent(getter_AddRefs(foundItem));
if (!foundItem) {
foundItem = this;
}
} else if (aName.LowerCaseEqualsLiteral("_top")) {
GetInProcessSameTypeRootTreeItem(getter_AddRefs(foundItem));
NS_ASSERTION(foundItem, "Must have this; worst case it's us!");
} else {
// Do the search for item by an actual name.
DoFindItemWithName(aName, aRequestor, aOriginalRequestor, aSkipTabGroup,
getter_AddRefs(foundItem));
}
if (foundItem && !CanAccessItem(foundItem, aOriginalRequestor)) {
foundItem = nullptr;
}
// DoFindItemWithName only returns active items and we don't check if
// the item is active for the special cases.
if (foundItem) {
foundItem.swap(*aResult);
}
return NS_OK;
}
}
void nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
// Chrome docshells must not have a private browsing OriginAttribute
// Content docshells must maintain the equality:
@ -2900,6 +2959,64 @@ void nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
}
}
nsresult nsDocShell::DoFindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
bool aSkipTabGroup,
nsIDocShellTreeItem** aResult) {
// First we check our name.
if (mBrowsingContext->NameEquals(aName) && ItemIsActive(this) &&
CanAccessItem(this, aOriginalRequestor)) {
NS_ADDREF(*aResult = this);
return NS_OK;
}
// Second we check our children making sure not to ask a child if
// it is the aRequestor.
#ifdef DEBUG
nsresult rv =
#endif
FindChildWithName(aName, true, true, aRequestor, aOriginalRequestor,
aResult);
NS_ASSERTION(NS_SUCCEEDED(rv),
"FindChildWithName should not be failing here.");
if (*aResult) {
return NS_OK;
}
// Third if we have a parent and it isn't the requestor then we
// should ask it to do the search. If it is the requestor we
// should just stop here and let the parent do the rest. If we
// don't have a parent, then we should ask the
// docShellTreeOwner to do the search.
nsCOMPtr<nsIDocShellTreeItem> parentAsTreeItem =
do_QueryInterface(GetAsSupports(mParent));
if (parentAsTreeItem) {
if (parentAsTreeItem == aRequestor) {
return NS_OK;
}
// If we have a same-type parent, respecting browser and app boundaries.
// NOTE: Could use GetInProcessSameTypeParent if the issues described in
// bug 1310344 are fixed.
if (!GetIsMozBrowser() && parentAsTreeItem->ItemType() == mItemType) {
return parentAsTreeItem->FindItemWithName(aName, this, aOriginalRequestor,
/* aSkipTabGroup = */ false,
aResult);
}
}
// If we have a null parent or the parent is not of the same type, we need to
// give up on finding it in our tree, and start looking in our TabGroup.
nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
if (window && !aSkipTabGroup) {
RefPtr<mozilla::dom::TabGroup> tabGroup = window->TabGroup();
tabGroup->FindItemWithName(aName, this, aOriginalRequestor, aResult);
}
return NS_OK;
}
bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) {
// If no target then not sandboxed.
if (!aTargetBC) {
@ -8587,9 +8704,11 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
MOZ_ASSERT(aLoadState, "need a load state!");
MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!");
nsresult rv = NS_OK;
nsresult rv;
nsCOMPtr<nsIDocShell> targetDocShell;
// Locate the target DocShell.
nsCOMPtr<nsIDocShellTreeItem> targetItem;
// Only _self, _parent, and _top are supported in noopener case. But we
// have to be careful to not apply that to the noreferrer case. See bug
// 1358469.
@ -8600,12 +8719,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
if (BrowsingContext* context =
mBrowsingContext->FindWithName(aLoadState->Target())) {
targetDocShell = context->GetDocShell();
}
rv = FindItemWithName(aLoadState->Target(), nullptr, this, false,
getter_AddRefs(targetItem));
NS_ENSURE_SUCCESS(rv, rv);
}
targetDocShell = do_QueryInterface(targetItem);
if (!targetDocShell) {
// If the targetDocShell doesn't exist, then this is a new docShell
// and we should consider this a TYPE_DOCUMENT load
@ -13464,6 +13583,35 @@ nsCommandManager* nsDocShell::GetCommandManager() {
return mCommandManager;
}
NS_IMETHODIMP
nsDocShell::GetIsOnlyToplevelInTabGroup(bool* aResult) {
MOZ_ASSERT(aResult);
nsPIDOMWindowOuter* outer = GetWindow();
MOZ_ASSERT(outer);
// If we are not toplevel then we are not the only toplevel window in the
// tab group.
if (outer->GetInProcessScriptableParentOrNull()) {
*aResult = false;
return NS_OK;
}
// If we have any other toplevel windows in our tab group, then we are not
// the only toplevel window in the tab group.
nsTArray<nsPIDOMWindowOuter*> toplevelWindows =
outer->TabGroup()->GetTopLevelWindows();
if (toplevelWindows.Length() > 1) {
*aResult = false;
return NS_OK;
}
MOZ_ASSERT(toplevelWindows.Length() == 1);
MOZ_ASSERT(toplevelWindows[0] == outer);
*aResult = true;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAwaitingLargeAlloc(bool* aResult) {
MOZ_ASSERT(aResult);

View File

@ -942,6 +942,14 @@ class nsDocShell final : public nsDocLoader,
MOZ_MUST_USE bool MaybeInitTiming();
void MaybeResetInitTiming(bool aReset);
// Separate function to do the actual name (i.e. not _top, _self etc.)
// searching for FindItemWithName.
nsresult DoFindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
bool aSkipTabGroup,
nsIDocShellTreeItem** aResult);
// Convenience method for getting our parent docshell. Can return null
already_AddRefed<nsDocShell> GetInProcessParentDocshell();

View File

@ -1055,6 +1055,20 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[infallible] attribute nsIDocShell_MetaViewportOverride metaViewportOverride;
/**
* This value is `true` if its corresponding unit of related browsing contexts
* (TabGroup) contains only 1 toplevel window, and that window is the outer
* window corresponding to this docshell.
*
* The value is `false` otherwise. This is the case if the docshell is an
* iframe, has window.opener set, or another window with window.opener
* referring to this window exists.
*
* If this value is `false`, it would be web content visible for a load
* occuring in this docshell to be performed within a different docshell.
*/
[infallible] readonly attribute boolean isOnlyToplevelInTabGroup;
/**
* Returns `true` if this docshell was created due to a Large-Allocation
* header, and has not seen the initiating load yet.

View File

@ -92,6 +92,39 @@ interface nsIDocShellTreeItem : nsISupports
[binaryname(InProcessSameTypeRootTreeItem)]
readonly attribute nsIDocShellTreeItem sameTypeRootTreeItem;
/*
Returns the docShellTreeItem with the specified name. Search order is as
follows...
1.) Check name of self, if it matches return it.
2.) For each immediate child.
a.) Check name of child and if it matches return it.
b.) Ask the child to perform the check
i.) Do not ask a child if it is the aRequestor
ii.) Do not ask a child if it is of a different item type.
3.) If there is a parent of the same item type ask parent to perform the check
a.) Do not ask parent if it is the aRequestor
4.) If there is a tab group ask the tab group to perform the check
a.) Do not ask the tab group if aSkipTabGroup
b.) This should only be done if there is no parent of the same type.
Return the child DocShellTreeItem with the specified name.
name - This is the name of the item that is trying to be found.
aRequestor - This is the object that is requesting the find. This
parameter is used to identify when the child is asking its parent to find
a child with the specific name. The parent uses this parameter to ensure
a resursive state does not occur by not again asking the requestor to find
a shell by the specified name. Inversely the child uses it to ensure it
does not ask its parent to do the search if its parent is the one that
asked it to search. Children also use this to test against the treeOwner;
aOriginalRequestor - The original treeitem that made the request, if any.
This is used to ensure that we don't run into cross-site issues.
aSkipTabGroup - Whether the tab group should be checked.
*/
nsIDocShellTreeItem findItemWithName(in AString name,
in nsIDocShellTreeItem aRequestor,
in nsIDocShellTreeItem aOriginalRequestor,
in bool aSkipTabGroup);
/*
The owner of the DocShell Tree. This interface will be called upon when
the docshell has things it needs to tell to the owner of the docshell.
@ -189,3 +222,4 @@ interface nsIDocShellTreeItem : nsISupports
[noscript,nostdcall,notxpcom] Document getDocument();
[noscript,nostdcall,notxpcom] nsPIDOMWindowOuter getWindow();
};

View File

@ -136,6 +136,8 @@ skip-if = true # Bug 1220415
[browser_click_link_within_view_source.js]
[browser_browsingContext-01.js]
[browser_browsingContext-02.js]
[browser_browsingContext-03.js]
skip-if = fission # Cross-process postMessage
[browser_browsingContext-embedder.js]
[browser_csp_uir.js]
support-files =

View File

@ -110,12 +110,11 @@ add_task(async function() {
// docShell.
function findWithName(bc, name) {
return content.SpecialPowers.spawn(bc, [bc, name], (bc, name) => {
return bc.findWithName(name);
return bc.findWithName(name, bc);
});
}
async function reachable(start, target) {
info(start.name, target.name);
is(
await findWithName(start, target.name),
target,

View File

@ -0,0 +1,194 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function() {
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function(browser) {
const BASE1 = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"http://example.com"
);
const BASE2 = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"http://test1.example.com"
);
const URL = BASE1 + "onload_message.html";
let sixth = BrowserTestUtils.waitForNewTab(
gBrowser,
URL + "#sixth",
true,
true
);
await ContentTask.spawn(
browser,
{ base1: BASE1, base2: BASE2 },
async function({ base1, base2 }) {
let top = content;
top.name = "top";
top.location.href += "#top";
let contexts = {
top: top.location.href,
first: base1 + "dummy_page.html#first",
third: base2 + "dummy_page.html#third",
second: base1 + "dummy_page.html#second",
fourth: base2 + "dummy_page.html#fourth",
fifth: base1 + "dummy_page.html#fifth",
sixth: base1 + "onload_message.html#sixth",
};
function addFrame(target, name) {
return content.SpecialPowers.spawn(
target,
[name, contexts[name]],
async (name, context) => {
let doc = this.content.document;
let frame = doc.createElement("iframe");
doc.body.appendChild(frame);
frame.name = name;
frame.src = context;
await new Promise(resolve => {
frame.addEventListener("load", resolve, { once: true });
});
return frame.browsingContext;
}
);
}
function addWindow(target, name) {
return content.SpecialPowers.spawn(
target,
[name, contexts[name]],
(name, context) => {
let win = this.content.open(context, name);
let bc = win && win.docShell.browsingContext;
return new Promise(resolve =>
this.content.addEventListener("message", () => resolve(bc))
);
}
);
}
// Generate all lists of length length with every combination of
// values in input
function* generate(input, length) {
let list = new Array(length);
function* values(pos) {
if (pos >= list.length) {
yield list;
} else {
for (let v of input) {
list[pos] = v;
yield* values(pos + 1);
}
}
}
yield* values(0);
}
// We're going to create a tree that looks like the
// follwing.
//
// top sixth
// / \
// / \ /
// first second
// / \ /
// / \
// third fourth - - -
// /
// /
// fifth
//
// The idea is to have one top level non-auxiliary browsing
// context, five nested, one top level auxiliary with an
// opener. Given that set of related browsing contexts we
// wish to confirm that targeting is semantically equivalent
// with how nsIDocShellTreeItem.findItemWithName works. The
// trick to ensure that is to give all frames the same name!
// and ensure that the find algorithms return the same nodes
// in the same order.
let first = await addFrame(top, "first");
let second = await addFrame(top, "second");
let third = await addFrame(first, "third");
let fourth = await addFrame(first, "fourth");
let fifth = await addFrame(fourth, "fifth");
let sixth = await addWindow(fourth, "sixth");
let browsingContexts = [
BrowsingContext.getFromWindow(top),
first,
second,
third,
fourth,
fifth,
sixth,
];
let docShells = browsingContexts.map(context => context.docShell);
ok(
top.docShell instanceof Ci.nsIDocShellTreeItem,
"When we remove nsIDocShellTreeItem this test should be removed"
);
// For every browsing context we generate all possible
// combinations of names for these browsing contexts using
// "dummy" and "target" as possible name.
for (let names of generate(["dummy", "target"], docShells.length)) {
for (let i = names.length - 1; i >= 0; --i) {
docShells[i].name = names[i];
}
for (let i = 0; i < docShells.length; ++i) {
let docShell = docShells[i].findItemWithName(
"target",
null,
docShells[i],
false
);
let browsingContext = browsingContexts[i].findWithName(
"target",
browsingContexts[i]
);
is(
docShell ? docShell.browsingContext : null,
browsingContext,
"findItemWithName should find same browsing context as findWithName"
);
}
}
for (let target of ["_self", "_top", "_parent", "_blank"]) {
for (let i = 0; i < docShells.length; ++i) {
let docShell = docShells[i].findItemWithName(
target,
null,
docShells[i],
false
);
let browsingContext = browsingContexts[i].findWithName(
target,
browsingContexts[i]
);
is(
docShell ? docShell.browsingContext : null,
browsingContext,
"findItemWithName should find same browsing context as findWithName for " +
target
);
}
}
}
);
BrowserTestUtils.removeTab(await sixth);
}
);
});

View File

@ -204,6 +204,64 @@ void TabGroup::MaybeDestroy() {
}
}
nsresult TabGroup::FindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aFoundItem);
*aFoundItem = nullptr;
MOZ_ASSERT(!aName.LowerCaseEqualsLiteral("_blank") &&
!aName.LowerCaseEqualsLiteral("_top") &&
!aName.LowerCaseEqualsLiteral("_parent") &&
!aName.LowerCaseEqualsLiteral("_self"));
for (nsPIDOMWindowOuter* outerWindow : mWindows) {
// Ignore non-toplevel windows
if (outerWindow->GetInProcessScriptableParentOrNull()) {
continue;
}
nsCOMPtr<nsIDocShellTreeItem> docshell = outerWindow->GetDocShell();
if (!docshell) {
continue;
}
BrowsingContext* bc = outerWindow->GetBrowsingContext();
if (!bc || !bc->IsTargetable()) {
continue;
}
nsCOMPtr<nsIDocShellTreeItem> root;
docshell->GetInProcessSameTypeRootTreeItem(getter_AddRefs(root));
MOZ_RELEASE_ASSERT(docshell == root);
if (root && aRequestor != root) {
root->FindItemWithName(aName, aRequestor, aOriginalRequestor,
/* aSkipTabGroup = */ true, aFoundItem);
if (*aFoundItem) {
break;
}
}
}
return NS_OK;
}
nsTArray<nsPIDOMWindowOuter*> TabGroup::GetTopLevelWindows() const {
MOZ_ASSERT(NS_IsMainThread());
nsTArray<nsPIDOMWindowOuter*> array;
for (nsPIDOMWindowOuter* outerWindow : mWindows) {
if (outerWindow->GetDocShell() &&
!outerWindow->GetInProcessScriptableParentOrNull()) {
array.AppendElement(outerWindow);
}
}
return array;
}
TabGroup::HashEntry::HashEntry(const nsACString* aKey)
: nsCStringHashKey(aKey), mDocGroup(nullptr) {}

View File

@ -101,6 +101,22 @@ class TabGroup final : public SchedulerGroup,
// Count with 'aActiveOnly' = true
uint32_t Count(bool aActiveOnly = false) const;
// Returns the nsIDocShellTreeItem with the given name, searching each of the
// docShell trees which are within this TabGroup. It will pass itself as
// aRequestor to each docShellTreeItem which it asks to search for the name,
// and will not search the docShellTreeItem which is passed as aRequestor.
//
// This method is used in order to correctly namespace named windows based on
// their unit of related browsing contexts.
//
// It is illegal to pass in the special case-insensitive names "_blank",
// "_self", "_parent" or "_top", as those should be handled elsewhere.
nsresult FindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
nsIDocShellTreeItem** aFoundItem);
nsTArray<nsPIDOMWindowOuter*> GetTopLevelWindows() const;
const nsTArray<nsPIDOMWindowOuter*>& GetWindows() { return mWindows; }
// This method is always safe to call off the main thread. The nsIEventTarget

View File

@ -45,8 +45,6 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/dom/BlobURLProtocolHandler.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/CustomElementRegistry.h"
@ -9245,11 +9243,7 @@ bool nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel) {
}
nsIDocShell* docShell = outer->GetDocShell();
BrowsingContext* browsingContext = docShell->GetBrowsingContext();
bool isOnlyToplevelBrowsingContext =
!browsingContext->GetParent() &&
browsingContext->Group()->Toplevels().Length() == 1;
if (!isOnlyToplevelBrowsingContext) {
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
outer->SetLargeAllocStatus(LargeAllocStatus::NOT_ONLY_TOPLEVEL_IN_TABGROUP);
return false;
}

View File

@ -4026,6 +4026,13 @@ bool nsGlobalWindowOuter::DispatchResizeEvent(const CSSIntSize& aSize) {
return target->DispatchEvent(*domEvent, CallerType::System, IgnoreErrors());
}
static already_AddRefed<nsIDocShellTreeItem> GetCallerDocShellTreeItem() {
nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
return callerItem.forget();
}
bool nsGlobalWindowOuter::WindowExists(const nsAString& aName,
bool aForceNoOpener,
bool aLookForCallerOnJSStack) {
@ -4037,7 +4044,20 @@ bool nsGlobalWindowOuter::WindowExists(const nsAString& aName,
aName.LowerCaseEqualsLiteral("_parent");
}
return !!mBrowsingContext->FindWithName(aName);
nsCOMPtr<nsIDocShellTreeItem> caller;
if (aLookForCallerOnJSStack) {
caller = GetCallerDocShellTreeItem();
}
if (!caller) {
caller = mDocShell;
}
nsCOMPtr<nsIDocShellTreeItem> namedItem;
mDocShell->FindItemWithName(aName, nullptr, caller,
/* aSkipTabGroup = */ false,
getter_AddRefs(namedItem));
return namedItem != nullptr;
}
already_AddRefed<nsIWidget> nsGlobalWindowOuter::GetMainWidget() {

View File

@ -12,7 +12,7 @@ interface BrowsingContext {
static BrowsingContext? getFromWindow(WindowProxy window);
BrowsingContext? findChildWithName(DOMString name, BrowsingContext accessor);
BrowsingContext? findWithName(DOMString name);
BrowsingContext? findWithName(DOMString name, BrowsingContext accessor);
readonly attribute DOMString name;

View File

@ -405,6 +405,20 @@ nsWebBrowser::GetInProcessSameTypeRootTreeItem(
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowser::FindItemWithName(const nsAString& aName,
nsIDocShellTreeItem* aRequestor,
nsIDocShellTreeItem* aOriginalRequestor,
bool aSkipTabGroup,
nsIDocShellTreeItem** aResult) {
NS_ENSURE_STATE(mDocShell);
NS_ASSERTION(mDocShellTreeOwner,
"This should always be set when in this situation");
return mDocShell->FindItemWithName(aName, aRequestor, aOriginalRequestor,
aSkipTabGroup, aResult);
}
dom::Document* nsWebBrowser::GetDocument() {
return mDocShell ? mDocShell->GetDocument() : nullptr;
}

View File

@ -26,8 +26,6 @@
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocumentLoader.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "nsIDOMWindow.h"
@ -1612,17 +1610,34 @@ nsWindowWatcher::GetWindowByName(const nsAString& aTargetName,
*aResult = nullptr;
BrowsingContext* currentContext =
aCurrentWindow
? nsPIDOMWindowOuter::From(aCurrentWindow)->GetBrowsingContext()
: nullptr;
nsPIDOMWindowOuter* currentWindow =
aCurrentWindow ? nsPIDOMWindowOuter::From(aCurrentWindow) : nullptr;
RefPtr<BrowsingContext> context =
GetBrowsingContextByName(aTargetName, false, currentContext);
nsCOMPtr<nsIDocShellTreeItem> treeItem;
if (context) {
*aResult = context->GetDOMWindow();
MOZ_ASSERT(*aResult);
nsCOMPtr<nsIDocShellTreeItem> startItem;
GetWindowTreeItem(currentWindow, getter_AddRefs(startItem));
if (startItem) {
// Note: original requestor is null here, per idl comments
startItem->FindItemWithName(aTargetName, nullptr, nullptr,
/* aSkipTabGroup = */ false,
getter_AddRefs(treeItem));
} else {
if (aTargetName.LowerCaseEqualsLiteral("_blank") ||
aTargetName.LowerCaseEqualsLiteral("_top") ||
aTargetName.LowerCaseEqualsLiteral("_parent") ||
aTargetName.LowerCaseEqualsLiteral("_self")) {
return NS_OK;
}
// Note: original requestor is null here, per idl comments
Unused << TabGroup::GetChromeTabGroup()->FindItemWithName(
aTargetName, nullptr, nullptr, getter_AddRefs(treeItem));
}
if (treeItem) {
nsCOMPtr<nsPIDOMWindowOuter> domWindow = treeItem->GetWindow();
domWindow.forget(aResult);
}
return NS_OK;
@ -2013,6 +2028,25 @@ int32_t nsWindowWatcher::WinHasOption(const nsACString& aOptions,
return found;
}
already_AddRefed<nsIDocShellTreeItem> nsWindowWatcher::GetCallerTreeItem(
nsIDocShellTreeItem* aParentItem) {
nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
if (!callerItem) {
callerItem = aParentItem;
}
return callerItem.forget();
}
BrowsingContext* nsWindowWatcher::GetCallerBrowsingContext(
BrowsingContext* aParentItem) {
if (nsCOMPtr<nsIDocShell> caller = do_GetInterface(GetEntryGlobal())) {
return caller->GetBrowsingContext();
}
return aParentItem;
}
already_AddRefed<BrowsingContext> nsWindowWatcher::GetBrowsingContextByName(
const nsAString& aName, bool aForceNoOpener,
BrowsingContext* aCurrentContext) {
@ -2029,8 +2063,12 @@ already_AddRefed<BrowsingContext> nsWindowWatcher::GetBrowsingContextByName(
}
}
RefPtr<BrowsingContext> currentContext(aCurrentContext);
if (!currentContext) {
RefPtr<BrowsingContext> caller = GetCallerBrowsingContext(aCurrentContext);
RefPtr<BrowsingContext> foundContext;
if (aCurrentContext) {
foundContext = aCurrentContext->FindWithName(aName, *caller);
} else {
if (aName.LowerCaseEqualsLiteral("_blank") ||
aName.LowerCaseEqualsLiteral("_top") ||
aName.LowerCaseEqualsLiteral("_parent") ||
@ -2040,14 +2078,15 @@ already_AddRefed<BrowsingContext> nsWindowWatcher::GetBrowsingContextByName(
// If we are looking for an item and we don't have a docshell we are
// checking on, let's just look in the chrome tab group!
currentContext =
BrowsingContextGroup::GetChromeGroup()->Toplevels().SafeElementAt(0);
nsCOMPtr<nsIDocShellTreeItem> foundItem;
Unused << TabGroup::GetChromeTabGroup()->FindItemWithName(
aName, nullptr, caller ? caller->GetDocShell() : nullptr,
getter_AddRefs(foundItem));
if (foundItem) {
foundContext = foundItem->GetBrowsingContext();
}
}
RefPtr<BrowsingContext> foundContext;
if (currentContext) {
foundContext = currentContext->FindWithName(aName);
}
return foundContext.forget();
}

View File

@ -66,6 +66,14 @@ class nsWindowWatcher : public nsIWindowWatcher,
nsWatcherWindowEntry* FindWindowEntry(mozIDOMWindowProxy* aWindow);
nsresult RemoveWindow(nsWatcherWindowEntry* aInfo);
// Get the caller tree item. Look on the JS stack, then fall back
// to the parent if there's nothing there.
already_AddRefed<nsIDocShellTreeItem> GetCallerTreeItem(
nsIDocShellTreeItem* aParentItem);
mozilla::dom::BrowsingContext* GetCallerBrowsingContext(
mozilla::dom::BrowsingContext* aParent);
// Will first look for a caller on the JS stack, and then fall back on
// aCurrentContext if it can't find one.
// It also knows to not look for things if aForceNoOpener is set.

View File

@ -659,14 +659,11 @@ var E10SUtils = {
// to change processes, we want to load into a new process so that we can throw
// this one out. We don't want to move into a new process if we have post data,
// because we would accidentally throw out that data.
let isOnlyToplevelBrowsingContext =
!aDocShell.browsingContext.parent &&
aDocShell.browsingContext.group.getToplevels().length == 1;
if (
!aHasPostData &&
Services.appinfo.remoteType == LARGE_ALLOCATION_REMOTE_TYPE &&
!aDocShell.awaitingLargeAlloc &&
isOnlyToplevelBrowsingContext
aDocShell.isOnlyToplevelInTabGroup
) {
return false;
}