Bug 1575051 - Remove nsIDocShellTreeItem.findItemWithName. r=kmag

This also allows us to remove TabGroup::FindItemWithName, which is a
big step towards removing TabGroup entirely.

Differential Revision: https://phabricator.services.mozilla.com/D46285

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andreas Farre 2019-09-24 13:16:26 +00:00
Родитель 141e986c3f
Коммит 3977fe175d
17 изменённых файлов: 58 добавлений и 533 удалений

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

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

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

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

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

@ -133,6 +133,19 @@ JSObject* BrowsingContextGroup::WrapObject(JSContext* aCx,
return BrowsingContextGroup_Binding::Wrap(aCx, this, aGivenProto); 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, NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BrowsingContextGroup, mContexts,
mToplevels, mSubscribers, mCachedContexts) mToplevels, mSubscribers, mCachedContexts)

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

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

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

@ -2888,65 +2888,6 @@ static bool ItemIsActive(nsIDocShellTreeItem* aItem) {
return false; 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() { void nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
// Chrome docshells must not have a private browsing OriginAttribute // Chrome docshells must not have a private browsing OriginAttribute
// Content docshells must maintain the equality: // Content docshells must maintain the equality:
@ -2959,64 +2900,6 @@ 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) { bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) {
// If no target then not sandboxed. // If no target then not sandboxed.
if (!aTargetBC) { if (!aTargetBC) {
@ -8704,11 +8587,9 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
MOZ_ASSERT(aLoadState, "need a load state!"); MOZ_ASSERT(aLoadState, "need a load state!");
MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!"); MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!");
nsresult rv; nsresult rv = NS_OK;
nsCOMPtr<nsIDocShell> targetDocShell; nsCOMPtr<nsIDocShell> targetDocShell;
// Locate the target DocShell.
nsCOMPtr<nsIDocShellTreeItem> targetItem;
// Only _self, _parent, and _top are supported in noopener case. But we // 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 // have to be careful to not apply that to the noreferrer case. See bug
// 1358469. // 1358469.
@ -8719,12 +8600,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState,
aLoadState->Target().LowerCaseEqualsLiteral("_self") || aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
aLoadState->Target().LowerCaseEqualsLiteral("_parent") || aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
aLoadState->Target().LowerCaseEqualsLiteral("_top")) { aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
rv = FindItemWithName(aLoadState->Target(), nullptr, this, false, if (BrowsingContext* context =
getter_AddRefs(targetItem)); mBrowsingContext->FindWithName(aLoadState->Target())) {
NS_ENSURE_SUCCESS(rv, rv); targetDocShell = context->GetDocShell();
}
} }
targetDocShell = do_QueryInterface(targetItem);
if (!targetDocShell) { if (!targetDocShell) {
// If the targetDocShell doesn't exist, then this is a new docShell // If the targetDocShell doesn't exist, then this is a new docShell
// and we should consider this a TYPE_DOCUMENT load // and we should consider this a TYPE_DOCUMENT load

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

@ -942,14 +942,6 @@ class nsDocShell final : public nsDocLoader,
MOZ_MUST_USE bool MaybeInitTiming(); MOZ_MUST_USE bool MaybeInitTiming();
void MaybeResetInitTiming(bool aReset); 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 // Convenience method for getting our parent docshell. Can return null
already_AddRefed<nsDocShell> GetInProcessParentDocshell(); already_AddRefed<nsDocShell> GetInProcessParentDocshell();

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

@ -92,39 +92,6 @@ interface nsIDocShellTreeItem : nsISupports
[binaryname(InProcessSameTypeRootTreeItem)] [binaryname(InProcessSameTypeRootTreeItem)]
readonly attribute nsIDocShellTreeItem sameTypeRootTreeItem; 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 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. the docshell has things it needs to tell to the owner of the docshell.
@ -222,4 +189,3 @@ interface nsIDocShellTreeItem : nsISupports
[noscript,nostdcall,notxpcom] Document getDocument(); [noscript,nostdcall,notxpcom] Document getDocument();
[noscript,nostdcall,notxpcom] nsPIDOMWindowOuter getWindow(); [noscript,nostdcall,notxpcom] nsPIDOMWindowOuter getWindow();
}; };

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

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

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

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

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

@ -1,194 +0,0 @@
/* 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);
}
);
});

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

@ -204,50 +204,6 @@ 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 { nsTArray<nsPIDOMWindowOuter*> TabGroup::GetTopLevelWindows() const {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsTArray<nsPIDOMWindowOuter*> array; nsTArray<nsPIDOMWindowOuter*> array;

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

@ -101,21 +101,6 @@ class TabGroup final : public SchedulerGroup,
// Count with 'aActiveOnly' = true // Count with 'aActiveOnly' = true
uint32_t Count(bool aActiveOnly = false) const; 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; nsTArray<nsPIDOMWindowOuter*> GetTopLevelWindows() const;
const nsTArray<nsPIDOMWindowOuter*>& GetWindows() { return mWindows; } const nsTArray<nsPIDOMWindowOuter*>& GetWindows() { return mWindows; }

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

@ -4026,13 +4026,6 @@ bool nsGlobalWindowOuter::DispatchResizeEvent(const CSSIntSize& aSize) {
return target->DispatchEvent(*domEvent, CallerType::System, IgnoreErrors()); 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 nsGlobalWindowOuter::WindowExists(const nsAString& aName,
bool aForceNoOpener, bool aForceNoOpener,
bool aLookForCallerOnJSStack) { bool aLookForCallerOnJSStack) {
@ -4044,20 +4037,7 @@ bool nsGlobalWindowOuter::WindowExists(const nsAString& aName,
aName.LowerCaseEqualsLiteral("_parent"); aName.LowerCaseEqualsLiteral("_parent");
} }
nsCOMPtr<nsIDocShellTreeItem> caller; return !!mBrowsingContext->FindWithName(aName);
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() { already_AddRefed<nsIWidget> nsGlobalWindowOuter::GetMainWidget() {

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

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

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

@ -405,20 +405,6 @@ nsWebBrowser::GetInProcessSameTypeRootTreeItem(
return NS_OK; 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() { dom::Document* nsWebBrowser::GetDocument() {
return mDocShell ? mDocShell->GetDocument() : nullptr; return mDocShell ? mDocShell->GetDocument() : nullptr;
} }

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

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

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

@ -66,14 +66,6 @@ class nsWindowWatcher : public nsIWindowWatcher,
nsWatcherWindowEntry* FindWindowEntry(mozIDOMWindowProxy* aWindow); nsWatcherWindowEntry* FindWindowEntry(mozIDOMWindowProxy* aWindow);
nsresult RemoveWindow(nsWatcherWindowEntry* aInfo); 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 // Will first look for a caller on the JS stack, and then fall back on
// aCurrentContext if it can't find one. // aCurrentContext if it can't find one.
// It also knows to not look for things if aForceNoOpener is set. // It also knows to not look for things if aForceNoOpener is set.