Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: e4e510eeb1e1ec1a12945f291423d8cf77d930b3
      
https://github.com/WebKit/WebKit/commit/e4e510eeb1e1ec1a12945f291423d8cf77d930b3
  Author: Rupin Mittal <[email protected]>
  Date:   2026-02-04 (Wed, 04 Feb 2026)

  Changed paths:
    M Source/WebKit/UIProcess/BrowsingContextGroup.cpp
    M Source/WebKit/UIProcess/BrowsingContextGroup.h
    M Source/WebKit/UIProcess/FrameProcess.cpp
    M Source/WebKit/UIProcess/FrameProcess.h
    M Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
    M Source/WebKit/UIProcess/WebFrameProxy.cpp
    M Tools/TestWebKitAPI/Tests/WebKitCocoa/SiteIsolation.mm

  Log Message:
  -----------
  [Site Isolation] Cross site iframe fails to window.open the main frame's site
https://bugs.webkit.org/show_bug.cgi?id=306842
rdar://169509909

Reviewed by Alex Christensen and Sihui Liu.

Imagine we have a main frame containing site1.com and an iframe containing
site2.com. Then, site2.com calls window.open("site.com"). The end result must 
be:

          WebProcess1               |              WebProcess2
------------------------------------|------------------------------------------
Site1WindowA      Site1WindowB      |      Site1WindowA     Site1WindowB
Site2FrameA                         |      Site2FrameA
                                    |
WebPage1          WebPage2          |      WebPage3         WebPage4

(where Site1 is local to WebProcess1).

Both WebPage1 and WebPage2 should each have an associated WebPageProxy and both
WebPage3 and WebPage4 should each have an associated RemotePageProxy. But 
currently,
after the call to window.open, WebPage4 does not have an associated 
RemotePageProxy.

When the window.open call happens, the steps we follow should be:
1. Create WebPage2 and WebPage4.

2. Create a WebPageProxy associated with WebPage4 (because the window.open call
   occurred in WebProcess2).

3. Create a RemotePageProxy associated with WebPage2.

4. When the load starts, we realize the load should occur in WebProcess 1, so we
   create a ProvisionalPageProxy and give it the RemotePageProxy's message 
registration.
   So now the ProvisionalPageProxy is associated with WebPage2. The 
RemotePageProxy
   is then destroyed.

   (See ProvisionalPageProxy::initializeWebPage).

5. When the load commits, create a new RemotePageProxy and give it the 
WebPageProxy's
   messager registration. So now a RemotePageProxy is associated with WebPage4.

   (See ProvisionalPageProxy::didCommitLoadForFrame and
   BrowsingContextGroup::transitionPageToRemotePage).

6. Give the WebPageProxy the message registration of the ProvisionalPageProxy. 
So now
   the WebPageProxy is associated with WebPage2.

   (See WebPageProxy::swapToProvisionalPage).

The problem is that step 5 doesn't happen and so WebPage4 gets left without a
RemotePageProxy.

In ProvisionalPageProxy::didCommitLoadForFrame, we only setup the new 
RemotePageProxy
(by calling BrowsingContextGroup::transitionPageToRemotePage) if
"m_browsingContextGroup->isFrameProcessInUseForMainFrame(pageMainFrameProcess.get())"
is true. At this point the WebPageProxy is still associated with WebPage4 and 
so with
WebProcess2. WebProcess2 is not in use for the main frame. That's WebProcess1. 
So this
condition is false. The code assumes that this WebProcess2 won't be used after 
this
load commits, so there is no point in setting up the RemotePageProxy.

This condition is wrong. It doesn't account for the fact that after the load 
commits,
there will be 1 frame that is local to WebProcess2 (Site2FrameA). So 
WebProcess2 will
still exist and so will WebPage4, and it will need a RemotePageProxy.

To fix this, we make FrameProcess track the number of frames local to its 
associated
WebProcess. We amend the condition so that if there are any such frames at the 
time
of the load committing, we must set up the RemotePageProxy.

This is tested by a new API test 
SiteIsolation.CrossSiteIFrameWindowOpensMainFrameSite.

This changed caused the test
SiteIsolation.BrowsingContextGroupSwitchForIncompatibleCrossOriginOpenerPolicy 
to fail.
In that test, when the page with unsafe-none opens a page with 
same-origin-allow-popups,
we do not want the opener relationship to be preserved, and so the the two 
WebProcesses
are put in different BrowsingContentGroups. So we do not need the 
RemotePageProxy.
So we add an extra check. If the load causes the WebProcess to put into a 
different
BrowsingContextGroup, we do not setup the RemotePageProxy.

* Source/WebKit/UIProcess/BrowsingContextGroup.cpp:
(WebKit::BrowsingContextGroup::isFrameProcessInUseForMainFrame): Deleted.
* Source/WebKit/UIProcess/BrowsingContextGroup.h:
* Source/WebKit/UIProcess/FrameProcess.cpp:
(WebKit::FrameProcess::~FrameProcess):
(WebKit::FrameProcess::browsingContextGroup const):
* Source/WebKit/UIProcess/FrameProcess.h:
(WebKit::FrameProcess::incrementFrameCount):
(WebKit::FrameProcess::decrementFrameCount):
(WebKit::FrameProcess::frameCount const):
* Source/WebKit/UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::didCommitLoadForFrame):

If the Frame Process's associated WebProcess has any frames that are local to 
it,
and is still in the same BrowsingContextGroup, we must setup the 
RemotePageProxy.

* Source/WebKit/UIProcess/WebFrameProxy.cpp:
(WebKit::WebFrameProxy::WebFrameProxy):
(WebKit::WebFrameProxy::~WebFrameProxy):
(WebKit::WebFrameProxy::commitProvisionalFrame):
(WebKit::WebFrameProxy::setProcess):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/SiteIsolation.mm:
(TestWebKitAPI::TEST(SiteIsolation, CrossSiteIFrameWindowOpensMainFrameSite)):

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



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

Reply via email to