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

[IntersectionObserver] Use inclusive intersect with remote frame parent

The rest of the MapToVisualRectInAncestorSpace code will do inclusive
intersections when the kEdgeInclusive flag is set, as required by
IntersectionObserver to correctly handle zero-area targets.

This patch adds coverage for this situation to the existing WPT for
cross-origin IntersectionObserver. Since the bug only affects
IntersectionObserver running inside an OOPIF, this also updates the
test to force the iframe into a different domain, rather than just
using the sandbox attribute (which is not sufficient to trigger OOPIF).

BUG=978759

Change-Id: I7dbe52d2f3e39e029fed3dda5be31190c593a1e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1754595Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Commit-Queue: Stefan Zager <szager@chromium.org>
Cr-Commit-Position: refs/heads/master@{#687361}
parent 7dc7c87c
......@@ -4284,10 +4284,7 @@ bool LocalFrameView::MapToVisualRectInTopFrameSpace(PhysicalRect& rect) {
PhysicalRect viewport_intersection_rect(
GetFrame().RemoteViewportIntersection());
rect.Intersect(viewport_intersection_rect);
if (rect.IsEmpty())
return false;
return true;
return rect.InclusiveIntersect(viewport_intersection_rect);
}
void LocalFrameView::ApplyTransformForTopFrameSpace(
......
......@@ -21,7 +21,7 @@ iframe {
</style>
<div class="spacer"></div>
<iframe src="resources/cross-origin-subframe.html" sandbox="allow-scripts"></iframe>
<iframe src="http://{{hosts[alt][]}}:{{ports[http][0]}}/intersection-observer/resources/cross-origin-subframe.html" sandbox="allow-scripts"></iframe>
<div class="spacer"></div>
<script>
......
<!DOCTYPE html>
<div style="height: 200px; width: 100px;"></div>
<div id="target" style="background-color: green; width:100px; height:100px"></div>
<div id="empty-target" style="width: 100px"></div>
<div style="height: 200px; width: 100px;"></div>
<script>
var port;
var entries = [];
var target = document.getElementById('target');
var target = document.getElementById("target");
var emptyTarget = document.getElementById("empty-target");
var scroller = document.scrollingElement;
var nextStep;
......@@ -26,19 +28,11 @@ function entryToJson(entry) {
boundingClientRect: clientRectToJson(entry.boundingClientRect),
intersectionRect: clientRectToJson(entry.intersectionRect),
rootBounds: clientRectToJson(entry.rootBounds),
isIntersecting: entry.isIntersecting,
target: entry.target.id
};
}
function coordinatesToClientRectJson(top, right, bottom, left) {
return {
top: top,
right: right,
bottom: bottom,
left: left
};
}
// 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
// RAF when it is received, and then send us a message to cause the next step to run.
......@@ -48,15 +42,23 @@ var observer = new IntersectionObserver(function(changes) {
entries = entries.concat(changes)
}, { rootMargin: "7px" });
observer.observe(target);
observer.observe(emptyTarget);
function step0() {
entries = entries.concat(observer.takeRecords());
nextStep = step1;
var expected = [{
boundingClientRect: coordinatesToClientRectJson(8, 208, 108, 308),
intersectionRect: coordinatesToClientRectJson(0, 0, 0, 0),
boundingClientRect: [8, 108, 208, 308],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: target.id
}, {
boundingClientRect: [8, 108, 308, 308],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: emptyTarget.id
}];
port.postMessage({
actual: entries.map(entryToJson),
......@@ -83,10 +85,17 @@ function step1() {
function step2() {
entries = entries.concat(observer.takeRecords());
var expected = [{
boundingClientRect: coordinatesToClientRectJson(-42, 108, 58, 8),
intersectionRect: coordinatesToClientRectJson(0, 108, 58, 8),
boundingClientRect: [8, 108, -42, 58],
intersectionRect: [8, 108, 0, 58],
rootBounds: "null",
isIntersecting: true,
target: target.id
}, {
boundingClientRect: [8, 108, 58, 58],
intersectionRect: [8, 108, 58, 58],
rootBounds: "null",
isIntersecting: true,
target: emptyTarget.id
}];
port.postMessage({
actual: entries.map(entryToJson),
......@@ -101,10 +110,17 @@ function step2() {
function step3() {
entries = entries.concat(observer.takeRecords());
var expected = [{
boundingClientRect: coordinatesToClientRectJson(-42, 108, 58, 8),
intersectionRect: coordinatesToClientRectJson(0, 0, 0, 0),
boundingClientRect: [8, 108, -42, 58],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: target.id
}, {
boundingClientRect: [8, 108, 58, 58],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: emptyTarget.id
}];
port.postMessage({
actual: entries.map(entryToJson),
......
......@@ -178,6 +178,7 @@ function checkJsonEntry(actual, expected) {
assert_equals(expected.rootBounds, 'null', 'rootBounds is null');
else
checkRect(actual.rootBounds, expected.rootBounds, 'entry.rootBounds');
assert_equals(actual.isIntersecting, expected.isIntersecting);
assert_equals(actual.target, expected.target);
}
......
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