Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: d86c4e68319ab64a1deaafd7052be2d6694b5f0b
      
https://github.com/WebKit/WebKit/commit/d86c4e68319ab64a1deaafd7052be2d6694b5f0b
  Author: Tyler Wilcock <[email protected]>
  Date:   2026-05-22 (Fri, 22 May 2026)

  Changed paths:
    A 
LayoutTests/http/tests/site-isolation/accessibility/client/walk-up-from-iframe-content-expected.txt
    A 
LayoutTests/http/tests/site-isolation/accessibility/client/walk-up-from-iframe-content.html
    M Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm

  Log Message:
  -----------
  AX Site Isolation: macOS VoiceOver wraps to the top of the page when trying 
to navigate past a cross-origin iframe
https://bugs.webkit.org/show_bug.cgi?id=315356
rdar://177714038

Reviewed by Dominic Mazzoni.

This bug occurred because the root scroll area associated with an remote
iframe had an AXProperty::RemoteParent (a WKAccessibilityWebPageObject)
that itself never had its m_parent set, breaking the accessibility tree
and thus preventing VoiceOver from navigating effectively.

This was possible due to this sequence:

  1. Pre-warmed iframe process is spawned (Safari prewarms some web
     content processes).

  2. platformInitializeAccessibility runs in this iframe process,
     calling createMockAccessibilityElement() (this creates a 
WKAccessibilityWebPageObject).
     Note that its m_parent is nil at this point.

  3. An accessibility query reaches the iframe process, triggering
     AXIsolatedTree::create. The iframe root scrollarea caches an
     AXProperty::RemoteParent with a pointer to the
     WKAccessibilityWebPageObject from step 2 (whose m_parent is still nil).

  4. The parent web content process creates an AXRemoteFrame representing the
     iframe web content process. It sends 
bindRemoteAccessibilityFrames(parentPid, parentToken)
     through the UI process.

  5. Iframe's WebPage::bindRemoteAccessibilityFrames runs as result, and calls
     registerRemoteFrameAccessibilityTokens. Prior to this commit, this
     unconditionally replaced m_mockAccessibilityElement (the 
WKAccessibilityWebPageObject)
     with a brand new instance, and sets m_parent for the new instance.

  6. The iframe's root scroll area still has the old
     WKAccessibilityWebPageObject cached in its AXProperty::RemoteFrame
     from step #2, with a nil m_parent.

This bug is intermittent, critically depending on whether there was a
prewarmed process available for the iframe web content. If there was not
a prewarmed process available, AXProperty::RemoteParent is set up from
the start with the WKAccessibilityWebPageObject that used to be
unconditionally created in step 5, and the bug did not manifest.

This commit fixes the issue by changing registerRemoteFrameAccessibilityTokens
to only create a new m_mockAccessibilityElement if one doesn't already
exist, preventing the iframe scroll area from being associated with a
stale one that has no parent.

Because the bug depends on prewarming behavior, the added layout test
passes with and without this commit. I couldn't find a good way to
emulate that in our testing environment. Fix manually confirmed in Safari.

* 
LayoutTests/http/tests/site-isolation/accessibility/client/walk-up-from-iframe-content-expected.txt:
 Added.
* 
LayoutTests/http/tests/site-isolation/accessibility/client/walk-up-from-iframe-content.html:
 Added.
* Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::registerRemoteFrameAccessibilityTokens):

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



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

Reply via email to