Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 444bd55f430068ef071504ce4cebeaaae92333df
      
https://github.com/WebKit/WebKit/commit/444bd55f430068ef071504ce4cebeaaae92333df
  Author: Basuke Suzuki <[email protected]>
  Date:   2026-05-28 (Thu, 28 May 2026)

  Changed paths:
    M Source/WebCore/history/BackForwardCache.cpp
    M Source/WebCore/loader/FrameLoader.cpp
    M Source/WebCore/loader/FrameLoader.h
    M Source/WebCore/loader/FrameLoaderTypes.h
    M Source/WebCore/loader/HistoryController.h
    M Source/WebCore/page/Page.h
    M Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
    M Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
    M Source/WebKit/UIProcess/WebBackForwardCacheEntry.cpp
    M Source/WebKit/UIProcess/WebBackForwardCacheEntry.h
    M Source/WebKit/UIProcess/WebPageProxy.cpp
    M Source/WebKit/UIProcess/WebPageProxy.h
    M Source/WebKit/UIProcess/WebPageProxyInternals.h
    M Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm

  Log Message:
  -----------
  [Site Isolation] Enable same-site BFCache with cross-site iframes via 
UIProcess coordination
https://bugs.webkit.org/show_bug.cgi?id=313657
rdar://175857874

Reviewed by Sihui Liu.

Builds on the plumbing added in "[BFCache] Plumb 
ShouldRestoreFromBackForwardCache
and RestoredFromBackForwardCache signals as preparation" (bug 315606). Building 
on bug 315104
and bug 315105, enable same-site back/forward cache for pages with cross-site
iframes under Site Isolation. The UIProcess orchestrates iframe-process
suspend and restore in parallel with the main WebProcess, gated by the
MultiProcessBackForwardCacheEnabled feature flag.

On cache, the UIProcess walks its live frame tree, dispatches
SuspendWithFrameItem to each iframe process, and detaches the iframe
WebFrameProxy subtree into the cache entry.

On restore, the UIProcess is the sole driver of the take action for every
in-process BFCache entry — not just orchestrated SI multi-process entries.
WebPageProxy::goToBackForwardItem takes the UI-side mirror synchronously
for any non-suspended-page cache entry that the UIProcess tracks, removes
the forward-list entry, and sets shouldRestoreFromBackForwardCache =
ShouldRestoreFromBackForwardCache::Yes on GoToBackForwardItemParameters
to signal the target WebProcess that the take happened upstream. The
WebProcess restores from cache only when its own
BackForwardCache::singleton().get() lookup succeeds; ::Yes with no cached
page logs an error and falls through to a normal load. Code paths without
an authoritative UIProcess decision (e.g. unsuspend via SuspendedPageProxy,
JavaScript history.back() inside the WebProcess, WebKitLegacy WebView
back/forward) pass ::Unspecified, which preserves the legacy
hasCachedPage-driven restore semantics. ::No is reserved for explicit
suppression — when received together with a cached page, FrameLoader
evicts the orphan WP-side entry to keep UIProcess and WebProcess in sync.

For orchestrated SI entries (cachedChildren non-empty) the inner block also
dispatches RestoreWithFrameItem to each iframe process in parallel and
reattaches the iframe subtree on main-frame commit, gated by the new
RestoredFromBackForwardCache parameter on DidCommitLoadForFrame so cache
misses do not reattach onto a fresh-loaded page. Aggregator failure
triggers reload(ExpiredOnly). WebBackForwardCacheEntry::takeForRestoration()
returns the cached children together with the deduplicated iframe
processes in a single atomic call, eliminating the order-dependence
between collecting processes and consuming the children. Live-tree
iframe-process enumeration in didCacheBackForwardItem goes through a new
WebPageProxy::activeRemoteFrameProcesses() helper that returns the
de-duplicated set of remote frame processes hosting iframes.

didTakeBackForwardItemForRestoration (WP→UI) is retained as a dual-path
fallback notification. Its UIProcess handler bails via the existing
`if (!item->backForwardCacheEntry()) return;` guard once UI has taken the
entry, but its IPC fire-site in commitProvisionalLoad is load-bearing for
several layout-test scenarios (multiple-back-forward-navigations,
page-cache-navigate-during-restore, main-resource-delegates-on-back-navigation,
websocket BFCache CCNS tests), so the path is intentionally preserved.

The destructor-suppression contract for UI-driven take — takeForRestoration()
and takeSuspendedPage() both call markAsTakenForRestoration() to clear
m_backForwardFrameItemID so ~WebBackForwardCacheEntry skips its
ClearCachedPage IPC and leaves the WP-side cached Page intact for the actual
restore in commitProvisionalLoad — is documented at the destructor site in
WebBackForwardCacheEntry.cpp.

A race guard in didCacheBackForwardItem (review feedback) covers the case
where the WebProcess fires DidCacheBackForwardItem when its outgoing page
enters the local back/forward cache, but the user navigates back to the
same item before the IPC arrives. The WebProcess has (or will) consume
its own cache for the restoration, so creating a UI-side mirror would be
stale. The guard skips cache-entry creation when the item URL matches
pageLoadState.pendingAPIRequestURL(), which is set when the UI dispatches
a goToBackForwardItem and cleared once the WebProcess starts the
provisional load. A currentItem-based check is not used: in the common
forward-navigation flow addIfCacheable runs before BackForwardAddItem in
commitProvisionalLoad, so when DidCacheBackForwardItem arrives the
outgoing (cached) item is still the current item — that check would
falsely reject every legitimate cache add.

Tests:
- MultiProcessBFCacheSameSiteWithCrossSiteIframe[MultipleCycles]: main
  and iframe markers survive goBack/goForward.
- MultiProcessBFCacheSameSiteWithDifferentCrossSiteIframes: cached a1
  iframe does not pollute a2's live tree.

* Source/WebCore/history/BackForwardCache.cpp:
(WebCore::BackForwardCache::addIfCacheable):
* Source/WebCore/loader/FrameLoader.cpp:
(WebCore::FrameLoader::continueLoadAfterNavigationPolicy):
* Source/WebKit/UIProcess/WebBackForwardCacheEntry.cpp:
(WebKit::WebBackForwardCacheEntry::~WebBackForwardCacheEntry):
(WebKit::WebBackForwardCacheEntry::takeSuspendedPage):
(WebKit::WebBackForwardCacheEntry::iframeProcesses):
(WebKit::WebBackForwardCacheEntry::takeForRestoration):
(WebKit::WebBackForwardCacheEntry::markAsTakenForRestoration):
* Source/WebKit/UIProcess/WebBackForwardCacheEntry.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::didCommitLoadForFrame):
(WebKit::WebPageProxy::activeRemoteFrameProcesses):
(WebKit::WebPageProxy::didCacheBackForwardItem):
(WebKit::WebPageProxy::didTakeBackForwardItemForRestoration):
(WebKit::WebPageProxy::discardBackForwardCacheEntry):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/WebPageProxyInternals.h:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm:
(TEST(SiteIsolation, MultiProcessBFCacheSameSiteWithCrossSiteIframe)):
(TEST(SiteIsolation, 
MultiProcessBFCacheSameSiteWithCrossSiteIframeMultipleCycles)):
(TEST(SiteIsolation, MultiProcessBFCacheSameSiteWithDifferentCrossSiteIframes)):

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



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

Reply via email to