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