Title: [237737] trunk
Revision
237737
Author
aj...@chromium.org
Date
2018-11-02 09:55:13 -0700 (Fri, 02 Nov 2018)

Log Message

Allow cross-document intersection observing
https://bugs.webkit.org/show_bug.cgi?id=165746

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

Update expectations for tests that now pass.

* web-platform-tests/intersection-observer/client-rect-expected.txt:
* web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt:
* web-platform-tests/intersection-observer/iframe-no-root-expected.txt:
* web-platform-tests/intersection-observer/timestamp-expected.txt:

Source/WebCore:

Add logic to compute the intersection between the viewport and an element in a
subframe.

Add a FloatRect version of ScrollView::rootViewToContents, and FloatRect versions
of the methods it calls.

Test: http/tests/intersection-observer/intermediate-frame-changes.html
Also covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.

* dom/Document.cpp:
(WebCore::computeClippedRectInRootContentsSpace):
(WebCore::computeIntersectionState):
(WebCore::Document::updateIntersectionObservations):
* page/FrameView.cpp:
(WebCore::FrameView::viewportContentsChanged):
(WebCore::FrameView::convertFromContainingViewToRenderer const):
(WebCore::FrameView::convertFromContainingView const):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::viewToContents const):
(WebCore::ScrollView::contentsToView const):
(WebCore::ScrollView::rootViewToContents const):
* platform/ScrollView.h:
* platform/Widget.cpp:
(WebCore::Widget::convertFromRootView const):
(WebCore::Widget::convertFromContainingView const):
* platform/Widget.h:

LayoutTests:

Add a test that cross-document intersection observations are triggered when an intermediate frame
scrolls. Skip the test on WK1 platforms where IntersectionObserver is not supported.

Add platform-specific baselines for tests involving iframe scrolling, which isn't supported on iOS.

* http/tests/intersection-observer/intermediate-frame-changes-expected.txt: Added.
* http/tests/intersection-observer/intermediate-frame-changes.html: Added.
* http/tests/intersection-observer/resources/intermediate-frame.html: Added.
* http/tests/intersection-observer/resources/nested-frame.html: Added.
* platform/ios/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt.
* platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt.
* platform/mac-wk1/TestExpectations:
* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (237736 => 237737)


--- trunk/LayoutTests/ChangeLog	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/ChangeLog	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1,3 +1,25 @@
+2018-11-02  Ali Juma  <aj...@chromium.org>
+
+        Allow cross-document intersection observing
+        https://bugs.webkit.org/show_bug.cgi?id=165746
+
+        Reviewed by Simon Fraser.
+
+        Add a test that cross-document intersection observations are triggered when an intermediate frame
+        scrolls. Skip the test on WK1 platforms where IntersectionObserver is not supported.
+
+        Add platform-specific baselines for tests involving iframe scrolling, which isn't supported on iOS.
+
+        * http/tests/intersection-observer/intermediate-frame-changes-expected.txt: Added.
+        * http/tests/intersection-observer/intermediate-frame-changes.html: Added.
+        * http/tests/intersection-observer/resources/intermediate-frame.html: Added.
+        * http/tests/intersection-observer/resources/nested-frame.html: Added.
+        * platform/ios/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt.
+        * platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt: Copied from LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt.
+        * platform/mac-wk1/TestExpectations:
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+
 2018-11-02  Per Arne Vollan  <pvol...@apple.com>
 
         [Win] Layout Test fast/block/basic/inline-content-with-floating-image.html is failing

Added: trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes-expected.txt (0 => 237737)


--- trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,4 @@
+
+
+PASS Intersection observations are updated when an intermediate frame changes 
+

Added: trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes.html (0 => 237737)


--- trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/intersection-observer/intermediate-frame-changes.html	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<script src=""
+<script src=""
+
+<style>
+iframe {
+  width: 300px;
+  height: 300px;
+}
+</style>
+<iframe id="intermediateFrame" src=""
+
+<script>
+var entries = [];
+var iframe = document.getElementById("intermediateFrame");
+iframe._onload_ = function() {
+    var nestedFrame = iframe.contentDocument.getElementById("nestedFrame");
+    var scroller = iframe.contentDocument.getElementById("scroller");
+    var target = nestedFrame.contentDocument.getElementById("target");
+
+    async_test(function(t) {
+        new IntersectionObserver(function(changes) {
+            entries = entries.concat(changes);
+            if (entries.length == 1) {
+                assert_false(entries[0].isIntersecting);
+                scroller.scrollTop = 250;
+            } else if (entries.length == 2) {
+                assert_true(entries[1].isIntersecting);
+                scroller.scrollTop = 0;
+            } else {
+                assert_false(entries[2].isIntersecting);
+                t.done();
+            }
+        }).observe(target);
+    }, "Intersection observations are updated when an intermediate frame changes");
+};
+</script>

Added: trunk/LayoutTests/http/tests/intersection-observer/resources/intermediate-frame.html (0 => 237737)


--- trunk/LayoutTests/http/tests/intersection-observer/resources/intermediate-frame.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/intersection-observer/resources/intermediate-frame.html	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+iframe {
+  width: 200px;
+  height: 300px;
+}
+
+#scroller {
+  width: 250px;
+  height: 100px;
+  overflow: scroll;
+}
+</style>
+
+<div id="scroller">
+    <iframe id="nestedFrame" src=""
+</div>

Added: trunk/LayoutTests/http/tests/intersection-observer/resources/nested-frame.html (0 => 237737)


--- trunk/LayoutTests/http/tests/intersection-observer/resources/nested-frame.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/intersection-observer/resources/nested-frame.html	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+#target {
+  width: 50px;
+  height: 100px;
+  background-color: green;
+}
+
+#spacer {
+  width: 50px;
+  height: 200px;
+}
+</style>
+
+<div id="spacer"></div>
+<div id="target"</div>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237736 => 237737)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1,3 +1,17 @@
+2018-11-02  Ali Juma  <aj...@chromium.org>
+
+        Allow cross-document intersection observing
+        https://bugs.webkit.org/show_bug.cgi?id=165746
+
+        Reviewed by Simon Fraser.
+
+        Update expectations for tests that now pass. 
+
+        * web-platform-tests/intersection-observer/client-rect-expected.txt:
+        * web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt:
+        * web-platform-tests/intersection-observer/iframe-no-root-expected.txt:
+        * web-platform-tests/intersection-observer/timestamp-expected.txt:
+
 2018-11-01  Chris Dumez  <cdu...@apple.com>
 
         Location object sans browsing context

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/client-rect-expected.txt (237736 => 237737)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/client-rect-expected.txt	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/client-rect-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1,4 +1,4 @@
 
 PASS IntersectionObserverEntry.boundingClientRect should match target.boundingClientRect() 
-FAIL First rAF should generate notification. assert_equals: entries[0].boundingClientRect.left expected 8 but got 0
+PASS First rAF should generate notification. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt (237736 => 237737)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -3,6 +3,6 @@
 PASS Intersection observer test with no explicit root and target in a cross-origin iframe. 
 PASS First rAF 
 PASS topDocument.scrollingElement.scrollTop = 200 
-FAIL iframeDocument.scrollingElement.scrollTop = 250 assert_equals: expected 1 but got 0
-FAIL topDocument.scrollingElement.scrollTop = 100 assert_equals: expected 1 but got 0
+PASS iframeDocument.scrollingElement.scrollTop = 250 
+PASS topDocument.scrollingElement.scrollTop = 100 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt (237736 => 237737)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1,8 +1,8 @@
 
 
 PASS Observer with the implicit root; target in a same-origin iframe. 
-FAIL First rAF. assert_equals: entries[0].boundingClientRect.left expected 8 but got 0
+PASS First rAF. 
 PASS document.scrollingElement.scrollTop = 200 
-FAIL iframe.contentDocument.scrollingElement.scrollTop = 250 assert_equals: entries.length expected 2 but got 1
-FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+PASS iframe.contentDocument.scrollingElement.scrollTop = 250 
+PASS document.scrollingElement.scrollTop = 100 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/timestamp-expected.txt (237736 => 237737)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/timestamp-expected.txt	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/timestamp-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -2,5 +2,5 @@
 
 PASS Check that timestamps correspond to the to execution context that created the observer. 
 PASS First rAF after iframe is loaded. 
-FAIL Generate notifications. undefined is not an object (evaluating 'topWindowEntries[1].time')
+PASS Generate notifications. 
 

Copied: trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt (from rev 237735, trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt) (0 => 237737)


--- trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,8 @@
+
+
+PASS Intersection observer test with no explicit root and target in a cross-origin iframe. 
+PASS First rAF 
+PASS topDocument.scrollingElement.scrollTop = 200 
+FAIL iframeDocument.scrollingElement.scrollTop = 250 assert_equals: expected 1 but got 0
+FAIL topDocument.scrollingElement.scrollTop = 100 assert_equals: expected 1 but got 0
+

Copied: trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt (from rev 237735, trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt) (0 => 237737)


--- trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt	2018-11-02 16:55:13 UTC (rev 237737)
@@ -0,0 +1,8 @@
+
+
+PASS Observer with the implicit root; target in a same-origin iframe. 
+PASS First rAF. 
+PASS document.scrollingElement.scrollTop = 200 
+FAIL iframe.contentDocument.scrollingElement.scrollTop = 250 assert_equals: entries.length expected 2 but got 1
+FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (237736 => 237737)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2018-11-02 16:55:13 UTC (rev 237737)
@@ -531,6 +531,7 @@
 webkit.org/b/172044 [ Debug ] imported/w3c/web-platform-tests/IndexedDB/open-request-queue.html [ Pass Timeout ]
 
 # Not supported on WK1
+http/tests/intersection-observer [ Skip ]
 imported/w3c/web-platform-tests/intersection-observer [ Skip ]
 intersection-observer [ Skip ]
 

Modified: trunk/LayoutTests/platform/win/TestExpectations (237736 => 237737)


--- trunk/LayoutTests/platform/win/TestExpectations	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/platform/win/TestExpectations	2018-11-02 16:55:13 UTC (rev 237737)
@@ -133,6 +133,7 @@
 
 # IntersectionObserver is off by default
 webkit.org/b/188613 intersection-observer [ Skip ]
+webkit.org/b/188613 http/tests/intersection-observer [ Skip ]
 
 # TODO Should be moved to platform/mac <rdar://5621425>
 http/tests/misc/willCacheResponse-delegate-callback.html [ Skip ]

Modified: trunk/LayoutTests/platform/wincairo/TestExpectations (237736 => 237737)


--- trunk/LayoutTests/platform/wincairo/TestExpectations	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/LayoutTests/platform/wincairo/TestExpectations	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1463,6 +1463,7 @@
 
 # IntersectionObserver is off by default
 webkit.org/b/188613 intersection-observer [ Skip ]
+webkit.org/b/188613 http/tests/intersection-observer [ Skip ]
 
 [ Debug ] css2.1/20110323/replaced-intrinsic-ratio-001.htm [ Pass Failure ]
 

Modified: trunk/Source/WebCore/ChangeLog (237736 => 237737)


--- trunk/Source/WebCore/ChangeLog	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/ChangeLog	2018-11-02 16:55:13 UTC (rev 237737)
@@ -1,3 +1,38 @@
+2018-11-02  Ali Juma  <aj...@chromium.org>
+
+        Allow cross-document intersection observing
+        https://bugs.webkit.org/show_bug.cgi?id=165746
+
+        Reviewed by Simon Fraser.
+
+        Add logic to compute the intersection between the viewport and an element in a
+        subframe.
+
+        Add a FloatRect version of ScrollView::rootViewToContents, and FloatRect versions
+        of the methods it calls.
+
+        Test: http/tests/intersection-observer/intermediate-frame-changes.html
+        Also covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.
+
+        * dom/Document.cpp:
+        (WebCore::computeClippedRectInRootContentsSpace):
+        (WebCore::computeIntersectionState):
+        (WebCore::Document::updateIntersectionObservations):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::viewportContentsChanged):
+        (WebCore::FrameView::convertFromContainingViewToRenderer const):
+        (WebCore::FrameView::convertFromContainingView const):
+        * page/FrameView.h:
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::viewToContents const):
+        (WebCore::ScrollView::contentsToView const):
+        (WebCore::ScrollView::rootViewToContents const):
+        * platform/ScrollView.h:
+        * platform/Widget.cpp:
+        (WebCore::Widget::convertFromRootView const):
+        (WebCore::Widget::convertFromContainingView const):
+        * platform/Widget.h:
+
 2018-11-02  Rob Buis  <rb...@igalia.com>
 
         Remove ENABLE_OPENCL fully

Modified: trunk/Source/WebCore/dom/Document.cpp (237736 => 237737)


--- trunk/Source/WebCore/dom/Document.cpp	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-11-02 16:55:13 UTC (rev 237737)
@@ -7603,6 +7603,26 @@
     localRootBounds.expand(rootMarginFloatBox);
 }
 
+static std::optional<LayoutRect> computeClippedRectInRootContentsSpace(const LayoutRect& rect, const RenderElement* renderer)
+{
+    OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
+    std::optional<LayoutRect> rectInFrameAbsoluteSpace = renderer->computeVisibleRectInContainer(rect, &renderer->view(),  {false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
+    if (!rectInFrameAbsoluteSpace || renderer->frame().isMainFrame())
+        return rectInFrameAbsoluteSpace;
+
+    bool intersects = rectInFrameAbsoluteSpace->edgeInclusiveIntersect(renderer->view().frameView().layoutViewportRect());
+    if (!intersects)
+        return std::nullopt;
+
+    LayoutRect rectInFrameViewSpace(renderer->view().frameView().contentsToView(snappedIntRect(*rectInFrameAbsoluteSpace)));
+    auto* ownerRenderer = renderer->frame().ownerRenderer();
+    if (!ownerRenderer)
+        return std::nullopt;
+
+    rectInFrameViewSpace.moveBy(ownerRenderer->contentBoxLocation());
+    return computeClippedRectInRootContentsSpace(rectInFrameViewSpace, ownerRenderer);
+}
+
 struct IntersectionObservationState {
     FloatRect absoluteTargetRect;
     FloatRect absoluteRootBounds;
@@ -7610,12 +7630,8 @@
     bool isIntersecting { false };
 };
 
-static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target)
+static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target, bool applyRootMargin)
 {
-    // FIXME: Implement intersection computation for the cross-document case.
-    if (observer.trackingDocument() != &target.document())
-        return std::nullopt;
-
     auto* targetRenderer = target.renderer();
     if (!targetRenderer)
         return std::nullopt;
@@ -7623,6 +7639,9 @@
     FloatRect localRootBounds;
     RenderBlock* rootRenderer;
     if (observer.root()) {
+        if (observer.trackingDocument() != &target.document())
+            return std::nullopt;
+
         if (!observer.root()->renderer() || !is<RenderBlock>(observer.root()->renderer()))
             return std::nullopt;
 
@@ -7636,11 +7655,15 @@
             localRootBounds = { FloatPoint(), rootRenderer->size() };
     } else {
         ASSERT(frameView.frame().isMainFrame());
+        // FIXME: Handle the case of an implicit-root observer that has a target in a different frame tree.
+        if (&targetRenderer->frame().mainFrame() != &frameView.frame())
+            return std::nullopt;
         rootRenderer = frameView.renderView();
         localRootBounds = frameView.layoutViewportRect();
     }
 
-    expandRootBoundsWithRootMargin(localRootBounds, observer.rootMarginBox());
+    if (applyRootMargin)
+        expandRootBoundsWithRootMargin(localRootBounds, observer.rootMarginBox());
 
     LayoutRect localTargetBounds;
     if (is<RenderBox>(*targetRenderer))
@@ -7650,15 +7673,27 @@
     else if (is<RenderLineBreak>(targetRenderer))
         localTargetBounds = downcast<RenderLineBreak>(targetRenderer)->linesBoundingBox();
 
-    OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
-    std::optional<LayoutRect> rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
+    std::optional<LayoutRect> rootLocalTargetRect;
+    if (observer.root()) {
+        OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
+        rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
+    } else
+        rootLocalTargetRect = computeClippedRectInRootContentsSpace(localTargetBounds, targetRenderer);
+
     FloatRect rootLocalIntersectionRect = localRootBounds;
 
     IntersectionObservationState intersectionState;
     intersectionState.isIntersecting = rootLocalTargetRect && rootLocalIntersectionRect.edgeInclusiveIntersect(*rootLocalTargetRect);
 
-    if (intersectionState.isIntersecting)
-        intersectionState.absoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+    if (intersectionState.isIntersecting) {
+        FloatRect rootAbsoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+        if (&targetRenderer->frame() == &rootRenderer->frame())
+            intersectionState.absoluteIntersectionRect = rootAbsoluteIntersectionRect;
+        else {
+            FloatRect rootViewIntersectionRect = frameView.delegatesScrolling() ? rootAbsoluteIntersectionRect : frameView.contentsToView(rootAbsoluteIntersectionRect);
+            intersectionState.absoluteIntersectionRect = targetRenderer->view().frameView().rootViewToContents(rootViewIntersectionRect);
+        }
+    }
 
     intersectionState.absoluteTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
     intersectionState.absoluteRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
@@ -7690,7 +7725,8 @@
             ASSERT(index != notFound);
             auto& registration = targetRegistrations[index];
 
-            auto intersectionState = computeIntersectionState(*frameView, *observer, *target);
+            bool isSameOriginObservation = &target->document() == this || target->document().securityOrigin().canAccess(securityOrigin());
+            auto intersectionState = computeIntersectionState(*frameView, *observer, *target, isSameOriginObservation);
 
             float intersectionRatio = 0;
             size_t thresholdIndex = 0;
@@ -7708,26 +7744,27 @@
                 }
             }
 
-
             if (!registration.previousThresholdIndex || thresholdIndex != registration.previousThresholdIndex) {
                 FloatRect targetBoundingClientRect;
                 FloatRect clientIntersectionRect;
                 FloatRect clientRootBounds;
                 if (intersectionState) {
-                    targetBoundingClientRect = frameView->absoluteToClientRect(intersectionState->absoluteTargetRect);
+                    auto* targetFrameView = target->document().view();
+                    targetBoundingClientRect = targetFrameView->absoluteToClientRect(intersectionState->absoluteTargetRect);
                     clientRootBounds = frameView->absoluteToClientRect(intersectionState->absoluteRootBounds);
                     if (intersectionState->isIntersecting)
-                        clientIntersectionRect = frameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);
+                        clientIntersectionRect = targetFrameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);
                 }
 
-                // FIXME: Once cross-document observation is implemented, only report root bounds if the target document and
-                // the root document are similar-origin.
-                std::optional<DOMRectInit> reportedRootBounds = DOMRectInit({
-                    clientRootBounds.x(),
-                    clientRootBounds.y(),
-                    clientRootBounds.width(),
-                    clientRootBounds.height()
-                });
+                std::optional<DOMRectInit> reportedRootBounds;
+                if (isSameOriginObservation) {
+                    reportedRootBounds = DOMRectInit({
+                        clientRootBounds.x(),
+                        clientRootBounds.y(),
+                        clientRootBounds.width(),
+                        clientRootBounds.height()
+                    });
+                }
 
                 observer->appendQueuedEntry(IntersectionObserverEntry::create({
                     timestamp,

Modified: trunk/Source/WebCore/page/FrameView.cpp (237736 => 237737)


--- trunk/Source/WebCore/page/FrameView.cpp	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/page/FrameView.cpp	2018-11-02 16:55:13 UTC (rev 237737)
@@ -2009,9 +2009,15 @@
 
 #if ENABLE(INTERSECTION_OBSERVER)
     if (auto* document = frame().document()) {
-        if (document->numberOfIntersectionObservers()) {
-            if (auto* page = frame().page())
+        if (auto* page = frame().page()) {
+            if (document->numberOfIntersectionObservers())
                 page->addDocumentNeedingIntersectionObservationUpdate(*document);
+            if (!frame().isMainFrame()) {
+                if (auto* mainDocument = frame().mainFrame().document()) {
+                    if (mainDocument->numberOfIntersectionObservers())
+                        page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument);
+                }
+            }
         }
     }
 #endif
@@ -4554,6 +4560,17 @@
     return rect;
 }
 
+FloatRect FrameView::convertFromContainingViewToRenderer(const RenderElement* renderer, const FloatRect& viewRect) const
+{
+    FloatRect rect = viewRect;
+
+    // Convert from FrameView coords into page ("absolute") coordinates.
+    if (!delegatesScrolling())
+        rect = viewToContents(rect);
+
+    return (renderer->absoluteToLocalQuad(rect)).boundingBox();
+}
+
 IntPoint FrameView::convertFromRendererToContainingView(const RenderElement* renderer, const IntPoint& rendererPoint) const
 {
     IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms));
@@ -4619,6 +4636,28 @@
     return parentRect;
 }
 
+FloatRect FrameView::convertFromContainingView(const FloatRect& parentRect) const
+{
+    if (const ScrollView* parentScrollView = parent()) {
+        if (is<FrameView>(*parentScrollView)) {
+            const FrameView& parentView = downcast<FrameView>(*parentScrollView);
+
+            // Get our renderer in the parent view
+            RenderWidget* renderer = frame().ownerRenderer();
+            if (!renderer)
+                return parentRect;
+
+            auto rect = parentView.convertFromContainingViewToRenderer(renderer, parentRect);
+            rect.moveBy(-renderer->contentBoxLocation());
+            return rect;
+        }
+
+        return Widget::convertFromContainingView(parentRect);
+    }
+
+    return parentRect;
+}
+
 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const
 {
     if (const ScrollView* parentScrollView = parent()) {

Modified: trunk/Source/WebCore/page/FrameView.h (237736 => 237737)


--- trunk/Source/WebCore/page/FrameView.h	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/page/FrameView.h	2018-11-02 16:55:13 UTC (rev 237737)
@@ -459,6 +459,7 @@
     // Methods to convert points and rects between the coordinate space of the renderer, and this view.
     WEBCORE_EXPORT IntRect convertFromRendererToContainingView(const RenderElement*, const IntRect&) const;
     WEBCORE_EXPORT IntRect convertFromContainingViewToRenderer(const RenderElement*, const IntRect&) const;
+    WEBCORE_EXPORT FloatRect convertFromContainingViewToRenderer(const RenderElement*, const FloatRect&) const;
     WEBCORE_EXPORT IntPoint convertFromRendererToContainingView(const RenderElement*, const IntPoint&) const;
     WEBCORE_EXPORT IntPoint convertFromContainingViewToRenderer(const RenderElement*, const IntPoint&) const;
 
@@ -465,6 +466,7 @@
     // Override ScrollView methods to do point conversion via renderers, in order to take transforms into account.
     IntRect convertToContainingView(const IntRect&) const final;
     IntRect convertFromContainingView(const IntRect&) const final;
+    FloatRect convertFromContainingView(const FloatRect&) const final;
     IntPoint convertToContainingView(const IntPoint&) const final;
     IntPoint convertFromContainingView(const IntPoint&) const final;
 

Modified: trunk/Source/WebCore/platform/ScrollView.cpp (237736 => 237737)


--- trunk/Source/WebCore/platform/ScrollView.cpp	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/platform/ScrollView.cpp	2018-11-02 16:55:13 UTC (rev 237737)
@@ -829,6 +829,12 @@
     return rect;
 }
 
+FloatRect ScrollView::viewToContents(FloatRect rect) const
+{
+    rect.moveBy(documentScrollPositionRelativeToViewOrigin());
+    return rect;
+}
+
 IntRect ScrollView::contentsToView(IntRect rect) const
 {
     rect.moveBy(-documentScrollPositionRelativeToViewOrigin());
@@ -835,6 +841,12 @@
     return rect;
 }
 
+FloatRect ScrollView::contentsToView(FloatRect rect) const
+{
+    rect.moveBy(-documentScrollPositionRelativeToViewOrigin());
+    return rect;
+}
+
 IntPoint ScrollView::contentsToContainingViewContents(const IntPoint& point) const
 {
     if (const ScrollView* parentScrollView = parent()) {
@@ -882,6 +894,14 @@
     return viewToContents(convertFromRootView(rootViewRect));
 }
 
+FloatRect ScrollView::rootViewToContents(const FloatRect& rootViewRect) const
+{
+    if (delegatesScrolling())
+        return convertFromRootView(rootViewRect);
+
+    return viewToContents(convertFromRootView(rootViewRect));
+}
+
 IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) const
 {
     if (delegatesScrolling())

Modified: trunk/Source/WebCore/platform/ScrollView.h (237736 => 237737)


--- trunk/Source/WebCore/platform/ScrollView.h	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/platform/ScrollView.h	2018-11-02 16:55:13 UTC (rev 237737)
@@ -283,6 +283,7 @@
     WEBCORE_EXPORT IntPoint contentsToRootView(const IntPoint&) const;
     WEBCORE_EXPORT IntRect rootViewToContents(const IntRect&) const;
     WEBCORE_EXPORT IntRect contentsToRootView(const IntRect&) const;
+    WEBCORE_EXPORT FloatRect rootViewToContents(const FloatRect&) const;
 
     IntPoint viewToContents(const IntPoint&) const;
     IntPoint contentsToView(const IntPoint&) const;
@@ -290,6 +291,9 @@
     IntRect viewToContents(IntRect) const;
     IntRect contentsToView(IntRect) const;
 
+    FloatRect viewToContents(FloatRect) const;
+    FloatRect contentsToView(FloatRect) const;
+
     IntPoint contentsToContainingViewContents(const IntPoint&) const;
     IntRect contentsToContainingViewContents(IntRect) const;
 

Modified: trunk/Source/WebCore/platform/Widget.cpp (237736 => 237737)


--- trunk/Source/WebCore/platform/Widget.cpp	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/platform/Widget.cpp	2018-11-02 16:55:13 UTC (rev 237737)
@@ -76,6 +76,15 @@
     return rootRect;
 }
 
+FloatRect Widget::convertFromRootView(const FloatRect& rootRect) const
+{
+    if (const ScrollView* parentScrollView = parent()) {
+        FloatRect parentRect = parentScrollView->convertFromRootView(rootRect);
+        return convertFromContainingView(parentRect);
+    }
+    return rootRect;
+}
+
 IntRect Widget::convertToRootView(const IntRect& localRect) const
 {
     if (const ScrollView* parentScrollView = parent()) {
@@ -182,6 +191,11 @@
     return parentRect;
 }
 
+FloatRect Widget::convertFromContainingView(const FloatRect& parentRect) const
+{
+    return convertFromContainingView(IntRect(parentRect));
+}
+
 IntPoint Widget::convertToContainingView(const IntPoint& localPoint) const
 {
     if (const ScrollView* parentScrollView = parent())

Modified: trunk/Source/WebCore/platform/Widget.h (237736 => 237737)


--- trunk/Source/WebCore/platform/Widget.h	2018-11-02 16:49:13 UTC (rev 237736)
+++ trunk/Source/WebCore/platform/Widget.h	2018-11-02 16:55:13 UTC (rev 237737)
@@ -150,6 +150,8 @@
     WEBCORE_EXPORT IntRect convertToRootView(const IntRect&) const;
     IntRect convertFromRootView(const IntRect&) const;
 
+    FloatRect convertFromRootView(const FloatRect&) const;
+
     IntPoint convertToRootView(const IntPoint&) const;
     IntPoint convertFromRootView(const IntPoint&) const;
 
@@ -184,6 +186,7 @@
     // Virtual methods to convert points to/from the containing ScrollView
     WEBCORE_EXPORT virtual IntRect convertToContainingView(const IntRect&) const;
     WEBCORE_EXPORT virtual IntRect convertFromContainingView(const IntRect&) const;
+    WEBCORE_EXPORT virtual FloatRect convertFromContainingView(const FloatRect&) const;
     WEBCORE_EXPORT virtual IntPoint convertToContainingView(const IntPoint&) const;
     WEBCORE_EXPORT virtual IntPoint convertFromContainingView(const IntPoint&) const;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to