Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: b7bbb825266afcbe86fb36e734e21b6f630945c7
https://github.com/WebKit/WebKit/commit/b7bbb825266afcbe86fb36e734e21b6f630945c7
Author: Roberto Rodriguez <[email protected]>
Date: 2026-10-10 (Sat, 10 Oct 2026)
Changed paths:
M Source/WebCore/page/RemoteFrame.cpp
M Source/WebCore/page/RemoteFrame.h
M Source/WebCore/page/RemoteFrameClient.h
M Source/WebKit/WebProcess/WebCoreSupport/WebRemoteFrameClient.cpp
M Source/WebKit/WebProcess/WebCoreSupport/WebRemoteFrameClient.h
M Source/WebKit/WebProcess/WebPage/WebFrame.cpp
M Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm
Log Message:
-----------
[Site Isolation] Same-site grandchild frame is not detached when its
cross-site parent frame is detached
https://bugs.webkit.org/show_bug.cgi?id=325777
rdar://188788112
Reviewed by Alex Christensen.
With site isolation, if a page on site A has an iframe on site B containing a
frame on site A, and no
other frame on B, that grandchild never gets detached when the iframe is
removed, the main frame
navigates same-site with the back/forward cache disabled, or the page closes.
Its unload handlers don't
run, and closing the page hits ASSERT(m_rootFrames.isEmpty()).
In A's process, the grandchild is a root frame whose parent is B's RemoteFrame.
RemoteFrame::frameDetached() takes B out of the tree but doesn't detach the
grandchild, and
Page::~Page() doesn't detach it either.
Fix by having RemoteFrame::frameDetached() detach its local descendants first.
Remote children aren't
detached themselves, since that would unload a same-site grandchild before its
parent, but their local
descendants are. Their provisional frames are destroyed directly, because the
UI process's message to
do that is dropped if their WebFrame is invalidated first. A guard handles
re-entry from unload handlers.
B's process now gets FrameWasRemovedInAnotherProcess for the grandchild before
B. If the grandchild's
iframe is display:none, its RemoteFrame in B's process is then freed while the
owner element still
counts it, and removing B hits ASSERT(node.connectedSubframeCount() == count).
Disconnect the owner
element in WebFrame::removeFromTree() for RemoteFrames, as ~LocalFrame()
already does for LocalFrames.
Test: Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm
* Source/WebCore/page/RemoteFrame.cpp:
(WebCore::RemoteFrame::frameDetached):
(WebCore::RemoteFrame::detachLocalDescendants):
* Source/WebCore/page/RemoteFrame.h:
* Source/WebCore/page/RemoteFrameClient.h:
* Source/WebKit/WebProcess/WebCoreSupport/WebRemoteFrameClient.cpp:
(WebKit::WebRemoteFrameClient::destroyProvisionalFrame):
* Source/WebKit/WebProcess/WebCoreSupport/WebRemoteFrameClient.h:
* Source/WebKit/WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::removeFromTree):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/SiteIsolation.mm:
(TestWebKitAPI::openerAndOpenedViews):
(TestWebKitAPI::closeOpenedViewAndCheckOpenerProcess):
(TestWebKitAPI::serverWithSameSiteGrandchildOfCrossSiteIframe):
(TestWebKitAPI::checkSameSiteGrandchildOfCrossSiteIframe):
(TestWebKitAPI::TEST(SiteIsolation,
RemoveCrossSiteIframeWithSameSiteGrandchildThenClosePage)):
(TestWebKitAPI::TEST(SiteIsolation,
SameSiteMainFrameNavigationWithCrossSiteIframeThenClosePage)):
(TestWebKitAPI::TEST(SiteIsolation,
ClosePageWithSameSiteGrandchildOfCrossSiteIframe)):
(TestWebKitAPI::TEST(SiteIsolation,
RemoveCrossSiteIframeWithHiddenSameSiteGrandchild)):
(TestWebKitAPI::TEST(SiteIsolation,
RemoveCrossSiteIframeWhoseChildIsNavigatingToTheMainFrameSite)):
(TestWebKitAPI::TEST(SiteIsolation,
RemoveCrossSiteIframeWithSameSiteDescendantBelowAnotherSite)):
(TestWebKitAPI::TEST(SiteIsolation,
RemoveCrossSiteIframeAgainFromSameSiteGrandchildUnloadHandler)):
(TestWebKitAPI::TEST(SiteIsolation,
UnloadOrderOfSameSiteChildAndGrandchildUnderCrossSiteParent)):
Canonical link: https://commits.webkit.org/323293@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications