Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: bbef52230d06c1615a08fc6c75d6cbf2e1648f53
      
https://github.com/WebKit/WebKit/commit/bbef52230d06c1615a08fc6c75d6cbf2e1648f53
  Author: Basuke Suzuki <[email protected]>
  Date:   2026-06-29 (Mon, 29 Jun 2026)

  Changed paths:
    M LayoutTests/platform/mac-wk2/TestExpectations
    M Source/WebKit/UIProcess/WebBackForwardList.cpp
    M Source/WebKit/UIProcess/WebBackForwardList.h
    M Source/WebKit/UIProcess/WebBackForwardList.swift
    M Source/WebKit/UIProcess/WebPageProxy.cpp

  Log Message:
  -----------
  [Site Isolation] Positional back/forward child-frame lookup corrupts a 
sibling frameID, producing duplicate frameIDs in the BF tree
https://bugs.webkit.org/show_bug.cgi?id=318112
rdar://180926736

Reviewed by Sihui Liu.

This is the capture-side root cause behind bug 318015, which only added a 
defensive guard in
the per-frame back/forward walk.

Under UseUIProcessForBackForwardItemLoading, when a child frame performs a 
back/forward
navigation, WebPageProxy::frameStateForBackForwardChildFrame looks up the 
child's stored
FrameState in the target back/forward item positionally: it takes the live 
frame's document-order
index (WebFrameProxy::indexInFrameTreeSiblings) and calls 
WebBackForwardList::findFrameStateInItem,
which fetches the BF child via 
WebBackForwardListFrameItem::childItemAtIndex(index).

But the BF item's children are stored in commit/append order (the order in 
which each iframe
recorded its initial history item), which can differ from the live frame tree's 
document order.
When a page has two sibling iframes and the second commits its initial history 
item before the
first (e.g. the second has a script and the first is empty), the BF children 
end up reversed
relative to the live tree.

With that ordering mismatch, the positional lookup returns the wrong sibling's 
FrameState.
frameStateForBackForwardChildFrame then sees frameState->frameID != live 
frame.frameID() and
"corrects" it by calling WebBackForwardList::updateFrameIdentifier(storedID -> 
liveID), which walks
all back/forward entries and rewrites the first frame carrying storedID. That 
rewrites the
unaffected sibling's frameID onto the navigated frame's frameID, leaving two 
sibling frame items
with the same frameID in a back/forward entry. The duplicate then makes the 
per-frame walk dispatch
a second GoToBackForwardItem to the same live frame, clobbering the intended 
navigation -- the flaky
timeout that bug 318015 fixed defensively. On Debug it also fires the
HistoryItem::addChildItem duplicate-frameID assertion when the WebProcess 
reconstructs the
HistoryItem from the corrupted FrameState.

Fix: in findFrameStateInItem, match the child by the live frame's identifier 
first
(childItemForFrameID), and fall back to the positional lookup only when that 
identifier is absent --
i.e. the stored identifiers no longer match the live frames, which happens 
after session restore or
when a cross-site child frame is recreated (where updateFrameIdentifier then 
legitimately remaps the
regenerated identifier). In the common live case the identifier matches, so the 
wrong sibling can no
longer be selected and updateFrameIdentifier is no longer triggered spuriously. 
The change is
mirrored in the Swift (ENABLE_BACK_FORWARD_LIST_SWIFT) implementation.

Because the corruption is fixed at the source, the WebProcess never 
reconstructs a HistoryItem with
a duplicate frameID, so the bug-317799 Debug skip for the 
overlapping-navigations cluster test is
removed; the test passes on Debug with the fix.

Covered by existing tests (SiteIsolation.NavigateFrameWithSiblingsBackForward, 
previously flaky;
SiteIsolation.BackNavigationOverCrossSiteIframeWithoutBFCache; and the 
session-restore back/forward
tests that exercise the positional fallback) and by
http/wpt/site-isolation/overlapping-navigations-and-traversals/cross-document-traversal-cross-document-traversal.html
on Debug. Verified on both the C++ and Swift back/forward list implementations: 
the
duplicate-frameID corruption no longer appears across many iterations (it 
reproduced roughly one run
in ten to twenty-five before), and the Debug assertion fires without the fix 
and is quiet with it.

* LayoutTests/platform/mac-wk2/TestExpectations: Remove the bug-317799 Debug 
skip.
* Source/WebKit/UIProcess/WebBackForwardList.cpp:
(WebKit::WebBackForwardList::findFrameStateInItem):
* Source/WebKit/UIProcess/WebBackForwardList.h:
* Source/WebKit/UIProcess/WebBackForwardList.swift:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::frameStateForBackForwardChildFrame):

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



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

Reply via email to