Title: [284610] trunk
Revision
284610
Author
[email protected]
Date
2021-10-21 09:47:49 -0700 (Thu, 21 Oct 2021)

Log Message

WebKit should process-swap for initial navigation of a popup if it has no opener
https://bugs.webkit.org/show_bug.cgi?id=231990
<rdar://84425504>

Reviewed by Brent Fulgham.

LayoutTests/imported/w3c:

* web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt:
* web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt:
Rebaseline tests due to minor logging differences.

Source/WebKit:

WebKit should process-swap for initial navigation of a popup if it has no opener, even if the navigation is
same-site. Swapping process is not Web-observable here since there is no opener relationship. However, swapping
processes has benefits here since we don't want to end up with too many tabs sharing the same process.

This impacts Google Drive where double-clicking a document will open Google Docs in a new tab and in the same
WebProcess as Google Drive.

No new tests, updated existing API tests and this is not Web-observable.

* Shared/FrameInfoData.cpp:
(WebKit::FrameInfoData::encode const):
(WebKit::FrameInfoData::decode):
* Shared/FrameInfoData.h:
* Shared/LoadParameters.cpp:
(WebKit::LoadParameters::encode const):
(WebKit::LoadParameters::decode):
* Shared/LoadParameters.h:
* Shared/NavigationActionData.cpp:
(WebKit::NavigationActionData::encode const):
(WebKit::NavigationActionData::decode):
* Shared/NavigationActionData.h:
* UIProcess/API/APINavigation.h:
(API::Navigation::effectiveSandboxFlags const):
* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest):
* UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::cancel):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::loadRequestWithNavigationShared):
(WebKit::WebPageProxy::loadSimulatedRequest):
(WebKit::WebPageProxy::receivedNavigationPolicyDecision):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
* UIProcess/WebPageProxy.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::processForNavigation):
(WebKit::WebProcessPool::processForNavigationInternal):
* UIProcess/WebProcessPool.h:
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::info const):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::loadRequest):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONUIDelegate webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:]):
(-[PSONUIDelegate webViewDidClose:]):
Updated existing API tests to reflect behavior change.
Also extend an API test to make sure that a popup opened by JS can still close itself
via JS (by calling window.close()), even in the case where we process swap.

* WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
(WTR::InjectedBundle::didReceiveMessageToPage):
(WTR::InjectedBundle::outputText):
* WebKitTestRunner/InjectedBundle/InjectedBundle.h:
* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::dump):
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::createOtherPage):
(WTR::TestController::didReceivePageMessageFromInjectedBundle):
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
We have some tests that open a new popup with 'noopener' and the popup would be the
one to call `testRunner.notifyDone()`. This used to work fine when the popup would
end up in the same WebProcess because the injected bundle would know which page is
the main test page and use that one. However, now that we process-swap, the popup
page would think it is the main test page and try to dump its own output. However,
the UIProcess wasn't listening for messages from auxiliary pages' injected bundles.
The UIProcess now listens for those messages and asks the main test page to dump
its output when an auxiliary page in another process says the test is done.

LayoutTests:

* fast/dom/open-and-close-by-DOM.html:
The test is relying on testRunner.windowCount(), which is only able to count windows inside the
current WebProcess. Add `rel=opener` to the link so that the new window keep opening in the same
process, so that `testRunner.windowCount()` actually keeps working as expected.
I added an API test to cover to make sure that windows opened by DOM can still close themselves
in the case where we swap processes.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (284609 => 284610)


--- trunk/LayoutTests/ChangeLog	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/ChangeLog	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,3 +1,18 @@
+2021-10-21  Chris Dumez  <[email protected]>
+
+        WebKit should process-swap for initial navigation of a popup if it has no opener
+        https://bugs.webkit.org/show_bug.cgi?id=231990
+        <rdar://84425504>
+
+        Reviewed by Brent Fulgham.
+
+        * fast/dom/open-and-close-by-DOM.html:
+        The test is relying on testRunner.windowCount(), which is only able to count windows inside the
+        current WebProcess. Add `rel=opener` to the link so that the new window keep opening in the same
+        process, so that `testRunner.windowCount()` actually keeps working as expected.
+        I added an API test to cover to make sure that windows opened by DOM can still close themselves
+        in the case where we swap processes.
+
 2021-10-21  Ayumi Kojima  <[email protected]>
 
         Regression(r284439): [ iPad ] fast/canvas/canvas-createPattern-video-loading.html is failing.

Modified: trunk/LayoutTests/fast/dom/open-and-close-by-DOM.html (284609 => 284610)


--- trunk/LayoutTests/fast/dom/open-and-close-by-DOM.html	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/fast/dom/open-and-close-by-DOM.html	2021-10-21 16:47:49 UTC (rev 284610)
@@ -53,7 +53,7 @@
 <br/>
 <div id="console" />
 <br/>
-<a href="" id="anchorLink" target="_blank">Open new window that will close itself</a>
+<a href="" id="anchorLink" target="_blank" rel="opener">Open new window that will close itself</a>
 <br/><br/>
 
 </body>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (284609 => 284610)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,3 +1,15 @@
+2021-10-21  Chris Dumez  <[email protected]>
+
+        WebKit should process-swap for initial navigation of a popup if it has no opener
+        https://bugs.webkit.org/show_bug.cgi?id=231990
+        <rdar://84425504>
+
+        Reviewed by Brent Fulgham.
+
+        * web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt:
+        * web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt:
+        Rebaseline tests due to minor logging differences.
+
 2021-10-20  Alex Christensen  <[email protected]>
 
         URLParser should reject hosts with C0 control characters or U+007F

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coep-blob-popup.https-expected.txt (284609 => 284610)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coep-blob-popup.https-expected.txt	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coep-blob-popup.https-expected.txt	2021-10-21 16:47:49 UTC (rev 284610)
@@ -2,6 +2,8 @@
 CONSOLE MESSAGE: Fetch API cannot load https://127.0.0.1:9443/common/blank.html due to access control checks.
 CONSOLE MESSAGE: Cancelled load to https://127.0.0.1:9443/common/blank.html because it violates the resource's Cross-Origin-Resource-Policy response header.
 CONSOLE MESSAGE: Fetch API cannot load https://127.0.0.1:9443/common/blank.html due to access control checks.
+CONSOLE MESSAGE: Cancelled load to https://127.0.0.1:9443/common/blank.html because it violates the resource's Cross-Origin-Resource-Policy response header.
+CONSOLE MESSAGE: Fetch API cannot load https://127.0.0.1:9443/common/blank.html due to access control checks.
 
 PASS COOP+COEP blob URL popup: window.open()
 PASS COOP+COEP blob URL popup: <a>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt (284609 => 284610)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,5 +1,4 @@
 CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
-CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
 
 PASS <iframe sandbox="allow-popups allow-scripts allow-same-origin"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error
 PASS <iframe sandbox="allow-popups allow-scripts"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-csp-sandbox.https-expected.txt (284609 => 284610)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-csp-sandbox.https-expected.txt	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-csp-sandbox.https-expected.txt	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,3 +1,5 @@
+CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
+CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
 
 PASS CSP: sandbox allow-popups allow-scripts allow-same-origin; CSP sandboxed Cross-Origin-Opener-Policy popup should result in a network error
 PASS CSP: sandbox allow-popups allow-scripts; CSP sandboxed Cross-Origin-Opener-Policy popup should result in a network error

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt (284609 => 284610)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,5 +1,4 @@
 CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
-CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
 
 PASS <iframe sandbox="allow-popups allow-scripts allow-same-origin"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error
 PASS <iframe sandbox="allow-popups allow-scripts"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error

Modified: trunk/Source/WebCore/page/Page.h (284609 => 284610)


--- trunk/Source/WebCore/page/Page.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebCore/page/Page.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -279,7 +279,7 @@
     const Frame& mainFrame() const { return m_mainFrame.get(); }
 
     bool openedByDOM() const;
-    void setOpenedByDOM();
+    WEBCORE_EXPORT void setOpenedByDOM();
 
     bool openedByDOMWithOpener() const { return m_openedByDOMWithOpener; }
     void setOpenedByDOMWithOpener(bool value) { m_openedByDOMWithOpener = value; }

Modified: trunk/Source/WebKit/ChangeLog (284609 => 284610)


--- trunk/Source/WebKit/ChangeLog	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/ChangeLog	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,3 +1,55 @@
+2021-10-21  Chris Dumez  <[email protected]>
+
+        WebKit should process-swap for initial navigation of a popup if it has no opener
+        https://bugs.webkit.org/show_bug.cgi?id=231990
+        <rdar://84425504>
+
+        Reviewed by Brent Fulgham.
+
+        WebKit should process-swap for initial navigation of a popup if it has no opener, even if the navigation is
+        same-site. Swapping process is not Web-observable here since there is no opener relationship. However, swapping
+        processes has benefits here since we don't want to end up with too many tabs sharing the same process.
+
+        This impacts Google Drive where double-clicking a document will open Google Docs in a new tab and in the same
+        WebProcess as Google Drive.
+
+        No new tests, updated existing API tests and this is not Web-observable.
+
+        * Shared/FrameInfoData.cpp:
+        (WebKit::FrameInfoData::encode const):
+        (WebKit::FrameInfoData::decode):
+        * Shared/FrameInfoData.h:
+        * Shared/LoadParameters.cpp:
+        (WebKit::LoadParameters::encode const):
+        (WebKit::LoadParameters::decode):
+        * Shared/LoadParameters.h:
+        * Shared/NavigationActionData.cpp:
+        (WebKit::NavigationActionData::encode const):
+        (WebKit::NavigationActionData::decode):
+        * Shared/NavigationActionData.h:
+        * UIProcess/API/APINavigation.h:
+        (API::Navigation::effectiveSandboxFlags const):
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::UIDelegate::UIClient::decidePolicyForUserMediaPermissionRequest):
+        * UIProcess/ProvisionalPageProxy.cpp:
+        (WebKit::ProvisionalPageProxy::cancel):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::loadRequestWithNavigationShared):
+        (WebKit::WebPageProxy::loadSimulatedRequest):
+        (WebKit::WebPageProxy::receivedNavigationPolicyDecision):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::processForNavigation):
+        (WebKit::WebProcessPool::processForNavigationInternal):
+        * UIProcess/WebProcessPool.h:
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::WebFrame::info const):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::loadRequest):
+
 2021-10-21  Chris Lord  <[email protected]>
 
         [WPE][GTK] Enable smooth scrolling by default

Modified: trunk/Source/WebKit/Shared/FrameInfoData.cpp (284609 => 284610)


--- trunk/Source/WebKit/Shared/FrameInfoData.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/FrameInfoData.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -35,6 +35,7 @@
     encoder << isMainFrame;
     encoder << request;
     encoder << securityOrigin;
+    encoder << frameName;
     encoder << frameID;
     encoder << parentFrameID;
 }
@@ -56,6 +57,11 @@
     if (!securityOrigin)
         return std::nullopt;
 
+    std::optional<String> frameName;
+    decoder >> frameName;
+    if (!frameName)
+        return std::nullopt;
+
     std::optional<std::optional<WebCore::FrameIdentifier>> frameID;
     decoder >> frameID;
     if (!frameID)
@@ -70,6 +76,7 @@
         WTFMove(*isMainFrame),
         WTFMove(*request),
         WTFMove(*securityOrigin),
+        WTFMove(*frameName),
         WTFMove(*frameID),
         WTFMove(*parentFrameID)
     }};

Modified: trunk/Source/WebKit/Shared/FrameInfoData.h (284609 => 284610)


--- trunk/Source/WebKit/Shared/FrameInfoData.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/FrameInfoData.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -43,6 +43,7 @@
     bool isMainFrame { false };
     WebCore::ResourceRequest request;
     WebCore::SecurityOriginData securityOrigin;
+    String frameName;
     std::optional<WebCore::FrameIdentifier> frameID;
     std::optional<WebCore::FrameIdentifier> parentFrameID;
 };

Modified: trunk/Source/WebKit/Shared/LoadParameters.cpp (284609 => 284610)


--- trunk/Source/WebKit/Shared/LoadParameters.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/LoadParameters.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -56,6 +56,7 @@
     encoder << lockHistory;
     encoder << lockBackForwardList;
     encoder << clientRedirectSourceForHistory;
+    encoder << effectiveSandboxFlags;
     encoder << isNavigatingToAppBoundDomain;
     encoder << existingNetworkResourceLoadIdentifierToResume;
     encoder << isServiceWorkerLoad;
@@ -136,6 +137,12 @@
     if (!clientRedirectSourceForHistory)
         return false;
     data.clientRedirectSourceForHistory = WTFMove(*clientRedirectSourceForHistory);
+
+    std::optional<WebCore::SandboxFlags> effectiveSandboxFlags;
+    decoder >> effectiveSandboxFlags;
+    if (!effectiveSandboxFlags)
+        return false;
+    data.effectiveSandboxFlags = *effectiveSandboxFlags;
     
     if (!decoder.decode(data.isNavigatingToAppBoundDomain))
         return false;

Modified: trunk/Source/WebKit/Shared/LoadParameters.h (284609 => 284610)


--- trunk/Source/WebKit/Shared/LoadParameters.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/LoadParameters.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -43,6 +43,10 @@
 class Encoder;
 }
 
+namespace WebCore {
+typedef int SandboxFlags;
+}
+
 namespace WebKit {
 
 struct LoadParameters {
@@ -74,6 +78,7 @@
     WebCore::LockBackForwardList lockBackForwardList { WebCore::LockBackForwardList::No };
     WebCore::SubstituteData::SessionHistoryVisibility sessionHistoryVisibility { WebCore::SubstituteData::SessionHistoryVisibility::Visible };
     String clientRedirectSourceForHistory;
+    WebCore::SandboxFlags effectiveSandboxFlags { 0 };
     std::optional<NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain;
     std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume;
     bool isServiceWorkerLoad { false };

Modified: trunk/Source/WebKit/Shared/NavigationActionData.cpp (284609 => 284610)


--- trunk/Source/WebKit/Shared/NavigationActionData.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/NavigationActionData.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -54,6 +54,7 @@
     encoder << lockHistory;
     encoder << lockBackForwardList;
     encoder << clientRedirectSourceForHistory;
+    encoder << effectiveSandboxFlags;
     encoder << privateClickMeasurement;
 }
 
@@ -146,6 +147,11 @@
     if (!clientRedirectSourceForHistory)
         return std::nullopt;
 
+    std::optional<WebCore::SandboxFlags> effectiveSandboxFlags;
+    decoder >> effectiveSandboxFlags;
+    if (!effectiveSandboxFlags)
+        return std::nullopt;
+
     std::optional<std::optional<WebCore::PrivateClickMeasurement>> privateClickMeasurement;
     decoder >> privateClickMeasurement;
     if (!privateClickMeasurement)
@@ -154,7 +160,7 @@
     return {{ WTFMove(navigationType), modifiers, WTFMove(mouseButton), WTFMove(syntheticClickType), WTFMove(*userGestureTokenIdentifier),
         WTFMove(*canHandleRequest), WTFMove(shouldOpenExternalURLsPolicy), WTFMove(*downloadAttribute), WTFMove(clickLocationInRootViewCoordinates),
         WTFMove(*isRedirect), *treatAsSameOriginNavigation, *hasOpenedFrames, *openedByDOMWithOpener, WTFMove(*requesterOrigin),
-        WTFMove(*targetBackForwardItemIdentifier), WTFMove(*sourceBackForwardItemIdentifier), lockHistory, lockBackForwardList, WTFMove(*clientRedirectSourceForHistory), WTFMove(*privateClickMeasurement) }};
+        WTFMove(*targetBackForwardItemIdentifier), WTFMove(*sourceBackForwardItemIdentifier), lockHistory, lockBackForwardList, WTFMove(*clientRedirectSourceForHistory), *effectiveSandboxFlags, WTFMove(*privateClickMeasurement) }};
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Shared/NavigationActionData.h (284609 => 284610)


--- trunk/Source/WebKit/Shared/NavigationActionData.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/NavigationActionData.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -37,6 +37,10 @@
 class Encoder;
 }
 
+namespace WebCore {
+typedef int SandboxFlags;
+}
+
 namespace WebKit {
 
 struct NavigationActionData {
@@ -62,6 +66,7 @@
     WebCore::LockHistory lockHistory { WebCore::LockHistory::No };
     WebCore::LockBackForwardList lockBackForwardList { WebCore::LockBackForwardList::No };
     WTF::String clientRedirectSourceForHistory;
+    WebCore::SandboxFlags effectiveSandboxFlags { 0 };
     std::optional<WebCore::PrivateClickMeasurement> privateClickMeasurement;
 };
 

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp (284609 => 284610)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -65,6 +65,7 @@
     encoder << topContentInset;
     encoder << mediaVolume;
     encoder << muted;
+    encoder << openedByDOM;
     encoder << mayStartMediaWhenInWindow;
     encoder << mediaPlaybackIsSuspended;
     encoder << minimumSizeForAutoLayout;
@@ -290,6 +291,8 @@
         return std::nullopt;
     parameters.muted = *mutedStateFlags;
 
+    if (!decoder.decode(parameters.openedByDOM))
+        return std::nullopt;
     if (!decoder.decode(parameters.mayStartMediaWhenInWindow))
         return std::nullopt;
     if (!decoder.decode(parameters.mediaPlaybackIsSuspended))

Modified: trunk/Source/WebKit/Shared/WebPageCreationParameters.h (284609 => 284610)


--- trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/Shared/WebPageCreationParameters.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -120,6 +120,7 @@
     
     float mediaVolume;
     WebCore::MediaProducerMutedStateFlags muted;
+    bool openedByDOM { false };
     bool mayStartMediaWhenInWindow;
     bool mediaPlaybackIsSuspended { false };
 

Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/API/APINavigation.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -144,6 +144,7 @@
     WebCore::LockBackForwardList lockBackForwardList() const { return m_lastNavigationAction.lockBackForwardList; }
 
     WTF::String clientRedirectSourceForHistory() const { return m_lastNavigationAction.clientRedirectSourceForHistory; }
+    WebCore::SandboxFlags effectiveSandboxFlags() const { return m_lastNavigationAction.effectiveSandboxFlags; }
 
     void setLastNavigationAction(const WebKit::NavigationActionData& navigationAction) { m_lastNavigationAction = navigationAction; }
     const WebKit::NavigationActionData& lastNavigationAction() const { return m_lastNavigationAction; }

Modified: trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1152,7 +1152,7 @@
         std::optional<WebCore::FrameIdentifier> mainFrameID;
         if (auto* mainFrame = frame.page() ? frame.page()->mainFrame() : nullptr)
             mainFrameID = mainFrame->frameID();
-        FrameInfoData frameInfo { frame.isMainFrame(), { }, userMediaOrigin.securityOrigin(), frame.frameID(), mainFrameID };
+        FrameInfoData frameInfo { frame.isMainFrame(), { }, userMediaOrigin.securityOrigin(), { }, frame.frameID(), mainFrameID };
         RetainPtr<WKFrameInfo> frameInfoWrapper = wrapper(API::FrameInfo::create(WTFMove(frameInfo), frame.page()));
 
         WKMediaCaptureType type = WKMediaCaptureTypeCamera;

Modified: trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -149,6 +149,7 @@
         true, // isMainFrame
         m_request,
         SecurityOriginData::fromURL(m_request.url()),
+        { },
         m_mainFrame->frameID(),
         std::nullopt,
     };

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1416,6 +1416,7 @@
     loadParameters.lockHistory = navigation.lockHistory();
     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
+    loadParameters.effectiveSandboxFlags = navigation.effectiveSandboxFlags();
     loadParameters.isNavigatingToAppBoundDomain = isNavigatingToAppBoundDomain;
     loadParameters.existingNetworkResourceLoadIdentifierToResume = existingNetworkResourceLoadIdentifierToResume;
     maybeInitializeSandboxExtensionHandle(process, url, m_pageLoadState.resourceDirectoryURL(), loadParameters.sandboxExtensionHandle);
@@ -1602,6 +1603,7 @@
     loadParameters.lockHistory = navigation->lockHistory();
     loadParameters.lockBackForwardList = navigation->lockBackForwardList();
     loadParameters.clientRedirectSourceForHistory = navigation->clientRedirectSourceForHistory();
+    loadParameters.effectiveSandboxFlags = navigation->effectiveSandboxFlags();
     loadParameters.isNavigatingToAppBoundDomain = isNavigatingToAppBoundDomain();
 
     simulatedResponse.setExpectedContentLength(data.size());
@@ -3455,7 +3457,7 @@
 #endif
 }
 
-void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, Ref<API::NavigationAction>&& navigationAction, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, RefPtr<API::WebsitePolicies>&& policies, Ref<PolicyDecisionSender>&& sender)
+void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, Ref<API::NavigationAction>&& navigationAction, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, const FrameInfoData& frameInfo, RefPtr<API::WebsitePolicies>&& policies, Ref<PolicyDecisionSender>&& sender)
 {
     WEBPAGEPROXY_RELEASE_LOG(Loading, "receivedNavigationPolicyDecision: frameID=%llu, navigationID=%llu, policyAction=%u", frame.frameID().toUInt64(), navigation ? navigation->navigationID() : 0, (unsigned)policyAction);
 
@@ -3508,7 +3510,7 @@
         }
     }
 
-    process().processPool().processForNavigation(*this, *navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, WTFMove(websiteDataStore), [this, protectedThis = Ref { *this }, policyAction, navigation = Ref { *navigation }, navigationAction = WTFMove(navigationAction), sourceProcess = sourceProcess.copyRef(),
+    process().processPool().processForNavigation(*this, *navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, frameInfo, WTFMove(websiteDataStore), [this, protectedThis = Ref { *this }, policyAction, navigation = Ref { *navigation }, navigationAction = WTFMove(navigationAction), sourceProcess = sourceProcess.copyRef(),
         policies = WTFMove(policies), sender = WTFMove(sender), processSwapRequestedByClient] (Ref<WebProcessProxy>&& processForNavigation, SuspendedPageProxy* destinationSuspendedPage, const String& reason) mutable {
         // If the navigation has been destroyed, then no need to proceed.
         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
@@ -5430,7 +5432,7 @@
     Ref listener = frame.setUpPolicyListenerProxy([this, protectedThis = Ref { *this }, frame = Ref { frame }, sender = WTFMove(sender), navigation, navigationAction, frameInfo, userDataObject = process->transformHandlesToObjects(userData.object()).get()] (PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, std::optional<NavigatingToAppBoundDomain> isAppBoundDomain) mutable {
         WEBPAGEPROXY_RELEASE_LOG(Loading, "decidePolicyForNavigationAction: listener called: frameID=%llu, navigationID=%llu, policyAction=%u, safeBrowsingWarning=%d, isAppBoundDomain=%d", frame->frameID().toUInt64(), navigation ? navigation->navigationID() : 0, (unsigned)policyAction, !!safeBrowsingWarning, !!isAppBoundDomain);
 
-        auto completionHandler = [this, protectedThis, frame, sender = WTFMove(sender), navigation, navigationAction = WTFMove(navigationAction), processSwapRequestedByClient, policies = RefPtr { policies }] (PolicyAction policyAction) mutable {
+        auto completionHandler = [this, protectedThis, frame, frameInfo, sender = WTFMove(sender), navigation, navigationAction = WTFMove(navigationAction), processSwapRequestedByClient, policies = RefPtr { policies }] (PolicyAction policyAction) mutable {
             if (frame->isMainFrame()) {
                 if (!policies) {
                     if (auto* defaultPolicies = m_configuration->defaultWebsitePolicies())
@@ -5439,7 +5441,7 @@
                 if (policies)
                     navigation->setEffectiveContentMode(effectiveContentModeAfterAdjustingPolicies(*policies, navigation->currentRequest()));
             }
-            receivedNavigationPolicyDecision(policyAction, navigation.get(), WTFMove(navigationAction), processSwapRequestedByClient, frame, WTFMove(policies), WTFMove(sender));
+            receivedNavigationPolicyDecision(policyAction, navigation.get(), WTFMove(navigationAction), processSwapRequestedByClient, frame, frameInfo, WTFMove(policies), WTFMove(sender));
         };
 
 #if ENABLE(APP_BOUND_DOMAINS)
@@ -8221,6 +8223,7 @@
     parameters.topContentInset = m_topContentInset;
     parameters.mediaVolume = m_mediaVolume;
     parameters.muted = m_mutedState;
+    parameters.openedByDOM = m_openedByDOM;
     parameters.mayStartMediaWhenInWindow = m_mayStartMediaWhenInWindow;
     parameters.mediaPlaybackIsSuspended = m_mediaPlaybackIsSuspended;
     parameters.minimumSizeForAutoLayout = m_minimumSizeForAutoLayout;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1223,7 +1223,7 @@
     class PolicyDecisionSender;
     enum class WillContinueLoadInNewProcess : bool { No, Yes };
     void receivedPolicyDecision(WebCore::PolicyAction, API::Navigation*, RefPtr<API::WebsitePolicies>&&, std::variant<Ref<API::NavigationResponse>, Ref<API::NavigationAction>>&&, Ref<PolicyDecisionSender>&&, std::optional<SandboxExtension::Handle> = { }, WillContinueLoadInNewProcess = WillContinueLoadInNewProcess::No);
-    void receivedNavigationPolicyDecision(WebCore::PolicyAction, API::Navigation*, Ref<API::NavigationAction>&&, ProcessSwapRequestedByClient, WebFrameProxy&, RefPtr<API::WebsitePolicies>&&, Ref<PolicyDecisionSender>&&);
+    void receivedNavigationPolicyDecision(WebCore::PolicyAction, API::Navigation*, Ref<API::NavigationAction>&&, ProcessSwapRequestedByClient, WebFrameProxy&, const FrameInfoData&, RefPtr<API::WebsitePolicies>&&, Ref<PolicyDecisionSender>&&);
 
     void backForwardRemovedItem(const WebCore::BackForwardItemIdentifier&);
 

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1814,9 +1814,9 @@
         m_swappedProcessesPerRegistrableDomain.remove(registrableDomain);
 }
 
-void WebProcessPool::processForNavigation(WebPageProxy& page, const API::Navigation& navigation, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient processSwapRequestedByClient, Ref<WebsiteDataStore>&& dataStore, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
+void WebProcessPool::processForNavigation(WebPageProxy& page, const API::Navigation& navigation, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient processSwapRequestedByClient, const FrameInfoData& frameInfo, Ref<WebsiteDataStore>&& dataStore, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
 {
-    processForNavigationInternal(page, navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, WTFMove(dataStore), [this, page = Ref { page }, navigation = Ref { navigation }, sourceProcess = sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, completionHandler = WTFMove(completionHandler)](Ref<WebProcessProxy>&& process, SuspendedPageProxy* suspendedPage, const String& reason) mutable {
+    processForNavigationInternal(page, navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, frameInfo, WTFMove(dataStore), [this, page = Ref { page }, navigation = Ref { navigation }, sourceProcess = sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, completionHandler = WTFMove(completionHandler)](Ref<WebProcessProxy>&& process, SuspendedPageProxy* suspendedPage, const String& reason) mutable {
         // We are process-swapping so automatic process prewarming would be beneficial if the client has not explicitly enabled / disabled it.
         bool doingAnAutomaticProcessSwap = processSwapRequestedByClient == ProcessSwapRequestedByClient::No && process.ptr() != sourceProcess.ptr();
         if (doingAnAutomaticProcessSwap && !configuration().wasAutomaticProcessWarmingSetByClient() && !configuration().clientWouldBenefitFromAutomaticProcessPrewarming()) {
@@ -1839,7 +1839,7 @@
     });
 }
 
-void WebProcessPool::processForNavigationInternal(WebPageProxy& page, const API::Navigation& navigation, Ref<WebProcessProxy>&& sourceProcess, const URL& pageSourceURL, ProcessSwapRequestedByClient processSwapRequestedByClient, Ref<WebsiteDataStore>&& dataStore, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
+void WebProcessPool::processForNavigationInternal(WebPageProxy& page, const API::Navigation& navigation, Ref<WebProcessProxy>&& sourceProcess, const URL& pageSourceURL, ProcessSwapRequestedByClient processSwapRequestedByClient, const FrameInfoData& frameInfo, Ref<WebsiteDataStore>&& dataStore, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&& completionHandler)
 {
     auto& targetURL = navigation.currentRequest().url();
     auto targetRegistrableDomain = WebCore::RegistrableDomain { targetURL };
@@ -1897,6 +1897,13 @@
         }
     }
 
+    // If it is the first navigation in a DOM popup and there is no opener, then force a process swap no matter what since
+    // popup windows are originally created in their opener's process.
+    // Note that we currently do not process swap if the window popup has a name. In theory, we should be able to swap in this case too
+    // but we would need to transfer over the name to the new process. At this point, it is not clear it is worth the extra complexity.
+    if (page.openedByDOM() && !navigation.openedByDOMWithOpener() && !page.hasCommittedAnyProvisionalLoads() && frameInfo.frameName.isEmpty() && !targetURL.protocolIsBlob())
+        return completionHandler(createNewProcess(), nullptr, "Process swap because this is a first navigation in a DOM popup without opener"_s);
+
     if (navigation.treatAsSameOriginNavigation())
         return completionHandler(WTFMove(sourceProcess), nullptr, "The treatAsSameOriginNavigation flag is set"_s);
 

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (284609 => 284610)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -446,7 +446,7 @@
     bool hasForegroundWebProcesses() const { return m_foregroundWebProcessCounter.value(); }
     bool hasBackgroundWebProcesses() const { return m_backgroundWebProcessCounter.value(); }
 
-    void processForNavigation(WebPageProxy&, const API::Navigation&, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient, Ref<WebsiteDataStore>&&, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&&);
+    void processForNavigation(WebPageProxy&, const API::Navigation&, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient, const FrameInfoData&, Ref<WebsiteDataStore>&&, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&&);
 
     void didReachGoodTimeToPrewarm();
 
@@ -523,7 +523,7 @@
     void platformInitializeWebProcess(const WebProcessProxy&, WebProcessCreationParameters&);
     void platformInvalidateContext();
 
-    void processForNavigationInternal(WebPageProxy&, const API::Navigation&, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient, Ref<WebsiteDataStore>&&, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&&);
+    void processForNavigationInternal(WebPageProxy&, const API::Navigation&, Ref<WebProcessProxy>&& sourceProcess, const URL& sourceURL, ProcessSwapRequestedByClient, const FrameInfoData&, Ref<WebsiteDataStore>&&, CompletionHandler<void(Ref<WebProcessProxy>&&, SuspendedPageProxy*, const String&)>&&);
 
     RefPtr<WebProcessProxy> tryTakePrewarmedProcess(WebsiteDataStore&);
 

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (284609 => 284610)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -968,6 +968,7 @@
         navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes,
         ResourceRequest { requester.url },
         requester.securityOrigin->data(),
+        { },
         WTFMove(originatingFrameID),
         WTFMove(parentFrameID),
     };
@@ -1012,6 +1013,7 @@
         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
 
     navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
+    navigationActionData.effectiveSandboxFlags = coreFrame->loader().effectiveSandboxFlags();
 
     // Notify the UIProcess.
     Ref protector { *coreFrame };

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebFrame.cpp (284609 => 284610)


--- trunk/Source/WebKit/WebProcess/WebPage/WebFrame.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebFrame.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -193,6 +193,7 @@
         // FIXME: This should use the full request.
         ResourceRequest(url()),
         SecurityOriginData::fromFrame(m_coreFrame.get()),
+        m_coreFrame ? m_coreFrame->tree().name().string() : String(),
         m_frameID,
         parent ? std::optional<WebCore::FrameIdentifier> { parent->frameID() } : std::nullopt,
     };

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (284609 => 284610)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -726,6 +726,9 @@
     if (parameters.mediaPlaybackIsSuspended)
         m_page->suspendAllMediaPlayback();
 
+    if (parameters.openedByDOM)
+        m_page->setOpenedByDOM();
+
     m_page->setGroupName(m_pageGroup->identifier());
     m_page->setDeviceScaleFactor(parameters.deviceScaleFactor);
     m_page->setUserInterfaceLayoutDirection(m_userInterfaceLayoutDirection);
@@ -1733,6 +1736,9 @@
     frameLoadRequest.setClientRedirectSourceForHistory(loadParameters.clientRedirectSourceForHistory);
     frameLoadRequest.setIsRequestFromClientOrUserInput();
 
+    if (loadParameters.effectiveSandboxFlags)
+        corePage()->mainFrame().loader().forceSandboxFlags(loadParameters.effectiveSandboxFlags);
+
     corePage()->userInputBridge().loadRequest(WTFMove(frameLoadRequest));
 
     ASSERT(!m_pendingNavigationID);

Modified: trunk/Tools/ChangeLog (284609 => 284610)


--- trunk/Tools/ChangeLog	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/ChangeLog	2021-10-21 16:47:49 UTC (rev 284610)
@@ -1,3 +1,38 @@
+2021-10-21  Chris Dumez  <[email protected]>
+
+        WebKit should process-swap for initial navigation of a popup if it has no opener
+        https://bugs.webkit.org/show_bug.cgi?id=231990
+        <rdar://84425504>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONUIDelegate webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:]):
+        (-[PSONUIDelegate webViewDidClose:]):
+        Updated existing API tests to reflect behavior change.
+        Also extend an API test to make sure that a popup opened by JS can still close itself
+        via JS (by calling window.close()), even in the case where we process swap.
+
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+        (WTR::InjectedBundle::didReceiveMessageToPage):
+        (WTR::InjectedBundle::outputText):
+        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::dump):
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::createOtherPage):
+        (WTR::TestController::didReceivePageMessageFromInjectedBundle):
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
+        We have some tests that open a new popup with 'noopener' and the popup would be the
+        one to call `testRunner.notifyDone()`. This used to work fine when the popup would
+        end up in the same WebProcess because the injected bundle would know which page is
+        the main test page and use that one. However, now that we process-swap, the popup
+        page would think it is the main test page and try to dump its own output. However,
+        the UIProcess wasn't listening for messages from auxiliary pages' injected bundles.
+        The UIProcess now listens for those messages and asks the main test page to dump
+        its output when an auxiliary page in another process says the test is done.
+
 2021-10-21  Simon Fraser  <[email protected]>
 
         run-webkit-tests --ios-simulator --print-expectations fails

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (284609 => 284610)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2021-10-21 16:47:49 UTC (rev 284610)
@@ -86,6 +86,7 @@
 static bool willPerformClientRedirect;
 static bool didPerformClientRedirect;
 static bool shouldConvertToDownload;
+static bool didCloseWindow;
 static RetainPtr<NSURL> clientRedirectSourceURL;
 static RetainPtr<NSURL> clientRedirectDestinationURL;
 
@@ -241,10 +242,18 @@
 {
     createdWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
     [createdWebView setNavigationDelegate:_navigationDelegate.get()];
+    [createdWebView setUIDelegate:self];
     didCreateWebView = true;
     return createdWebView.get();
 }
 
+- (void)webViewDidClose:(WKWebView *)webView
+{
+    EXPECT_EQ(createdWebView.get(), webView);
+    createdWebView = nullptr;
+    didCloseWindow = true;
+}
+
 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler
 {
     didReceiveAlert = true;
@@ -456,11 +465,20 @@
 <script>
 window._onload_ = function() {
     if (!opener)
-        window.open("pson://www.webkit.org/main.html", "_blank", "noopener");
+        window.open("pson://www.webkit.org/popup.html", "_blank", "noopener");
 }
 </script>
 )PSONRESOURCE";
 
+static const char* windowOpenWithNameSameSiteNoOpenerTestBytes = R"PSONRESOURCE(
+<script>
+window._onload_ = function() {
+    if (!opener)
+        window.open("pson://www.webkit.org/popup.html", "foo", "noopener");
+}
+</script>
+)PSONRESOURCE";
+
 static const char* targetBlankCrossSiteWithExplicitOpenerTestBytes = R"PSONRESOURCE(
 <a id="testLink" target="_blank" href="" rel="opener">Link</a>
 <script>
@@ -1283,7 +1301,8 @@
     auto pid2 = [createdWebView _webProcessIdentifier];
     EXPECT_TRUE(!!pid2);
 
-    EXPECT_EQ(pid1, pid2);
+    // Since there is no opener, we process-swap, even though the navigation is same-site.
+    EXPECT_NE(pid1, pid2);
 }
 
 TEST(ProcessSwap, CrossSiteWindowOpenWithOpener)
@@ -1327,7 +1346,9 @@
     EXPECT_NE(pid1, pid2);
 }
 
-TEST(ProcessSwap, SameSiteWindowOpenNoOpener)
+enum class ExpectSwap { No, Yes };
+enum class WindowHasName : bool { No, Yes };
+static void runSameSiteWindowOpenNoOpenerTest(WindowHasName windowHasName, ExpectSwap expectSwap)
 {
     auto processPoolConfiguration = psonProcessPoolConfiguration();
     auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
@@ -1335,7 +1356,11 @@
     auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     [webViewConfiguration setProcessPool:processPool.get()];
     [webViewConfiguration preferences]._javascript_CanOpenWindowsAutomatically = YES;
-    auto handler = adoptNS([[PSONScheme alloc] initWithBytes:windowOpenSameSiteNoOpenerTestBytes]);
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    if (windowHasName == WindowHasName::Yes)
+        [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenWithNameSameSiteNoOpenerTestBytes];
+    else
+        [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenSameSiteNoOpenerTestBytes];
     [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
 
     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
@@ -1363,9 +1388,39 @@
     auto pid2 = [createdWebView _webProcessIdentifier];
     EXPECT_TRUE(!!pid2);
 
-    EXPECT_EQ(pid1, pid2);
+    // Since there is no opener, we process-swap, even though the navigation is same-site.
+    if (expectSwap == ExpectSwap::Yes)
+        EXPECT_NE(pid1, pid2);
+    else
+        EXPECT_EQ(pid1, pid2);
+
+    done = false;
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/popup2.html"]];
+    [createdWebView loadRequest:request];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    EXPECT_EQ(pid2, [createdWebView _webProcessIdentifier]);
+
+    // Since the window was opened via JS, it should be able to close itself.
+    didCloseWindow = false;
+    [createdWebView evaluateJavaScript:@"window.close()" completionHandler:nil];
+    TestWebKitAPI::Util::run(&didCloseWindow);
 }
 
+TEST(ProcessSwap, SameSiteWindowOpenNoOpener)
+{
+    // We process-swap even though the navigation is same-site, because the popup has no opener.
+    runSameSiteWindowOpenNoOpenerTest(WindowHasName::No, ExpectSwap::Yes);
+}
+
+TEST(ProcessSwap, SameSiteWindowOpenWithNameNoOpener)
+{
+    // We currently do no process-swap when navigating same-site a popup without opener if the window
+    // has a name. We should be able to support this but we would need to pass the window name over
+    // to the new process.
+    runSameSiteWindowOpenNoOpenerTest(WindowHasName::Yes, ExpectSwap::No);
+}
+
 TEST(ProcessSwap, CrossSiteBlankTargetWithOpener)
 {
     auto processPoolConfiguration = psonProcessPoolConfiguration();
@@ -1523,7 +1578,8 @@
     auto pid2 = [createdWebView _webProcessIdentifier];
     EXPECT_TRUE(!!pid2);
 
-    EXPECT_EQ(pid1, pid2);
+    // Since there is no opener, we process-swap, even though the navigation is same-site.
+    EXPECT_NE(pid1, pid2);
 }
 
 TEST(ProcessSwap, ServerRedirectFromNewWebView)
@@ -5253,7 +5309,6 @@
     done = false;
 }
 
-enum class ExpectSwap { No, Yes };
 static void runProcessSwapDueToRelatedWebViewTest(NSURL* relatedViewURL, NSURL* targetURL, ExpectSwap expectSwap)
 {
     auto processPoolConfiguration = psonProcessPoolConfiguration();
@@ -6269,8 +6324,10 @@
     // New WKWebView has now navigated to webkit.org.
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]);
     auto pid2 = [createdWebView _webProcessIdentifier];
-    EXPECT_EQ(pid1, pid2);
 
+    // We process-swap since there is no opener relationship.
+    EXPECT_NE(pid1, pid2);
+
     // Click link in new WKWebView so that it navigates cross-site to apple.com.
     [createdWebView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
     TestWebKitAPI::Util::run(&done);
@@ -6288,7 +6345,7 @@
 
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main2.html", [[createdWebView URL] absoluteString]);
     auto pid4 = [createdWebView _webProcessIdentifier];
-    EXPECT_EQ(pid1, pid4); // Should have process-swapped to the original "suspended" process.
+    EXPECT_EQ(pid2, pid4); // Should have process-swapped to the original "suspended" process.
 
     // Do a fragment navigation in the original WKWebView and make sure this does not crash.
     request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html#testLink"]];
@@ -6298,7 +6355,7 @@
 
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html#testLink", [[webView1 URL] absoluteString]);
     auto pid5 = [createdWebView _webProcessIdentifier];
-    EXPECT_EQ(pid1, pid5);
+    EXPECT_EQ(pid2, pid5);
 }
 
 #endif // PLATFORM(MAC)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp (284609 => 284610)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -437,6 +437,11 @@
         return;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "NotifyDone")) {
+        InjectedBundle::page()->dump();
+        return;
+    }
+
     if (WKStringIsEqualToUTF8CString(messageName, "CallUISideScriptCallback")) {
         auto messageBodyDictionary = dictionaryValue(messageBody);
         auto callbackID = uint64Value(messageBodyDictionary, "CallbackID");
@@ -589,7 +594,7 @@
     postPageMessage("DumpToStdErr", string ? string->data() : "Out of memory\n");
 }
 
-void InjectedBundle::outputText(const String& output)
+void InjectedBundle::outputText(const String& output, IsFinalTestOutput isFinalTestOutput)
 {
     if (m_state != Testing)
         return;
@@ -600,7 +605,8 @@
     // We use WKBundlePagePostMessageIgnoringFullySynchronousMode() instead of WKBundlePagePostMessage() to make sure that all text output
     // is done via asynchronous IPC, even if the connection is in fully synchronous mode due to a WKBundlePagePostSynchronousMessageForTesting()
     // call. Otherwise, messages logged via sync and async IPC may end up out of order and cause flakiness.
-    WKBundlePagePostMessageIgnoringFullySynchronousMode(page()->page(), toWK("TextOutput").get(), toWK(string ? string->data() : "Out of memory\n").get());
+    auto messageName = isFinalTestOutput == IsFinalTestOutput::Yes ? toWK("FinalTextOutput") : toWK("TextOutput");
+    WKBundlePagePostMessageIgnoringFullySynchronousMode(page()->page(), messageName.get(), toWK(string ? string->data() : "Out of memory\n").get());
 }
 
 void InjectedBundle::postNewBeforeUnloadReturnValue(bool value)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h (284609 => 284610)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h	2021-10-21 16:47:49 UTC (rev 284610)
@@ -81,7 +81,8 @@
     bool shouldDumpPixels() const { return m_dumpPixels; }
     bool dumpJSConsoleLogInStdErr() const { return m_dumpJSConsoleLogInStdErr; };
 
-    void outputText(const String&);
+    enum class IsFinalTestOutput : bool { No, Yes };
+    void outputText(const String&, IsFinalTestOutput = IsFinalTestOutput::No);
     void dumpToStdErr(const String&);
     void postNewBeforeUnloadReturnValue(bool);
     void postAddChromeInputField();

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp (284609 => 284610)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -846,7 +846,7 @@
             injectedBundle.setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get());
     }
 
-    injectedBundle.outputText(stringBuilder.toString());
+    injectedBundle.outputText(stringBuilder.toString(), InjectedBundle::IsFinalTestOutput::Yes);
     injectedBundle.done();
 }
 

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (284609 => 284610)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -491,6 +491,14 @@
     };
     WKPageSetPageNavigationClient(newPage, &pageNavigationClient.base);
 
+    WKPageInjectedBundleClientV1 injectedBundleClient = {
+        { 1, this },
+        didReceivePageMessageFromInjectedBundle,
+        nullptr,
+        didReceiveSynchronousPageMessageFromInjectedBundleWithListener,
+    };
+    WKPageSetPageInjectedBundleClient(newPage, &injectedBundleClient.base);
+
     view->didInitializeClients();
 
     TestController::singleton().updateWindowScaleForTest(view.ptr(), *TestController::singleton().m_currentInvocation);
@@ -1572,7 +1580,16 @@
 
 void TestController::didReceivePageMessageFromInjectedBundle(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
 {
-    static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
+    auto* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
+    if (page != testController->mainWebView()->page()) {
+        // If this is a Done message from an auxiliary view in its own WebProcess (due to process-swapping), we need to notify the injected bundle of the main WebView
+        // that the test is done.
+        if (WKStringIsEqualToUTF8CString(messageName, "Done") && testController->m_currentInvocation)
+            WKPagePostMessageToInjectedBundle(testController->mainWebView()->page(), toWK("NotifyDone").get(), nullptr);
+        if (!WKStringIsEqualToUTF8CString(messageName, "TextOutput"))
+            return;
+    }
+    testController->didReceiveMessageFromInjectedBundle(messageName, messageBody);
 }
 
 void TestController::didReceiveSynchronousPageMessageFromInjectedBundleWithListener(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, WKMessageListenerRef listener, const void* clientInfo)

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (284609 => 284610)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-10-21 16:34:16 UTC (rev 284609)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2021-10-21 16:47:49 UTC (rev 284610)
@@ -332,7 +332,7 @@
         return;
     }
 
-    if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) {
+    if (WKStringIsEqualToUTF8CString(messageName, "TextOutput") || WKStringIsEqualToUTF8CString(messageName, "FinalTextOutput")) {
         m_textOutput.append(toWTFString(stringValue(messageBody)));
         return;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to