Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 9e93965484305236b05b2a0000b9bbee624017c3
      
https://github.com/WebKit/WebKit/commit/9e93965484305236b05b2a0000b9bbee624017c3
  Author: Kiet Ho <[email protected]>
  Date:   2026-07-08 (Wed, 08 Jul 2026)

  Changed paths:
    M LayoutTests/platform/ios-site-isolation/TestExpectations
    M LayoutTests/platform/mac-site-isolation/TestExpectations
    M Source/WebCore/page/IntersectionObserver.cpp

  Log Message:
  -----------
  [Site Isolation] [intersection-observer] In Site Isolation mode, scroll 
margin can get applied to cross-origin frame
rdar://177992045
https://bugs.webkit.org/show_bug.cgi?id=315617

Reviewed by Simon Fraser.

computeClippedRectInRootContentsSpace (in IntersectionObserver.cpp) works by
computing the visible rect of an element in its frame, then recurses if the
frame is another frame, up until it reaches the main frame. When crossing
frame boundaries, it checks whether the current frame is same-origin to the
target element, for applying scroll margin:

    RefPtr rendererOrFrameSecurityOrigin = WTF::visit(WTF::makeVisitor(
        [&] (const RenderElement* renderer) { return Ref<const 
Frame>(renderer->frame())->frameDocumentSecurityOrigin(); },
        [&] (const Frame* frame) { return frame->frameDocumentSecurityOrigin(); 
}
    ), rendererOrFrame);

    bool isSameOriginDomain = [&] () {
        if (rendererOrFrameSecurityOrigin)
            return 
rendererOrFrameSecurityOrigin->isSameOriginDomain(targetSecurityOrigin);

         return false;
     }();
     if (!isSameOriginDomain)
         scrollMargin.reset();

If the parent frame's owner renderer is available, then
computeClippedRectInRootContentsSpace is called with that owner renderer.
Then renderer->frame() is the parent frame, and rendererOrFrameSecurityOrigin
is the parent frame's security origin.

If the parent frame's owner renderer is not available (when Site Isolation
is enabled and the parent frame is in another process), then
computeClippedRectInRootContentsSpace is called with the Frame object of
the current frame instead. The intention is to use this as the proxy to
the frame's owner renderer. But in this case, rendererOrFrameSecurityOrigin
would be the frame's security origin, instead of the parent frame's.

As an example, in an page with nested iframes that look like this: (cross
and same-origin are relative to main frame):

(1) main <- (2) cross-origin <- (3) same-origin <- (4) target element

First computeClippedRectInRootContentsSpace is called on (4), then it's
called on the (3)'s Frame object (because (3)'s owner renderer is in (2),
which is cross-origin and out of process). We cross a cross-origin frame
boundary, so we should not apply and propagate scroll margin. But because
the object being passed to computeClippedRectInRootContentsSpace is (3)'s
Frame object, rendererOrFrameSecurityOrigin is the security origin of (3),
which is also the security origin of (4), as (4) is in (3)

Fix this by getting the security origin from enclosingFrame instead, which is
guaranteed to be the parent frame (aka the frame enclosing rendererOrFrame)

* LayoutTests/platform/ios-site-isolation/TestExpectations:
* LayoutTests/platform/mac-site-isolation/TestExpectations:
* Source/WebCore/page/IntersectionObserver.cpp:
(WebCore::computeClippedRectInRootContentsSpace):

Canonical link: https://commits.webkit.org/316774@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to