diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 348203c2cb8..006997c4c87 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3131,6 +3131,20 @@ nsIDocument::ElementFromPoint(float aX, float aY) return ElementFromPointHelper(aX, aY, false, true); } +static nsIContent* +GetNonanonymousContent(nsIFrame* aFrame) +{ + for (nsIFrame* f = aFrame; f; + f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) { + nsIContent* content = f->GetContent(); + if (content && !content->IsInAnonymousSubtree()) { + return content; + } + } + + return nullptr; +} + Element* nsDocument::ElementFromPointHelper(float aX, float aY, bool aIgnoreRootScrollFrame, @@ -3162,13 +3176,14 @@ nsDocument::ElementFromPointHelper(float aX, float aY, } nsIFrame *ptFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, pt, - nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | + nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_CROSS_DOC | (aIgnoreRootScrollFrame ? nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME : 0)); if (!ptFrame) { return nullptr; } - nsIContent* elem = GetContentInThisDocument(ptFrame); + nsIContent* elem = GetNonanonymousContent(ptFrame); + NS_ASSERTION(!elem || elem->OwnerDoc() == this, "Wrong document"); if (elem && !elem->IsElement()) { elem = elem->GetParent(); } @@ -3217,14 +3232,15 @@ nsDocument::NodesFromRectHelper(float aX, float aY, nsAutoTArray outFrames; nsLayoutUtils::GetFramesForArea(rootFrame, rect, outFrames, - nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | + nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_CROSS_DOC | (aIgnoreRootScrollFrame ? nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME : 0)); // Used to filter out repeated elements in sequence. nsIContent* lastAdded = nullptr; for (uint32_t i = 0; i < outFrames.Length(); i++) { - nsIContent* node = GetContentInThisDocument(outFrames[i]); + nsIContent* node = GetNonanonymousContent(outFrames[i]); + NS_ASSERTION(!node || node->OwnerDoc() == this, "Wrong document"); if (node && !node->IsElement() && !node->IsNodeOfType(nsINode::eTEXT)) { // We have a node that isn't an element or a text node, @@ -8068,27 +8084,6 @@ nsDocument::DoUnblockOnload() } } -nsIContent* -nsDocument::GetContentInThisDocument(nsIFrame* aFrame) const -{ - for (nsIFrame* f = aFrame; f; - f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) { - nsIContent* content = f->GetContent(); - if (!content || content->IsInAnonymousSubtree()) - continue; - - if (content->OwnerDoc() == this) { - return content; - } - // We must be in a subdocument so jump directly to the root frame. - // GetParentOrPlaceholderForCrossDoc gets called immediately to jump up to - // the containing document. - f = f->PresContext()->GetPresShell()->GetRootFrame(); - } - - return nullptr; -} - void nsDocument::DispatchPageTransition(EventTarget* aDispatchTarget, const nsAString& aType, diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 8607143debe..fdb5b5883dd 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -1310,16 +1310,6 @@ private: mCSPWebConsoleErrorQueue.Flush(this); } - /** - * Find the (non-anonymous) content in this document for aFrame. It will - * be aFrame's content node if that content is in this document and not - * anonymous. Otherwise, when aFrame is in a subdocument, we use the frame - * element containing the subdocument containing aFrame, and/or find the - * nearest non-anonymous ancestor in this document. - * Returns null if there is no such element. - */ - nsIContent* GetContentInThisDocument(nsIFrame* aFrame) const; - // Just like EnableStyleSheetsForSet, but doesn't check whether // aSheetSet is null and allows the caller to control whether to set // aSheetSet as the preferred set in the CSSLoader. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e8cb2669fa7..6ef210a2075 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -486,6 +486,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, mHadToIgnoreSuppression(false), mIsAtRootOfPseudoStackingContext(false), mIncludeAllOutOfFlows(false), + mDescendIntoSubdocuments(true), mSelectedFramesOnly(false), mAccurateVisibleRegions(false), mAllowMergingAndFlattening(true), diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index d7a929ec9e9..b02f01ad00a 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -283,6 +283,11 @@ public: */ void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; } bool IsPaintingToWindow() const { return mIsPaintingToWindow; } + /** + * Call this to prevent descending into subdocuments. + */ + void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; } + bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; } /** * Returns true if merging and flattening of display lists should be @@ -647,6 +652,7 @@ private: bool mHadToIgnoreSuppression; bool mIsAtRootOfPseudoStackingContext; bool mIncludeAllOutOfFlows; + bool mDescendIntoSubdocuments; bool mSelectedFramesOnly; bool mAccurateVisibleRegions; bool mAllowMergingAndFlattening; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index fd72da235db..7c0539bc70a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2090,6 +2090,9 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect, builder.SetIgnoreScrollFrame(rootScrollFrame); } } + if (aFlags & IGNORE_CROSS_DOC) { + builder.SetDescendIntoSubdocuments(false); + } builder.EnterPresShell(aFrame, target); aFrame->BuildDisplayListForStackingContext(&builder, target, &list); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 4224503b9c3..5284dd6670c 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -607,7 +607,11 @@ public: * When set, clipping due to the root scroll frame (and any other viewport- * related clipping) is ignored. */ - IGNORE_ROOT_SCROLL_FRAME = 0x02 + IGNORE_ROOT_SCROLL_FRAME = 0x02, + /** + * When set, return only content in the same document as aFrame. + */ + IGNORE_CROSS_DOC = 0x04 }; /** diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 3dfa4c59e59..a27aad5d809 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -288,8 +288,9 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, DisplayBorderBackgroundOutline(aBuilder, aLists); } - if (!mInnerView) + if (!mInnerView || !aBuilder->GetDescendIntoSubdocuments()) { return; + } nsFrameLoader* frameLoader = FrameLoader(); if (frameLoader) {