Source/WebCore/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Previous, COOP handling was fully implemented in the WebContent process. This meant that a
 10 WebProcess for origin A could get a network response with COOP header from origin B, decide
 11 that cross-origin isolation is needed and ask the UIProcess to process-swap. This was not a
 12 good design given that the WebContent process is not a trusted process. We should not trust
 13 the WebProcess for origin A to make the swap on behavior of origin B. Also, the network
 14 response from origin B may contain sensitive headers that we don't want origin A's WebProcess
 15 to see.
 16
 17 To address these issues, I have moved COOP handling from the WebContent process to the
 18 NetworkProcess. As soon as the NetworkProcess gets the network response, it makes the decision
 19 whether or not cross-origin isolation is needed. If isolation is needed, the network process
 20 asks the UIProcess directly to continue the load in a new WebProcess instead of sending the
 21 network response to the currently associated WebProcess. When the new WebProcess resumes the
 22 load, the network process sends it the network response it already has.
 23
 24 I moved most of the COOP specification implementation from DocumentLoader.cpp/h to
 25 CrossOriginOpenerPolicy.cpp/h so that we can leverage it from the NetworkResourceLoader in
 26 the network process. We still have to do *some* COOP handling at DocumentLoader level
 27 currently for non-initial navigations to about:blank given that those can trigger a browsing
 28 context group switch but currently do not involved the network process. I also had to add
 29 more information to NetworkResourceLoadParameters so that we are able to make appropriate
 30 COOP decisions in the NetworkProcess.
 31
 32 No new tests, covered by existing COOP tests that are still passing.
 33
 34 * Headers.cmake:
 35 * Sources.txt:
 36 * WebCore.xcodeproj/project.pbxproj:
 37 * dom/Document.h:
 38
 39 * loader/CrossOriginOpenerPolicy.cpp:
 40 (WebCore::checkIfCOOPValuesRequireBrowsingContextGroupSwitch):
 41 (WebCore::checkIfEnforcingReportOnlyCOOPWouldRequireBrowsingContextGroupSwitch):
 42 (WebCore::computeResponseOriginAndCOOP):
 43 (WebCore::enforceResponseCrossOriginOpenerPolicy):
 44 (WebCore::obtainCrossOriginOpenerPolicy):
 45 (WebCore::sendViolationReportWhenNavigatingToCOOPResponse):
 46 (WebCore::sendViolationReportWhenNavigatingAwayFromCOOPResponse):
 47 (WebCore::doCrossOriginOpenerHandlingOfResponse):
 48 (WebCore::CrossOriginOpenerPolicyEnforcementResult::from):
 49 * loader/CrossOriginOpenerPolicy.h:
 50 (WebCore::CrossOriginOpenerPolicy::reportingEndpointForDisposition const):
 51 (WebCore::CrossOriginOpenerPolicy::hasReportingEndpoint const):
 52 * loader/DocumentLoader.cpp:
 53 (WebCore::DocumentLoader::willSendRequest):
 54 (WebCore::DocumentLoader::doCrossOriginOpenerHandlingOfResponse):
 55 (WebCore::DocumentLoader::responseReceived):
 56 (WebCore::DocumentLoader::maybeLoadEmpty):
 57 (WebCore::DocumentLoader::clearMainResource):
 58 * loader/DocumentLoader.h:
 59 (WebCore::DocumentLoader::crossOriginOpenerPolicy const):
 60 (WebCore::DocumentLoader::isContinuingLoadAfterProvisionalLoadStarted const):
 61 (WebCore::DocumentLoader::setIsContinuingLoadAfterProvisionalLoadStarted):
 62 Move most of the COOP logic from DocumentLoader.cpp to CrossOriginOpenerPolicy.cpp, so that
 63 it can be reused by NetworkResourceLoader in the network process.
 64
 65 * loader/EmptyClients.cpp:
 66 (WebCore::EmptyFrameLoaderClient::dispatchDecidePolicyForResponse):
 67 * loader/EmptyFrameLoaderClient.h:
 68 * loader/FrameLoader.cpp:
 69 (WebCore::FrameLoader::checkContentPolicy):
 70 (WebCore::FrameLoader::load):
 71 * loader/FrameLoader.h:
 72 * loader/FrameLoaderClient.h:
 73
 74 * loader/NavigationAction.cpp:
 75 (WebCore::NavigationAction::NavigationAction):
 76 * loader/NavigationAction.h:
 77 (WebCore::NavigationAction::requester const):
 78 (WebCore::NavigationAction::isEmpty const):
 79 * loader/NavigationRequester.cpp: Added.
 80 * loader/NavigationRequester.h: Added.
 81 Extracted NavigationAction::Requester to its own header and rename it to NavigationRequester,
 82 so that its implementation can be shared between NavigationAction, NetworkResourceLoadParameters
 83 and COOP.
 84
 85 * loader/ReportingEndpointsCache.cpp:
 86 (WebCore::ReportingEndpointsCache::addEndPointsFromResponse):
 87 (WebCore::ReportingEndpointsCache::addEndPointsFromReportToHeader):
 88 * loader/ReportingEndpointsCache.h:
 89 * loader/ShouldTreatAsContinuingLoad.h:
 90 * page/Page.h:
 91
1922021-09-24 Alan Bujtas <zalan@apple.com>
293
394 [LFC][IFC] Line::Run only needs a handful of style properties

Source/WebKit/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Implement COOP handling in the NetworkProcess, inside the NetworkResourceLoader class.
 10 This was logic that was currently implemented at DocumentLoader-level, in the WebProcess.
 11
 12 * NetworkProcess/NetworkProcess.cpp:
 13 * NetworkProcess/NetworkProcess.h:
 14 * NetworkProcess/NetworkProcess.messages.in:
 15 * NetworkProcess/NetworkResourceLoadParameters.cpp:
 16 (WebKit::NetworkResourceLoadParameters::encode const):
 17 (WebKit::NetworkResourceLoadParameters::decode):
 18 * NetworkProcess/NetworkResourceLoadParameters.h:
 19 * NetworkProcess/NetworkResourceLoader.cpp:
 20 (WebKit::NetworkResourceLoader::doCrossOriginOpenerHandlingOfResponse):
 21 (WebKit::toBrowsingContextGroupSwitchDecision):
 22 (WebKit::NetworkResourceLoader::didReceiveResponse):
 23 (WebKit::NetworkResourceLoader::sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup):
 24 (WebKit::NetworkResourceLoader::willSendRedirectedRequest):
 25 (WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
 26 * NetworkProcess/NetworkResourceLoader.h:
 27 * NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp:
 28 (WebKit::ServiceWorkerFetchTask::didReceiveResponse):
 29 * Scripts/webkit/messages.py:
 30 (types_that_cannot_be_forward_declared):
 31 (headers_for_type):
 32 * UIProcess/Network/NetworkProcessProxy.cpp:
 33 (WebKit::NetworkProcessProxy::triggerBrowsingContextGroupSwitchForNavigation):
 34 * UIProcess/Network/NetworkProcessProxy.h:
 35 * UIProcess/Network/NetworkProcessProxy.messages.in:
 36 * UIProcess/ProvisionalPageProxy.cpp:
 37 (WebKit::ProvisionalPageProxy::decidePolicyForResponse):
 38 * UIProcess/ProvisionalPageProxy.h:
 39 * UIProcess/WebPageProxy.cpp:
 40 (WebKit::WebPageProxy::continueNavigationInNewProcess):
 41 (WebKit::WebPageProxy::decidePolicyForResponse):
 42 (WebKit::WebPageProxy::decidePolicyForResponseShared):
 43 (WebKit::WebPageProxy::triggerBrowsingContextGroupSwitchForNavigation):
 44 * UIProcess/WebPageProxy.h:
 45 * UIProcess/WebPageProxy.messages.in:
 46 * WebProcess/Network/WebLoaderStrategy.cpp:
 47 (WebKit::WebLoaderStrategy::scheduleLoadFromNetworkProcess):
 48 * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
 49 (WebKit::WebFrameLoaderClient::dispatchDidStartProvisionalLoad):
 50 (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
 51 (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
 52 * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
 53 * WebProcess/WebPage/WebPage.cpp:
 54 (WebKit::WebPage::sendViolationReportWhenNavigatingToCOOPResponse):
 55 (WebKit::WebPage::sendViolationReportWhenNavigatingAwayFromCOOPResponse):
 56 * WebProcess/WebPage/WebPage.h:
 57 * WebProcess/WebPage/WebPage.messages.in:
 58
1592021-09-24 Per Arne Vollan <pvollan@apple.com>
260
361 Remove directory rule from sandboxes

Source/WebKitLegacy/mac/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * WebCoreSupport/WebFrameLoaderClient.h:
 10 * WebCoreSupport/WebFrameLoaderClient.mm:
 11 (WebFrameLoaderClient::dispatchDecidePolicyForResponse):
 12
1132021-09-23 Tim Horton <timothy_horton@apple.com>
214
315 Move more linked-on-or-after checks to WebCore::linkedOnOrAfter()

Source/WebKitLegacy/win/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * WebCoreSupport/WebFrameLoaderClient.cpp:
 10 (WebFrameLoaderClient::dispatchDecidePolicyForResponse):
 11 * WebCoreSupport/WebFrameLoaderClient.h:
 12
1132021-09-17 Alex Christensen <achristensen@webkit.org>
214
315 Use ObjectIdentifier for ResourceLoader

Source/WebCore/Headers.cmake

@@set(WebCore_PRIVATE_FRAMEWORK_HEADERS
831831 loader/MediaResourceLoader.h
832832 loader/MixedContentChecker.h
833833 loader/NavigationAction.h
 834 loader/NavigationRequester.h
834835 loader/NetscapePlugInStreamLoader.h
835836 loader/PingLoader.h
836837 loader/PolicyChecker.h

Source/WebCore/Sources.txt

@@loader/LoaderStrategy.cpp
15601560loader/MediaResourceLoader.cpp
15611561loader/MixedContentChecker.cpp
15621562loader/NavigationAction.cpp
 1563loader/NavigationRequester.cpp
15631564loader/NavigationScheduler.cpp
15641565loader/NetscapePlugInStreamLoader.cpp
15651566loader/PingLoader.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

13231323 468344E01EDDFAAA00B7795B /* DOMRectList.h in Headers */ = {isa = PBXBuildFile; fileRef = 468344DE1EDDFA5F00B7795B /* DOMRectList.h */; settings = {ATTRIBUTES = (Private, ); }; };
13241324 4688EE3C26DD2610002AF5C4 /* CrossOriginMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4688EE3A26DD260C002AF5C4 /* CrossOriginMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
13251325 469CCCFE269D021C006E0314 /* BroadcastChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 469CCCFC269D0202006E0314 /* BroadcastChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1326 469D77B82701625100142FA6 /* NavigationRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 469D77B62701625000142FA6 /* NavigationRequester.h */; settings = {ATTRIBUTES = (Private, ); }; };
13261327 46AAAA3D25D3632000BAF42F /* AudioFileReaderCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 46AAAA3A25D3631400BAF42F /* AudioFileReaderCocoa.h */; };
13271328 46B63F6C1C6E8D19002E914B /* JSEventTargetCustom.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B63F6B1C6E8CDF002E914B /* JSEventTargetCustom.h */; settings = {ATTRIBUTES = (Private, ); }; };
13281329 46B650DD2296262700FD8AA4 /* PageIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B650DB2296262700FD8AA4 /* PageIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };

84638464 469CCCFA269D0202006E0314 /* BroadcastChannel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcastChannel.cpp; sourceTree = "<group>"; };
84648465 469CCCFC269D0202006E0314 /* BroadcastChannel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BroadcastChannel.h; sourceTree = "<group>"; };
84658466 469CCCFD269D0203006E0314 /* BroadcastChannel.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = BroadcastChannel.idl; sourceTree = "<group>"; };
 8467 469D77B62701625000142FA6 /* NavigationRequester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationRequester.h; sourceTree = "<group>"; };
84668468 46AAAA3A25D3631400BAF42F /* AudioFileReaderCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioFileReaderCocoa.h; sourceTree = "<group>"; };
84678469 46AAAA3C25D3631400BAF42F /* AudioFileReaderCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioFileReaderCocoa.cpp; sourceTree = "<group>"; };
 8470 46ACD8112701656A00EF8CED /* NavigationRequester.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigationRequester.cpp; sourceTree = "<group>"; };
84688471 46B63F6B1C6E8CDF002E914B /* JSEventTargetCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventTargetCustom.h; sourceTree = "<group>"; };
84698472 46B650DB2296262700FD8AA4 /* PageIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageIdentifier.h; sourceTree = "<group>"; };
84708473 46B8593A2616720C0019EDC6 /* ScriptBufferSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScriptBufferSourceProvider.h; sourceTree = "<group>"; };

2778927792 93CCF05F0AF6CA7600018E89 /* NavigationAction.cpp */,
2779027793 93CCF0260AF6C52900018E89 /* NavigationAction.h */,
2779127794 9BA827781F06156500F71E75 /* NavigationDisabler.h */,
 27795 46ACD8112701656A00EF8CED /* NavigationRequester.cpp */,
 27796 469D77B62701625000142FA6 /* NavigationRequester.h */,
2779227797 979F43D11075E44A0000F83B /* NavigationScheduler.cpp */,
2779327798 979F43D21075E44A0000F83B /* NavigationScheduler.h */,
2779427799 93E227DD0AF589AD00D48324 /* NetscapePlugInStreamLoader.cpp */,

3421734222 83B2D1751B8BCD6A00A02E47 /* NativeNodeFilter.h in Headers */,
3421834223 E10B9B6C0B747599003ED890 /* NativeXPathNSResolver.h in Headers */,
3421934224 93CCF0270AF6C52900018E89 /* NavigationAction.h in Headers */,
 34225 469D77B82701625100142FA6 /* NavigationRequester.h in Headers */,
3422034226 979F43D41075E44A0000F83B /* NavigationScheduler.h in Headers */,
3422134227 A9C6E5A60D746458006442E9 /* Navigator.h in Headers */,
3422234228 E12719C70EEEC16800F61213 /* NavigatorBase.h in Headers */,

Source/WebCore/dom/Document.h

@@public:
13671367 bool isSameOriginAsTopDocument() const { return securityOrigin().isSameOriginAs(topOrigin()); }
13681368 bool shouldForceNoOpenerBasedOnCOOP() const;
13691369
1370  const CrossOriginOpenerPolicy& crossOriginOpenerPolicy() const final;
 1370 WEBCORE_EXPORT const CrossOriginOpenerPolicy& crossOriginOpenerPolicy() const final;
13711371 void setCrossOriginOpenerPolicy(const CrossOriginOpenerPolicy&);
13721372
13731373 void willLoadScriptElement(const URL&);

Source/WebCore/loader/CrossOriginOpenerPolicy.cpp

2626#include "config.h"
2727#include "CrossOriginOpenerPolicy.h"
2828
 29#include "ContentSecurityPolicy.h"
2930#include "CrossOriginEmbedderPolicy.h"
3031#include "FormData.h"
3132#include "Frame.h"
3233#include "HTTPHeaderNames.h"
3334#include "HTTPParsers.h"
 35#include "NavigationRequester.h"
3436#include "Page.h"
3537#include "PingLoader.h"
3638#include "ResourceResponse.h"

@@static ASCIILiteral crossOriginOpenerPolicyValueToEffectivePolicyString(CrossOri
6870 return "unsafe-none"_s;
6971}
7072
 73// https://html.spec.whatwg.org/multipage/origin.html#check-browsing-context-group-switch-coop-value
 74static bool checkIfCOOPValuesRequireBrowsingContextGroupSwitch(bool isInitialAboutBlank, CrossOriginOpenerPolicyValue activeDocumentCOOPValue, const SecurityOrigin& activeDocumentNavigationOrigin, CrossOriginOpenerPolicyValue responseCOOPValue, const SecurityOrigin& responseOrigin)
 75{
 76 // If the result of matching activeDocumentCOOPValue, activeDocumentNavigationOrigin, responseCOOPValue, and responseOrigin is true, return false.
 77 // https://html.spec.whatwg.org/multipage/origin.html#matching-coop
 78 if (activeDocumentCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone && responseCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone)
 79 return false;
 80 if (activeDocumentCOOPValue == responseCOOPValue && activeDocumentNavigationOrigin.isSameOriginAs(responseOrigin))
 81 return false;
 82
 83 // If all of the following are true:
 84 // - isInitialAboutBlank,
 85 // - activeDocumentCOOPValue's value is "same-origin-allow-popups".
 86 // - responseCOOPValue is "unsafe-none",
 87 // then return false.
 88 if (isInitialAboutBlank && activeDocumentCOOPValue == CrossOriginOpenerPolicyValue::SameOriginAllowPopups && responseCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone)
 89 return false;
 90
 91 return true;
 92}
 93
 94// https://html.spec.whatwg.org/multipage/origin.html#check-bcg-switch-navigation-report-only
 95static bool checkIfEnforcingReportOnlyCOOPWouldRequireBrowsingContextGroupSwitch(bool isInitialAboutBlank, const CrossOriginOpenerPolicy& activeDocumentCOOP, const SecurityOrigin& activeDocumentNavigationOrigin, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin)
 96{
 97 if (!checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.reportOnlyValue, activeDocumentNavigationOrigin, responseCOOP.reportOnlyValue, responseOrigin))
 98 return false;
 99
 100 if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.reportOnlyValue, activeDocumentNavigationOrigin, responseCOOP.value, responseOrigin))
 101 return true;
 102
 103 if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.value, activeDocumentNavigationOrigin, responseCOOP.reportOnlyValue, responseOrigin))
 104 return true;
 105
 106 return false;
 107}
 108
 109static std::tuple<Ref<SecurityOrigin>, CrossOriginOpenerPolicy> computeResponseOriginAndCOOP(const ResourceResponse& response, const std::optional<NavigationRequester>& requester, ContentSecurityPolicy* responseCSP)
 110{
 111 // Non-initial empty documents (about:blank) should inherit their cross-origin-opener-policy from the navigation's initiator top level document,
 112 // if the initiator and its top level document are same-origin, or default (unsafe-none) otherwise.
 113 // https://github.com/whatwg/html/issues/6913
 114 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(response.url()) && requester)
 115 return std::make_tuple(requester->securityOrigin, requester->securityOrigin->isSameOriginAs(requester->topOrigin) ? requester->crossOriginOpenerPolicy : CrossOriginOpenerPolicy { });
 116
 117 // If the HTTP response contains a CSP header, it may set sandbox flags, which would cause the origin to become unique.
 118 auto responseOrigin = responseCSP && responseCSP->sandboxFlags() != SandboxNone ? SecurityOrigin::createUnique() : SecurityOrigin::create(response.url());
 119 return std::make_tuple(WTFMove(responseOrigin), obtainCrossOriginOpenerPolicy(response));
 120}
 121
 122// https://html.spec.whatwg.org/multipage/origin.html#coop-enforce
 123static CrossOriginOpenerPolicyEnforcementResult enforceResponseCrossOriginOpenerPolicy(const CrossOriginOpenerPolicyEnforcementResult& currentCoopEnforcementResult, const URL& responseURL, SecurityOrigin& responseOrigin, const CrossOriginOpenerPolicy& responseCOOP, bool isDisplayingInitialEmptyDocument, const Function<void(COOPDisposition)>& sendViolationReports)
 124{
 125 CrossOriginOpenerPolicyEnforcementResult newCOOPEnforcementResult = {
 126 responseURL,
 127 responseOrigin,
 128 responseCOOP,
 129 true /* isCurrentContextNavigationSource */,
 130 currentCoopEnforcementResult.needsBrowsingContextGroupSwitch,
 131 currentCoopEnforcementResult.needsBrowsingContextGroupSwitchDueToReportOnly
 132 };
 133
 134 if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isDisplayingInitialEmptyDocument, currentCoopEnforcementResult.crossOriginOpenerPolicy.value, currentCoopEnforcementResult.currentOrigin, responseCOOP.value, responseOrigin)) {
 135 newCOOPEnforcementResult.needsBrowsingContextGroupSwitch = true;
 136 sendViolationReports(COOPDisposition::Enforce);
 137 }
 138
 139 if (checkIfEnforcingReportOnlyCOOPWouldRequireBrowsingContextGroupSwitch(isDisplayingInitialEmptyDocument, currentCoopEnforcementResult.crossOriginOpenerPolicy, currentCoopEnforcementResult.currentOrigin, responseCOOP, responseOrigin)) {
 140 newCOOPEnforcementResult.needsBrowsingContextGroupSwitchDueToReportOnly = true;
 141 sendViolationReports(COOPDisposition::Reporting);
 142 }
 143
 144 return newCOOPEnforcementResult;
 145}
 146
71147// https://html.spec.whatwg.org/multipage/origin.html#obtain-coop
72 CrossOriginOpenerPolicy obtainCrossOriginOpenerPolicy(const ResourceResponse& response, const ScriptExecutionContext& context)
 148CrossOriginOpenerPolicy obtainCrossOriginOpenerPolicy(const ResourceResponse& response)
73149{
74150 std::optional<CrossOriginEmbedderPolicy> coep;
75  auto ensureCOEP = [&coep, &response, &context]() -> CrossOriginEmbedderPolicy& {
 151 auto ensureCOEP = [&coep, &response]() -> CrossOriginEmbedderPolicy& {
76152 if (!coep)
77  coep = obtainCrossOriginEmbedderPolicy(response, &context);
 153 coep = obtainCrossOriginEmbedderPolicy(response, nullptr);
78154 return *coep;
79155 };
80156 auto parseCOOP = [&response, &ensureCOEP](HTTPHeaderName headerName, auto& value, auto& reportingEndpoint) {

@@CrossOriginOpenerPolicy obtainCrossOriginOpenerPolicy(const ResourceResponse& re
95171 };
96172
97173 CrossOriginOpenerPolicy policy;
98  if (!context.settingsValues().crossOriginOpenerPolicyEnabled || !SecurityOrigin::create(response.url())->isPotentiallyTrustworthy())
 174 if (!SecurityOrigin::create(response.url())->isPotentiallyTrustworthy())
99175 return policy;
100176
101177 parseCOOP(HTTPHeaderName::CrossOriginOpenerPolicy, policy.value, policy.reportingEndpoint);

@@void addCrossOriginOpenerPolicyHeaders(ResourceResponse& response, const CrossOr
132208// https://html.spec.whatwg.org/multipage/origin.html#coop-violation-navigation-to
133209void sendViolationReportWhenNavigatingToCOOPResponse(Frame& frame, CrossOriginOpenerPolicy coop, COOPDisposition disposition, const URL& coopURL, const URL& previousResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& previousResponseOrigin, const String& referrer, const String& userAgent)
134210{
135  auto& endpoint = disposition == COOPDisposition::Reporting ? coop.reportOnlyReportingEndpoint : coop.reportingEndpoint;
 211 auto& endpoint = coop.reportingEndpointForDisposition(disposition);
136212 if (endpoint.isEmpty())
137213 return;
138214

@@void sendViolationReportWhenNavigatingToCOOPResponse(Frame& frame, CrossOriginOp
148224// https://html.spec.whatwg.org/multipage/origin.html#coop-violation-navigation-from
149225void sendViolationReportWhenNavigatingAwayFromCOOPResponse(Frame& frame, CrossOriginOpenerPolicy coop, COOPDisposition disposition, const URL& coopURL, const URL& nextResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& nextResponseOrigin, bool isCOOPResponseNavigationSource, const String& userAgent)
150226{
151  auto& endpoint = disposition == COOPDisposition::Reporting ? coop.reportOnlyReportingEndpoint : coop.reportingEndpoint;
 227 auto& endpoint = coop.reportingEndpointForDisposition(disposition);
152228 if (endpoint.isEmpty())
153229 return;
154230

@@void sendViolationReportWhenNavigatingAwayFromCOOPResponse(Frame& frame, CrossOr
160236 });
161237}
162238
 239// https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6)
 240std::optional<CrossOriginOpenerPolicyEnforcementResult> doCrossOriginOpenerHandlingOfResponse(const ResourceResponse& response, const std::optional<NavigationRequester>& requester, ContentSecurityPolicy* responseCSP, SandboxFlags effectiveSandboxFlags, bool isDisplayingInitialEmptyDocument, const CrossOriginOpenerPolicyEnforcementResult& currentCoopEnforcementResult, const Function<void(COOPDisposition disposition, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin)>& sendViolationReports)
 241{
 242 auto [responseOrigin, responseCOOP] = computeResponseOriginAndCOOP(response, requester, responseCSP);
 243
 244 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6.2)
 245 // If sandboxFlags is not empty and responseCOOP's value is not "unsafe-none", then set response to an appropriate network error and break.
 246 if (responseCOOP.value != CrossOriginOpenerPolicyValue::UnsafeNone && effectiveSandboxFlags != SandboxNone)
 247 return std::nullopt;
 248
 249 return enforceResponseCrossOriginOpenerPolicy(currentCoopEnforcementResult, response.url(), responseOrigin, responseCOOP, isDisplayingInitialEmptyDocument, [&, responseOrigin = responseOrigin, responseCOOP = responseCOOP](COOPDisposition disposition) {
 250 sendViolationReports(disposition, responseCOOP, responseOrigin);
 251 });
 252}
 253
 254CrossOriginOpenerPolicyEnforcementResult CrossOriginOpenerPolicyEnforcementResult::from(const URL& currentURL, Ref<SecurityOrigin>&& currentOrigin, const CrossOriginOpenerPolicy& crossOriginOpenerPolicy, std::optional<NavigationRequester> requester, const URL& openerURL)
 255{
 256 CrossOriginOpenerPolicyEnforcementResult result { currentURL, WTFMove(currentOrigin), crossOriginOpenerPolicy };
 257 result.isCurrentContextNavigationSource = requester && result.currentOrigin->isSameOriginAs(requester->securityOrigin);
 258 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(currentURL) && openerURL.isValid())
 259 result.url = openerURL;
 260 return result;
 261}
 262
163263} // namespace WebCore

Source/WebCore/loader/CrossOriginOpenerPolicy.h

3131
3232namespace WebCore {
3333
 34class ContentSecurityPolicy;
3435class ResourceResponse;
3536class ScriptExecutionContext;
3637
 38struct NavigationRequester;
 39
 40typedef int SandboxFlags;
 41
3742// https://html.spec.whatwg.org/multipage/origin.html#cross-origin-opener-policy-value
3843enum class CrossOriginOpenerPolicyValue : uint8_t {
3944 UnsafeNone,

@@enum class CrossOriginOpenerPolicyValue : uint8_t {
4247 SameOriginAllowPopups
4348};
4449
 50enum class COOPDisposition : bool { Reporting , Enforce };
 51
4552// https://html.spec.whatwg.org/multipage/origin.html#cross-origin-opener-policy
4653struct CrossOriginOpenerPolicy {
4754 CrossOriginOpenerPolicyValue value { CrossOriginOpenerPolicyValue::UnsafeNone };

@@struct CrossOriginOpenerPolicy {
4956 CrossOriginOpenerPolicyValue reportOnlyValue { CrossOriginOpenerPolicyValue::UnsafeNone };
5057 String reportOnlyReportingEndpoint;
5158
 59 const String& reportingEndpointForDisposition(COOPDisposition) const;
 60 bool hasReportingEndpoint(COOPDisposition) const;
 61
5262 CrossOriginOpenerPolicy isolatedCopy() const;
5363 template<class Encoder> void encode(Encoder&) const;
5464 template<class Decoder> static std::optional<CrossOriginOpenerPolicy> decode(Decoder&);
5565};
5666
 67inline const String& CrossOriginOpenerPolicy::reportingEndpointForDisposition(COOPDisposition disposition) const
 68{
 69 return disposition == COOPDisposition::Enforce ? reportingEndpoint : reportOnlyReportingEndpoint;
 70}
 71
 72inline bool CrossOriginOpenerPolicy::hasReportingEndpoint(COOPDisposition disposition) const
 73{
 74 return !reportingEndpointForDisposition(disposition).isEmpty();
 75}
 76
5777inline bool operator==(const CrossOriginOpenerPolicy& a, const CrossOriginOpenerPolicy& b)
5878{
5979 return a.value == b.value && a.reportingEndpoint == b.reportingEndpoint && a.reportOnlyValue == b.reportOnlyValue && a.reportOnlyReportingEndpoint == b.reportOnlyReportingEndpoint;

@@std::optional<CrossOriginOpenerPolicy> CrossOriginOpenerPolicy::decode(Decoder&
98118
99119// https://html.spec.whatwg.org/multipage/origin.html#coop-enforcement-result
100120struct CrossOriginOpenerPolicyEnforcementResult {
101  bool needsBrowsingContextGroupSwitch { false };
102  bool needsBrowsingContextGroupSwitchDueToReportOnly { false };
 121 WEBCORE_EXPORT static CrossOriginOpenerPolicyEnforcementResult from(const URL& currentURL, Ref<SecurityOrigin>&& currentOrigin, const CrossOriginOpenerPolicy&, std::optional<NavigationRequester>, const URL& openerURL);
 122
103123 URL url;
104124 Ref<SecurityOrigin> currentOrigin;
105125 CrossOriginOpenerPolicy crossOriginOpenerPolicy;
106126 bool isCurrentContextNavigationSource { true };
 127 bool needsBrowsingContextGroupSwitch { false };
 128 bool needsBrowsingContextGroupSwitchDueToReportOnly { false };
107129};
108130
109 enum class COOPDisposition : bool { Reporting , Enforce };
110 
111 CrossOriginOpenerPolicy obtainCrossOriginOpenerPolicy(const ResourceResponse&, const ScriptExecutionContext&);
 131CrossOriginOpenerPolicy obtainCrossOriginOpenerPolicy(const ResourceResponse&);
112132WEBCORE_EXPORT void addCrossOriginOpenerPolicyHeaders(ResourceResponse&, const CrossOriginOpenerPolicy&);
113 void sendViolationReportWhenNavigatingToCOOPResponse(Frame&, CrossOriginOpenerPolicy, COOPDisposition, const URL& coopURL, const URL& previousResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& previousResponseOrigin, const String& referrer, const String& userAgent);
114 void sendViolationReportWhenNavigatingAwayFromCOOPResponse(Frame&, CrossOriginOpenerPolicy, COOPDisposition, const URL& coopURL, const URL& nextResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& nextResponseOrigin, bool isCOOPResponseNavigationSource, const String& userAgent);
 133WEBCORE_EXPORT void sendViolationReportWhenNavigatingToCOOPResponse(Frame&, CrossOriginOpenerPolicy, COOPDisposition, const URL& coopURL, const URL& previousResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& previousResponseOrigin, const String& referrer, const String& userAgent);
 134WEBCORE_EXPORT void sendViolationReportWhenNavigatingAwayFromCOOPResponse(Frame&, CrossOriginOpenerPolicy, COOPDisposition, const URL& coopURL, const URL& nextResponseURL, const SecurityOrigin& coopOrigin, const SecurityOrigin& nextResponseOrigin, bool isCOOPResponseNavigationSource, const String& userAgent);
 135WEBCORE_EXPORT std::optional<CrossOriginOpenerPolicyEnforcementResult> doCrossOriginOpenerHandlingOfResponse(const ResourceResponse&, const std::optional<NavigationRequester>&, ContentSecurityPolicy* responseCSP, SandboxFlags effectiveSandboxFlags, bool isDisplayingInitialEmptyDocument, const CrossOriginOpenerPolicyEnforcementResult& currentCoopEnforcementResult, const Function<void(COOPDisposition disposition, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin)>& sendViolationReports);
115136
116137} // namespace WebCore
117138

Source/WebCore/loader/DocumentLoader.cpp

6969#include "Logging.h"
7070#include "MemoryCache.h"
7171#include "MixedContentChecker.h"
 72#include "NavigationRequester.h"
7273#include "NavigationScheduler.h"
7374#include "NetworkLoadMetrics.h"
7475#include "NetworkStorageSession.h"

@@void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc
702703 }
703704 }
704705
705  if (didReceiveRedirectResponse && !doCrossOriginOpenerHandlingOfResponse(redirectResponse))
706  return;
707 
708706 if (!newRequest.url().host().isEmpty() && SecurityOrigin::shouldIgnoreHost(newRequest.url())) {
709707 auto url = newRequest.url();
710708 url.setHostAndPort({ });

@@void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc
744742 policyChecker.checkNavigationPolicy(WTFMove(newRequest), redirectResponse, WTFMove(navigationPolicyCompletionHandler));
745743}
746744
747 // https://html.spec.whatwg.org/multipage/origin.html#check-browsing-context-group-switch-coop-value
748 static bool checkIfCOOPValuesRequireBrowsingContextGroupSwitch(bool isInitialAboutBlank, CrossOriginOpenerPolicyValue activeDocumentCOOPValue, const SecurityOrigin& activeDocumentNavigationOrigin, CrossOriginOpenerPolicyValue responseCOOPValue, const SecurityOrigin& responseOrigin)
749 {
750  // If the result of matching activeDocumentCOOPValue, activeDocumentNavigationOrigin, responseCOOPValue, and responseOrigin is true, return false.
751  // https://html.spec.whatwg.org/multipage/origin.html#matching-coop
752  if (activeDocumentCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone && responseCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone)
753  return false;
754  if (activeDocumentCOOPValue == responseCOOPValue && activeDocumentNavigationOrigin.isSameOriginAs(responseOrigin))
755  return false;
756 
757  // If all of the following are true:
758  // - isInitialAboutBlank,
759  // - activeDocumentCOOPValue's value is "same-origin-allow-popups".
760  // - responseCOOPValue is "unsafe-none",
761  // then return false.
762  if (isInitialAboutBlank && activeDocumentCOOPValue == CrossOriginOpenerPolicyValue::SameOriginAllowPopups && responseCOOPValue == CrossOriginOpenerPolicyValue::UnsafeNone)
763  return false;
764 
765  return true;
766 }
767 
768 // https://html.spec.whatwg.org/multipage/origin.html#check-bcg-switch-navigation-report-only
769 static bool checkIfEnforcingReportOnlyCOOPWouldRequireBrowsingContextGroupSwitch(bool isInitialAboutBlank, const CrossOriginOpenerPolicy& activeDocumentCOOP, const SecurityOrigin& activeDocumentNavigationOrigin, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin)
770 {
771  if (!checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.reportOnlyValue, activeDocumentNavigationOrigin, responseCOOP.reportOnlyValue, responseOrigin))
772  return false;
773 
774  if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.reportOnlyValue, activeDocumentNavigationOrigin, responseCOOP.value, responseOrigin))
775  return true;
776 
777  if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(isInitialAboutBlank, activeDocumentCOOP.value, activeDocumentNavigationOrigin, responseCOOP.reportOnlyValue, responseOrigin))
778  return true;
779 
780  return false;
781 }
782 
783 static std::tuple<Ref<SecurityOrigin>, CrossOriginOpenerPolicy> computeResponseOriginAndCOOP(const ResourceResponse& response, const Document& document, const std::optional<NavigationAction::Requester>& requester, ContentSecurityPolicy* responseCSP)
784 {
785  // Non-initial empty documents (about:blank) should inherit their cross-origin-opener-policy from the navigation's initiator top level document,
786  // if the initiator and its top level document are same-origin, or default (unsafe-none) otherwise.
787  // https://github.com/whatwg/html/issues/6913
788  if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(response.url()) && requester)
789  return std::make_tuple(Ref { requester->securityOrigin() }, requester->securityOrigin().isSameOriginAs(requester->topOrigin()) ? requester->crossOriginOpenerPolicy() : CrossOriginOpenerPolicy { });
790 
791  // If the HTTP response contains a CSP header, it may set sandbox flags, which would cause the origin to become unique.
792  auto responseOrigin = responseCSP && responseCSP->sandboxFlags() != SandboxNone ? SecurityOrigin::createUnique() : SecurityOrigin::create(response.url());
793  return std::make_tuple(WTFMove(responseOrigin), obtainCrossOriginOpenerPolicy(response, document));
794 }
795 
796745// https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6)
797 bool DocumentLoader::doCrossOriginOpenerHandlingOfResponse(const ResourceResponse& response)
 746std::optional<CrossOriginOpenerPolicyEnforcementResult> DocumentLoader::doCrossOriginOpenerHandlingOfResponse(const ResourceResponse& response)
798747{
799748 // COOP only applies to top-level browsing contexts.
800749 if (!m_frame->isMainFrame())
801  return true;
 750 return std::nullopt;
802751
803752 if (!m_frame->document() || !m_frame->document()->settings().crossOriginOpenerPolicyEnabled())
804  return true;
805 
806  auto [responseOrigin, responseCOOP] = computeResponseOriginAndCOOP(response, *m_frame->document(), m_triggeringAction.requester(), m_contentSecurityPolicy.get());
807 
808  // https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6.2)
809  // If sandboxFlags is not empty and responseCOOP's value is not "unsafe-none", then set response to an appropriate network error and break.
810  if (responseCOOP.value != CrossOriginOpenerPolicyValue::UnsafeNone && frameLoader()->effectiveSandboxFlags() != SandboxNone) {
811  cancelMainResourceLoad(frameLoader()->cancelledError(m_request));
812  return false;
813  }
814 
815  m_currentCoopEnforcementResult = enforceResponseCrossOriginOpenerPolicy(response.url(), responseOrigin, responseCOOP);
816  return true;
817 }
818 
819 // https://html.spec.whatwg.org/multipage/origin.html#coop-enforce
820 CrossOriginOpenerPolicyEnforcementResult DocumentLoader::enforceResponseCrossOriginOpenerPolicy(const URL& responseURL, SecurityOrigin& responseOrigin, const CrossOriginOpenerPolicy& responseCOOP)
821 {
822  ASSERT(m_frame->isMainFrame());
823  ASSERT(m_frame->document());
824  ASSERT(m_frame->document()->settings().crossOriginOpenerPolicyEnabled());
825 
826  if (!m_currentCoopEnforcementResult) {
827  auto requester = m_triggeringAction.requester();
828  bool currentContextIsSource = requester && m_frame->document()->securityOrigin().isSameOriginAs(requester->securityOrigin());
829  m_currentCoopEnforcementResult = CrossOriginOpenerPolicyEnforcementResult {
830  false,
831  false,
832  m_frame->document()->url(),
833  m_frame->document()->securityOrigin(),
834  m_frame->document()->crossOriginOpenerPolicy(),
835  currentContextIsSource,
836  };
837  if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(m_frame->document()->url())) {
838  if (auto openerFrame = m_frame->loader().opener()) {
839  if (auto openerDocument = openerFrame->document())
840  m_currentCoopEnforcementResult->url = openerDocument->url();
841  }
842  }
843  }
 753 return std::nullopt;
844754
845  CrossOriginOpenerPolicyEnforcementResult newCOOPEnforcementResult = {
846  m_currentCoopEnforcementResult->needsBrowsingContextGroupSwitch,
847  m_currentCoopEnforcementResult->needsBrowsingContextGroupSwitchDueToReportOnly,
848  responseURL,
849  responseOrigin,
850  responseCOOP,
851  true
852  };
 755 URL openerURL;
 756 if (auto openerFrame = m_frame->loader().opener())
 757 openerURL = openerFrame->document() ? openerFrame->document()->url() : URL();
853758
854  if (checkIfCOOPValuesRequireBrowsingContextGroupSwitch(frameLoader()->stateMachine().isDisplayingInitialEmptyDocument(), m_currentCoopEnforcementResult->crossOriginOpenerPolicy.value, m_currentCoopEnforcementResult->currentOrigin, responseCOOP.value, responseOrigin)) {
855  newCOOPEnforcementResult.needsBrowsingContextGroupSwitch = true;
 759 auto currentCoopEnforcementResult = CrossOriginOpenerPolicyEnforcementResult::from(m_frame->document()->url(), m_frame->document()->securityOrigin(), m_frame->document()->crossOriginOpenerPolicy(), m_triggeringAction.requester(), openerURL);
856760
 761 auto newCoopEnforcementResult = WebCore::doCrossOriginOpenerHandlingOfResponse(response, m_triggeringAction.requester(), m_contentSecurityPolicy.get(), frameLoader()->effectiveSandboxFlags(), frameLoader()->stateMachine().isDisplayingInitialEmptyDocument(), currentCoopEnforcementResult, [&](COOPDisposition disposition, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin) {
857762 // FIXME: Add the concept of browsing context group like in the specification instead of treating the whole process as a group.
858763 if (Page::nonUtilityPageCount() > 1) {
859  sendViolationReportWhenNavigatingToCOOPResponse(*m_frame, responseCOOP, COOPDisposition::Enforce, responseURL, m_currentCoopEnforcementResult->url, responseOrigin, m_currentCoopEnforcementResult->currentOrigin, m_request.httpReferrer(), m_request.httpUserAgent());
860  sendViolationReportWhenNavigatingAwayFromCOOPResponse(*m_frame, m_currentCoopEnforcementResult->crossOriginOpenerPolicy, COOPDisposition::Enforce, m_currentCoopEnforcementResult->url, responseURL, m_currentCoopEnforcementResult->currentOrigin, responseOrigin, m_currentCoopEnforcementResult->isCurrentContextNavigationSource, m_request.httpUserAgent());
861  }
862  }
863 
864  if (checkIfEnforcingReportOnlyCOOPWouldRequireBrowsingContextGroupSwitch(frameLoader()->stateMachine().isDisplayingInitialEmptyDocument(), m_currentCoopEnforcementResult->crossOriginOpenerPolicy, m_currentCoopEnforcementResult->currentOrigin, responseCOOP, responseOrigin)) {
865  newCOOPEnforcementResult.needsBrowsingContextGroupSwitchDueToReportOnly = true;
866 
867  // FIXME: Add the concept of browsing context group like in the specification instead of treating the whole process as a group.
868  if (Page::nonUtilityPageCount() > 1) {
869  sendViolationReportWhenNavigatingToCOOPResponse(*m_frame, responseCOOP, COOPDisposition::Reporting, responseURL, m_currentCoopEnforcementResult->url, responseOrigin, m_currentCoopEnforcementResult->currentOrigin, m_request.httpReferrer(), m_request.httpUserAgent());
870  sendViolationReportWhenNavigatingAwayFromCOOPResponse(*m_frame, m_currentCoopEnforcementResult->crossOriginOpenerPolicy, COOPDisposition::Reporting, m_currentCoopEnforcementResult->url, responseURL, m_currentCoopEnforcementResult->currentOrigin, responseOrigin, m_currentCoopEnforcementResult->isCurrentContextNavigationSource, m_request.httpUserAgent());
 764 sendViolationReportWhenNavigatingToCOOPResponse(*m_frame, responseCOOP, disposition, response.url(), currentCoopEnforcementResult.url, responseOrigin, currentCoopEnforcementResult.currentOrigin, m_request.httpReferrer(), m_request.httpUserAgent());
 765 sendViolationReportWhenNavigatingAwayFromCOOPResponse(*m_frame, currentCoopEnforcementResult.crossOriginOpenerPolicy, disposition, currentCoopEnforcementResult.url, response.url(), currentCoopEnforcementResult.currentOrigin, responseOrigin, currentCoopEnforcementResult.isCurrentContextNavigationSource, m_request.httpUserAgent());
871766 }
 767 });
 768 if (!newCoopEnforcementResult) {
 769 cancelMainResourceLoad(frameLoader()->cancelledError(m_request));
 770 return std::nullopt;
872771 }
873772
874  return newCOOPEnforcementResult;
 773 return newCoopEnforcementResult;
875774}
876775
877776bool DocumentLoader::tryLoadingRequestFromApplicationCache()

@@void DocumentLoader::responseReceived(CachedResource& resource, const ResourceRe
968867 m_contentSecurityPolicy->didReceiveHeaders(ContentSecurityPolicyResponseHeaders { response }, m_request.httpReferrer(), ContentSecurityPolicy::ReportParsingErrors::No);
969868 } else
970869 m_contentSecurityPolicy = nullptr;
 870 if (m_frame && m_frame->document() && m_frame->document()->settings().crossOriginOpenerPolicyEnabled())
 871 m_responseCOOP = obtainCrossOriginOpenerPolicy(response);
971872
972873#if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
973874 // FIXME(218779): Remove this quirk once microsoft.com completes their login flow redesign.

@@void DocumentLoader::responseReceived(CachedResource& resource, const ResourceRe
1001902 responseReceived(response, WTFMove(completionHandler));
1002903}
1003904
1004 static BrowsingContextGroupSwitchDecision toBrowsingContextGroupSwitchDecision(const std::optional<CrossOriginOpenerPolicyEnforcementResult>& currentCoopEnforcementResult)
1005 {
1006  if (!currentCoopEnforcementResult || !currentCoopEnforcementResult->needsBrowsingContextGroupSwitch)
1007  return BrowsingContextGroupSwitchDecision::StayInGroup;
1008  if (currentCoopEnforcementResult->crossOriginOpenerPolicy.value == CrossOriginOpenerPolicyValue::SameOriginPlusCOEP)
1009  return BrowsingContextGroupSwitchDecision::NewIsolatedGroup;
1010  return BrowsingContextGroupSwitchDecision::NewSharedGroup;
1011 }
1012 
1013905void DocumentLoader::responseReceived(const ResourceResponse& response, CompletionHandler<void()>&& completionHandler)
1014906{
1015907 ASSERT(response.certificateInfo());

@@void DocumentLoader::responseReceived(const ResourceResponse& response, Completi
1103995 }
1104996#endif
1105997
1106  if (!doCrossOriginOpenerHandlingOfResponse(response))
1107  return;
1108 
1109  if (std::exchange(m_isContinuingLoadAfterResponsePolicyCheck, false)) {
1110  continueAfterContentPolicy(PolicyAction::Use);
1111  return;
1112  }
1113 
1114998 RefPtr<SubresourceLoader> mainResourceLoader = this->mainResourceLoader();
1115999 if (mainResourceLoader)
11161000 mainResourceLoader->markInAsyncResponsePolicyCheck();
11171001 auto requestIdentifier = PolicyCheckIdentifier::create();
1118  auto browsingContextGroupSwitchDecision = toBrowsingContextGroupSwitchDecision(m_currentCoopEnforcementResult);
1119  frameLoader()->checkContentPolicy(m_response, requestIdentifier, browsingContextGroupSwitchDecision, [this, protectedThis = Ref { *this }, mainResourceLoader = WTFMove(mainResourceLoader),
 1002 frameLoader()->checkContentPolicy(m_response, requestIdentifier, [this, protectedThis = Ref { *this }, mainResourceLoader = WTFMove(mainResourceLoader),
11201003 completionHandler = completionHandlerCaller.release(), requestIdentifier] (PolicyAction policy, PolicyCheckIdentifier responseIdentifier) mutable {
11211004 RELEASE_ASSERT(responseIdentifier.isValidFor(requestIdentifier));
11221005 continueAfterContentPolicy(policy);

@@bool DocumentLoader::maybeLoadEmpty()
21041987 m_response = ResourceResponse(m_request.url(), mimeType, 0, "UTF-8"_s);
21051988
21061989 if (!frameLoader()->stateMachine().isDisplayingInitialEmptyDocument()) {
2107  doCrossOriginOpenerHandlingOfResponse(m_response);
2108 
2109  // FIXME: Non-initial about:blank loads may cause a browsing context group switch. However, such load is synchronous and doesn't
2110  // involve a response policy decision. As a result, we simulate a browsing context group switch without actually swapping process.
2111  if (m_currentCoopEnforcementResult && m_currentCoopEnforcementResult->needsBrowsingContextGroupSwitch)
2112  frameLoader()->switchBrowsingContextsGroup();
 1990 if (auto coopEnforcementResult = doCrossOriginOpenerHandlingOfResponse(m_response)) {
 1991 m_responseCOOP = coopEnforcementResult->crossOriginOpenerPolicy;
 1992 if (coopEnforcementResult->needsBrowsingContextGroupSwitch)
 1993 frameLoader()->switchBrowsingContextsGroup();
 1994 }
21131995 }
21141996
21151997 finishedLoading();

@@void DocumentLoader::clearMainResource()
23392221#endif
23402222
23412223 m_mainResource = nullptr;
2342  m_isContinuingLoadAfterResponsePolicyCheck = false;
 2224 m_isContinuingLoadAfterProvisionalLoadStarted = false;
23432225
23442226 unregisterTemporaryServiceWorkerClient();
23452227}

Source/WebCore/loader/DocumentLoader.h

@@public:
425425 void setLastNavigationWasAppInitiated(bool lastNavigationWasAppInitiated) { m_lastNavigationWasAppInitiated = lastNavigationWasAppInitiated; }
426426
427427 ContentSecurityPolicy* contentSecurityPolicy() const { return m_contentSecurityPolicy.get(); }
428  std::optional<CrossOriginOpenerPolicy> crossOriginOpenerPolicy() const { return m_currentCoopEnforcementResult ? std::make_optional(m_currentCoopEnforcementResult->crossOriginOpenerPolicy) : std::nullopt; }
 428 const std::optional<CrossOriginOpenerPolicy>& crossOriginOpenerPolicy() const { return m_responseCOOP; }
429429
430  bool isContinuingLoadAfterResponsePolicyCheck() const { return m_isContinuingLoadAfterResponsePolicyCheck; }
431  void setIsContinuingLoadAfterResponsePolicyCheck(bool isContinuingLoadAfterResponsePolicyCheck) { m_isContinuingLoadAfterResponsePolicyCheck = isContinuingLoadAfterResponsePolicyCheck; }
 430 bool isContinuingLoadAfterProvisionalLoadStarted() const { return m_isContinuingLoadAfterProvisionalLoadStarted; }
 431 void setIsContinuingLoadAfterProvisionalLoadStarted(bool isContinuingLoadAfterProvisionalLoadStarted) { m_isContinuingLoadAfterProvisionalLoadStarted = isContinuingLoadAfterProvisionalLoadStarted; }
432432
433433protected:
434434 WEBCORE_EXPORT DocumentLoader(const ResourceRequest&, const SubstituteData&);

@@private:
450450#endif
451451 void unregisterTemporaryServiceWorkerClient();
452452
453  bool doCrossOriginOpenerHandlingOfResponse(const ResourceResponse&);
454  CrossOriginOpenerPolicyEnforcementResult enforceResponseCrossOriginOpenerPolicy(const URL& responseURL, SecurityOrigin& responseOrigin, const CrossOriginOpenerPolicy& responseCOOP);
 453 std::optional<CrossOriginOpenerPolicyEnforcementResult> doCrossOriginOpenerHandlingOfResponse(const ResourceResponse&);
455454
456455 void loadMainResource(ResourceRequest&&);
457456

@@private:
566565 bool m_gotFirstByte { false };
567566 bool m_isClientRedirect { false };
568567 bool m_isLoadingMultipartContent { false };
569  bool m_isContinuingLoadAfterResponsePolicyCheck { false };
 568 bool m_isContinuingLoadAfterProvisionalLoadStarted { false };
570569
571570 // FIXME: Document::m_processingLoadEvent and DocumentLoader::m_wasOnloadDispatched are roughly the same
572571 // and should be merged.

@@private:
590589 Vector<ResourceResponse> m_responses;
591590 bool m_stopRecordingResponses { false };
592591
593  std::optional<CrossOriginOpenerPolicyEnforcementResult> m_currentCoopEnforcementResult;
 592 std::optional<CrossOriginOpenerPolicy> m_responseCOOP;
594593
595594 typedef HashMap<RefPtr<ResourceLoader>, RefPtr<SubstituteResource>> SubstituteResourceMap;
596595 SubstituteResourceMap m_pendingSubstituteResources;

Source/WebCore/loader/EmptyClients.cpp

@@void EmptyFrameLoaderClient::dispatchShow()
818818{
819819}
820820
821 void EmptyFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String&, BrowsingContextGroupSwitchDecision, FramePolicyFunction&&)
 821void EmptyFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String&, FramePolicyFunction&&)
822822{
823823}
824824

Source/WebCore/loader/EmptyFrameLoaderClient.h

@@private:
9696 Frame* dispatchCreatePage(const NavigationAction&, NewFrameOpenerPolicy) final;
9797 void dispatchShow() final;
9898
99  void dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String&, BrowsingContextGroupSwitchDecision, FramePolicyFunction&&) final;
 99 void dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String&, FramePolicyFunction&&) final;
100100 void dispatchDecidePolicyForNewWindowAction(const NavigationAction&, const ResourceRequest&, FormState*, const String&, PolicyCheckIdentifier, FramePolicyFunction&&) final;
101101 void dispatchDecidePolicyForNavigationAction(const NavigationAction&, const ResourceRequest&, const ResourceResponse& redirectResponse, FormState*, PolicyDecisionMode, PolicyCheckIdentifier, FramePolicyFunction&&) final;
102102 void cancelPolicyCheck() final;

Source/WebCore/loader/FrameLoader.cpp

@@void FrameLoader::setDefersLoading(bool defers)
413413 }
414414}
415415
416 void FrameLoader::checkContentPolicy(const ResourceResponse& response, PolicyCheckIdentifier identifier, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, ContentPolicyDecisionFunction&& function)
 416void FrameLoader::checkContentPolicy(const ResourceResponse& response, PolicyCheckIdentifier identifier, ContentPolicyDecisionFunction&& function)
417417{
418418 if (!activeDocumentLoader()) {
419419 // Load was cancelled

@@void FrameLoader::checkContentPolicy(const ResourceResponse& response, PolicyChe
422422 }
423423
424424 // FIXME: Validate the policy check identifier.
425  client().dispatchDecidePolicyForResponse(response, activeDocumentLoader()->request(), identifier, activeDocumentLoader()->downloadAttribute(), browsingContextGroupSwitchDecision, WTFMove(function));
 425 client().dispatchDecidePolicyForResponse(response, activeDocumentLoader()->request(), identifier, activeDocumentLoader()->downloadAttribute(), WTFMove(function));
426426}
427427
428428void FrameLoader::changeLocation(const URL& url, const String& passedTarget, Event* triggeringEvent, const ReferrerPolicy& referrerPolicy, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, std::optional<NewFrameOpenerPolicy> openerPolicy, const AtomString& downloadAttribute, const SystemPreviewInfo& systemPreviewInfo, std::optional<PrivateClickMeasurement>&& privateClickMeasurement)

@@void FrameLoader::load(FrameLoadRequest&& request)
14761476 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request.resourceRequest(), request.substituteData());
14771477 loader->setAllowsWebArchiveForMainFrame(request.isRequestFromClientOrUserInput());
14781478 loader->setAllowsDataURLsForMainFrame(request.isRequestFromClientOrUserInput());
1479  loader->setIsContinuingLoadAfterResponsePolicyCheck(request.shouldTreatAsContinuingLoad() == ShouldTreatAsContinuingLoad::YesAfterResponsePolicyDecision);
 1479 loader->setIsContinuingLoadAfterProvisionalLoadStarted(request.shouldTreatAsContinuingLoad() == ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted);
14801480 addSameSiteInfoToRequestIfNeeded(loader->request());
14811481 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
14821482

Source/WebCore/loader/FrameLoader.h

@@public:
220220
221221 void setDefersLoading(bool);
222222
223  void checkContentPolicy(const ResourceResponse&, PolicyCheckIdentifier, BrowsingContextGroupSwitchDecision, ContentPolicyDecisionFunction&&);
 223 void checkContentPolicy(const ResourceResponse&, PolicyCheckIdentifier, ContentPolicyDecisionFunction&&);
224224
225225 void didExplicitOpen();
226226

@@public:
239239 // The following sandbox flags will be forced, regardless of changes to
240240 // the sandbox attribute of any parent frames.
241241 void forceSandboxFlags(SandboxFlags flags) { m_forcedSandboxFlags |= flags; }
242  SandboxFlags effectiveSandboxFlags() const;
 242 WEBCORE_EXPORT SandboxFlags effectiveSandboxFlags() const;
243243
244244 bool checkIfFormActionAllowedByCSP(const URL&, bool didReceiveRedirectResponse) const;
245245

@@public:
269269 bool loadsSynchronously() const { return m_loadsSynchronously; }
270270
271271 FrameLoaderStateMachine& stateMachine() { return m_stateMachine; }
 272 const FrameLoaderStateMachine& stateMachine() const { return m_stateMachine; }
272273
273274 // FIXME: should return RefPtr.
274275 WEBCORE_EXPORT Frame* findFrameForNavigation(const AtomString& name, Document* activeDocument = nullptr);

Source/WebCore/loader/FrameLoaderClient.h

@@public:
191191 virtual Frame* dispatchCreatePage(const NavigationAction&, NewFrameOpenerPolicy) = 0;
192192 virtual void dispatchShow() = 0;
193193
194  virtual void dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String& downloadAttribute, BrowsingContextGroupSwitchDecision, FramePolicyFunction&&) = 0;
 194 virtual void dispatchDecidePolicyForResponse(const ResourceResponse&, const ResourceRequest&, PolicyCheckIdentifier, const String& downloadAttribute, FramePolicyFunction&&) = 0;
195195 virtual void dispatchDecidePolicyForNewWindowAction(const NavigationAction&, const ResourceRequest&, FormState*, const String& frameName, PolicyCheckIdentifier, FramePolicyFunction&&) = 0;
196196 virtual void dispatchDecidePolicyForNavigationAction(const NavigationAction&, const ResourceRequest&, const ResourceResponse& redirectResponse, FormState*, PolicyDecisionMode, PolicyCheckIdentifier, FramePolicyFunction&&) = 0;
197197 virtual void cancelPolicyCheck() = 0;

Source/WebCore/loader/NavigationAction.cpp

3737
3838namespace WebCore {
3939
40 static GlobalFrameIdentifier createGlobalFrameIdentifier(const Document& document)
41 {
42  if (document.frame())
43  return { document.frame()->loader().pageID().value_or(PageIdentifier { }), document.frame()->loader().frameID().value_or(FrameIdentifier { }) };
44  return GlobalFrameIdentifier();
45 }
46 
47 NavigationAction::Requester::Requester(const Document& document)
48  : m_url { URL { document.url() } }
49  , m_origin { &document.securityOrigin() }
50  , m_topOrigin { &document.topOrigin() }
51  , m_crossOriginOpenerPolicy { document.crossOriginOpenerPolicy() }
52  , m_globalFrameIdentifier(createGlobalFrameIdentifier(document))
53 {
54 }
55 
5640NavigationAction::UIEventWithKeyStateData::UIEventWithKeyStateData(const UIEventWithKeyState& uiEvent)
5741 : isTrusted { uiEvent.isTrusted() }
5842 , shiftKey { uiEvent.shiftKey() }

@@static std::optional<NavigationAction::MouseEventData> mouseEventDataForFirstMou
10387}
10488
10589NavigationAction::NavigationAction(Document& requester, const ResourceRequest& resourceRequest, InitiatedByMainFrame initiatedByMainFrame, NavigationType type, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, Event* event, const AtomString& downloadAttribute)
106  : m_requester { requester }
 90 : m_requester { NavigationRequester::from(requester) }
10791 , m_resourceRequest { resourceRequest }
10892 , m_type { type }
10993 , m_shouldOpenExternalURLsPolicy { shouldOpenExternalURLsPolicy }

@@static NavigationType navigationType(FrameLoadType frameLoadType, bool isFormSub
129113}
130114
131115NavigationAction::NavigationAction(Document& requester, const ResourceRequest& resourceRequest, InitiatedByMainFrame initiatedByMainFrame, FrameLoadType frameLoadType, bool isFormSubmission, Event* event, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, const AtomString& downloadAttribute)
132  : m_requester { requester }
 116 : m_requester { NavigationRequester::from(requester) }
133117 , m_resourceRequest { resourceRequest }
134118 , m_type { navigationType(frameLoadType, isFormSubmission, !!event) }
135119 , m_shouldOpenExternalURLsPolicy { shouldOpenExternalURLsPolicy }

Source/WebCore/loader/NavigationAction.h

3333#include "FrameLoaderTypes.h"
3434#include "GlobalFrameIdentifier.h"
3535#include "LayoutPoint.h"
 36#include "NavigationRequester.h"
3637#include "PrivateClickMeasurement.h"
3738#include "ResourceRequest.h"
3839#include "SecurityOrigin.h"

@@public:
6465 NavigationAction(NavigationAction&&);
6566 NavigationAction& operator=(NavigationAction&&);
6667
67  class Requester {
68  public:
69  Requester(const Document&);
70 
71  const URL& url() const { return m_url; }
72  SecurityOrigin& securityOrigin() const { return *m_origin; }
73  SecurityOrigin& topOrigin() const { return *m_topOrigin; }
74  CrossOriginOpenerPolicy crossOriginOpenerPolicy() const { return m_crossOriginOpenerPolicy; }
75  const GlobalFrameIdentifier& globalFrameIdentifier() const { return m_globalFrameIdentifier; }
76  private:
77  URL m_url;
78  RefPtr<SecurityOrigin> m_origin;
79  RefPtr<SecurityOrigin> m_topOrigin;
80  CrossOriginOpenerPolicy m_crossOriginOpenerPolicy;
81  GlobalFrameIdentifier m_globalFrameIdentifier;
82  };
83  const std::optional<Requester>& requester() const { return m_requester; }
 68 const std::optional<NavigationRequester>& requester() const { return m_requester; }
8469
8570 struct UIEventWithKeyStateData {
8671 UIEventWithKeyStateData(const UIEventWithKeyState&);

@@public:
10590
10691 NavigationAction copyWithShouldOpenExternalURLsPolicy(ShouldOpenExternalURLsPolicy) const;
10792
108  bool isEmpty() const { return !m_requester || m_requester->url().isEmpty() || m_resourceRequest.url().isEmpty(); }
 93 bool isEmpty() const { return !m_requester || m_requester->url.isEmpty() || m_resourceRequest.url().isEmpty(); }
10994
11095 URL url() const { return m_resourceRequest.url(); }
11196 const ResourceRequest& resourceRequest() const { return m_resourceRequest; }

@@public:
147132private:
148133 // Do not add a strong reference to the originating document or a subobject that holds the
149134 // originating document. See comment above the class for more details.
150  std::optional<Requester> m_requester;
 135 std::optional<NavigationRequester> m_requester;
151136 ResourceRequest m_resourceRequest;
152137 NavigationType m_type;
153138 ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy;

Source/WebCore/loader/NavigationRequester.cpp

 1/*
 2 * Copyright (C) 2021 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "NavigationRequester.h"
 28
 29#include "Document.h"
 30#include "Frame.h"
 31#include "FrameLoader.h"
 32
 33namespace WebCore {
 34
 35static std::optional<GlobalFrameIdentifier> createGlobalFrameIdentifier(const Document& document)
 36{
 37 if (!document.frame())
 38 return std::nullopt;
 39
 40 auto pageID = document.frame()->loader().pageID();
 41 auto frameID = document.frame()->loader().frameID();
 42 if (!pageID || !frameID)
 43 return std::nullopt;
 44
 45 return GlobalFrameIdentifier { *pageID, *frameID };
 46}
 47
 48NavigationRequester NavigationRequester::from(Document& document)
 49{
 50 return {
 51 document.url(),
 52 document.securityOrigin(),
 53 document.topOrigin(),
 54 document.crossOriginOpenerPolicy(),
 55 createGlobalFrameIdentifier(document)
 56 };
 57}
 58
 59} // namespace WebCore

Source/WebCore/loader/NavigationRequester.h

 1/*
 2 * Copyright (C) 2021 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "CrossOriginOpenerPolicy.h"
 29#include "GlobalFrameIdentifier.h"
 30#include "SecurityOrigin.h"
 31
 32namespace WebCore {
 33
 34class Document;
 35
 36struct NavigationRequester {
 37 static NavigationRequester from(Document&);
 38
 39 URL url;
 40 Ref<SecurityOrigin> securityOrigin;
 41 Ref<SecurityOrigin> topOrigin;
 42 CrossOriginOpenerPolicy crossOriginOpenerPolicy;
 43 std::optional<GlobalFrameIdentifier> globalFrameIdentifier;
 44
 45 template<class Encoder> void encode(Encoder&) const;
 46 template<class Decoder> static std::optional<NavigationRequester> decode(Decoder&);
 47};
 48
 49template<class Encoder>
 50void NavigationRequester::encode(Encoder& encoder) const
 51{
 52 encoder << url << securityOrigin.get() << topOrigin.get() << crossOriginOpenerPolicy << globalFrameIdentifier;
 53}
 54
 55template<class Decoder>
 56std::optional<NavigationRequester> NavigationRequester::decode(Decoder& decoder)
 57{
 58 std::optional<URL> url;
 59 decoder >> url;
 60 if (!url)
 61 return std::nullopt;
 62
 63 auto securityOrigin = SecurityOrigin::decode(decoder);
 64 if (!securityOrigin)
 65 return std::nullopt;
 66
 67 auto topOrigin = SecurityOrigin::decode(decoder);
 68 if (!topOrigin)
 69 return std::nullopt;
 70
 71 std::optional<CrossOriginOpenerPolicy> crossOriginOpenerPolicy;
 72 decoder >> crossOriginOpenerPolicy;
 73 if (!crossOriginOpenerPolicy)
 74 return std::nullopt;
 75
 76 std::optional<std::optional<GlobalFrameIdentifier>> globalFrameIdentifier;
 77 decoder >> globalFrameIdentifier;
 78 if (!globalFrameIdentifier)
 79 return std::nullopt;
 80
 81 return NavigationRequester { WTFMove(*url), securityOrigin.releaseNonNull(), topOrigin.releaseNonNull(), WTFMove(*crossOriginOpenerPolicy), WTFMove(*globalFrameIdentifier) };
 82}
 83
 84} // namespace WebCore

Source/WebCore/loader/ReportingEndpointsCache.cpp

@@ReportingEndpointsCache::~ReportingEndpointsCache() = default;
6767// https://www.w3.org/TR/reporting/#process-header
6868void ReportingEndpointsCache::addEndPointsFromResponse(const ResourceResponse& response)
6969{
70  auto reportToHeaderValue = response.httpHeaderField(HTTPHeaderName::ReportTo);
 70 return addEndPointsFromReportToHeader(response.url(), response.httpHeaderField(HTTPHeaderName::ReportTo));
 71}
 72
 73void ReportingEndpointsCache::addEndPointsFromReportToHeader(const URL& responseURL, const String& reportToHeaderValue)
 74{
7175 if (reportToHeaderValue.isEmpty())
7276 return;
7377
74  auto securityOrigin = SecurityOrigin::create(response.url());
 78 auto securityOrigin = SecurityOrigin::create(responseURL);
7579 if (securityOrigin->isUnique() || !securityOrigin->isPotentiallyTrustworthy())
7680 return;
7781

@@void ReportingEndpointsCache::addEndPointsFromResponse(const ResourceResponse& r
9498 while (dictionaryStart < reportToHeaderValue.length()) {
9599 auto indexOfNextTopLevelComma = findNextTopLevelComma(dictionaryStart);
96100 if (indexOfNextTopLevelComma == notFound) {
97  addEndpointFromDictionary(securityOrigin->data(), response.url(), reportToHeaderValue.substring(dictionaryStart));
 101 addEndpointFromDictionary(securityOrigin->data(), responseURL, reportToHeaderValue.substring(dictionaryStart));
98102 break;
99103 }
100  addEndpointFromDictionary(securityOrigin->data(), response.url(), reportToHeaderValue.substring(dictionaryStart, indexOfNextTopLevelComma - dictionaryStart));
 104 addEndpointFromDictionary(securityOrigin->data(), responseURL, reportToHeaderValue.substring(dictionaryStart, indexOfNextTopLevelComma - dictionaryStart));
101105 dictionaryStart = indexOfNextTopLevelComma + 1;
102106 }
103107}

Source/WebCore/loader/ReportingEndpointsCache.h

@@public:
4242 WEBCORE_EXPORT static Ref<ReportingEndpointsCache> create();
4343 WEBCORE_EXPORT ~ReportingEndpointsCache();
4444
 45 WEBCORE_EXPORT void addEndPointsFromReportToHeader(const URL&, const String&);
4546 void addEndPointsFromResponse(const ResourceResponse&);
4647 URL endpointURL(const SecurityOriginData&, const String& group) const;
4748

Source/WebCore/loader/ShouldTreatAsContinuingLoad.h

2929
3030namespace WebCore {
3131
32 enum class ShouldTreatAsContinuingLoad : uint8_t { No, YesAfterNavigationPolicyDecision, YesAfterResponsePolicyDecision };
 32enum class ShouldTreatAsContinuingLoad : uint8_t { No, YesAfterNavigationPolicyDecision, YesAfterProvisionalLoadStarted };
3333
3434} // namespace WebCore
3535

@@template<> struct EnumTraits<WebCore::ShouldTreatAsContinuingLoad> {
4040 WebCore::ShouldTreatAsContinuingLoad,
4141 WebCore::ShouldTreatAsContinuingLoad::No,
4242 WebCore::ShouldTreatAsContinuingLoad::YesAfterNavigationPolicyDecision,
43  WebCore::ShouldTreatAsContinuingLoad::YesAfterResponsePolicyDecision
 43 WebCore::ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted
4444 >;
4545};
4646

Source/WebCore/page/Page.h

@@public:
285285 WEBCORE_EXPORT void setBroadcastChannelRegistry(Ref<BroadcastChannelRegistry>&&); // Only used by WebKitLegacy.
286286
287287 WEBCORE_EXPORT static void forEachPage(const WTF::Function<void(Page&)>&);
288  static unsigned nonUtilityPageCount();
 288 WEBCORE_EXPORT static unsigned nonUtilityPageCount();
289289
290290 unsigned subframeCount() const;
291291

Source/WebKit/NetworkProcess/NetworkProcess.cpp

@@RTCDataChannelRemoteManagerProxy& NetworkProcess::rtcDataChannelProxy()
28432843}
28442844#endif
28452845
2846 void NetworkProcess::prepareLoadForWebProcessTransfer(WebCore::ProcessIdentifier sourceProcessIdentifier, std::optional<WebCore::ResourceLoaderIdentifier> resourceLoadIdentifier, CompletionHandler<void(std::optional<NetworkResourceLoadIdentifier>)>&& completionHandler)
2847 {
2848  if (!resourceLoadIdentifier) {
2849  ASSERT_NOT_REACHED();
2850  return completionHandler(std::nullopt);
2851  }
2852  auto* connection = webProcessConnection(sourceProcessIdentifier);
2853  if (!connection)
2854  return completionHandler(std::nullopt);
2855 
2856  auto session = connection->networkSession();
2857  if (!session)
2858  return completionHandler(std::nullopt);
2859 
2860  auto loader = connection->takeNetworkResourceLoader(*resourceLoadIdentifier);
2861  if (!loader)
2862  return completionHandler(std::nullopt);
2863 
2864  auto identifier = loader->identifier();
2865  session->addLoaderAwaitingWebProcessTransfer(loader.releaseNonNull());
2866  completionHandler(identifier);
2867 }
2868 
28692846void NetworkProcess::addWebPageNetworkParameters(PAL::SessionID sessionID, WebPageProxyIdentifier pageID, WebPageNetworkParameters&& parameters)
28702847{
28712848 auto session = networkSession(sessionID);

Source/WebKit/NetworkProcess/NetworkProcess.h

@@private:
425425 bool didReceiveSyncNetworkProcessMessage(IPC::Connection&, IPC::Decoder&, UniqueRef<IPC::Encoder>&);
426426 void initializeNetworkProcess(NetworkProcessCreationParameters&&);
427427 void createNetworkConnectionToWebProcess(WebCore::ProcessIdentifier, PAL::SessionID, CompletionHandler<void(std::optional<IPC::Attachment>&&, WebCore::HTTPCookieAcceptPolicy)>&&);
428  void prepareLoadForWebProcessTransfer(WebCore::ProcessIdentifier sourceProcessIdentifier, std::optional<WebCore::ResourceLoaderIdentifier> resourceLoadIdentifier, CompletionHandler<void(std::optional<NetworkResourceLoadIdentifier>)>&&);
429428
430429 void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, CompletionHandler<void(WebsiteData&&)>&&);
431430 void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&&);

Source/WebKit/NetworkProcess/NetworkProcess.messages.in

@@messages -> NetworkProcess LegacyReceiver {
196196 ClearAppPrivacyReportTestingData(PAL::SessionID sessionID) -> () Async
197197#endif
198198
199  PrepareLoadForWebProcessTransfer(WebCore::ProcessIdentifier sourceProcessIdentifier, std::optional<WebCore::ResourceLoaderIdentifier> resourceLoadIdentifier) -> (std::optional<WebKit::NetworkResourceLoadIdentifier> networkResourceLoadIdentifier) Async
200 
201199 AddWebPageNetworkParameters(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier pageID, WebKit::WebPageNetworkParameters parameters)
202200 RemoveWebPageNetworkParameters(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier pageID)
203201 CountNonDefaultSessionSets(PAL::SessionID sessionID) -> (size_t count) Async

Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp

@@void NetworkResourceLoadParameters::encode(IPC::Encoder& encoder) const
114114 encoder << crossOriginAccessControlCheckEnabled;
115115
116116 encoder << documentURL;
117 
 117
 118 encoder << isCrossOriginOpenerPolicyEnabled;
 119 encoder << isDisplayingInitialEmptyDocument;
 120 encoder << effectiveSandboxFlags;
 121 encoder << openerURL;
 122 encoder << sourceCrossOriginOpenerPolicy;
 123
 124 encoder << navigationID;
 125 encoder << navigationRequester;
 126
118127#if ENABLE(SERVICE_WORKER)
119128 encoder << serviceWorkersMode;
120129 encoder << serviceWorkerRegistrationIdentifier;

@@std::optional<NetworkResourceLoadParameters> NetworkResourceLoadParameters::deco
292301 return std::nullopt;
293302 result.documentURL = *documentURL;
294303
 304 std::optional<bool> isCrossOriginOpenerPolicyEnabled;
 305 decoder >> isCrossOriginOpenerPolicyEnabled;
 306 if (!isCrossOriginOpenerPolicyEnabled)
 307 return std::nullopt;
 308 result.isCrossOriginOpenerPolicyEnabled = *isCrossOriginOpenerPolicyEnabled;
 309
 310 std::optional<bool> isDisplayingInitialEmptyDocument;
 311 decoder >> isDisplayingInitialEmptyDocument;
 312 if (!isDisplayingInitialEmptyDocument)
 313 return std::nullopt;
 314 result.isDisplayingInitialEmptyDocument = *isDisplayingInitialEmptyDocument;
 315
 316 std::optional<SandboxFlags> effectiveSandboxFlags;
 317 decoder >> effectiveSandboxFlags;
 318 if (!effectiveSandboxFlags)
 319 return std::nullopt;
 320 result.effectiveSandboxFlags = *effectiveSandboxFlags;
 321
 322 std::optional<URL> openerURL;
 323 decoder >> openerURL;
 324 if (!openerURL)
 325 return std::nullopt;
 326 result.openerURL = *openerURL;
 327
 328 std::optional<CrossOriginOpenerPolicy> sourceCrossOriginOpenerPolicy;
 329 decoder >> sourceCrossOriginOpenerPolicy;
 330 if (!sourceCrossOriginOpenerPolicy)
 331 return std::nullopt;
 332 result.sourceCrossOriginOpenerPolicy = WTFMove(*sourceCrossOriginOpenerPolicy);
 333
 334 std::optional<uint64_t> navigationID;
 335 decoder >> navigationID;
 336 if (!navigationID)
 337 return std::nullopt;
 338 result.navigationID = *navigationID;
 339
 340 std::optional<std::optional<NavigationRequester>> navigationRequester;
 341 decoder >> navigationRequester;
 342 if (!navigationRequester)
 343 return std::nullopt;
 344
 345 result.navigationRequester = WTFMove(*navigationRequester);
 346
295347#if ENABLE(SERVICE_WORKER)
296348 std::optional<ServiceWorkersMode> serviceWorkersMode;
297349 decoder >> serviceWorkersMode;

Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h

3333#include <WebCore/CrossOriginAccessControl.h>
3434#include <WebCore/CrossOriginEmbedderPolicy.h>
3535#include <WebCore/FetchOptions.h>
 36#include <WebCore/NavigationRequester.h>
3637#include <WebCore/ResourceLoaderIdentifier.h>
3738#include <wtf/Seconds.h>
3839

@@public:
6768 std::optional<WebCore::FrameIdentifier> parentFrameID;
6869 bool crossOriginAccessControlCheckEnabled { true };
6970 URL documentURL;
 71
 72 bool isCrossOriginOpenerPolicyEnabled { false };
 73 bool isDisplayingInitialEmptyDocument { false };
 74 WebCore::SandboxFlags effectiveSandboxFlags { WebCore::SandboxNone };
 75 URL openerURL;
 76 WebCore::CrossOriginOpenerPolicy sourceCrossOriginOpenerPolicy;
 77 uint64_t navigationID { 0 };
 78 std::optional<WebCore::NavigationRequester> navigationRequester;
7079
7180#if ENABLE(SERVICE_WORKER)
7281 WebCore::ServiceWorkersMode serviceWorkersMode { WebCore::ServiceWorkersMode::None };

Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

5858#include <WebCore/RegistrableDomain.h>
5959#include <WebCore/SameSiteInfo.h>
6060#include <WebCore/SecurityOrigin.h>
 61#include <WebCore/SecurityPolicy.h>
6162#include <WebCore/SharedBuffer.h>
6263#include <wtf/Expected.h>
6364#include <wtf/RunLoop.h>

@@bool NetworkResourceLoader::shouldInterruptWorkerLoadForCrossOriginEmbedderPolic
652653 return false;
653654}
654655
 656// https://html.spec.whatwg.org/multipage/browsing-the-web.html#process-a-navigate-fetch (Step 12.5.6)
 657bool NetworkResourceLoader::doCrossOriginOpenerHandlingOfResponse(const ResourceResponse& response)
 658{
 659 // COOP only applies to top-level browsing contexts.
 660 if (!isMainFrameLoad())
 661 return true;
 662
 663 if (!m_parameters.isCrossOriginOpenerPolicyEnabled)
 664 return true;
 665
 666 std::unique_ptr<ContentSecurityPolicy> contentSecurityPolicy;
 667 if (!response.httpHeaderField(HTTPHeaderName::ContentSecurityPolicy).isNull()) {
 668 contentSecurityPolicy = makeUnique<ContentSecurityPolicy>(URL { response.url() }, nullptr);
 669 contentSecurityPolicy->didReceiveHeaders(ContentSecurityPolicyResponseHeaders { response }, originalRequest().httpReferrer(), ContentSecurityPolicy::ReportParsingErrors::No);
 670 }
 671
 672 if (!m_currentCoopEnforcementResult) {
 673 auto sourceOrigin = m_parameters.sourceOrigin ? Ref { *m_parameters.sourceOrigin } : SecurityOrigin::createUnique();
 674 m_currentCoopEnforcementResult = CrossOriginOpenerPolicyEnforcementResult::from(m_parameters.documentURL, WTFMove(sourceOrigin), m_parameters.sourceCrossOriginOpenerPolicy, m_parameters.navigationRequester, m_parameters.openerURL);
 675 }
 676
 677 m_currentCoopEnforcementResult = WebCore::doCrossOriginOpenerHandlingOfResponse(response, m_parameters.navigationRequester, contentSecurityPolicy.get(), m_parameters.effectiveSandboxFlags, m_parameters.isDisplayingInitialEmptyDocument, *m_currentCoopEnforcementResult, [&](COOPDisposition disposition, const CrossOriginOpenerPolicy& responseCOOP, const SecurityOrigin& responseOrigin) {
 678 if (responseCOOP.hasReportingEndpoint(disposition))
 679 send(Messages::WebPage::SendViolationReportWhenNavigatingToCOOPResponse { m_parameters.webFrameID, responseCOOP, disposition, response.url(), m_currentCoopEnforcementResult->url, responseOrigin.data(), m_currentCoopEnforcementResult->currentOrigin->data(), originalRequest().httpReferrer(), originalRequest().httpUserAgent(), response.httpHeaderField(HTTPHeaderName::ReportTo) }, m_parameters.webPageID);
 680 if (m_currentCoopEnforcementResult->crossOriginOpenerPolicy.hasReportingEndpoint(disposition))
 681 send(Messages::WebPage::SendViolationReportWhenNavigatingAwayFromCOOPResponse { m_parameters.webFrameID, m_currentCoopEnforcementResult->crossOriginOpenerPolicy, disposition, m_currentCoopEnforcementResult->url, response.url(), m_currentCoopEnforcementResult->currentOrigin->data(), responseOrigin.data(), m_currentCoopEnforcementResult->isCurrentContextNavigationSource, originalRequest().httpUserAgent() }, m_parameters.webPageID);
 682 });
 683 return !!m_currentCoopEnforcementResult;
 684}
 685
 686static BrowsingContextGroupSwitchDecision toBrowsingContextGroupSwitchDecision(const std::optional<CrossOriginOpenerPolicyEnforcementResult>& currentCoopEnforcementResult)
 687{
 688 if (!currentCoopEnforcementResult || !currentCoopEnforcementResult->needsBrowsingContextGroupSwitch)
 689 return BrowsingContextGroupSwitchDecision::StayInGroup;
 690 if (currentCoopEnforcementResult->crossOriginOpenerPolicy.value == CrossOriginOpenerPolicyValue::SameOriginPlusCOEP)
 691 return BrowsingContextGroupSwitchDecision::NewIsolatedGroup;
 692 return BrowsingContextGroupSwitchDecision::NewSharedGroup;
 693}
 694
655695void NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedResponse, ResponseCompletionHandler&& completionHandler)
656696{
657697 LOADER_RELEASE_LOG("didReceiveResponse: (httpStatusCode=%d, MIMEType=%" PUBLIC_LOG_STRING ", expectedContentLength=%" PRId64 ", hasCachedEntryForValidation=%d, hasNetworkLoadChecker=%d)", receivedResponse.httpStatusCode(), receivedResponse.mimeType().utf8().data(), receivedResponse.expectedContentLength(), !!m_cacheEntryForValidation, !!m_networkLoadChecker);

@@void NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedRespon
740780 return completionHandler(PolicyAction::Ignore);
741781 }
742782
 783 if (!doCrossOriginOpenerHandlingOfResponse(m_response)) {
 784 LOADER_RELEASE_LOG_ERROR("didReceiveResponse: Interrupting load due to Cross-Origin-Opener-Policy");
 785 RunLoop::main().dispatch([protectedThis = Ref { *this }, url = m_response.url()] {
 786 if (protectedThis->m_networkLoad)
 787 protectedThis->didFailLoading(ResourceError { errorDomainWebKitInternal, 0, url, "Navigation was blocked by Cross-Origin-Opener-Policy"_s, ResourceError::Type::AccessControl });
 788 });
 789 return completionHandler(PolicyAction::Ignore);
 790 }
 791
743792 auto response = sanitizeResponseIfPossible(ResourceResponse { m_response }, ResourceResponse::SanitizationType::CrossOriginSafe);
744793 if (isSynchronous()) {
745794 LOADER_RELEASE_LOG("didReceiveResponse: Using response for synchronous load");

@@void NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedRespon
761810 // a main resource because the embedding client must decide whether to allow the load.
762811 bool willWaitForContinueDidReceiveResponse = isMainResource();
763812 LOADER_RELEASE_LOG("didReceiveResponse: Sending WebResourceLoader::DidReceiveResponse IPC (willWaitForContinueDidReceiveResponse=%d)", willWaitForContinueDidReceiveResponse);
764  send(Messages::WebResourceLoader::DidReceiveResponse { response, willWaitForContinueDidReceiveResponse });
 813 sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(response, willWaitForContinueDidReceiveResponse);
765814
766815 if (m_parameters.pageHasResourceLoadClient)
767816 m_connection->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::ResourceLoadDidReceiveResponse(m_parameters.webPageProxyID, resourceLoadInfo, response), 0);

@@void NetworkResourceLoader::didReceiveResponse(ResourceResponse&& receivedRespon
780829 completionHandler(PolicyAction::Use);
781830}
782831
 832void NetworkResourceLoader::sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(const WebCore::ResourceResponse& response, bool needsContinueDidReceiveResponseMessage)
 833{
 834 auto browsingContextGroupSwitchDecision = toBrowsingContextGroupSwitchDecision(m_currentCoopEnforcementResult);
 835 if (browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::StayInGroup) {
 836 send(Messages::WebResourceLoader::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage });
 837 return;
 838 }
 839
 840 auto loader = m_connection->takeNetworkResourceLoader(coreIdentifier());
 841 ASSERT(loader == this);
 842 auto existingNetworkResourceLoadIdentifierToResume = loader->identifier();
 843 m_connection->networkSession()->addLoaderAwaitingWebProcessTransfer(loader.releaseNonNull());
 844 RegistrableDomain responseDomain { response.url() };
 845 m_connection->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::TriggerBrowsingContextGroupSwitchForNavigation(m_parameters.webPageProxyID, m_parameters.navigationID, browsingContextGroupSwitchDecision, responseDomain, existingNetworkResourceLoadIdentifierToResume), 0);
 846}
 847
783848void NetworkResourceLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, int reportedEncodedDataLength)
784849{
785850 if (!m_numBytesReceived)

@@void NetworkResourceLoader::willSendRedirectedRequest(ResourceRequest&& request,
9431008 return;
9441009 }
9451010
 1011 if (!doCrossOriginOpenerHandlingOfResponse(redirectResponse)) {
 1012 didFailLoading(ResourceError { errorDomainWebKitInternal, 0, redirectRequest.url(), "Redirection was blocked by Cross-Origin-Opener-Policy"_s, ResourceError::Type::AccessControl });
 1013 return;
 1014 }
 1015
9461016 if (m_networkLoadChecker) {
9471017 if (privateClickMeasurementAttributionTriggerData)
9481018 m_networkLoadChecker->enableContentExtensionsCheck();

@@void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::
12491319 }
12501320 }
12511321
 1322 if (!doCrossOriginOpenerHandlingOfResponse(response)) {
 1323 LOADER_RELEASE_LOG_ERROR("didRetrieveCacheEntry: Interrupting load due to Cross-Origin-Opener-Policy");
 1324 didFailLoading(ResourceError { errorDomainWebKitInternal, 0, response.url(), "Navigation was blocked by Cross-Origin-Opener-Policy"_s, ResourceError::Type::AccessControl });
 1325 }
 1326
12521327 response = sanitizeResponseIfPossible(WTFMove(response), ResourceResponse::SanitizationType::CrossOriginSafe);
12531328 if (isSynchronous()) {
12541329 m_synchronousLoadData->response = WTFMove(response);

@@void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::
12591334
12601335 bool needsContinueDidReceiveResponseMessage = isMainResource();
12611336 LOADER_RELEASE_LOG("didRetrieveCacheEntry: Sending WebResourceLoader::DidReceiveResponse IPC (needsContinueDidReceiveResponseMessage=%d)", needsContinueDidReceiveResponseMessage);
1262  send(Messages::WebResourceLoader::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage });
 1337 sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(response, needsContinueDidReceiveResponseMessage);
12631338
12641339 if (needsContinueDidReceiveResponseMessage) {
12651340 m_response = WTFMove(response);

Source/WebKit/NetworkProcess/NetworkResourceLoader.h

@@public:
146146 void serviceWorkerDidNotHandle(ServiceWorkerFetchTask*);
147147#endif
148148
 149 bool doCrossOriginOpenerHandlingOfResponse(const WebCore::ResourceResponse&);
 150 void sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(const WebCore::ResourceResponse&, bool needsContinueDidReceiveResponseMessage);
 151
149152 bool isAppInitiated();
150153
151154private:

@@private:
257260 NetworkResourceLoadIdentifier m_resourceLoadID;
258261 WebCore::ResourceResponse m_redirectResponse;
259262 URL m_firstResponseURL; // First URL in response's URL list (https://fetch.spec.whatwg.org/#concept-response-url-list).
 263 std::optional<WebCore::CrossOriginOpenerPolicyEnforcementResult> m_currentCoopEnforcementResult;
260264};
261265
262266} // namespace WebKit

Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerFetchTask.cpp

@@void ServiceWorkerFetchTask::didReceiveResponse(ResourceResponse&& response, boo
160160 }
161161 }
162162
 163 if (!m_loader.doCrossOriginOpenerHandlingOfResponse(response)) {
 164 didFail(ResourceError { errorDomainWebKitInternal, 0, response.url(), "Navigation was blocked by Cross-Origin-Opener-Policy"_s, ResourceError::Type::AccessControl });
 165 return;
 166 }
 167
163168 response.setSource(ResourceResponse::Source::ServiceWorker);
164  sendToClient(Messages::WebResourceLoader::DidReceiveResponse { response, needsContinueDidReceiveResponseMessage });
 169 m_loader.sendDidReceiveResponsePotentiallyInNewBrowsingContextGroup(response, needsContinueDidReceiveResponseMessage);
165170 if (needsContinueDidReceiveResponseMessage)
166171 m_loader.setResponse(WTFMove(response));
167172}

Source/WebKit/Scripts/webkit/messages.py

@@def types_that_cannot_be_forward_declared():
327327 'WebKit::LibWebRTCResolverIdentifier',
328328 'WebKit::MDNSRegisterIdentifier',
329329 'WebKit::MediaRecorderIdentifier',
 330 'WebKit::NetworkResourceLoadIdentifier',
330331 'WebKit::PDFPluginIdentifier',
331332 'WebKit::PageGroupIdentifier',
332333 'WebKit::PlaybackSessionContextIdentifier',

@@def headers_for_type(type):
693694 'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
694695 'WebCore::BrowsingContextGroupSwitchDecision': ['<WebCore/FrameLoaderTypes.h>'],
695696 'WebCore::COEPDisposition': ['<WebCore/CrossOriginEmbedderPolicy.h>'],
 697 'WebCore::COOPDisposition': ['<WebCore/CrossOriginOpenerPolicy.h>'],
696698 'WebCore::CreateNewGroupForHighlight': ['<WebCore/AppHighlight.h>'],
697699 'WebCore::DOMPasteAccessResponse': ['<WebCore/DOMPasteAccess.h>'],
698700 'WebCore::DestinationColorSpace': ['<WebCore/ColorSpace.h>'],

Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

@@void NetworkProcessProxy::didNegotiateModernTLS(WebPageProxyIdentifier pageID, c
436436 page->didNegotiateModernTLS(url);
437437}
438438
 439void NetworkProcessProxy::triggerBrowsingContextGroupSwitchForNavigation(WebPageProxyIdentifier pageID, uint64_t navigationID, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume)
 440{
 441 RELEASE_LOG(ProcessSwapping, "%p - NetworkProcessProxy::triggerBrowsingContextGroupSwitchForNavigation: pageID=%" PRIu64 ", navigationID=%" PRIu64 ", browsingContextGroupSwitchDecision=%u, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, this, pageID.toUInt64(), navigationID, (unsigned)browsingContextGroupSwitchDecision, existingNetworkResourceLoadIdentifierToResume.toUInt64());
 442 if (auto* page = pageID ? WebProcessProxy::webPage(pageID) : nullptr)
 443 page->triggerBrowsingContextGroupSwitchForNavigation(navigationID, browsingContextGroupSwitchDecision, responseDomain, existingNetworkResourceLoadIdentifierToResume);
 444}
 445
439446void NetworkProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connection::Identifier connectionIdentifier)
440447{
441448 AuxiliaryProcessProxy::didFinishLaunching(launcher, connectionIdentifier);

@@void NetworkProcessProxy::terminateUnresponsiveServiceWorkerProcesses(WebCore::P
476483 }
477484}
478485
479 void NetworkProcessProxy::prepareLoadForWebProcessTransfer(WebCore::ProcessIdentifier sourceProcessIdentifier, std::optional<WebCore::ResourceLoaderIdentifier> resourceLoadIdentifier, CompletionHandler<void(std::optional<NetworkResourceLoadIdentifier>)>&& completionHandler)
480 {
481  RELEASE_LOG(ProcessSwapping, "%p - NetworkProcessProxy::prepareLoadForWebProcessTransfer: sourceProcessIdentifier: %" PRIu64 ", resourceLoadIdentifier: %" PRIu64, this, sourceProcessIdentifier.toUInt64(), resourceLoadIdentifier ? resourceLoadIdentifier->toUInt64() : 0);
482  if (!resourceLoadIdentifier) {
483  completionHandler({ });
484  return;
485  }
486 
487  sendWithAsyncReply(Messages::NetworkProcess::PrepareLoadForWebProcessTransfer(sourceProcessIdentifier, resourceLoadIdentifier), WTFMove(completionHandler));
488 }
489 
490486void NetworkProcessProxy::logDiagnosticMessageWithResult(WebPageProxyIdentifier pageID, const String& message, const String& description, uint32_t result, WebCore::ShouldSample shouldSample)
491487{
492488 WebPageProxy* page = WebProcessProxy::webPage(pageID);

Source/WebKit/UIProcess/Network/NetworkProcessProxy.h

@@public:
214214 void testProcessIncomingSyncMessagesWhenWaitingForSyncReply(WebPageProxyIdentifier, Messages::NetworkProcessProxy::TestProcessIncomingSyncMessagesWhenWaitingForSyncReplyDelayedReply&&);
215215 void terminateUnresponsiveServiceWorkerProcesses(WebCore::ProcessIdentifier);
216216
217  void prepareLoadForWebProcessTransfer(WebCore::ProcessIdentifier sourceProcessIdentifier, std::optional<WebCore::ResourceLoaderIdentifier>, CompletionHandler<void(std::optional<NetworkResourceLoadIdentifier>)>&&);
218 
219217 ProcessThrottler& throttler() final { return m_throttler; }
220218 void updateProcessAssertion();
221219

@@private:
322320
323321 void terminateWebProcess(WebCore::ProcessIdentifier);
324322
 323 void triggerBrowsingContextGroupSwitchForNavigation(WebPageProxyIdentifier, uint64_t navigationID, WebCore::BrowsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume);
 324
325325 void requestStorageSpace(PAL::SessionID, const WebCore::ClientOrigin&, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(std::optional<uint64_t> quota)>&&);
326326
327327 WebsiteDataStore* websiteDataStoreFromSessionID(PAL::SessionID);

Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in

@@messages -> NetworkProcessProxy LegacyReceiver {
7373 ResourceLoadDidReceiveResponse(WebKit::WebPageProxyIdentifier pageIdentifier, struct WebKit::ResourceLoadInfo resourceLoadInfo, WebCore::ResourceResponse response)
7474 ResourceLoadDidCompleteWithError(WebKit::WebPageProxyIdentifier pageIdentifier, struct WebKit::ResourceLoadInfo resourceLoadInfo, WebCore::ResourceResponse response, WebCore::ResourceError error)
7575
 76 TriggerBrowsingContextGroupSwitchForNavigation(WebKit::WebPageProxyIdentifier pageIdentifier, uint64_t navigationID, enum:uint8_t WebCore::BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, WebKit::NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume)
 77
7678#if USE(SOUP)
7779 DidExceedMemoryLimit()
7880#endif

Source/WebKit/UIProcess/ProvisionalPageProxy.cpp

@@void ProvisionalPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier
333333 m_page.decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
334334}
335335
336 void ProvisionalPageProxy::decidePolicyForResponse(FrameIdentifier frameID, FrameInfoData&& frameInfo, WebCore::PolicyCheckIdentifier identifier, uint64_t navigationID, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData& userData)
 336void ProvisionalPageProxy::decidePolicyForResponse(FrameIdentifier frameID, FrameInfoData&& frameInfo, WebCore::PolicyCheckIdentifier identifier, uint64_t navigationID, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData& userData)
337337{
338338 if (!validateInput(frameID, navigationID))
339339 return;
340340
341  m_page.decidePolicyForResponseShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, response, request, canShowMIMEType, downloadAttribute, wasAllowedByInjectedBundle, browsingContextGroupSwitchDecision, mainResourceLoadIdentifier, listenerID, userData);
 341 m_page.decidePolicyForResponseShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, response, request, canShowMIMEType, downloadAttribute, wasAllowedByInjectedBundle, listenerID, userData);
342342}
343343
344344void ProvisionalPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, FrameIdentifier frameID)

Source/WebKit/UIProcess/ProvisionalPageProxy.h

@@private:
125125 bool sendMessage(UniqueRef<IPC::Encoder>&&, OptionSet<IPC::SendOption>, std::optional<std::pair<CompletionHandler<void(IPC::Decoder*)>, uint64_t>>&&) final;
126126
127127 void decidePolicyForNavigationActionAsync(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, NavigationActionData&&, FrameInfoData&& originatingFrameInfo, std::optional<WebPageProxyIdentifier> originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, uint64_t listenerID);
128  void decidePolicyForResponse(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, WebCore::BrowsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData&);
 128 void decidePolicyForResponse(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData&);
129129 void didChangeProvisionalURLForFrame(WebCore::FrameIdentifier, uint64_t navigationID, URL&&);
130130 void didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, WebCore::FrameIdentifier);
131131 void didReceiveServerRedirectForProvisionalLoadForFrame(WebCore::FrameIdentifier, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);

Source/WebKit/UIProcess/WebPageProxy.cpp

@@void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, s
36463646 }
36473647
36483648 bool isServerSideRedirect = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::YesAfterNavigationPolicyDecision && navigation.currentRequestIsRedirect();
3649  bool shouldClosePreviousPageAfterCommit = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::YesAfterResponsePolicyDecision;
 3649 bool shouldClosePreviousPageAfterCommit = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted;
36503650 m_provisionalPage = makeUnique<ProvisionalPageProxy>(*this, WTFMove(newProcess), WTFMove(suspendedPage), navigation.navigationID(), isServerSideRedirect, navigation.currentRequest(), processSwapRequestedByClient, shouldClosePreviousPageAfterCommit, websitePolicies.get());
36513651 auto continuation = [this, protectedThis = Ref { *this }, navigation = Ref { navigation }, shouldTreatAsContinuingLoad, websitePolicies = WTFMove(websitePolicies), existingNetworkResourceLoadIdentifierToResume]() mutable {
36523652 if (auto* item = navigation->targetItem()) {

@@void WebPageProxy::decidePolicyForNewWindowAction(FrameIdentifier frameID, Frame
56315631
56325632void WebPageProxy::decidePolicyForResponse(FrameIdentifier frameID, FrameInfoData&& frameInfo, PolicyCheckIdentifier identifier,
56335633 uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute,
5634  bool wasAllowedByInjectedBundle, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData& userData)
 5634 bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData& userData)
56355635{
5636  decidePolicyForResponseShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, response, request, canShowMIMEType, downloadAttribute, wasAllowedByInjectedBundle, browsingContextGroupSwitchDecision, mainResourceLoadIdentifier, listenerID, userData);
 5636 decidePolicyForResponseShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, response, request, canShowMIMEType, downloadAttribute, wasAllowedByInjectedBundle, listenerID, userData);
56375637}
56385638
5639 void WebPageProxy::decidePolicyForResponseShared(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo, PolicyCheckIdentifier identifier, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData& userData)
 5639void WebPageProxy::decidePolicyForResponseShared(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo, PolicyCheckIdentifier identifier, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData& userData)
56405640{
56415641 PageClientProtector protector(pageClient());
56425642

@@void WebPageProxy::decidePolicyForResponseShared(Ref<WebProcessProxy>&& process,
56495649 RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
56505650 auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(WTFMove(frameInfo), this).get(), request, response, canShowMIMEType, downloadAttribute);
56515651
5652  Ref listener = frame->setUpPolicyListenerProxy([this, protectedThis = Ref { *this }, webPageID, frameID, browsingContextGroupSwitchDecision, mainResourceLoadIdentifier, identifier, listenerID, navigation = WTFMove(navigation),
 5652 Ref listener = frame->setUpPolicyListenerProxy([this, protectedThis = Ref { *this }, webPageID, frameID, identifier, listenerID, navigation = WTFMove(navigation),
56535653 process, navigationResponse] (PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, std::optional<NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain) mutable {
56545654 // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
56555655 RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No);

@@void WebPageProxy::decidePolicyForResponseShared(Ref<WebProcessProxy>&& process,
56585658 auto sender = PolicyDecisionSender::create(identifier, [webPageID, frameID, listenerID, process] (const auto& policyDecision) {
56595659 process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, policyDecision, createNetworkExtensionsSandboxExtensions(process)), webPageID);
56605660 });
5661 
5662  auto willContinueLoadInNewProcess = WillContinueLoadInNewProcess::No;
5663  if (policyAction == PolicyAction::Use && browsingContextGroupSwitchDecision != BrowsingContextGroupSwitchDecision::StayInGroup && navigation) {
5664  WEBPAGEPROXY_RELEASE_LOG(ProcessSwapping, "decidePolicyForResponseShared: Process-swapping due to Cross-Origin-Opener-Policy, newProcessIsCrossOriginIsolated=%d", browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup);
5665  RefPtr<WebProcessProxy> processForNavigation;
5666  if (browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup)
5667  processForNavigation = m_process->processPool().createNewWebProcess(&websiteDataStore(), WebProcessProxy::IsPrewarmed::No, CrossOriginMode::Isolated);
5668  else {
5669  RegistrableDomain responseDomain { navigationResponse->response().url() };
5670  processForNavigation = m_process->processPool().processForRegistrableDomain(websiteDataStore(), this, responseDomain);
5671  }
5672  websiteDataStore().networkProcess().prepareLoadForWebProcessTransfer(process->coreProcessIdentifier(), mainResourceLoadIdentifier, [this, protectedThis = WTFMove(protectedThis), navigation, navigationResponse = WTFMove(navigationResponse), sender = WTFMove(sender), processForNavigation = processForNavigation.releaseNonNull()](auto existingNetworkResourceLoadIdentifierToResume) mutable {
5673  continueNavigationInNewProcess(*navigation, nullptr, WTFMove(processForNavigation), ProcessSwapRequestedByClient::No, ShouldTreatAsContinuingLoad::YesAfterResponsePolicyDecision, nullptr, existingNetworkResourceLoadIdentifierToResume);
5674 
5675  receivedPolicyDecision(PolicyAction::Ignore, navigation.get(), nullptr, WTFMove(navigationResponse), WTFMove(sender), { }, WillContinueLoadInNewProcess::Yes);
5676  });
5677  return;
5678  }
56795661
5680  receivedPolicyDecision(policyAction, navigation.get(), nullptr, WTFMove(navigationResponse), WTFMove(sender), { }, willContinueLoadInNewProcess);
 5662 receivedPolicyDecision(policyAction, navigation.get(), nullptr, WTFMove(navigationResponse), WTFMove(sender));
56815663 }, ShouldExpectSafeBrowsingResult::No, ShouldExpectAppBoundDomainResult::No);
56825664
56835665 if (wasAllowedByInjectedBundle) {

@@void WebPageProxy::decidePolicyForResponseShared(Ref<WebProcessProxy>&& process,
56915673 m_navigationClient->decidePolicyForNavigationResponse(*this, WTFMove(navigationResponse), WTFMove(listener), process->transformHandlesToObjects(userData.object()).get());
56925674}
56935675
 5676void WebPageProxy::triggerBrowsingContextGroupSwitchForNavigation(uint64_t navigationID, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume)
 5677{
 5678 ASSERT(browsingContextGroupSwitchDecision != BrowsingContextGroupSwitchDecision::StayInGroup);
 5679 RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
 5680 WEBPAGEPROXY_RELEASE_LOG(ProcessSwapping, "triggerBrowsingContextGroupSwitchForNavigation: Process-swapping due to Cross-Origin-Opener-Policy, newProcessIsCrossOriginIsolated=%d, navigation=%p", browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup, navigation.get());
 5681 if (!navigation)
 5682 return;
 5683
 5684 RefPtr<WebProcessProxy> processForNavigation;
 5685 if (browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup)
 5686 processForNavigation = m_process->processPool().createNewWebProcess(&websiteDataStore(), WebProcessProxy::IsPrewarmed::No, CrossOriginMode::Isolated);
 5687 else
 5688 processForNavigation = m_process->processPool().processForRegistrableDomain(websiteDataStore(), this, responseDomain);
 5689
 5690 continueNavigationInNewProcess(*navigation, nullptr, processForNavigation.releaseNonNull(), ProcessSwapRequestedByClient::No, ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted, nullptr, existingNetworkResourceLoadIdentifierToResume);
 5691}
 5692
56945693void WebPageProxy::unableToImplementPolicy(FrameIdentifier frameID, const ResourceError& error, const UserData& userData)
56955694{
56965695 PageClientProtector protector(pageClient());

Source/WebKit/UIProcess/WebPageProxy.h

@@public:
685685 WebCore::Color underlayColor() const { return m_underlayColor; }
686686 void setUnderlayColor(const WebCore::Color&);
687687
 688 void triggerBrowsingContextGroupSwitchForNavigation(uint64_t navigationID, WebCore::BrowsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume);
 689
688690 // At this time, m_pageExtendedBackgroundColor can be set via pageExtendedBackgroundColorDidChange() which is a message
689691 // from the UIProcess, or by didCommitLayerTree(). When PLATFORM(MAC) adopts UI side compositing, we should get rid of
690692 // the message entirely.

@@public:
17461748 void didNavigateWithNavigationDataShared(Ref<WebProcessProxy>&&, const WebNavigationDataStore&, WebCore::FrameIdentifier);
17471749 void didChangeProvisionalURLForFrameShared(Ref<WebProcessProxy>&&, WebCore::FrameIdentifier, uint64_t navigationID, URL&&);
17481750 void decidePolicyForNavigationActionAsyncShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, NavigationActionData&&, FrameInfoData&& originatingFrameInfo, std::optional<WebPageProxyIdentifier> originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, uint64_t listenerID);
1749  void decidePolicyForResponseShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, WebCore::BrowsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData&);
 1751 void decidePolicyForResponseShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData&);
17501752 void startURLSchemeTaskShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, URLSchemeTaskParameters&&);
17511753 void loadDataWithNavigationShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, std::optional<NavigatingToAppBoundDomain>, std::optional<WebsitePoliciesData>&&, WebCore::ShouldOpenExternalURLsPolicy, WebCore::SubstituteData::SessionHistoryVisibility);
17521754 void loadRequestWithNavigationShared(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, std::optional<NavigatingToAppBoundDomain>, std::optional<WebsitePoliciesData>&& = std::nullopt, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume = std::nullopt);

@@private:
20642066 void decidePolicyForNewWindowAction(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, NavigationActionData&&,
20652067 WebCore::ResourceRequest&&, const String& frameName, uint64_t listenerID, const UserData&);
20662068 void decidePolicyForResponse(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID,
2067  const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, WebCore::BrowsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, const UserData&);
 2069 const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, const String& downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, const UserData&);
20682070 void unableToImplementPolicy(WebCore::FrameIdentifier, const WebCore::ResourceError&, const UserData&);
20692071 void beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListenerProxy&);
20702072

Source/WebKit/UIProcess/WebPageProxy.messages.in

@@messages -> WebPageProxy {
107107#endif
108108
109109 # Policy messages
110  DecidePolicyForResponse(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, WebCore::PolicyCheckIdentifier policyCheckIdentifier, uint64_t navigationID, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, String downloadAttribute, bool wasAllowedByInjectedBundle, enum:uint8_t WebCore::BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier, uint64_t listenerID, WebKit::UserData userData)
 110 DecidePolicyForResponse(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, WebCore::PolicyCheckIdentifier policyCheckIdentifier, uint64_t navigationID, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, String downloadAttribute, bool wasAllowedByInjectedBundle, uint64_t listenerID, WebKit::UserData userData)
111111 DecidePolicyForNavigationActionAsync(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, WebCore::PolicyCheckIdentifier policyCheckIdentifier, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, struct WebKit::FrameInfoData originatingFrameInfoData, std::optional<WebKit::WebPageProxyIdentifier> originatingPageID, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, IPC::FormDataReference requestBody, WebCore::ResourceResponse redirectResponse, WebKit::UserData userData, uint64_t listenerID)
112112 DecidePolicyForNavigationActionSync(WebCore::FrameIdentifier frameID, bool isMainFrame, struct WebKit::FrameInfoData frameInfo, WebCore::PolicyCheckIdentifier policyCheckIdentifier, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, struct WebKit::FrameInfoData originatingFrameInfoData, std::optional<WebKit::WebPageProxyIdentifier> originatingPageID, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, IPC::FormDataReference requestBody, WebCore::ResourceResponse redirectResponse, WebKit::UserData userData) -> (struct WebKit::PolicyDecision PolicyDecision) Synchronous
113113 DecidePolicyForNewWindowAction(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, WebCore::PolicyCheckIdentifier policyCheckIdentifier, struct WebKit::NavigationActionData navigationActionData, WebCore::ResourceRequest request, String frameName, uint64_t listenerID, WebKit::UserData userData)

Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp

3333#include "NetworkResourceLoadParameters.h"
3434#include "WebCompiledContentRuleList.h"
3535#include "WebCoreArgumentCoders.h"
 36#include "WebDocumentLoader.h"
3637#include "WebErrors.h"
3738#include "WebFrame.h"
3839#include "WebFrameLoaderClient.h"

@@void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL
398399 loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks();
399400
400401 loadParameters.isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate;
 402 if (loadParameters.isMainFrameNavigation && document)
 403 loadParameters.sourceCrossOriginOpenerPolicy = document->crossOriginOpenerPolicy();
401404
402405 loadParameters.isMainResourceNavigationForAnyFrame = resourceLoader.frame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate;
 406 if (loadParameters.isMainResourceNavigationForAnyFrame) {
 407 if (auto documentLoader = resourceLoader.documentLoader()) {
 408 loadParameters.navigationID = static_cast<WebDocumentLoader&>(*documentLoader).navigationID();
 409 loadParameters.navigationRequester = documentLoader->triggeringAction().requester();
 410 }
 411 }
 412 loadParameters.isCrossOriginOpenerPolicyEnabled = document && document->settings().crossOriginOpenerPolicyEnabled();
 413 loadParameters.isDisplayingInitialEmptyDocument = frame && frame->loader().stateMachine().isDisplayingInitialEmptyDocument();
 414 if (frame)
 415 loadParameters.effectiveSandboxFlags = frame->loader().effectiveSandboxFlags();
 416 if (auto openerFrame = frame ? frame->loader().opener() : nullptr) {
 417 if (auto openerDocument = openerFrame->document())
 418 loadParameters.openerURL = openerDocument->url();
 419 }
403420
404421 loadParameters.shouldEnableCrossOriginResourcePolicy = !loadParameters.isMainFrameNavigation;
405422

Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

@@void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
530530 webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(*webPage, m_frame, userData);
531531 RefPtr provisionalLoader = static_cast<WebDocumentLoader*>(m_frame->coreFrame()->loader().provisionalDocumentLoader());
532532
533  if (!provisionalLoader || provisionalLoader->isContinuingLoadAfterResponsePolicyCheck())
 533 if (!provisionalLoader || provisionalLoader->isContinuingLoadAfterProvisionalLoadStarted())
534534 return;
535535
536536 auto& url = provisionalLoader->url();

@@void WebFrameLoaderClient::dispatchShow()
817817 webPage->show();
818818}
819819
820 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String& downloadAttribute, BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, FramePolicyFunction&& function)
 820void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String& downloadAttribute, FramePolicyFunction&& function)
821821{
822822 auto* webPage = m_frame->page();
823823 if (!webPage) {

@@void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceRespons
838838 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame.ptr(), response, request, userData);
839839 // If a browsing context switch is requested, we still need to send the IPC to the UIProcess in order to process-swap if necessary, even though the
840840 // injected bundle has already handled the policy decision.
841  if (policy == WKBundlePagePolicyActionUse && browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::StayInGroup) {
 841 if (policy == WKBundlePagePolicyActionUse) {
842842 WEBFRAMELOADERCLIENT_RELEASE_LOG(Network, "dispatchDecidePolicyForResponse: continuing because injected bundle says so");
843843 function(PolicyAction::Use, identifier);
844844 return;

@@void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceRespons
849849 auto* coreFrame = m_frame->coreFrame();
850850 auto* policyDocumentLoader = coreFrame ? coreFrame->loader().provisionalDocumentLoader() : nullptr;
851851 auto navigationID = policyDocumentLoader ? static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID() : 0;
852  std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier;
853  if (auto mainResourceLoader = policyDocumentLoader ? policyDocumentLoader->mainResourceLoader() : nullptr)
854  mainResourceLoadIdentifier = mainResourceLoader->identifier();
855852
856853 bool wasAllowedByInjectedBundle = policy == WKBundlePagePolicyActionUse;
857854 auto protector = m_frame.copyRef();
858855 uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No);
859  if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), m_frame->info(), identifier, navigationID, response, request, canShowResponse, downloadAttribute, wasAllowedByInjectedBundle, browsingContextGroupSwitchDecision, mainResourceLoadIdentifier, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())))) {
 856 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), m_frame->info(), identifier, navigationID, response, request, canShowResponse, downloadAttribute, wasAllowedByInjectedBundle, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())))) {
860857 WEBFRAMELOADERCLIENT_RELEASE_LOG(Network, "dispatchDecidePolicyForResponse: ignoring because WebPageProxy::DecidePolicyForResponse failed");
861858 m_frame->didReceivePolicyDecision(listenerID, PolicyDecision { identifier, std::nullopt, PolicyAction::Ignore, 0, { }, { } });
862859 }

@@void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
956953 uint64_t listenerID = m_frame->setUpPolicyListener(requestIdentifier, WTFMove(function), WebFrame::ForNavigationAction::Yes);
957954
958955 ASSERT(navigationAction.requester());
959  auto requester = navigationAction.requester().value();
 956 auto& requester = navigationAction.requester().value();
960957
961  auto* requestingFrame = requester.globalFrameIdentifier().frameID ? WebProcess::singleton().webFrame(requester.globalFrameIdentifier().frameID) : nullptr;
 958 auto* requestingFrame = requester.globalFrameIdentifier && requester.globalFrameIdentifier->frameID ? WebProcess::singleton().webFrame(requester.globalFrameIdentifier->frameID) : nullptr;
962959 std::optional<WebCore::FrameIdentifier> originatingFrameID;
963960 std::optional<WebCore::FrameIdentifier> parentFrameID;
964961 if (requestingFrame) {

@@void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
969966
970967 FrameInfoData originatingFrameInfoData {
971968 navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes,
972  ResourceRequest { requester.url() },
973  requester.securityOrigin().data(),
 969 ResourceRequest { requester.url },
 970 requester.securityOrigin->data(),
974971 WTFMove(originatingFrameID),
975972 WTFMove(parentFrameID),
976973 };
977974
978975 std::optional<WebPageProxyIdentifier> originatingPageID;
979  if (auto& pageID = requester.globalFrameIdentifier().pageID) {
980  if (auto* webPage = WebProcess::singleton().webPage(pageID))
 976 if (requester.globalFrameIdentifier && requester.globalFrameIdentifier->pageID) {
 977 if (auto* webPage = WebProcess::singleton().webPage(requester.globalFrameIdentifier->pageID))
981978 originatingPageID = webPage->webPageProxyIdentifier();
982979 }
983980

@@void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const Navigat
995992 navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation();
996993 navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames();
997994 navigationActionData.openedByDOMWithOpener = navigationAction.openedByDOMWithOpener();
998  if (auto& requester = navigationAction.requester())
999  navigationActionData.requesterOrigin = requester->securityOrigin().data();
 995 navigationActionData.requesterOrigin = requester.securityOrigin->data();
1000996 navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
1001997 navigationActionData.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier();
1002998 navigationActionData.lockHistory = navigationAction.lockHistory();

Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h

@@private:
129129 WebCore::Frame* dispatchCreatePage(const WebCore::NavigationAction&, WebCore::NewFrameOpenerPolicy) final;
130130 void dispatchShow() final;
131131
132  void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::BrowsingContextGroupSwitchDecision, WebCore::FramePolicyFunction&&) final;
 132 void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::FramePolicyFunction&&) final;
133133 void dispatchDecidePolicyForNewWindowAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, WebCore::FormState*, const String& frameName, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) final;
134134 void dispatchDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse, WebCore::FormState*, WebCore::PolicyDecisionMode, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) final;
135135 void cancelPolicyCheck() final;

Source/WebKit/WebProcess/WebPage/WebPage.cpp

162162#include <WebCore/ContactsRequestData.h>
163163#include <WebCore/ContextMenuController.h>
164164#include <WebCore/CrossOriginEmbedderPolicy.h>
 165#include <WebCore/CrossOriginOpenerPolicy.h>
165166#include <WebCore/DOMPasteAccess.h>
166167#include <WebCore/DataTransfer.h>
167168#include <WebCore/DatabaseManager.h>

@@void WebPage::sendCOEPCORPViolation(FrameIdentifier frameID, const SecurityOrigi
43484349 WebCore::sendCOEPCORPViolation(*frame->coreFrame(), embedderOrigin, endpoint, disposition, destination, blockedURL);
43494350}
43504351
 4352void WebPage::sendViolationReportWhenNavigatingToCOOPResponse(FrameIdentifier frameID, const CrossOriginOpenerPolicy& coop, COOPDisposition disposition, const URL& coopURL, const URL& previousResponseURL, const SecurityOriginData& coopOrigin, const SecurityOriginData& previousResponseOrigin, const String& referrer, const String& userAgent, const String& reportToHeaderValue)
 4353{
 4354 if (!reportToHeaderValue.isEmpty())
 4355 WebProcess::singleton().reportingEndpointsCache().addEndPointsFromReportToHeader(coopURL, reportToHeaderValue);
 4356
 4357 // FIXME: Add the concept of browsing context group like in the specification instead of treating the whole process as a group.
 4358 if (Page::nonUtilityPageCount() <= 1)
 4359 return;
 4360
 4361 if (auto* frame = WebProcess::singleton().webFrame(frameID); frame->coreFrame())
 4362 WebCore::sendViolationReportWhenNavigatingToCOOPResponse(*frame->coreFrame(), coop, disposition, coopURL, previousResponseURL, coopOrigin.securityOrigin(), previousResponseOrigin.securityOrigin(), referrer, userAgent);
 4363}
 4364
 4365void WebPage::sendViolationReportWhenNavigatingAwayFromCOOPResponse(FrameIdentifier frameID, const CrossOriginOpenerPolicy& coop, COOPDisposition disposition, const URL& coopURL, const URL& nextResponseURL, const SecurityOriginData& coopOrigin, const SecurityOriginData& nextResponseOrigin, bool isCOOPResponseNavigationSource, const String& userAgent)
 4366{
 4367 // FIXME: Add the concept of browsing context group like in the specification instead of treating the whole process as a group.
 4368 if (Page::nonUtilityPageCount() <= 1)
 4369 return;
 4370
 4371 if (auto* frame = WebProcess::singleton().webFrame(frameID); frame->coreFrame())
 4372 WebCore::sendViolationReportWhenNavigatingAwayFromCOOPResponse(*frame->coreFrame(), coop, disposition, coopURL, nextResponseURL, coopOrigin.securityOrigin(), nextResponseOrigin.securityOrigin(), isCOOPResponseNavigationSource, userAgent);
 4373}
 4374
43514375void WebPage::enqueueSecurityPolicyViolationEvent(FrameIdentifier frameID, SecurityPolicyViolationEvent::Init&& eventInit)
43524376{
43534377 auto* frame = WebProcess::singleton().webFrame(frameID);

Source/WebKit/WebProcess/WebPage/WebPage.h

@@public:
441441 void sendCSPViolationReport(WebCore::FrameIdentifier, const URL& reportURL, IPC::FormDataReference&&);
442442 void sendCOEPPolicyInheritenceViolation(WebCore::FrameIdentifier, const WebCore::SecurityOriginData& embedderOrigin, const String& endpoint, WebCore::COEPDisposition, const String& type, const URL& blockedURL);
443443 void sendCOEPCORPViolation(WebCore::FrameIdentifier, const WebCore::SecurityOriginData& embedderOrigin, const String& endpoint, WebCore::COEPDisposition, WebCore::FetchOptions::Destination, const URL& blockedURL);
 444 void sendViolationReportWhenNavigatingToCOOPResponse(WebCore::FrameIdentifier, const WebCore::CrossOriginOpenerPolicy&, WebCore::COOPDisposition, const URL& coopURL, const URL& previousResponseURL, const WebCore::SecurityOriginData& coopOrigin, const WebCore::SecurityOriginData& previousResponseOrigin, const String& referrer, const String& userAgent, const String& reportToHeaderValue);
 445 void sendViolationReportWhenNavigatingAwayFromCOOPResponse(WebCore::FrameIdentifier, const WebCore::CrossOriginOpenerPolicy&, WebCore::COOPDisposition, const URL& coopURL, const URL& nextResponseURL, const WebCore::SecurityOriginData& coopOrigin, const WebCore::SecurityOriginData& nextResponseOrigin, bool isCOOPResponseNavigationSource, const String& userAgent);
444446 void enqueueSecurityPolicyViolationEvent(WebCore::FrameIdentifier, WebCore::SecurityPolicyViolationEvent::Init&&);
445447
446448 // -- Called by the DrawingArea.

Source/WebKit/WebProcess/WebPage/WebPage.messages.in

@@messages -> WebPage LegacyReceiver {
3131 SendCSPViolationReport(WebCore::FrameIdentifier frameID, URL reportURL, IPC::FormDataReference reportData)
3232 SendCOEPPolicyInheritenceViolation(WebCore::FrameIdentifier frameID, struct WebCore::SecurityOriginData embedderOrigin, String endpoint, enum:bool WebCore::COEPDisposition disposition, String type, URL blockedURL)
3333 SendCOEPCORPViolation(WebCore::FrameIdentifier frameID, struct WebCore::SecurityOriginData embedderOrigin, String endpoint, enum:bool WebCore::COEPDisposition disposition, enum:uint8_t WebCore::FetchOptions::Destination destination, URL blockedURL)
 34 SendViolationReportWhenNavigatingToCOOPResponse(WebCore::FrameIdentifier frameID, struct WebCore::CrossOriginOpenerPolicy coop, enum:bool WebCore::COOPDisposition disposition, URL coopURL, URL previousResponseURL, struct WebCore::SecurityOriginData coopOrigin, struct WebCore::SecurityOriginData previousResponseOrigin, String referrer, String userAgent, String reportToHeaderValue)
 35 SendViolationReportWhenNavigatingAwayFromCOOPResponse(WebCore::FrameIdentifier frameID, struct WebCore::CrossOriginOpenerPolicy coop, enum:bool WebCore::COOPDisposition disposition, URL coopURL, URL nextResponseURL, struct WebCore::SecurityOriginData coopOrigin, struct WebCore::SecurityOriginData nextResponseOrigin, bool isCOOPResponseNavigationSource, String userAgent)
3436 EnqueueSecurityPolicyViolationEvent(WebCore::FrameIdentifier frameID, WebCore::SecurityPolicyViolationEvent::Init eventInit)
3537
3638 TestProcessIncomingSyncMessagesWhenWaitingForSyncReply() -> (bool handled) Synchronous

Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h

@@private:
127127 WebCore::Frame* dispatchCreatePage(const WebCore::NavigationAction&, WebCore::NewFrameOpenerPolicy) final;
128128 void dispatchShow() final;
129129
130  void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::BrowsingContextGroupSwitchDecision, WebCore::FramePolicyFunction&&) final;
 130 void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::FramePolicyFunction&&) final;
131131 void dispatchDecidePolicyForNewWindowAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, WebCore::FormState*, const WTF::String& frameName, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) final;
132132 void dispatchDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse, WebCore::FormState*, WebCore::PolicyDecisionMode, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) final;
133133 void cancelPolicyCheck() final;

Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm

@@void WebFrameLoaderClient::dispatchShow()
855855 [[webView _UIDelegateForwarder] webViewShow:webView];
856856}
857857
858 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String&, WebCore::BrowsingContextGroupSwitchDecision, WebCore::FramePolicyFunction&& function)
 858void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String&, WebCore::FramePolicyFunction&& function)
859859{
860860 WebView *webView = getWebView(m_webFrame.get());
861861

Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp

@@void WebFrameLoaderClient::dispatchShow()
519519 ui->webViewShow(webView);
520520}
521521
522 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String&, BrowsingContextGroupSwitchDecision, FramePolicyFunction&& function)
 522void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String&, FramePolicyFunction&& function)
523523{
524524 WebView* webView = m_webFrame->webView();
525525 Frame* coreFrame = core(m_webFrame);

Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h

@@public:
9191 void dispatchDidFinishLoad() override;
9292 void dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone>) override;
9393
94  void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::BrowsingContextGroupSwitchDecision, WebCore::FramePolicyFunction&&) override;
 94 void dispatchDecidePolicyForResponse(const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, WebCore::PolicyCheckIdentifier, const String&, WebCore::FramePolicyFunction&&) override;
9595 void dispatchDecidePolicyForNewWindowAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, WebCore::FormState*, const WTF::String& frameName, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) override;
9696 void dispatchDecidePolicyForNavigationAction(const WebCore::NavigationAction&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse, WebCore::FormState*, WebCore::PolicyDecisionMode, WebCore::PolicyCheckIdentifier, WebCore::FramePolicyFunction&&) override;
9797 void cancelPolicyCheck() override;

Tools/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Port COOP API tests from PSONSchemeHandler to HTTPServer. This was necessary since custom scheme handler
 10 loads do not go via the networkProcess (Where COOP handling is now implemented).
 11
 12 * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
 13 (-[PSONNavigationDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]):
 14 (-[PSONScheme webView:startURLSchemeTask:]):
 15 * TestWebKitAPI/cocoa/HTTPServer.h:
 16
1172021-09-24 Sam Sneddon <gsnedders@apple.com>
218
319 LayoutTestFinder should return tests in order

Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

2525
2626#import "config.h"
2727
 28#import "HTTPServer.h"
2829#import "PlatformUtilities.h"
2930#import "Test.h"
3031#import "TestNavigationDelegate.h"

@@- (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didS
141142 done = true;
142143}
143144
 145- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
 146{
 147 EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
 148 completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
 149}
 150
144151- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
145152{
146153 didStartProvisionalLoad = true;

@@@interface PSONScheme : NSObject <WKURLSchemeHandler> {
250257 const char* _bytes;
251258 HashMap<String, String> _redirects;
252259 HashMap<String, RetainPtr<NSData>> _dataMappings;
253  HashMap<String, String> _coopValues;
254  HashMap<String, String> _coepValues;
255260 HashSet<id <WKURLSchemeTask>> _runningTasks;
256261 bool _shouldRespondAsynchronously;
257262}
258263- (instancetype)initWithBytes:(const char*)bytes;
259264- (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString;
260265- (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data;
261 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data withCOOPValue:(const char*)coopValue withCOEPValue:(const char*)coepValue;
262266@end
263267
264268@implementation PSONScheme

@@- (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data
280284 _dataMappings.set(urlString, [NSData dataWithBytesNoCopy:(void*)data length:strlen(data) freeWhenDone:NO]);
281285}
282286
283 - (void)addMappingFromURLString:(NSString *)urlString toData:(const char*)data withCOOPValue:(const char*)coopValue withCOEPValue:(const char*)coepValue
284 {
285  [self addMappingFromURLString:urlString toData:data];
286  if (coopValue)
287  _coopValues.add(urlString, coopValue);
288  if (coepValue)
289  _coepValues.add(urlString, coepValue);
290 }
291 
292287- (void)setShouldRespondAsynchronously:(BOOL)value
293288{
294289 _shouldRespondAsynchronously = value;

@@- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)ta
323318 [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()];
324319 }
325320
326  doAsynchronouslyIfNecessary([self, finalURL = retainPtr(finalURL)](id <WKURLSchemeTask> task) {
 321 doAsynchronouslyIfNecessary([finalURL = retainPtr(finalURL)](id <WKURLSchemeTask> task) {
327322 NSMutableDictionary* headerDictionary = [NSMutableDictionary dictionary];
328323 [headerDictionary setObject:@"text/html" forKey:@"Content-Type"];
329324 [headerDictionary setObject:@"1" forKey:@"Content-Length"];
330  auto coopValue = _coopValues.get([finalURL absoluteString]);
331  if (!coopValue.isEmpty())
332  [headerDictionary setObject:(NSString *)coopValue forKey:@"Cross-Origin-Opener-Policy"];
333  auto coepValue = _coepValues.get([finalURL absoluteString]);
334  if (!coepValue.isEmpty())
335  [headerDictionary setObject:(NSString *)coepValue forKey:@"Cross-Origin-Embedder-Policy"];
336325
337326 auto response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:finalURL.get() statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headerDictionary]);
338327 [task didReceiveResponse:response.get()];

@@TEST(WebProcessCache, ClearWhenEnteringCache)
71827171static const char* windowOpenCrossOriginCOOPTestBytes = R"PSONRESOURCE(
71837172<script>
71847173window.onload = function() {
7185  w = window.open("pson://www.apple.com/popup.html", "foo");
 7174 w = window.open("https://localhost:8181/popup.html", "foo");
71867175}
71877176</script>
71887177)PSONRESOURCE";

@@enum class IsSameOrigin : bool { No, Yes };
71997188enum class DoServerSideRedirect : bool { No, Yes };
72007189static void runCOOPProcessSwapTest(const char* sourceCOOP, const char* sourceCOEP, const char* destinationCOOP, const char* destinationCOEP, IsSameOrigin isSameOrigin, DoServerSideRedirect doServerSideRedirect, ExpectSwap expectSwap)
72017190{
 7191 using namespace TestWebKitAPI;
 7192
 7193 HashMap<String, String> sourceHeaders;
 7194 sourceHeaders.add("Content-Type"_s, "text/html"_s);
 7195 if (sourceCOOP)
 7196 sourceHeaders.add("Cross-Origin-Opener-Policy"_s, String(sourceCOOP));
 7197 if (sourceCOEP)
 7198 sourceHeaders.add("Cross-Origin-Embedder-Policy"_s, String(sourceCOEP));
 7199 HTTPResponse sourceResponse(WTFMove(sourceHeaders), isSameOrigin == IsSameOrigin::Yes ? windowOpenSameOriginCOOPTestBytes : windowOpenCrossOriginCOOPTestBytes);
 7200
 7201 HashMap<String, String> destinationHeaders;
 7202 destinationHeaders.add("Content-Type"_s, "text/html"_s);
 7203 if (destinationCOOP)
 7204 destinationHeaders.add("Cross-Origin-Opener-Policy"_s, String(destinationCOOP));
 7205 if (destinationCOEP)
 7206 destinationHeaders.add("Cross-Origin-Embedder-Policy"_s, String(destinationCOEP));
 7207 HTTPResponse destinationResponse(WTFMove(destinationHeaders), "popup"_s);
 7208
 7209 std::unique_ptr<HTTPServer> server;
 7210 if (doServerSideRedirect == DoServerSideRedirect::Yes) {
 7211 HashMap<String, String> redirectHeaders;
 7212 redirectHeaders.add("location"_s, isSameOrigin == IsSameOrigin::Yes ? "https://127.0.0.1:8181/popup-after-redirection.html"_s : "https://localhost:8181/popup-after-redirection.html"_s);
 7213 HTTPResponse redirectResponse(301, WTFMove(redirectHeaders));
 7214
 7215 server = makeUnique<HTTPServer>(std::initializer_list<std::pair<String, HTTPResponse>> {
 7216 { "/main.html", WTFMove(sourceResponse) },
 7217 { "/popup.html", WTFMove(redirectResponse) },
 7218 { "/popup-after-redirection.html", WTFMove(destinationResponse) }
 7219 }, HTTPServer::Protocol::Https, nullptr, nullptr, 8181);
 7220 } else {
 7221 server = makeUnique<HTTPServer>(std::initializer_list<std::pair<String, HTTPResponse>> {
 7222 { "/main.html", WTFMove(sourceResponse) },
 7223 { "/popup.html", WTFMove(destinationResponse) }
 7224 }, HTTPServer::Protocol::Https, nullptr, nullptr, 8181);
 7225 }
 7226
72027227 auto processPoolConfiguration = psonProcessPoolConfiguration();
72037228 auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
72047229 bool sourceShouldBeCrossOriginIsolated = sourceCOOP && !strcmp(sourceCOOP, "same-origin") && sourceCOEP && !strcmp(sourceCOEP, "require-corp");

@@static void runCOOPProcessSwapTest(const char* sourceCOOP, const char* sourceCOE
72157240 [[webViewConfiguration preferences] _setEnabled:YES forExperimentalFeature:feature];
72167241 }
72177242
7218  auto handler = adoptNS([[PSONScheme alloc] init]);
7219  if (isSameOrigin == IsSameOrigin::Yes) {
7220  [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenSameOriginCOOPTestBytes withCOOPValue:sourceCOOP withCOEPValue:sourceCOEP];
7221  if (doServerSideRedirect == DoServerSideRedirect::Yes) {
7222  [handler addRedirectFromURLString:@"pson://www.webkit.org/popup.html" toURLString:@"pson://www.webkit.org/popup-after-redirect.html"];
7223  [handler addMappingFromURLString:@"pson://www.webkit.org/popup-after-redirect.html" toData:"popup" withCOOPValue:destinationCOOP withCOEPValue:destinationCOEP];
7224  } else
7225  [handler addMappingFromURLString:@"pson://www.webkit.org/popup.html" toData:"popup" withCOOPValue:destinationCOOP withCOEPValue:destinationCOEP];
7226  } else {
7227  [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:windowOpenCrossOriginCOOPTestBytes withCOOPValue:sourceCOOP withCOEPValue:sourceCOEP];
7228  if (doServerSideRedirect == DoServerSideRedirect::Yes) {
7229  [handler addRedirectFromURLString:@"pson://www.apple.com/popup.html" toURLString:@"pson://www.apple.com/popup-after-redirect.html"];
7230  [handler addMappingFromURLString:@"pson://www.apple.com/popup-after-redirect.html" toData:"popup" withCOOPValue:destinationCOOP withCOEPValue:destinationCOEP];
7231  } else
7232  [handler addMappingFromURLString:@"pson://www.apple.com/popup.html" toData:"popup" withCOOPValue:destinationCOOP withCOEPValue:destinationCOEP];
7233  }
7234  [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
7235 
72367243 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
72377244 auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
72387245

@@static void runCOOPProcessSwapTest(const char* sourceCOOP, const char* sourceCOE
72487255 failed = false;
72497256 serverRedirected = false;
72507257 numberOfDecidePolicyCalls = 0;
7251  NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
 7258 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://127.0.0.1:8181/main.html"]];
72527259 [webView loadRequest:request];
72537260
72547261 TestWebKitAPI::Util::run(&done);

Tools/TestWebKitAPI/cocoa/HTTPServer.h

@@class Connection;
3838struct HTTPResponse;
3939
4040class HTTPServer {
 41 WTF_MAKE_FAST_ALLOCATED;
4142public:
4243 struct RequestData;
4344 enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2 };

LayoutTests/imported/w3c/ChangeLog

 12021-09-27 Chris Dumez <cdumez@apple.com>
 2
 3 Move Cross-Origin-Opener-Policy handling to the NetworkProcess
 4 https://bugs.webkit.org/show_bug.cgi?id=230812
 5 <rdar://83504842>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Rebaseline a couple of WPT tests due to some extra logging.
 10
 11 * web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt:
 12 * web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt:
 13
1142021-09-24 Sergio Villar Senin <svillar@igalia.com>
215
316 [css-flexbox] Import latest changes from css-flexbox WPT repo

LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-coep-sandbox.https-expected.txt

 1CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
 2CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
13
24PASS <iframe sandbox="allow-popups allow-scripts allow-same-origin"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error
35PASS <iframe sandbox="allow-popups allow-scripts"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error

LayoutTests/imported/w3c/web-platform-tests/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt

 1CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
 2CONSOLE MESSAGE: Navigation was blocked by Cross-Origin-Opener-Policy
13
24PASS <iframe sandbox="allow-popups allow-scripts allow-same-origin"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error
35PASS <iframe sandbox="allow-popups allow-scripts"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error