Commit c317bae5 authored by Stefan Zager's avatar Stefan Zager Committed by Commit Bot

[IntersectionObserver] Fix handling of remote parent frame intersection

If a process-isolated iframe has a zero-area intersection with its
parent frame, implicit root observations should not be able to have
isIntersecting=true.

BUG=1070332
R=vmpstr@chromium.org

Change-Id: I05e8a05af14e84d493609bbc1675a28793dc1823
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2166605
Commit-Queue: vmpstr <vmpstr@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#762875}
parent e95c82b1
...@@ -473,6 +473,10 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root, ...@@ -473,6 +473,10 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root,
// done yet. // done yet.
LocalFrame* local_root_frame = root->GetDocument().GetFrame(); LocalFrame* local_root_frame = root->GetDocument().GetFrame();
IntRect clip_rect(local_root_frame->RemoteViewportIntersection()); IntRect clip_rect(local_root_frame->RemoteViewportIntersection());
if (clip_rect.IsEmpty()) {
intersection_rect = PhysicalRect();
does_intersect = false;
} else {
// Map clip_rect from the coordinate system of the local root frame to // Map clip_rect from the coordinate system of the local root frame to
// the coordinate system of the remote main frame. // the coordinate system of the remote main frame.
clip_rect.MoveBy(IntPoint(local_root_frame->RemoteViewportOffset())); clip_rect.MoveBy(IntPoint(local_root_frame->RemoteViewportOffset()));
...@@ -480,6 +484,7 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root, ...@@ -480,6 +484,7 @@ bool IntersectionGeometry::ClipToRoot(const LayoutObject* root,
intersection_rect.InclusiveIntersect(PhysicalRect(clip_rect)); intersection_rect.InclusiveIntersect(PhysicalRect(clip_rect));
} }
} }
}
return does_intersect; return does_intersect;
} }
......
...@@ -29,10 +29,15 @@ function entryToJson(entry) { ...@@ -29,10 +29,15 @@ function entryToJson(entry) {
intersectionRect: clientRectToJson(entry.intersectionRect), intersectionRect: clientRectToJson(entry.intersectionRect),
rootBounds: clientRectToJson(entry.rootBounds), rootBounds: clientRectToJson(entry.rootBounds),
isIntersecting: entry.isIntersecting, isIntersecting: entry.isIntersecting,
target: entry.target.id target: entry.target === document.documentElement ? "html" : entry.target.id
}; };
} }
function boundingClientRectToJson(element) {
let r = element.getBoundingClientRect();
return [r.left, r.right, r.top, r.bottom];
}
// Note that we never use RAF in this code, because this frame might get render-throttled. // Note that we never use RAF in this code, because this frame might get render-throttled.
// Instead of RAF-ing, we just post an empty message to the parent window, which will // Instead of RAF-ing, we just post an empty message to the parent window, which will
// RAF when it is received, and then send us a message to cause the next step to run. // RAF when it is received, and then send us a message to cause the next step to run.
...@@ -43,6 +48,7 @@ var observer = new IntersectionObserver(function(changes) { ...@@ -43,6 +48,7 @@ var observer = new IntersectionObserver(function(changes) {
}, { rootMargin: "7px" }); }, { rootMargin: "7px" });
observer.observe(target); observer.observe(target);
observer.observe(emptyTarget); observer.observe(emptyTarget);
observer.observe(document.documentElement);
function step0() { function step0() {
entries = entries.concat(observer.takeRecords()); entries = entries.concat(observer.takeRecords());
...@@ -59,6 +65,12 @@ function step0() { ...@@ -59,6 +65,12 @@ function step0() {
rootBounds: "null", rootBounds: "null",
isIntersecting: false, isIntersecting: false,
target: emptyTarget.id target: emptyTarget.id
}, {
boundingClientRect: boundingClientRectToJson(document.documentElement),
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: "html"
}]; }];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
...@@ -71,9 +83,21 @@ function step0() { ...@@ -71,9 +83,21 @@ function step0() {
function step1() { function step1() {
entries = entries.concat(observer.takeRecords()); entries = entries.concat(observer.takeRecords());
var client_rect = boundingClientRectToJson(document.documentElement);
// When the top document is scrolled all the way up, the iframe element is
// 108px below the scrolling viewport, and the iframe has a 2px border. When
// the top document is scrolled to y=200, the top 90px of the iframe's content
// is visible.
var expected = [{
boundingClientRect: client_rect,
intersectionRect: client_rect.slice(0, 3).concat(90),
rootBounds: "null",
isIntersecting: true,
target: "html"
}];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
expected: [], expected: expected,
description: "topDocument.scrollingElement.scrollTop = 200" description: "topDocument.scrollingElement.scrollTop = 200"
}, "*"); }, "*");
entries = []; entries = [];
...@@ -121,6 +145,12 @@ function step3() { ...@@ -121,6 +145,12 @@ function step3() {
rootBounds: "null", rootBounds: "null",
isIntersecting: false, isIntersecting: false,
target: emptyTarget.id target: emptyTarget.id
}, {
boundingClientRect: boundingClientRectToJson(document.documentElement),
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: "html"
}]; }];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment