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) { ...@@ -4284,10 +4284,7 @@ bool LocalFrameView::MapToVisualRectInTopFrameSpace(PhysicalRect& rect) {
PhysicalRect viewport_intersection_rect( PhysicalRect viewport_intersection_rect(
GetFrame().RemoteViewportIntersection()); GetFrame().RemoteViewportIntersection());
rect.Intersect(viewport_intersection_rect); return rect.InclusiveIntersect(viewport_intersection_rect);
if (rect.IsEmpty())
return false;
return true;
} }
void LocalFrameView::ApplyTransformForTopFrameSpace( void LocalFrameView::ApplyTransformForTopFrameSpace(
......
...@@ -21,7 +21,7 @@ iframe { ...@@ -21,7 +21,7 @@ iframe {
</style> </style>
<div class="spacer"></div> <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> <div class="spacer"></div>
<script> <script>
......
<!DOCTYPE html> <!DOCTYPE html>
<div style="height: 200px; width: 100px;"></div> <div style="height: 200px; width: 100px;"></div>
<div id="target" style="background-color: green; width:100px; height: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> <div style="height: 200px; width: 100px;"></div>
<script> <script>
var port; var port;
var entries = []; var entries = [];
var target = document.getElementById('target'); var target = document.getElementById("target");
var emptyTarget = document.getElementById("empty-target");
var scroller = document.scrollingElement; var scroller = document.scrollingElement;
var nextStep; var nextStep;
...@@ -26,19 +28,11 @@ function entryToJson(entry) { ...@@ -26,19 +28,11 @@ function entryToJson(entry) {
boundingClientRect: clientRectToJson(entry.boundingClientRect), boundingClientRect: clientRectToJson(entry.boundingClientRect),
intersectionRect: clientRectToJson(entry.intersectionRect), intersectionRect: clientRectToJson(entry.intersectionRect),
rootBounds: clientRectToJson(entry.rootBounds), rootBounds: clientRectToJson(entry.rootBounds),
isIntersecting: entry.isIntersecting,
target: entry.target.id 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. // 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.
...@@ -48,15 +42,23 @@ var observer = new IntersectionObserver(function(changes) { ...@@ -48,15 +42,23 @@ var observer = new IntersectionObserver(function(changes) {
entries = entries.concat(changes) entries = entries.concat(changes)
}, { rootMargin: "7px" }); }, { rootMargin: "7px" });
observer.observe(target); observer.observe(target);
observer.observe(emptyTarget);
function step0() { function step0() {
entries = entries.concat(observer.takeRecords()); entries = entries.concat(observer.takeRecords());
nextStep = step1; nextStep = step1;
var expected = [{ var expected = [{
boundingClientRect: coordinatesToClientRectJson(8, 208, 108, 308), boundingClientRect: [8, 108, 208, 308],
intersectionRect: coordinatesToClientRectJson(0, 0, 0, 0), intersectionRect: [0, 0, 0, 0],
rootBounds: "null", rootBounds: "null",
isIntersecting: false,
target: target.id target: target.id
}, {
boundingClientRect: [8, 108, 308, 308],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: emptyTarget.id
}]; }];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
...@@ -83,10 +85,17 @@ function step1() { ...@@ -83,10 +85,17 @@ function step1() {
function step2() { function step2() {
entries = entries.concat(observer.takeRecords()); entries = entries.concat(observer.takeRecords());
var expected = [{ var expected = [{
boundingClientRect: coordinatesToClientRectJson(-42, 108, 58, 8), boundingClientRect: [8, 108, -42, 58],
intersectionRect: coordinatesToClientRectJson(0, 108, 58, 8), intersectionRect: [8, 108, 0, 58],
rootBounds: "null", rootBounds: "null",
isIntersecting: true,
target: target.id target: target.id
}, {
boundingClientRect: [8, 108, 58, 58],
intersectionRect: [8, 108, 58, 58],
rootBounds: "null",
isIntersecting: true,
target: emptyTarget.id
}]; }];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
...@@ -101,10 +110,17 @@ function step2() { ...@@ -101,10 +110,17 @@ function step2() {
function step3() { function step3() {
entries = entries.concat(observer.takeRecords()); entries = entries.concat(observer.takeRecords());
var expected = [{ var expected = [{
boundingClientRect: coordinatesToClientRectJson(-42, 108, 58, 8), boundingClientRect: [8, 108, -42, 58],
intersectionRect: coordinatesToClientRectJson(0, 0, 0, 0), intersectionRect: [0, 0, 0, 0],
rootBounds: "null", rootBounds: "null",
isIntersecting: false,
target: target.id target: target.id
}, {
boundingClientRect: [8, 108, 58, 58],
intersectionRect: [0, 0, 0, 0],
rootBounds: "null",
isIntersecting: false,
target: emptyTarget.id
}]; }];
port.postMessage({ port.postMessage({
actual: entries.map(entryToJson), actual: entries.map(entryToJson),
......
...@@ -178,6 +178,7 @@ function checkJsonEntry(actual, expected) { ...@@ -178,6 +178,7 @@ function checkJsonEntry(actual, expected) {
assert_equals(expected.rootBounds, 'null', 'rootBounds is null'); assert_equals(expected.rootBounds, 'null', 'rootBounds is null');
else else
checkRect(actual.rootBounds, expected.rootBounds, 'entry.rootBounds'); checkRect(actual.rootBounds, expected.rootBounds, 'entry.rootBounds');
assert_equals(actual.isIntersecting, expected.isIntersecting);
assert_equals(actual.target, expected.target); 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