Changeset 237737 in webkit
- Timestamp:
- Nov 2, 2018 9:55:13 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 17 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r237733 r237737 1 2018-11-02 Ali Juma <ajuma@chromium.org> 2 3 Allow cross-document intersection observing 4 https://bugs.webkit.org/show_bug.cgi?id=165746 5 6 Reviewed by Simon Fraser. 7 8 Add a test that cross-document intersection observations are triggered when an intermediate frame 9 scrolls. Skip the test on WK1 platforms where IntersectionObserver is not supported. 10 11 Add platform-specific baselines for tests involving iframe scrolling, which isn't supported on iOS. 12 13 * http/tests/intersection-observer/intermediate-frame-changes-expected.txt: Added. 14 * http/tests/intersection-observer/intermediate-frame-changes.html: Added. 15 * http/tests/intersection-observer/resources/intermediate-frame.html: Added. 16 * http/tests/intersection-observer/resources/nested-frame.html: Added. 17 * 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. 18 * 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. 19 * platform/mac-wk1/TestExpectations: 20 * platform/win/TestExpectations: 21 * platform/wincairo/TestExpectations: 22 1 23 2018-11-02 Per Arne Vollan <pvollan@apple.com> 2 24 -
trunk/LayoutTests/imported/w3c/ChangeLog
r237702 r237737 1 2018-11-02 Ali Juma <ajuma@chromium.org> 2 3 Allow cross-document intersection observing 4 https://bugs.webkit.org/show_bug.cgi?id=165746 5 6 Reviewed by Simon Fraser. 7 8 Update expectations for tests that now pass. 9 10 * web-platform-tests/intersection-observer/client-rect-expected.txt: 11 * web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt: 12 * web-platform-tests/intersection-observer/iframe-no-root-expected.txt: 13 * web-platform-tests/intersection-observer/timestamp-expected.txt: 14 1 15 2018-11-01 Chris Dumez <cdumez@apple.com> 2 16 -
trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/client-rect-expected.txt
r235014 r237737 1 1 2 2 PASS IntersectionObserverEntry.boundingClientRect should match target.boundingClientRect() 3 FAIL First rAF should generate notification. assert_equals: entries[0].boundingClientRect.left expected 8 but got 0 3 PASS First rAF should generate notification. 4 4 -
trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/cross-origin-iframe-expected.txt
r235014 r237737 4 4 PASS First rAF 5 5 PASS topDocument.scrollingElement.scrollTop = 200 6 FAIL iframeDocument.scrollingElement.scrollTop = 250 assert_equals: expected 1 but got 0 7 FAIL topDocument.scrollingElement.scrollTop = 100 assert_equals: expected 1 but got 0 6 PASS iframeDocument.scrollingElement.scrollTop = 250 7 PASS topDocument.scrollingElement.scrollTop = 100 8 8 -
trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt
r235014 r237737 2 2 3 3 PASS Observer with the implicit root; target in a same-origin iframe. 4 FAIL First rAF. assert_equals: entries[0].boundingClientRect.left expected 8 but got 0 4 PASS First rAF. 5 5 PASS document.scrollingElement.scrollTop = 200 6 FAIL iframe.contentDocument.scrollingElement.scrollTop = 250 assert_equals: entries.length expected 2 but got 1 7 FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1 6 PASS iframe.contentDocument.scrollingElement.scrollTop = 250 7 PASS document.scrollingElement.scrollTop = 100 8 8 -
trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/timestamp-expected.txt
r235014 r237737 3 3 PASS Check that timestamps correspond to the to execution context that created the observer. 4 4 PASS First rAF after iframe is loaded. 5 FAIL Generate notifications. undefined is not an object (evaluating 'topWindowEntries[1].time') 5 PASS Generate notifications. 6 6 -
trunk/LayoutTests/platform/ios/imported/w3c/web-platform-tests/intersection-observer/iframe-no-root-expected.txt
r237735 r237737 2 2 3 3 PASS Observer with the implicit root; target in a same-origin iframe. 4 FAIL First rAF. assert_equals: entries[0].boundingClientRect.left expected 8 but got 0 4 PASS First rAF. 5 5 PASS document.scrollingElement.scrollTop = 200 6 6 FAIL iframe.contentDocument.scrollingElement.scrollTop = 250 assert_equals: entries.length expected 2 but got 1 -
trunk/LayoutTests/platform/mac-wk1/TestExpectations
r237698 r237737 532 532 533 533 # Not supported on WK1 534 http/tests/intersection-observer [ Skip ] 534 535 imported/w3c/web-platform-tests/intersection-observer [ Skip ] 535 536 intersection-observer [ Skip ] -
trunk/LayoutTests/platform/win/TestExpectations
r237733 r237737 134 134 # IntersectionObserver is off by default 135 135 webkit.org/b/188613 intersection-observer [ Skip ] 136 webkit.org/b/188613 http/tests/intersection-observer [ Skip ] 136 137 137 138 # TODO Should be moved to platform/mac <rdar://5621425> -
trunk/LayoutTests/platform/wincairo/TestExpectations
r237701 r237737 1464 1464 # IntersectionObserver is off by default 1465 1465 webkit.org/b/188613 intersection-observer [ Skip ] 1466 webkit.org/b/188613 http/tests/intersection-observer [ Skip ] 1466 1467 1467 1468 [ Debug ] css2.1/20110323/replaced-intrinsic-ratio-001.htm [ Pass Failure ] -
trunk/Source/WebCore/ChangeLog
r237732 r237737 1 2018-11-02 Ali Juma <ajuma@chromium.org> 2 3 Allow cross-document intersection observing 4 https://bugs.webkit.org/show_bug.cgi?id=165746 5 6 Reviewed by Simon Fraser. 7 8 Add logic to compute the intersection between the viewport and an element in a 9 subframe. 10 11 Add a FloatRect version of ScrollView::rootViewToContents, and FloatRect versions 12 of the methods it calls. 13 14 Test: http/tests/intersection-observer/intermediate-frame-changes.html 15 Also covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer. 16 17 * dom/Document.cpp: 18 (WebCore::computeClippedRectInRootContentsSpace): 19 (WebCore::computeIntersectionState): 20 (WebCore::Document::updateIntersectionObservations): 21 * page/FrameView.cpp: 22 (WebCore::FrameView::viewportContentsChanged): 23 (WebCore::FrameView::convertFromContainingViewToRenderer const): 24 (WebCore::FrameView::convertFromContainingView const): 25 * page/FrameView.h: 26 * platform/ScrollView.cpp: 27 (WebCore::ScrollView::viewToContents const): 28 (WebCore::ScrollView::contentsToView const): 29 (WebCore::ScrollView::rootViewToContents const): 30 * platform/ScrollView.h: 31 * platform/Widget.cpp: 32 (WebCore::Widget::convertFromRootView const): 33 (WebCore::Widget::convertFromContainingView const): 34 * platform/Widget.h: 35 1 36 2018-11-02 Rob Buis <rbuis@igalia.com> 2 37 -
trunk/Source/WebCore/dom/Document.cpp
r237677 r237737 7604 7604 } 7605 7605 7606 static std::optional<LayoutRect> computeClippedRectInRootContentsSpace(const LayoutRect& rect, const RenderElement* renderer) 7607 { 7608 OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls }; 7609 std::optional<LayoutRect> rectInFrameAbsoluteSpace = renderer->computeVisibleRectInContainer(rect, &renderer->view(), {false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions }); 7610 if (!rectInFrameAbsoluteSpace || renderer->frame().isMainFrame()) 7611 return rectInFrameAbsoluteSpace; 7612 7613 bool intersects = rectInFrameAbsoluteSpace->edgeInclusiveIntersect(renderer->view().frameView().layoutViewportRect()); 7614 if (!intersects) 7615 return std::nullopt; 7616 7617 LayoutRect rectInFrameViewSpace(renderer->view().frameView().contentsToView(snappedIntRect(*rectInFrameAbsoluteSpace))); 7618 auto* ownerRenderer = renderer->frame().ownerRenderer(); 7619 if (!ownerRenderer) 7620 return std::nullopt; 7621 7622 rectInFrameViewSpace.moveBy(ownerRenderer->contentBoxLocation()); 7623 return computeClippedRectInRootContentsSpace(rectInFrameViewSpace, ownerRenderer); 7624 } 7625 7606 7626 struct IntersectionObservationState { 7607 7627 FloatRect absoluteTargetRect; … … 7611 7631 }; 7612 7632 7613 static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target) 7614 { 7615 // FIXME: Implement intersection computation for the cross-document case. 7616 if (observer.trackingDocument() != &target.document()) 7617 return std::nullopt; 7618 7633 static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target, bool applyRootMargin) 7634 { 7619 7635 auto* targetRenderer = target.renderer(); 7620 7636 if (!targetRenderer) … … 7624 7640 RenderBlock* rootRenderer; 7625 7641 if (observer.root()) { 7642 if (observer.trackingDocument() != &target.document()) 7643 return std::nullopt; 7644 7626 7645 if (!observer.root()->renderer() || !is<RenderBlock>(observer.root()->renderer())) 7627 7646 return std::nullopt; … … 7637 7656 } else { 7638 7657 ASSERT(frameView.frame().isMainFrame()); 7658 // FIXME: Handle the case of an implicit-root observer that has a target in a different frame tree. 7659 if (&targetRenderer->frame().mainFrame() != &frameView.frame()) 7660 return std::nullopt; 7639 7661 rootRenderer = frameView.renderView(); 7640 7662 localRootBounds = frameView.layoutViewportRect(); 7641 7663 } 7642 7664 7643 expandRootBoundsWithRootMargin(localRootBounds, observer.rootMarginBox()); 7665 if (applyRootMargin) 7666 expandRootBoundsWithRootMargin(localRootBounds, observer.rootMarginBox()); 7644 7667 7645 7668 LayoutRect localTargetBounds; … … 7651 7674 localTargetBounds = downcast<RenderLineBreak>(targetRenderer)->linesBoundingBox(); 7652 7675 7653 OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls }; 7654 std::optional<LayoutRect> rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions }); 7676 std::optional<LayoutRect> rootLocalTargetRect; 7677 if (observer.root()) { 7678 OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls }; 7679 rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions }); 7680 } else 7681 rootLocalTargetRect = computeClippedRectInRootContentsSpace(localTargetBounds, targetRenderer); 7682 7655 7683 FloatRect rootLocalIntersectionRect = localRootBounds; 7656 7684 … … 7658 7686 intersectionState.isIntersecting = rootLocalTargetRect && rootLocalIntersectionRect.edgeInclusiveIntersect(*rootLocalTargetRect); 7659 7687 7660 if (intersectionState.isIntersecting) 7661 intersectionState.absoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox(); 7688 if (intersectionState.isIntersecting) { 7689 FloatRect rootAbsoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox(); 7690 if (&targetRenderer->frame() == &rootRenderer->frame()) 7691 intersectionState.absoluteIntersectionRect = rootAbsoluteIntersectionRect; 7692 else { 7693 FloatRect rootViewIntersectionRect = frameView.delegatesScrolling() ? rootAbsoluteIntersectionRect : frameView.contentsToView(rootAbsoluteIntersectionRect); 7694 intersectionState.absoluteIntersectionRect = targetRenderer->view().frameView().rootViewToContents(rootViewIntersectionRect); 7695 } 7696 } 7662 7697 7663 7698 intersectionState.absoluteTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox(); … … 7691 7726 auto& registration = targetRegistrations[index]; 7692 7727 7693 auto intersectionState = computeIntersectionState(*frameView, *observer, *target); 7728 bool isSameOriginObservation = &target->document() == this || target->document().securityOrigin().canAccess(securityOrigin()); 7729 auto intersectionState = computeIntersectionState(*frameView, *observer, *target, isSameOriginObservation); 7694 7730 7695 7731 float intersectionRatio = 0; … … 7709 7745 } 7710 7746 7711 7712 7747 if (!registration.previousThresholdIndex || thresholdIndex != registration.previousThresholdIndex) { 7713 7748 FloatRect targetBoundingClientRect; … … 7715 7750 FloatRect clientRootBounds; 7716 7751 if (intersectionState) { 7717 targetBoundingClientRect = frameView->absoluteToClientRect(intersectionState->absoluteTargetRect); 7752 auto* targetFrameView = target->document().view(); 7753 targetBoundingClientRect = targetFrameView->absoluteToClientRect(intersectionState->absoluteTargetRect); 7718 7754 clientRootBounds = frameView->absoluteToClientRect(intersectionState->absoluteRootBounds); 7719 7755 if (intersectionState->isIntersecting) 7720 clientIntersectionRect = frameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);7756 clientIntersectionRect = targetFrameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect); 7721 7757 } 7722 7758 7723 // FIXME: Once cross-document observation is implemented, only report root bounds if the target document and 7724 // the root document are similar-origin. 7725 std::optional<DOMRectInit> reportedRootBounds = DOMRectInit({ 7726 clientRootBounds.x(), 7727 clientRootBounds.y(), 7728 clientRootBounds.width(), 7729 clientRootBounds.height() 7730 }); 7759 std::optional<DOMRectInit> reportedRootBounds; 7760 if (isSameOriginObservation) { 7761 reportedRootBounds = DOMRectInit({ 7762 clientRootBounds.x(), 7763 clientRootBounds.y(), 7764 clientRootBounds.width(), 7765 clientRootBounds.height() 7766 }); 7767 } 7731 7768 7732 7769 observer->appendQueuedEntry(IntersectionObserverEntry::create({ -
trunk/Source/WebCore/page/FrameView.cpp
r237468 r237737 2010 2010 #if ENABLE(INTERSECTION_OBSERVER) 2011 2011 if (auto* document = frame().document()) { 2012 if ( document->numberOfIntersectionObservers()) {2013 if ( auto* page = frame().page())2012 if (auto* page = frame().page()) { 2013 if (document->numberOfIntersectionObservers()) 2014 2014 page->addDocumentNeedingIntersectionObservationUpdate(*document); 2015 if (!frame().isMainFrame()) { 2016 if (auto* mainDocument = frame().mainFrame().document()) { 2017 if (mainDocument->numberOfIntersectionObservers()) 2018 page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument); 2019 } 2020 } 2015 2021 } 2016 2022 } … … 4555 4561 } 4556 4562 4563 FloatRect FrameView::convertFromContainingViewToRenderer(const RenderElement* renderer, const FloatRect& viewRect) const 4564 { 4565 FloatRect rect = viewRect; 4566 4567 // Convert from FrameView coords into page ("absolute") coordinates. 4568 if (!delegatesScrolling()) 4569 rect = viewToContents(rect); 4570 4571 return (renderer->absoluteToLocalQuad(rect)).boundingBox(); 4572 } 4573 4557 4574 IntPoint FrameView::convertFromRendererToContainingView(const RenderElement* renderer, const IntPoint& rendererPoint) const 4558 4575 { … … 4620 4637 } 4621 4638 4639 FloatRect FrameView::convertFromContainingView(const FloatRect& parentRect) const 4640 { 4641 if (const ScrollView* parentScrollView = parent()) { 4642 if (is<FrameView>(*parentScrollView)) { 4643 const FrameView& parentView = downcast<FrameView>(*parentScrollView); 4644 4645 // Get our renderer in the parent view 4646 RenderWidget* renderer = frame().ownerRenderer(); 4647 if (!renderer) 4648 return parentRect; 4649 4650 auto rect = parentView.convertFromContainingViewToRenderer(renderer, parentRect); 4651 rect.moveBy(-renderer->contentBoxLocation()); 4652 return rect; 4653 } 4654 4655 return Widget::convertFromContainingView(parentRect); 4656 } 4657 4658 return parentRect; 4659 } 4660 4622 4661 IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const 4623 4662 { -
trunk/Source/WebCore/page/FrameView.h
r237466 r237737 460 460 WEBCORE_EXPORT IntRect convertFromRendererToContainingView(const RenderElement*, const IntRect&) const; 461 461 WEBCORE_EXPORT IntRect convertFromContainingViewToRenderer(const RenderElement*, const IntRect&) const; 462 WEBCORE_EXPORT FloatRect convertFromContainingViewToRenderer(const RenderElement*, const FloatRect&) const; 462 463 WEBCORE_EXPORT IntPoint convertFromRendererToContainingView(const RenderElement*, const IntPoint&) const; 463 464 WEBCORE_EXPORT IntPoint convertFromContainingViewToRenderer(const RenderElement*, const IntPoint&) const; … … 466 467 IntRect convertToContainingView(const IntRect&) const final; 467 468 IntRect convertFromContainingView(const IntRect&) const final; 469 FloatRect convertFromContainingView(const FloatRect&) const final; 468 470 IntPoint convertToContainingView(const IntPoint&) const final; 469 471 IntPoint convertFromContainingView(const IntPoint&) const final; -
trunk/Source/WebCore/platform/ScrollView.cpp
r237266 r237737 830 830 } 831 831 832 FloatRect ScrollView::viewToContents(FloatRect rect) const 833 { 834 rect.moveBy(documentScrollPositionRelativeToViewOrigin()); 835 return rect; 836 } 837 832 838 IntRect ScrollView::contentsToView(IntRect rect) const 839 { 840 rect.moveBy(-documentScrollPositionRelativeToViewOrigin()); 841 return rect; 842 } 843 844 FloatRect ScrollView::contentsToView(FloatRect rect) const 833 845 { 834 846 rect.moveBy(-documentScrollPositionRelativeToViewOrigin()); … … 876 888 877 889 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const 890 { 891 if (delegatesScrolling()) 892 return convertFromRootView(rootViewRect); 893 894 return viewToContents(convertFromRootView(rootViewRect)); 895 } 896 897 FloatRect ScrollView::rootViewToContents(const FloatRect& rootViewRect) const 878 898 { 879 899 if (delegatesScrolling()) -
trunk/Source/WebCore/platform/ScrollView.h
r237266 r237737 284 284 WEBCORE_EXPORT IntRect rootViewToContents(const IntRect&) const; 285 285 WEBCORE_EXPORT IntRect contentsToRootView(const IntRect&) const; 286 WEBCORE_EXPORT FloatRect rootViewToContents(const FloatRect&) const; 286 287 287 288 IntPoint viewToContents(const IntPoint&) const; … … 290 291 IntRect viewToContents(IntRect) const; 291 292 IntRect contentsToView(IntRect) const; 293 294 FloatRect viewToContents(FloatRect) const; 295 FloatRect contentsToView(FloatRect) const; 292 296 293 297 IntPoint contentsToContainingViewContents(const IntPoint&) const; -
trunk/Source/WebCore/platform/Widget.cpp
r232613 r237737 77 77 } 78 78 79 FloatRect Widget::convertFromRootView(const FloatRect& rootRect) const 80 { 81 if (const ScrollView* parentScrollView = parent()) { 82 FloatRect parentRect = parentScrollView->convertFromRootView(rootRect); 83 return convertFromContainingView(parentRect); 84 } 85 return rootRect; 86 } 87 79 88 IntRect Widget::convertToRootView(const IntRect& localRect) const 80 89 { … … 183 192 } 184 193 194 FloatRect Widget::convertFromContainingView(const FloatRect& parentRect) const 195 { 196 return convertFromContainingView(IntRect(parentRect)); 197 } 198 185 199 IntPoint Widget::convertToContainingView(const IntPoint& localPoint) const 186 200 { -
trunk/Source/WebCore/platform/Widget.h
r237266 r237737 151 151 IntRect convertFromRootView(const IntRect&) const; 152 152 153 FloatRect convertFromRootView(const FloatRect&) const; 154 153 155 IntPoint convertToRootView(const IntPoint&) const; 154 156 IntPoint convertFromRootView(const IntPoint&) const; … … 185 187 WEBCORE_EXPORT virtual IntRect convertToContainingView(const IntRect&) const; 186 188 WEBCORE_EXPORT virtual IntRect convertFromContainingView(const IntRect&) const; 189 WEBCORE_EXPORT virtual FloatRect convertFromContainingView(const FloatRect&) const; 187 190 WEBCORE_EXPORT virtual IntPoint convertToContainingView(const IntPoint&) const; 188 191 WEBCORE_EXPORT virtual IntPoint convertFromContainingView(const IntPoint&) const;
Note: See TracChangeset
for help on using the changeset viewer.