Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 0165aa33122d51c5ca9d495dfffb4775e1c5d88f
      
https://github.com/WebKit/WebKit/commit/0165aa33122d51c5ca9d495dfffb4775e1c5d88f
  Author: Ryosuke Niwa <[email protected]>
  Date:   2026-08-03 (Mon, 03 Aug 2026)

  Changed paths:
    A 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-extends-selection-in-cross-origin-iframe-expected.txt
    A 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-extends-selection-in-cross-origin-iframe.html
    A 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-in-scrolled-cross-origin-iframe-expected.txt
    A 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-in-scrolled-cross-origin-iframe.html
    A 
LayoutTests/http/tests/site-isolation/ios/select-and-drag-in-transformed-cross-origin-iframe-expected.txt
    A 
LayoutTests/http/tests/site-isolation/ios/select-and-drag-in-transformed-cross-origin-iframe.html
    A 
LayoutTests/http/tests/site-isolation/resources/multiline-selectable-text-frame.html
    M 
LayoutTests/http/tests/site-isolation/resources/scrollable-selectable-text-frame.html
    M Source/WebCore/page/FrameView.cpp
    M Source/WebCore/page/FrameView.h
    M Source/WebCore/page/IntersectionObserver.cpp
    M Source/WebCore/page/RemoteFrameGeometryTransformer.cpp
    M Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
    M Source/WebKit/UIProcess/WebPageProxy.cpp
    M Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
    M Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm
    M Source/WebKit/WebProcess/WebPage/WebPage.h
    M Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

  Log Message:
  -----------
  [Site Isolation] [iOS] Can't adjust selection endpoints inside a cross-site 
iframe
https://bugs.webkit.org/show_bug.cgi?id=320751

Reviewed by Megan Gardner, Wenson Hsieh, and Lily Spiniolas.

When a selection is inside a cross-origin (site-isolated) iframe on iOS, 
dragging the selection
handles did nothing, and the selection/caret coordinates were mapped into and 
out of the subframe
using only a translation offset, which is wrong whenever the iframe or an 
ancestor has a CSS
transform.

Three problems, all stemming from the selection living in the subframe's 
process while these code
paths assumed it's in the main frame's process:

  - The UI process sent UpdateSelectionWithTouches, 
UpdateSelectionWithExtentPoint, and
    UpdateSelectionWithExtentPointAndBoundary unconditionally to the main-frame 
process, where
    focusedOrMainFrame() is not the cross-origin subframe, so the drag operated 
on the wrong
    frame (or no selection at all).
  - Even once routed correctly, rangeForPointInRootViewCoordinates() 
early-returned when
    LocalFrame::localMainFrame() was null - always the case in a cross-origin 
subframe's process -
    so no range was ever computed and the selection never changed.
  - Points and rects were mapped between main-frame and subframe coordinates by 
adding/subtracting
    the frame's origin within the main frame (a translation), which cannot 
represent a CSS
    transform (e.g. scale()) on the iframe or any ancestor, so the selection 
landed on the wrong
    line and the handles/highlight were drawn in the wrong place inside a 
transformed iframe.

Route these three selection-update messages to the process containing the 
focused frame rather
than always the main-frame process, and respond with the original point back to 
UIKit. This
handles arbitrary nesting in one hop because the focused frame is known up 
front. For the
non-isolated case the focused frame is the main frame, so behavior is 
unchanged; Mac is likewise
unaffected.

Replace the translation-only coordinate mapping with transform-aware 
conversions on FrameView:
convertFromRootViewAcrossIsolatedFrames(), 
convertToRootViewAcrossIsolatedFrames(), and
rootViewToContentsAcrossSiteIsolation(). Unlike 
Widget::convertFromRootView()/rootViewToContents(),
these follow the frame tree even across process boundaries (Widget::parent() is 
not populated for
a RemoteFrameView under Site Isolation) and apply the CSS transform on each 
intervening frame owner
via the synced 
absoluteToChildFrameOwnerLocalTransform()/childFrameOwnerToRootContentTransform().
This logic previously existed as file-static helpers in 
IntersectionObserver.cpp; promote it to
FrameView so both features share one implementation. For a same-process frame 
tree, and for a
subframe positioned by a plain offset, these reduce to the previous behavior.

Selection input now uses these conversions: mainFrameCoordinatesToRootView() 
(used by
UpdateSelectionWithTouches and the two extent-point messages) maps the UIKit 
interaction point,
supplied in main-frame coordinates, into the focused frame's local root-view 
coordinates; and
RemoteFrameGeometryTransformer, which routes the initial selection/tap gesture 
into a remote
subframe, applies the owner element's transform (obtained from the parent 
LocalFrameView, whose
owner renderer is in-process) instead of a translation. Selection output - the 
caret rects and
selection geometry quads in getPlatformEditorState() - is mapped back to 
main-frame coordinates
with the inverse conversion, so UIKit reads correct rects synchronously 
mid-gesture. Both are
gated on the frame having a remote main frame (!localMainFrame()); the offset 
channel
(m_remoteFrameOffsetInMainFrame) is retained for accessibility but no longer 
used by selection.

In rangeForPointInRootViewCoordinates(), localMainFrame is used only to clamp 
the point to the
over-expanded the selection because that clamp used the subframe's 
unobscuredContentRect() (a
contents-space rect whose origin is the scroll offset), double-applying the 
scroll; convert that
rect to root-view coordinates before clamping so the scroll is applied exactly 
once.

Note that synthetic mouse events during selection (gated by
Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection, a 
top-document-scoped quirk) are
not dispatched inside cross-origin iframes since the quirk only applies to the 
local top document.

Tests: 
http/tests/site-isolation/ios/drag-selection-grabber-extends-selection-in-cross-origin-iframe.html
       
http/tests/site-isolation/ios/drag-selection-grabber-in-scrolled-cross-origin-iframe.html
       
http/tests/site-isolation/ios/select-and-drag-in-transformed-cross-origin-iframe.html

* 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-extends-selection-in-cross-origin-iframe-expected.txt:
 Added.
* 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-extends-selection-in-cross-origin-iframe.html:
 Added.
* 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-in-scrolled-cross-origin-iframe-expected.txt:
 Added.
* 
LayoutTests/http/tests/site-isolation/ios/drag-selection-grabber-in-scrolled-cross-origin-iframe.html:
 Added.
* 
LayoutTests/http/tests/site-isolation/ios/select-and-drag-in-transformed-cross-origin-iframe-expected.txt:
 Added.
* 
LayoutTests/http/tests/site-isolation/ios/select-and-drag-in-transformed-cross-origin-iframe.html:
 Added.
* 
LayoutTests/http/tests/site-isolation/resources/multiline-selectable-text-frame.html:
 Added.
* 
LayoutTests/http/tests/site-isolation/resources/scrollable-selectable-text-frame.html:
Parameterized the scroll offset via a query string.
* Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::WebPageProxy::updateSelectionWithExtentPoint): Route to the focused 
frame's process.
(WebKit::WebPageProxy::updateSelectionWithExtentPointAndBoundary): Ditto.
* Source/WebKit/UIProcess/WebPageProxy.cpp:
* Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::updateSelectionWithTouches): Ditto.
* Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::mainFrameCoordinatesToRootView const): Map the point 
transform-aware into
the focused frame's local root-view coordinates when the main frame is remote.
(WebKit::WebPage::updateSelectionWithExtentPointAndBoundary): Convert the 
incoming point.
(WebKit::WebPage::updateSelectionWithExtentPoint): Ditto.
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::rangeForPointInRootViewCoordinates): Fall back to this frame's view 
for the viewport
clamp when the main frame is remote, instead of returning early.
(WebKit::WebPage::updateSelectionWithTouches): Convert the point and echo the 
original back.
(WebKit::WebPage::getPlatformEditorState const): Map the selection caret rects 
and geometry
quads to main-frame coordinates with the transform-aware conversion.
* Source/WebCore/page/FrameView.cpp:
(WebCore::siteIsolationAwareParentView): Added; frame-tree parent that is 
populated across process
boundaries.
(WebCore::FrameView::convertFromRootViewAcrossIsolatedFrames const): Added.
(WebCore::FrameView::convertToRootViewAcrossIsolatedFrames const): Added.
(WebCore::FrameView::rootViewToContentsAcrossSiteIsolation const): Added.
(WebCore::FrameView::convertFromRootViewAcrossIsolatedFrames const):
(WebCore::FrameView::convertToRootViewAcrossIsolatedFrames const):
(WebCore::FrameView::rootViewToContentsAcrossIsolatedFrames const):
* Source/WebCore/page/FrameView.h:
* Source/WebCore/page/IntersectionObserver.cpp:
(WebCore::IntersectionObserver::computeIntersectionState const): Use the shared 
FrameView conversions.
(WebCore::convertFromContainingView): Deleted.
(WebCore::convertFromRootView): Deleted.
(WebCore::mainFrameViewToContents): Deleted.
* Source/WebCore/page/RemoteFrameGeometryTransformer.cpp:
(WebCore::RemoteFrameGeometryTransformer::transformToRemoteFrameCoordinates 
const): Apply the remote
frame owner's transform instead of a translation.

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



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

Reply via email to