Bug 1581974 - Change DOMIntersectionObserver::Update to use the BrowsingContext parent chain. r=jwatt
Using the BrowsingUsing parent chain is able to avoid 1) obtaining a wrong root in cross-process documents and also avoid 2) not being able to obtain the proper root in same-origin documents in the case where there is a cross-process document in between the top level document and the same-origin documents. dom/base/test/test_intersectionobservers.html is a test of case 1). testing/web-platform/tests/intersection-observer/same-origin-grand-child-iframe.sub.html is a test case of case 2). Differential Revision: https://phabricator.services.mozilla.com/D46432
This commit is contained in:
@@ -230,8 +230,26 @@ static BrowsingContextOrigin SimilarOrigin(const Element& aTarget,
|
||||
: BrowsingContextOrigin::Different;
|
||||
}
|
||||
|
||||
// NOTE: This returns nullptr if |aDocument| is in a cross process.
|
||||
static Document* GetTopLevelDocument(const Document& aDocument) {
|
||||
BrowsingContext* browsingContext = aDocument.GetBrowsingContext();
|
||||
if (!browsingContext) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* topWindow = browsingContext->Top()->GetDOMWindow();
|
||||
if (!topWindow) {
|
||||
// If we don't have a DOMWindow, We are not in same origin.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return topWindow->GetExtantDoc();
|
||||
}
|
||||
|
||||
void DOMIntersectionObserver::Update(Document* aDocument,
|
||||
DOMHighResTimeStamp time) {
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
nsRect rootRect;
|
||||
nsIFrame* rootFrame = nullptr;
|
||||
Element* root = mRoot;
|
||||
@@ -252,28 +270,14 @@ void DOMIntersectionObserver::Update(Document* aDocument,
|
||||
rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||
rootFrame, rootRectRelativeToRootFrame, containingBlock);
|
||||
}
|
||||
} else if (PresShell* presShell = aDocument->GetPresShell()) {
|
||||
// FIXME(emilio): This shouldn't probably go through the presShell and just
|
||||
// through the document tree.
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
nsPresContext* presContext = rootFrame->PresContext();
|
||||
while (!presContext->IsRootContentDocument()) {
|
||||
presContext = presContext->GetParentPresContext();
|
||||
if (!presContext) {
|
||||
break;
|
||||
}
|
||||
nsIFrame* rootScrollFrame =
|
||||
presContext->PresShell()->GetRootScrollFrame();
|
||||
if (rootScrollFrame) {
|
||||
rootFrame = rootScrollFrame;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (Document* topLevelDocument = GetTopLevelDocument(*aDocument)) {
|
||||
if (PresShell* presShell = topLevelDocument->GetPresShell()) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,12 +405,11 @@ void DOMIntersectionObserver::Update(Document* aDocument,
|
||||
}
|
||||
|
||||
if (target->UpdateIntersectionObservation(this, threshold)) {
|
||||
QueueIntersectionObserverEntry(target, time,
|
||||
origin == BrowsingContextOrigin::Different
|
||||
? Nothing()
|
||||
: Some(rootIntersectionRect),
|
||||
targetRect, intersectionRect,
|
||||
intersectionRatio);
|
||||
QueueIntersectionObserverEntry(
|
||||
target, time,
|
||||
origin == BrowsingContextOrigin::Similar ? Some(rootIntersectionRect)
|
||||
: Nothing(),
|
||||
targetRect, intersectionRect, intersectionRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user