Re-enable NSURLSession isolation after r252116
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Nov 2019 17:05:18 +0000 (17:05 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Nov 2019 17:05:18 +0000 (17:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203934
<rdar://problem/56921584>

Reviewed by Chris Dumez.

Source/WebCore:

* platform/network/StoredCredentialsPolicy.h:

Source/WebKit:

r252116 was a rollout of r248640, which introduced cases where data tasks from different NSURLSessions
which can have the same task identifiers were put into the same maps.  This key collision caused data from the wrong
tasks to be sent to NetworkResourceLoader, causing rare and strange loading bugs.  In order to prevent insertion into
wrong maps again, I made a new abstraction, SessionWrapper, which wraps a NSURLSession, its delegate, and all maps
that are scoped to that NSURLSession.  Along the way I found a few other places where we had made similar mistakes.

Covered by an API test which would've failed before r252116 because it exercises the key collision condition,
and by tests which were skipped in r252116 and I now unskipped.

* NetworkProcess/Downloads/cocoa/DownloadCocoa.mm:
(WebKit::Download::resume):
* NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
(WebKit::NetworkDataTaskCocoa::~NetworkDataTaskCocoa):
* NetworkProcess/cocoa/NetworkSessionCocoa.h:
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate initWithSessionWrapper:withCredentials:]):
(-[WKNetworkSessionDelegate sessionInvalidated]):
(-[WKNetworkSessionDelegate existingTask:]):
(-[WKNetworkSessionDelegate sessionCocoa]):
(-[WKNetworkSessionDelegate URLSession:didBecomeInvalidWithError:]):
(-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:willCacheResponse:completionHandler:]):
(processServerTrustEvaluation):
(-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
(-[WKNetworkSessionDelegate existingWebSocketTask:]):
(WebKit::SessionWrapper::initialize):
(WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
(WebKit::NetworkSessionCocoa::initializeEphemeralStatelessSession):
(WebKit::NetworkSessionCocoa::sessionWrapperForTask):
(WebKit::NetworkSessionCocoa::isolatedSession):
(WebKit::NetworkSessionCocoa::invalidateAndCancel):
(WebKit::NetworkSessionCocoa::continueDidReceiveChallenge):
(WebKit::NetworkSessionCocoa::createWebSocketTask):
(WebKit::NetworkSessionCocoa::addWebSocketTask):
(WebKit::NetworkSessionCocoa::removeWebSocketTask):
(-[WKNetworkSessionDelegate initWithNetworkSession:withCredentials:]): Deleted.
(WebKit::NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession): Deleted.
(WebKit::NetworkSessionCocoa::session): Deleted.
(WebKit::NetworkSessionCocoa::dataTaskForIdentifier): Deleted.
(WebKit::NetworkSessionCocoa::downloadTaskWithResumeData): Deleted.
(WebKit::NetworkSessionCocoa::addDownloadID): Deleted.
(WebKit::NetworkSessionCocoa::downloadID): Deleted.
(WebKit::NetworkSessionCocoa::takeDownloadID): Deleted.
(WebKit::NetworkSessionCocoa::webSocketDataTaskForIdentifier): Deleted.
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(-[WKWebsiteDataStore _logUserInteraction:completionHandler:]):
* UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm:
(-[DataTaskIdentifierCollisionDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
(-[DataTaskIdentifierCollisionDelegate waitForMessages:]):
(-[DataTaskIdentifierCollisionDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]):
(TEST):

LayoutTests:

* platform/wk2/TestExpectations:
Re-enable skipped tests.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252185 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/platform/network/StoredCredentialsPolicy.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/AdClickAttributionManager.cpp
Source/WebKit/NetworkProcess/Downloads/cocoa/DownloadCocoa.mm
Source/WebKit/NetworkProcess/NetworkDataTask.cpp
Source/WebKit/NetworkProcess/NetworkDataTask.h
Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h
Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h
Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit/Shared/WebCoreArgumentCoders.h
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm

index f5f6aab..5eed1a8 100644 (file)
@@ -1,3 +1,14 @@
+2019-11-07  Alex Christensen  <achristensen@webkit.org>
+
+        Re-enable NSURLSession isolation after r252116
+        https://bugs.webkit.org/show_bug.cgi?id=203934
+        <rdar://problem/56921584>
+
+        Reviewed by Chris Dumez.
+
+        * platform/wk2/TestExpectations:
+        Re-enable skipped tests.
+
 2019-11-06  Antti Koivisto  <antti@apple.com>
 
         REGRESSION: [ iOS ] ( r251015 ) Layout Test fast/text/whitespace/pre-wrap-overflow-selection.html is flaky
index c818547..f2e9b0a 100644 (file)
@@ -746,10 +746,6 @@ http/tests/resourceLoadStatistics/do-not-remove-blocking-in-redirect.html [ Skip
 http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Skip ]
 http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Skip ]
 
-# rdar://problem/56921584
-http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction.php [ Skip ]
-http/tests/resourceLoadStatistics/switch-session-on-navigation-to-prevalent-with-interaction-database.php [ Skip ]
-
 # This feature is currently disabled by default and unfinished <rdar://problem/38925077>.
 http/tests/navigation/process-swap-window-open.html [ Skip ]
 
index 57f6965..d63aea3 100644 (file)
@@ -1,3 +1,13 @@
+2019-11-07  Alex Christensen  <achristensen@webkit.org>
+
+        Re-enable NSURLSession isolation after r252116
+        https://bugs.webkit.org/show_bug.cgi?id=203934
+        <rdar://problem/56921584>
+
+        Reviewed by Chris Dumez.
+
+        * platform/network/StoredCredentialsPolicy.h:
+
 2019-11-07  Andres Gonzalez  <andresg_22@apple.com>
 
         Rename AXIsolatedTreeNode to AXIsolatedObject for consistency with AXCoreObject and AccessibilityObject.
index 1495a08..ad474fb 100644 (file)
@@ -30,7 +30,7 @@ namespace WebCore {
 enum class StoredCredentialsPolicy : uint8_t {
     DoNotUse,
     Use,
-    EphemeralStatelessCookieless
+    EphemeralStateless
 };
 
 } // namespace WebCore
index 02b4097..c01d7f0 100644 (file)
@@ -1,3 +1,67 @@
+2019-11-07  Alex Christensen  <achristensen@webkit.org>
+
+        Re-enable NSURLSession isolation after r252116
+        https://bugs.webkit.org/show_bug.cgi?id=203934
+        <rdar://problem/56921584>
+
+        Reviewed by Chris Dumez.
+
+        r252116 was a rollout of r248640, which introduced cases where data tasks from different NSURLSessions
+        which can have the same task identifiers were put into the same maps.  This key collision caused data from the wrong
+        tasks to be sent to NetworkResourceLoader, causing rare and strange loading bugs.  In order to prevent insertion into
+        wrong maps again, I made a new abstraction, SessionWrapper, which wraps a NSURLSession, its delegate, and all maps
+        that are scoped to that NSURLSession.  Along the way I found a few other places where we had made similar mistakes.
+
+        Covered by an API test which would've failed before r252116 because it exercises the key collision condition,
+        and by tests which were skipped in r252116 and I now unskipped.
+
+        * NetworkProcess/Downloads/cocoa/DownloadCocoa.mm:
+        (WebKit::Download::resume):
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.h:
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTaskCocoa::NetworkDataTaskCocoa):
+        (WebKit::NetworkDataTaskCocoa::~NetworkDataTaskCocoa):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.h:
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate initWithSessionWrapper:withCredentials:]):
+        (-[WKNetworkSessionDelegate sessionInvalidated]):
+        (-[WKNetworkSessionDelegate existingTask:]):
+        (-[WKNetworkSessionDelegate sessionCocoa]):
+        (-[WKNetworkSessionDelegate URLSession:didBecomeInvalidWithError:]):
+        (-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:task:_schemeUpgraded:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:dataTask:willCacheResponse:completionHandler:]):
+        (processServerTrustEvaluation):
+        (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
+        (-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
+        (-[WKNetworkSessionDelegate URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:]):
+        (-[WKNetworkSessionDelegate URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:]):
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
+        (-[WKNetworkSessionDelegate existingWebSocketTask:]):
+        (WebKit::SessionWrapper::initialize):
+        (WebKit::NetworkSessionCocoa::NetworkSessionCocoa):
+        (WebKit::NetworkSessionCocoa::initializeEphemeralStatelessSession):
+        (WebKit::NetworkSessionCocoa::sessionWrapperForTask):
+        (WebKit::NetworkSessionCocoa::isolatedSession):
+        (WebKit::NetworkSessionCocoa::invalidateAndCancel):
+        (WebKit::NetworkSessionCocoa::continueDidReceiveChallenge):
+        (WebKit::NetworkSessionCocoa::createWebSocketTask):
+        (WebKit::NetworkSessionCocoa::addWebSocketTask):
+        (WebKit::NetworkSessionCocoa::removeWebSocketTask):
+        (-[WKNetworkSessionDelegate initWithNetworkSession:withCredentials:]): Deleted.
+        (WebKit::NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession): Deleted.
+        (WebKit::NetworkSessionCocoa::session): Deleted.
+        (WebKit::NetworkSessionCocoa::dataTaskForIdentifier): Deleted.
+        (WebKit::NetworkSessionCocoa::downloadTaskWithResumeData): Deleted.
+        (WebKit::NetworkSessionCocoa::addDownloadID): Deleted.
+        (WebKit::NetworkSessionCocoa::downloadID): Deleted.
+        (WebKit::NetworkSessionCocoa::takeDownloadID): Deleted.
+        (WebKit::NetworkSessionCocoa::webSocketDataTaskForIdentifier): Deleted.
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        (-[WKWebsiteDataStore _logUserInteraction:completionHandler:]):
+        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+
 2019-11-07  Peng Liu  <peng.liu6@apple.com>
 
         ASSERTION FAILED: m_clientCounts.contains(contextId) in WebKit::VideoFullscreenManagerProxy::removeClientForContext(uint64_t)
index f3e2f0e..ba49b46 100644 (file)
@@ -168,7 +168,7 @@ void AdClickAttributionManager::fireConversionRequest(const AdClickAttribution&
     loadParameters.request = request;
     loadParameters.sourceOrigin = SecurityOrigin::create(conversionReferrerURL);
     loadParameters.parentPID = presentingApplicationPID();
-    loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::EphemeralStatelessCookieless;
+    loadParameters.storedCredentialsPolicy = StoredCredentialsPolicy::EphemeralStateless;
     loadParameters.options = options;
     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = true;
     loadParameters.shouldRestrictHTTPResponseAccess = false;
index aff16db..04e5d80 100644 (file)
@@ -70,8 +70,10 @@ void Download::resume(const IPC::DataReference& resumeData, const String& path,
     NSData *updatedData = [NSPropertyListSerialization dataWithPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nullptr];
 #endif
 
-    m_downloadTask = cocoaSession.downloadTaskWithResumeData(updatedData);
-    cocoaSession.addDownloadID(m_downloadTask.get().taskIdentifier, m_downloadID);
+    m_downloadTask = [cocoaSession.sessionWrapperForDownloads().session downloadTaskWithResumeData:updatedData];
+    auto taskIdentifier = [m_downloadTask taskIdentifier];
+    ASSERT(!cocoaSession.sessionWrapperForDownloads().downloadMap.contains(taskIdentifier));
+    cocoaSession.sessionWrapperForDownloads().downloadMap.add(taskIdentifier, m_downloadID);
     m_downloadTask.get()._pathToDownloadTaskFile = path;
 
     [m_downloadTask resume];
index 38e7583..a9ea6d0 100644 (file)
@@ -158,4 +158,9 @@ PAL::SessionID NetworkDataTask::sessionID() const
     return m_session->sessionID();
 }
 
+NetworkSession* NetworkDataTask::networkSession()
+{
+    return m_session.get();
+}
+
 } // namespace WebKit
index 9a984e8..94f9820 100644 (file)
@@ -133,6 +133,8 @@ public:
 
     PAL::SessionID sessionID() const;
 
+    NetworkSession* networkSession();
+
 protected:
     NetworkDataTask(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::StoredCredentialsPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect, bool dataTaskIsForMainFrameNavigation);
 
index 89d64da..1ef4846 100644 (file)
@@ -38,6 +38,7 @@ namespace WebKit {
 
 class Download;
 class NetworkSessionCocoa;
+struct SessionWrapper;
 
 class NetworkDataTaskCocoa final : public NetworkDataTask {
     friend class NetworkSessionCocoa;
@@ -89,6 +90,7 @@ private:
     bool isThirdPartyRequest(const WebCore::ResourceRequest&) const;
     bool isAlwaysOnLoggingAllowed() const;
 
+    SessionWrapper& m_sessionWrapper;
     RefPtr<SandboxExtension> m_sandboxExtension;
     RetainPtr<NSURLSessionDataTask> m_task;
     WebCore::NetworkLoadMetrics m_networkLoadMetrics;
index 189fc26..1d0acfb 100644 (file)
@@ -172,6 +172,7 @@ static inline bool computeIsAlwaysOnLoggingAllowed(NetworkSession& session)
 
 NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataTaskClient& client, const WebCore::ResourceRequest& requestWithCredentials, WebCore::FrameIdentifier frameID, WebCore::PageIdentifier pageID, WebCore::StoredCredentialsPolicy storedCredentialsPolicy, WebCore::ContentSniffingPolicy shouldContentSniff, WebCore::ContentEncodingSniffingPolicy shouldContentEncodingSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect, PreconnectOnly shouldPreconnectOnly, bool dataTaskIsForMainFrameNavigation, bool dataTaskIsForMainResourceNavigationForAnyFrame, Optional<NetworkActivityTracker> networkActivityTracker)
     : NetworkDataTask(session, client, requestWithCredentials, storedCredentialsPolicy, shouldClearReferrerOnHTTPSToHTTPRedirect, dataTaskIsForMainFrameNavigation)
+    , m_sessionWrapper(static_cast<NetworkSessionCocoa&>(session).sessionWrapperForTask(requestWithCredentials, storedCredentialsPolicy))
     , m_frameID(frameID)
     , m_pageID(pageID)
     , m_isForMainResourceNavigationForAnyFrame(dataTaskIsForMainResourceNavigationForAnyFrame)
@@ -206,14 +207,11 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
 #endif
 
     bool shouldBlockCookies = false;
-    bool needsIsolatedSession = false;
-    auto firstParty = WebCore::RegistrableDomain(request.firstPartyForCookies());
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-    shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless;
+    shouldBlockCookies = storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStateless;
     if (auto* networkStorageSession = session.networkStorageSession()) {
         if (!shouldBlockCookies)
             shouldBlockCookies = networkStorageSession->shouldBlockCookies(request, frameID, pageID);
-        // FIXME: <rdar://problem/56921584> needsIsolatedSession should be set here.
     }
 #endif
     restrictRequestReferrerToOriginIfNeeded(request);
@@ -221,14 +219,11 @@ NetworkDataTaskCocoa::NetworkDataTaskCocoa(NetworkSession& session, NetworkDataT
     NSURLRequest *nsRequest = request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
     applySniffingPoliciesAndBindRequestToInferfaceIfNeeded(nsRequest, shouldContentSniff == WebCore::ContentSniffingPolicy::SniffContent && !url.isLocalFile(), shouldContentEncodingSniff == WebCore::ContentEncodingSniffingPolicy::Sniff);
 
-    auto& cocoaSession = static_cast<NetworkSessionCocoa&>(*m_session);
-    if (needsIsolatedSession)
-        m_task = [cocoaSession.isolatedSession(storedCredentialsPolicy, firstParty) dataTaskWithRequest:nsRequest];
-    else
-        m_task = [cocoaSession.session(storedCredentialsPolicy) dataTaskWithRequest:nsRequest];
+    m_task = [m_sessionWrapper.session dataTaskWithRequest:nsRequest];
 
-    LOG(NetworkSession, "%llu Creating NetworkDataTask with storedCredentialsPolicy=%u and URL=%s", [m_task taskIdentifier], storedCredentialsPolicy, nsRequest.URL.absoluteString.UTF8String);
-    cocoaSession.registerDataTask([m_task taskIdentifier], *this, storedCredentialsPolicy);
+    RELEASE_ASSERT(!m_sessionWrapper.dataTaskMap.contains([m_task taskIdentifier]));
+    m_sessionWrapper.dataTaskMap.add([m_task taskIdentifier], this);
+    LOG(NetworkSession, "%llu Creating NetworkDataTask with URL %s", [m_task taskIdentifier], nsRequest.URL.absoluteString.UTF8String);
 
     if (shouldPreconnectOnly == PreconnectOnly::Yes) {
 #if ENABLE(SERVER_PRECONNECT)
@@ -266,8 +261,8 @@ NetworkDataTaskCocoa::~NetworkDataTaskCocoa()
     if (!m_task || !m_session)
         return;
 
-    auto& cocoaSession = static_cast<NetworkSessionCocoa&>(*m_session);
-    cocoaSession.unregisterDataTask([m_task taskIdentifier], *this, m_storedCredentialsPolicy);
+    RELEASE_ASSERT(m_sessionWrapper.dataTaskMap.get([m_task taskIdentifier]) == this);
+    m_sessionWrapper.dataTaskMap.remove([m_task taskIdentifier]);
 }
 
 void NetworkDataTaskCocoa::restrictRequestReferrerToOriginIfNeeded(WebCore::ResourceRequest& request)
@@ -357,7 +352,7 @@ void NetworkDataTaskCocoa::willPerformHTTPRedirection(WebCore::ResourceResponse&
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     if (!m_hasBeenSetToUseStatelessCookieStorage) {
-        if (m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless
+        if (m_storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::EphemeralStateless
             || (m_session->networkStorageSession() && m_session->networkStorageSession()->shouldBlockCookies(request, m_frameID, m_pageID)))
             blockCookies();
     }
index 6a8deeb..53da467 100644 (file)
@@ -28,6 +28,7 @@
 OBJC_CLASS DMFWebsitePolicyMonitor;
 OBJC_CLASS NSData;
 OBJC_CLASS NSURLSession;
+OBJC_CLASS NSURLSessionConfiguration;
 OBJC_CLASS NSURLSessionDownloadTask;
 OBJC_CLASS NSOperationQueue;
 OBJC_CLASS WKNetworkSessionDelegate;
@@ -45,6 +46,19 @@ OBJC_CLASS WKNetworkSessionWebSocketDelegate;
 namespace WebKit {
 
 class LegacyCustomProtocolManager;
+class NetworkSessionCocoa;
+
+struct SessionWrapper : public CanMakeWeakPtr<SessionWrapper> {
+    void initialize(NSURLSessionConfiguration *, NetworkSessionCocoa&, WebCore::StoredCredentialsPolicy);
+
+    RetainPtr<NSURLSession> session;
+    RetainPtr<WKNetworkSessionDelegate> delegate;
+    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> dataTaskMap;
+    HashMap<NetworkDataTaskCocoa::TaskIdentifier, DownloadID> downloadMap;
+#if HAVE(NSURLSESSION_WEBSOCKET)
+    HashMap<NetworkDataTaskCocoa::TaskIdentifier, WebSocketTask*> webSocketDataTaskMap;
+#endif
+};
 
 class NetworkSessionCocoa final : public NetworkSession {
     friend class NetworkDataTaskCocoa;
@@ -54,7 +68,7 @@ public:
     NetworkSessionCocoa(NetworkProcess&, NetworkSessionCreationParameters&&);
     ~NetworkSessionCocoa();
 
-    void initializeEphemeralStatelessCookielessSession();
+    void initializeEphemeralStatelessSession();
 
     const String& boundInterfaceIdentifier() const;
     const String& sourceApplicationBundleIdentifier() const;
@@ -63,21 +77,11 @@ public:
     const String& dataConnectionServiceType() const { return m_dataConnectionServiceType; }
 #endif
 
-    NetworkDataTaskCocoa* dataTaskForIdentifier(NetworkDataTaskCocoa::TaskIdentifier, WebCore::StoredCredentialsPolicy);
-    void registerDataTask(NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa&, WebCore::StoredCredentialsPolicy);
-    void unregisterDataTask(NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa&, WebCore::StoredCredentialsPolicy);
-
-    NSURLSessionDownloadTask* downloadTaskWithResumeData(NSData*);
-
-    WebSocketTask* webSocketDataTaskForIdentifier(WebSocketTask::TaskIdentifier);
-
-    void addDownloadID(NetworkDataTaskCocoa::TaskIdentifier, DownloadID);
-    DownloadID downloadID(NetworkDataTaskCocoa::TaskIdentifier);
-    DownloadID takeDownloadID(NetworkDataTaskCocoa::TaskIdentifier);
-
     static bool allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge&);
 
-    void continueDidReceiveChallenge(const WebCore::AuthenticationChallenge&, NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*, CompletionHandler<void(WebKit::AuthenticationChallengeDisposition, const WebCore::Credential&)>&&);
+    void continueDidReceiveChallenge(SessionWrapper&, const WebCore::AuthenticationChallenge&, NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*, CompletionHandler<void(WebKit::AuthenticationChallengeDisposition, const WebCore::Credential&)>&&);
+
+    SessionWrapper& sessionWrapperForDownloads() { return m_sessionWithCredentialStorage; }
 
     bool fastServerTrustEvaluationEnabled() const { return m_fastServerTrustEvaluationEnabled; }
     bool deviceManagementRestrictionsEnabled() const { return m_deviceManagementRestrictionsEnabled; }
@@ -86,8 +90,6 @@ public:
 
     CFDictionaryRef proxyConfiguration() const { return m_proxyConfiguration.get(); }
 
-    NSURLSession* session(WebCore::StoredCredentialsPolicy);
-    NSURLSession* isolatedSession(WebCore::StoredCredentialsPolicy, const WebCore::RegistrableDomain);
     bool hasIsolatedSession(const WebCore::RegistrableDomain) const override;
     void clearIsolatedSessions() override;
 
@@ -96,6 +98,8 @@ private:
     void clearCredentials() override;
     bool shouldLogCookieInformation() const override { return m_shouldLogCookieInformation; }
     Seconds loadThrottleLatency() const override { return m_loadThrottleLatency; }
+    SessionWrapper& sessionWrapperForTask(const WebCore::ResourceRequest&, WebCore::StoredCredentialsPolicy);
+    SessionWrapper& isolatedSession(WebCore::StoredCredentialsPolicy, const WebCore::RegistrableDomain);
 
 #if HAVE(NSURLSESSION_WEBSOCKET)
     std::unique_ptr<WebSocketTask> createWebSocketTask(NetworkSocketChannel&, const WebCore::ResourceRequest&, const String& protocol) final;
@@ -103,32 +107,19 @@ private:
     void removeWebSocketTask(WebSocketTask&) final;
 #endif
 
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*>& dataTaskMap(WebCore::StoredCredentialsPolicy);
-
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapWithCredentials;
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapWithoutState;
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*> m_dataTaskMapEphemeralStatelessCookieless;
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, DownloadID> m_downloadMap;
-#if HAVE(NSURLSESSION_WEBSOCKET)
-    HashMap<NetworkDataTaskCocoa::TaskIdentifier, WebSocketTask*> m_webSocketDataTaskMap;
-#endif
-
     struct IsolatedSession {
-        RetainPtr<NSURLSession> sessionWithCredentialStorage;
-        RetainPtr<WKNetworkSessionDelegate> sessionWithCredentialStorageDelegate;
-        RetainPtr<NSURLSession> statelessSession;
-        RetainPtr<WKNetworkSessionDelegate> statelessSessionDelegate;
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        SessionWrapper sessionWithCredentialStorage;
+        SessionWrapper sessionWithoutCredentialStorage;
         WallTime lastUsed;
     };
 
-    HashMap<WebCore::RegistrableDomain, IsolatedSession> m_isolatedSessions;
+    HashMap<WebCore::RegistrableDomain, std::unique_ptr<IsolatedSession>> m_isolatedSessions;
 
-    RetainPtr<NSURLSession> m_sessionWithCredentialStorage;
-    RetainPtr<WKNetworkSessionDelegate> m_sessionWithCredentialStorageDelegate;
-    RetainPtr<NSURLSession> m_statelessSession;
-    RetainPtr<WKNetworkSessionDelegate> m_statelessSessionDelegate;
-    RetainPtr<NSURLSession> m_ephemeralStatelessCookielessSession;
-    RetainPtr<WKNetworkSessionDelegate> m_ephemeralStatelessCookielessSessionDelegate;
+    SessionWrapper m_sessionWithCredentialStorage;
+    SessionWrapper m_sessionWithoutCredentialStorage;
+    SessionWrapper m_ephemeralStatelessSession;
 
     String m_boundInterfaceIdentifier;
     String m_sourceApplicationBundleIdentifier;
index 418125a..05cf516 100644 (file)
 #import <WebCore/SharedBuffer.h>
 #import <WebCore/WebCoreURLResponse.h>
 #import <pal/spi/cf/CFNetworkSPI.h>
+#import <wtf/BlockPtr.h>
 #import <wtf/MainThread.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/ObjCRuntimeExtras.h>
 #import <wtf/ProcessPrivilege.h>
 #import <wtf/SoftLinking.h>
 #import <wtf/URL.h>
+#import <wtf/WeakObjCPtr.h>
 #import <wtf/text/WTFString.h>
-#import <wtf/BlockPtr.h>
 
 #if USE(APPLE_INTERNAL_SDK)
 #include <WebKitAdditions/NetworkSessionCocoaAdditions.h>
@@ -396,23 +397,25 @@ static String stringForSSLCipher(SSLCipherSuite cipher)
 #endif
 > {
     WeakPtr<WebKit::NetworkSessionCocoa> _session;
+    WeakPtr<WebKit::SessionWrapper> _sessionWrapper;
     bool _withCredentials;
 }
 
-- (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session withCredentials:(bool)withCredentials;
+- (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session wrapper:(WebKit::SessionWrapper&)sessionWrapper withCredentials:(bool)withCredentials;
 - (void)sessionInvalidated;
 
 @end
 
 @implementation WKNetworkSessionDelegate
 
-- (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session withCredentials:(bool)withCredentials
+- (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session wrapper:(WebKit::SessionWrapper&)sessionWrapper withCredentials:(bool)withCredentials
 {
     self = [super init];
     if (!self)
         return nil;
 
     _session = makeWeakPtr(session);
+    _sessionWrapper = makeWeakPtr(sessionWrapper);
     _withCredentials = withCredentials;
 
     return self;
@@ -420,24 +423,23 @@ static String stringForSSLCipher(SSLCipherSuite cipher)
 
 - (void)sessionInvalidated
 {
-    _session = nullptr;
+    _sessionWrapper = nullptr;
 }
 
 - (NetworkDataTaskCocoa*)existingTask:(NSURLSessionTask *)task
 {
-    if (!_session)
+    if (!_sessionWrapper)
         return nullptr;
 
     if (!task)
         return nullptr;
 
-    auto storedCredentialsPolicy = _withCredentials ? WebCore::StoredCredentialsPolicy::Use : WebCore::StoredCredentialsPolicy::DoNotUse;
-    return _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentialsPolicy);
+    return _sessionWrapper->dataTaskMap.get(task.taskIdentifier);
 }
 
 - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
 {
-    ASSERT(!_session);
+    ASSERT(!_sessionWrapper);
 }
 
 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
@@ -527,12 +529,15 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
 
         bool shouldIgnoreHSTS = false;
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && _session->networkProcess().storageSession(_session->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
-        if (shouldIgnoreHSTS) {
-            request = downgradeRequest(request);
-            ASSERT([request.URL.scheme isEqualToString:@"http"]);
-            LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
-        }
+        if (auto* sessionCocoa = networkDataTask->networkSession()) {
+            shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && sessionCocoa->networkProcess().storageSession(sessionCocoa->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
+            if (shouldIgnoreHSTS) {
+                request = downgradeRequest(request);
+                ASSERT([request.URL.scheme isEqualToString:@"http"]);
+                LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
+            }
+        } else
+            ASSERT_NOT_REACHED();
 #endif
 
         networkDataTask->willPerformHTTPRedirection(response, request, [completionHandlerCopy, taskIdentifier, shouldIgnoreHSTS](auto&& request) {
@@ -560,12 +565,15 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
     if (auto* networkDataTask = [self existingTask:task]) {
         bool shouldIgnoreHSTS = false;
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
-        shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && _session->networkProcess().storageSession(_session->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
-        if (shouldIgnoreHSTS) {
-            request = downgradeRequest(request);
-            ASSERT([request.URL.scheme isEqualToString:@"http"]);
-            LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
-        }
+        if (auto* sessionCocoa = networkDataTask->networkSession()) {
+            shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && sessionCocoa->networkProcess().storageSession(sessionCocoa->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
+            if (shouldIgnoreHSTS) {
+                request = downgradeRequest(request);
+                ASSERT([request.URL.scheme isEqualToString:@"http"]);
+                LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
+            }
+        } else
+            ASSERT_NOT_REACHED();
 #endif
 
         auto completionHandlerCopy = Block_copy(completionHandler);
@@ -588,11 +596,6 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
 
 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
 {
-    if (!_session) {
-        completionHandler(nil);
-        return;
-    }
-
     // FIXME: remove if <rdar://problem/20001985> is ever resolved.
     if ([proposedResponse.response respondsToSelector:@selector(allHeaderFields)]
         && [[(id)proposedResponse.response allHeaderFields] objectForKey:@"Content-Range"])
@@ -602,9 +605,9 @@ static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURL
 }
 
 #if HAVE(CFNETWORK_NSURLSESSION_STRICTRUSTEVALUATE)
-static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NSURLAuthenticationChallenge *challenge, NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa* networkDataTask, CompletionHandler<void(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential)>&& completionHandler)
+static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, SessionWrapper& sessionWrapper, NSURLAuthenticationChallenge *challenge, NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa* networkDataTask, CompletionHandler<void(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential)>&& completionHandler)
 {
-    session->continueDidReceiveChallenge(challenge, taskIdentifier, networkDataTask, [completionHandler = WTFMove(completionHandler), secTrust = retainPtr(challenge.protectionSpace.serverTrust)] (WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) mutable {
+    session->continueDidReceiveChallenge(sessionWrapper, challenge, taskIdentifier, networkDataTask, [completionHandler = WTFMove(completionHandler), secTrust = retainPtr(challenge.protectionSpace.serverTrust)] (WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) mutable {
         // FIXME: UIProcess should send us back non nil credentials but the credential IPC encoder currently only serializes ns credentials for username/password.
         if (disposition == WebKit::AuthenticationChallengeDisposition::UseCredential && !credential.nsCredential()) {
             completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust: secTrust.get()]);
@@ -617,7 +620,9 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NS
 
 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
 {
-    if (!_session || [task state] == NSURLSessionTaskStateCanceling) {
+    auto* networkDataTask = [self existingTask:task];
+    auto* sessionCocoa = networkDataTask ? static_cast<NetworkSessionCocoa*>(networkDataTask->networkSession()) : nullptr;
+    if (!sessionCocoa || [task state] == NSURLSessionTaskStateCanceling) {
         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
         return;
     }
@@ -637,18 +642,21 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NS
             return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
 
         // Handle server trust evaluation at platform-level if requested, for performance reasons and to use ATS defaults.
-        if (_session->fastServerTrustEvaluationEnabled()) {
+        if (sessionCocoa->fastServerTrustEvaluationEnabled()) {
 #if HAVE(CFNETWORK_NSURLSESSION_STRICTRUSTEVALUATE)
             auto* networkDataTask = [self existingTask:task];
             ASSERT(networkDataTask);
-            auto decisionHandler = makeBlockPtr([_session = makeWeakPtr(_session.get()), completionHandler = makeBlockPtr(completionHandler), taskIdentifier, networkDataTask = RefPtr<NetworkDataTaskCocoa>(networkDataTask)](NSURLAuthenticationChallenge *challenge, OSStatus trustResult) mutable {
+            auto decisionHandler = makeBlockPtr([weakSelf = WeakObjCPtr<WKNetworkSessionDelegate>(self), sessionCocoa = makeWeakPtr(sessionCocoa), completionHandler = makeBlockPtr(completionHandler), taskIdentifier, networkDataTask = RefPtr<NetworkDataTaskCocoa>(networkDataTask)](NSURLAuthenticationChallenge *challenge, OSStatus trustResult) mutable {
+                auto strongSelf = weakSelf.get();
+                if (!strongSelf)
+                    return completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
                 auto task = WTFMove(networkDataTask);
-                auto* session = _session.get();
+                auto* session = sessionCocoa.get();
                 if (trustResult == noErr || !session) {
                     completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
                     return;
                 }
-                processServerTrustEvaluation(session, challenge, taskIdentifier, task.get(), WTFMove(completionHandler));
+                processServerTrustEvaluation(session, *strongSelf->_sessionWrapper, challenge, taskIdentifier, task.get(), WTFMove(completionHandler));
             });
             [NSURLSession _strictTrustEvaluate:challenge queue:[NSOperationQueue mainQueue].underlyingQueue completionHandler:decisionHandler.get()];
             return;
@@ -657,16 +665,13 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NS
 #endif
         }
     }
-    _session->continueDidReceiveChallenge(challenge, taskIdentifier, [self existingTask:task], [completionHandler = makeBlockPtr(completionHandler)] (WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) mutable {
+    sessionCocoa->continueDidReceiveChallenge(*_sessionWrapper, challenge, taskIdentifier, [self existingTask:task], [completionHandler = makeBlockPtr(completionHandler)] (WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) mutable {
         completionHandler(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
     });
 }
 
 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
 {
-    if (!_session)
-        return;
-
     LOG(NetworkSession, "%llu didCompleteWithError %@", task.taskIdentifier, error);
 
     if (error) {
@@ -679,29 +684,35 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NS
     if (auto* networkDataTask = [self existingTask:task])
         networkDataTask->didCompleteWithError(error, networkDataTask->networkLoadMetrics());
     else if (error) {
-        auto downloadID = _session->takeDownloadID(task.taskIdentifier);
-        if (downloadID.downloadID()) {
-            if (auto* download = _session->networkProcess().downloadManager().download(downloadID)) {
-                NSData *resumeData = nil;
-                if (id userInfo = error.userInfo) {
-                    if ([userInfo isKindOfClass:[NSDictionary class]]) {
-                        resumeData = userInfo[@"NSURLSessionDownloadTaskResumeData"];
-                        if (resumeData && ![resumeData isKindOfClass:[NSData class]]) {
-                            RELEASE_LOG(NetworkSession, "Download task %llu finished with resume data of wrong class: %s", (unsigned long long)task.taskIdentifier, NSStringFromClass([resumeData class]).UTF8String);
-                            ASSERT_NOT_REACHED();
-                            resumeData = nil;
-                        }
-                    }
-                }
-
-                auto resumeDataReference = resumeData ? IPC::DataReference { static_cast<const uint8_t*>(resumeData.bytes), resumeData.length } : IPC::DataReference { };
+        if (!_sessionWrapper)
+            return;
+        auto downloadID = _sessionWrapper->downloadMap.take(task.taskIdentifier);
+        if (!downloadID.downloadID())
+            return;
+        if (!_session)
+            return;
+        auto* download = _session->networkProcess().downloadManager().download(downloadID);
+        if (!download)
+            return;
 
-                if (download->wasCanceled())
-                    download->didCancel(resumeDataReference);
-                else
-                    download->didFail(error, resumeDataReference);
+        NSData *resumeData = nil;
+        if (id userInfo = error.userInfo) {
+            if ([userInfo isKindOfClass:[NSDictionary class]]) {
+                resumeData = userInfo[@"NSURLSessionDownloadTaskResumeData"];
+                if (resumeData && ![resumeData isKindOfClass:[NSData class]]) {
+                    RELEASE_LOG(NetworkSession, "Download task %llu finished with resume data of wrong class: %s", (unsigned long long)task.taskIdentifier, NSStringFromClass([resumeData class]).UTF8String);
+                    ASSERT_NOT_REACHED();
+                    resumeData = nil;
+                }
             }
         }
+
+        auto resumeDataReference = resumeData ? IPC::DataReference { static_cast<const uint8_t*>(resumeData.bytes), resumeData.length } : IPC::DataReference { };
+
+        if (download->wasCanceled())
+            download->didCancel(resumeDataReference);
+        else
+            download->didFail(error, resumeDataReference);
     }
 }
 
@@ -836,60 +847,73 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa *session, NS
 
 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
 {
+    if (!_sessionWrapper)
+        return;
+    auto downloadID = _sessionWrapper->downloadMap.take([downloadTask taskIdentifier]);
+    if (!downloadID.downloadID())
+        return;
     if (!_session)
         return;
-
-    auto downloadID = _session->takeDownloadID([downloadTask taskIdentifier]);
-    if (auto* download = _session->networkProcess().downloadManager().download(downloadID))
-        download->didFinish();
+    auto* download = _session->networkProcess().downloadManager().download(downloadID);
+    if (!download)
+        return;
+    download->didFinish();
 }
 
 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
 {
-    if (!_session)
-        return;
-
     ASSERT_WITH_MESSAGE(![self existingTask:downloadTask], "The NetworkDataTask should be destroyed immediately after didBecomeDownloadTask returns");
 
-    auto downloadID = _session->downloadID([downloadTask taskIdentifier]);
-    if (auto* download = _session->networkProcess().downloadManager().download(downloadID))
-        download->didReceiveData(bytesWritten);
+    if (!_sessionWrapper)
+        return;
+    auto downloadID = _sessionWrapper->downloadMap.get([downloadTask taskIdentifier]);
+    if (!downloadID.downloadID())
+        return;
+    if (!_session)
+        return;
+    auto* download = _session->networkProcess().downloadManager().download(downloadID);
+    if (!download)
+        return;
+    download->didReceiveData(bytesWritten);
 }
 
 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
 {
-    if (!_session)
-        return;
-
     notImplemented();
 }
 
 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
 {
-    if (auto* networkDataTask = [self existingTask:dataTask]) {
-        Ref<NetworkDataTaskCocoa> protectedNetworkDataTask(*networkDataTask);
-        auto downloadID = networkDataTask->pendingDownloadID();
-        auto& downloadManager = _session->networkProcess().downloadManager();
-        auto download = makeUnique<WebKit::Download>(downloadManager, downloadID, downloadTask, *_session, networkDataTask->suggestedFilename());
-        networkDataTask->transferSandboxExtensionToDownload(*download);
-        ASSERT(FileSystem::fileExists(networkDataTask->pendingDownloadLocation()));
-        download->didCreateDestination(networkDataTask->pendingDownloadLocation());
-        downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
-
-        _session->addDownloadID([downloadTask taskIdentifier], downloadID);
-    }
+    auto* networkDataTask = [self existingTask:dataTask];
+    if (!networkDataTask)
+        return;
+    auto* sessionCocoa = networkDataTask->networkSession();
+    if (!sessionCocoa)
+        return;
+
+    Ref<NetworkDataTaskCocoa> protectedNetworkDataTask(*networkDataTask);
+    auto downloadID = networkDataTask->pendingDownloadID();
+    auto& downloadManager = sessionCocoa->networkProcess().downloadManager();
+    auto download = makeUnique<WebKit::Download>(downloadManager, downloadID, downloadTask, *sessionCocoa, networkDataTask->suggestedFilename());
+    networkDataTask->transferSandboxExtensionToDownload(*download);
+    ASSERT(FileSystem::fileExists(networkDataTask->pendingDownloadLocation()));
+    download->didCreateDestination(networkDataTask->pendingDownloadLocation());
+    downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
+
+    RELEASE_ASSERT(!_sessionWrapper->downloadMap.contains(downloadTask.taskIdentifier));
+    _sessionWrapper->downloadMap.add(downloadTask.taskIdentifier, downloadID);
 }
 
 #if HAVE(NSURLSESSION_WEBSOCKET)
 - (WebSocketTask*)existingWebSocketTask:(NSURLSessionWebSocketTask *)task
 {
-    if (!_session)
+    if (!_sessionWrapper)
         return nullptr;
 
     if (!task)
         return nullptr;
 
-    return _session->webSocketDataTaskForIdentifier(task.taskIdentifier);
+    return _sessionWrapper->webSocketDataTaskMap.get(task.taskIdentifier);
 }
 
 
@@ -972,6 +996,12 @@ static NSDictionary *proxyDictionary(const URL& httpProxy, const URL& httpsProxy
     ALLOW_DEPRECATED_DECLARATIONS_END
 }
 
+void SessionWrapper::initialize(NSURLSessionConfiguration *configuration, NetworkSessionCocoa& networkSession, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
+{
+    delegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:networkSession wrapper:*this withCredentials:storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use]);
+    session = [NSURLSession sessionWithConfiguration:configuration delegate:delegate.get() delegateQueue:[NSOperationQueue mainQueue]];
+}
+
 NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, NetworkSessionCreationParameters&& parameters)
     : NetworkSession(networkProcess, parameters)
     , m_boundInterfaceIdentifier(parameters.boundInterfaceIdentifier)
@@ -1063,8 +1093,7 @@ NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, Network
         cookieStorage._overrideSessionCookieAcceptPolicy = YES;
 #endif
 
-    m_sessionWithCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:true]);
-    m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
+    m_sessionWithCredentialStorage.initialize(configuration, *this, WebCore::StoredCredentialsPolicy::Use);
     LOG(NetworkSession, "Created NetworkSession with cookieAcceptPolicy %lu", configuration.HTTPCookieStorage.cookieAcceptPolicy);
 
     configuration.URLCredentialStorage = nil;
@@ -1073,8 +1102,7 @@ NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, Network
     // configuration.HTTPCookieStorage = nil;
     // configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
 
-    m_statelessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
-    m_statelessSession = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
+    m_sessionWithoutCredentialStorage.initialize(configuration, *this, WebCore::StoredCredentialsPolicy::DoNotUse);
 
     m_deviceManagementRestrictionsEnabled = parameters.deviceManagementRestrictionsEnabled;
     m_allLoadsBlockedByDeviceManagementRestrictionsForTesting = parameters.allLoadsBlockedByDeviceManagementRestrictionsForTesting;
@@ -1097,10 +1125,10 @@ NetworkSessionCocoa::~NetworkSessionCocoa()
 {
 }
 
-void NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession()
+void NetworkSessionCocoa::initializeEphemeralStatelessSession()
 {
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
-    NSURLSessionConfiguration *existingConfiguration = m_statelessSession.get().configuration;
+    NSURLSessionConfiguration *existingConfiguration = m_sessionWithoutCredentialStorage.session.get().configuration;
 
     configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
     configuration.URLCredentialStorage = nil;
@@ -1115,44 +1143,48 @@ void NetworkSessionCocoa::initializeEphemeralStatelessCookielessSession()
     configuration._CTDataConnectionServiceType = existingConfiguration._CTDataConnectionServiceType;
 #endif
 
-    m_ephemeralStatelessCookielessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
-    m_ephemeralStatelessCookielessSession = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_ephemeralStatelessCookielessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
+    m_ephemeralStatelessSession.initialize(configuration, *this, WebCore::StoredCredentialsPolicy::EphemeralStateless);
 }
 
-NSURLSession* NetworkSessionCocoa::session(WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
+SessionWrapper& NetworkSessionCocoa::sessionWrapperForTask(const WebCore::ResourceRequest& request, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
 {
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    if (auto* storageSession = networkStorageSession()) {
+        auto firstParty = WebCore::RegistrableDomain(request.firstPartyForCookies());
+        if (storageSession->shouldBlockThirdPartyCookiesButKeepFirstPartyCookiesFor(firstParty))
+            return isolatedSession(storedCredentialsPolicy, firstParty);
+    } else
+        ASSERT_NOT_REACHED();
+#endif
+
     switch (storedCredentialsPolicy) {
     case WebCore::StoredCredentialsPolicy::Use:
-        return m_sessionWithCredentialStorage.get();
+        return m_sessionWithCredentialStorage;
     case WebCore::StoredCredentialsPolicy::DoNotUse:
-        return m_statelessSession.get();
-    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
-        if (!m_ephemeralStatelessCookielessSession)
-            initializeEphemeralStatelessCookielessSession();
-        return m_ephemeralStatelessCookielessSession.get();
+        return m_sessionWithoutCredentialStorage;
+    case WebCore::StoredCredentialsPolicy::EphemeralStateless:
+        if (!m_ephemeralStatelessSession.session)
+            initializeEphemeralStatelessSession();
+        return m_ephemeralStatelessSession;
     }
 }
 
-NSURLSession* NetworkSessionCocoa::isolatedSession(WebCore::StoredCredentialsPolicy storedCredentialsPolicy, const WebCore::RegistrableDomain firstPartyDomain)
+SessionWrapper& NetworkSessionCocoa::isolatedSession(WebCore::StoredCredentialsPolicy storedCredentialsPolicy, const WebCore::RegistrableDomain firstPartyDomain)
 {
-    auto entry = m_isolatedSessions.ensure(firstPartyDomain, [this] {
-        IsolatedSession newEntry { };
-        newEntry.sessionWithCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:true]);
-        newEntry.sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(newEntry.sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
-
-        newEntry.statelessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
-        newEntry.statelessSession = [NSURLSession sessionWithConfiguration:m_statelessSession.get().configuration delegate:static_cast<id>(newEntry.statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
-
+    auto& entry = m_isolatedSessions.ensure(firstPartyDomain, [this] {
+        auto newEntry = makeUnique<IsolatedSession>();
+        newEntry->sessionWithCredentialStorage.initialize(m_sessionWithCredentialStorage.session.get().configuration, *this, WebCore::StoredCredentialsPolicy::Use);
+        newEntry->sessionWithoutCredentialStorage.initialize(m_sessionWithoutCredentialStorage.session.get().configuration, *this, WebCore::StoredCredentialsPolicy::DoNotUse);
         return newEntry;
     }).iterator->value;
 
-    entry.lastUsed = WallTime::now();
+    entry->lastUsed = WallTime::now();
 
     if (m_isolatedSessions.size() > maxNumberOfIsolatedSessions) {
         WebCore::RegistrableDomain keyToRemove;
         auto oldestTimestamp = WallTime::now();
         for (auto& key : m_isolatedSessions.keys()) {
-            auto timestamp = m_isolatedSessions.get(key).lastUsed;
+            auto timestamp = m_isolatedSessions.get(key)->lastUsed;
             if (timestamp < oldestTimestamp) {
                 oldestTimestamp = timestamp;
                 keyToRemove = key;
@@ -1167,14 +1199,14 @@ NSURLSession* NetworkSessionCocoa::isolatedSession(WebCore::StoredCredentialsPol
     switch (storedCredentialsPolicy) {
     case WebCore::StoredCredentialsPolicy::Use:
         LOG(NetworkSession, "Using isolated NSURLSession with credential storage.");
-        return entry.sessionWithCredentialStorage.get();
+        return entry->sessionWithCredentialStorage;
     case WebCore::StoredCredentialsPolicy::DoNotUse:
         LOG(NetworkSession, "Using isolated NSURLSession without credential storage.");
-        return entry.statelessSession.get();
-    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
-        if (!m_ephemeralStatelessCookielessSession)
-            initializeEphemeralStatelessCookielessSession();
-        return m_ephemeralStatelessCookielessSession.get();
+        return entry->sessionWithoutCredentialStorage;
+    case WebCore::StoredCredentialsPolicy::EphemeralStateless:
+        if (!m_ephemeralStatelessSession.session)
+            initializeEphemeralStatelessSession();
+        return m_ephemeralStatelessSession;
     }
 }
 
@@ -1192,16 +1224,18 @@ void NetworkSessionCocoa::invalidateAndCancel()
 {
     NetworkSession::invalidateAndCancel();
 
-    [m_sessionWithCredentialStorage invalidateAndCancel];
-    [m_statelessSession invalidateAndCancel];
-    [m_ephemeralStatelessCookielessSession invalidateAndCancel];
-    [m_sessionWithCredentialStorageDelegate sessionInvalidated];
-    [m_statelessSessionDelegate sessionInvalidated];
-    [m_ephemeralStatelessCookielessSessionDelegate sessionInvalidated];
+    [m_sessionWithCredentialStorage.session invalidateAndCancel];
+    [m_sessionWithoutCredentialStorage.session invalidateAndCancel];
+    [m_ephemeralStatelessSession.session invalidateAndCancel];
+    [m_sessionWithCredentialStorage.delegate sessionInvalidated];
+    [m_sessionWithoutCredentialStorage.delegate sessionInvalidated];
+    [m_ephemeralStatelessSession.delegate sessionInvalidated];
 
     for (auto& session : m_isolatedSessions.values()) {
-        [session.sessionWithCredentialStorage invalidateAndCancel];
-        [session.sessionWithCredentialStorageDelegate sessionInvalidated];
+        [session->sessionWithCredentialStorage.session invalidateAndCancel];
+        [session->sessionWithCredentialStorage.delegate sessionInvalidated];
+        [session->sessionWithoutCredentialStorage.session invalidateAndCancel];
+        [session->sessionWithoutCredentialStorage.delegate sessionInvalidated];
     }
     m_isolatedSessions.clear();
 }
@@ -1220,68 +1254,6 @@ void NetworkSessionCocoa::clearCredentials()
 #endif
 }
 
-HashMap<NetworkDataTaskCocoa::TaskIdentifier, NetworkDataTaskCocoa*>& NetworkSessionCocoa::dataTaskMap(WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
-{
-    ASSERT(RunLoop::isMain());
-    switch (storedCredentialsPolicy) {
-    case WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless:
-        return m_dataTaskMapEphemeralStatelessCookieless;
-    case WebCore::StoredCredentialsPolicy::DoNotUse:
-        return m_dataTaskMapWithoutState;
-    case WebCore::StoredCredentialsPolicy::Use:
-        return m_dataTaskMapWithCredentials;
-    }
-    ASSERT_NOT_REACHED();
-    return m_dataTaskMapWithCredentials;
-}
-
-NetworkDataTaskCocoa* NetworkSessionCocoa::dataTaskForIdentifier(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
-{
-    ASSERT(RunLoop::isMain());
-    return dataTaskMap(storedCredentialsPolicy).get(taskIdentifier);
-}
-
-void NetworkSessionCocoa::registerDataTask(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa& dataTask, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
-{
-    auto& map = dataTaskMap(storedCredentialsPolicy);
-    RELEASE_ASSERT(!map.contains(taskIdentifier));
-    map.add(taskIdentifier, &dataTask);
-}
-
-void NetworkSessionCocoa::unregisterDataTask(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa& dataTask, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
-{
-    auto& map = dataTaskMap(storedCredentialsPolicy);
-    RELEASE_ASSERT(map.get(taskIdentifier) == &dataTask);
-    map.remove(taskIdentifier);
-}
-
-NSURLSessionDownloadTask* NetworkSessionCocoa::downloadTaskWithResumeData(NSData* resumeData)
-{
-    return [m_sessionWithCredentialStorage downloadTaskWithResumeData:resumeData];
-}
-
-void NetworkSessionCocoa::addDownloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, DownloadID downloadID)
-{
-#ifndef NDEBUG
-    ASSERT(!m_downloadMap.contains(taskIdentifier));
-    for (auto idInMap : m_downloadMap.values())
-        ASSERT(idInMap != downloadID);
-#endif
-    m_downloadMap.add(taskIdentifier, downloadID);
-}
-
-DownloadID NetworkSessionCocoa::downloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier)
-{
-    ASSERT(m_downloadMap.get(taskIdentifier).downloadID());
-    return m_downloadMap.get(taskIdentifier);
-}
-
-DownloadID NetworkSessionCocoa::takeDownloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier)
-{
-    auto downloadID = m_downloadMap.take(taskIdentifier);
-    return downloadID;
-}
-
 static bool certificatesMatch(SecTrustRef trust1, SecTrustRef trust2)
 {
     if (!trust1 || !trust2)
@@ -1322,18 +1294,17 @@ bool NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(const WebCore::A
     return certificatesMatch(trust.get(), challenge.nsURLAuthenticationChallenge().protectionSpace.serverTrust);
 }
 
-void NetworkSessionCocoa::continueDidReceiveChallenge(const WebCore::AuthenticationChallenge& challenge, NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa* networkDataTask, CompletionHandler<void(WebKit::AuthenticationChallengeDisposition, const WebCore::Credential&)>&& completionHandler)
+void NetworkSessionCocoa::continueDidReceiveChallenge(SessionWrapper& sessionWrapper, const WebCore::AuthenticationChallenge& challenge, NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, NetworkDataTaskCocoa* networkDataTask, CompletionHandler<void(WebKit::AuthenticationChallengeDisposition, const WebCore::Credential&)>&& completionHandler)
 {
     if (!networkDataTask) {
 #if HAVE(NSURLSESSION_WEBSOCKET)
-        if (auto* webSocketTask = webSocketDataTaskForIdentifier(taskIdentifier)) {
+        if (auto* webSocketTask = sessionWrapper.webSocketDataTaskMap.get(taskIdentifier)) {
             // FIXME: Handle challenges for web socket.
             completionHandler(AuthenticationChallengeDisposition::PerformDefaultHandling, { });
             return;
         }
 #endif
-
-        auto downloadID = this->downloadID(taskIdentifier);
+        auto downloadID = sessionWrapper.downloadMap.get(taskIdentifier);
         if (downloadID.downloadID()) {
             if (auto* download = networkProcess().downloadManager().download(downloadID)) {
                 WebCore::AuthenticationChallenge authenticationChallenge { challenge };
@@ -1395,26 +1366,22 @@ DMFWebsitePolicyMonitor *NetworkSessionCocoa::deviceManagementPolicyMonitor()
 std::unique_ptr<WebSocketTask> NetworkSessionCocoa::createWebSocketTask(NetworkSocketChannel& channel, const WebCore::ResourceRequest& request, const String& protocol)
 {
     // FIXME: Use protocol.
-    RetainPtr<NSURLSessionWebSocketTask> task = [m_sessionWithCredentialStorage.get() webSocketTaskWithRequest: request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
+    RetainPtr<NSURLSessionWebSocketTask> task = [m_sessionWithCredentialStorage.session webSocketTaskWithRequest:request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody)];
     return makeUnique<WebSocketTask>(channel, WTFMove(task));
 }
 
 void NetworkSessionCocoa::addWebSocketTask(WebSocketTask& task)
 {
-    ASSERT(!m_webSocketDataTaskMap.contains(task.identifier()));
-    m_webSocketDataTaskMap.add(task.identifier(), &task);
+    RELEASE_ASSERT(!m_sessionWithCredentialStorage.webSocketDataTaskMap.contains(task.identifier()));
+    m_sessionWithCredentialStorage.webSocketDataTaskMap.add(task.identifier(), &task);
 }
 
 void NetworkSessionCocoa::removeWebSocketTask(WebSocketTask& task)
 {
-    ASSERT(m_webSocketDataTaskMap.contains(task.identifier()));
-    m_webSocketDataTaskMap.remove(task.identifier());
+    RELEASE_ASSERT(m_sessionWithCredentialStorage.webSocketDataTaskMap.contains(task.identifier()));
+    m_sessionWithCredentialStorage.webSocketDataTaskMap.remove(task.identifier());
 }
 
-WebSocketTask* NetworkSessionCocoa::webSocketDataTaskForIdentifier(WebSocketTask::TaskIdentifier identifier)
-{
-    return m_webSocketDataTaskMap.get(identifier);
-}
+#endif // HAVE(NSURLSESSION_WEBSOCKET)
 
-#endif
 }
index e89efac..606dbca 100644 (file)
@@ -879,7 +879,7 @@ template<> struct EnumTraits<WebCore::StoredCredentialsPolicy> {
         WebCore::StoredCredentialsPolicy,
         WebCore::StoredCredentialsPolicy::DoNotUse,
         WebCore::StoredCredentialsPolicy::Use,
-        WebCore::StoredCredentialsPolicy::EphemeralStatelessCookieless
+        WebCore::StoredCredentialsPolicy::EphemeralStateless
     >;
 };
 
index ad0b731..348467d 100644 (file)
@@ -463,6 +463,17 @@ static Vector<WebKit::WebsiteDataRecord> toWebsiteDataRecords(NSArray *dataRecor
 #endif
 }
 
+- (void)_logUserInteraction:(NSURL *)domain completionHandler:(void (^)(void))completionHandler
+{
+#if ENABLE(RESOURCE_LOAD_STATISTICS)
+    _websiteDataStore->logUserInteraction(domain, [completionHandler = makeBlockPtr(completionHandler)] {
+        completionHandler();
+    });
+#else
+    completionHandler();
+#endif
+}
+
 - (void)_setPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(void))completionHandler
 {
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
index a26106c..9e3e612 100644 (file)
@@ -68,6 +68,7 @@ typedef NS_OPTIONS(NSUInteger, _WKWebsiteDataStoreFetchOptions) {
 - (bool)_hasRegisteredServiceWorker WK_API_AVAILABLE(macos(10.14), ios(12.0));
 
 - (void)_scheduleCookieBlockingUpdate:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0));
+- (void)_logUserInteraction:(NSURL *)domain completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_setPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0));
 - (void)_getIsPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0));
 - (void)_clearPrevalentDomain:(NSURL *)domain completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
index 9f10337..c5980bd 100644 (file)
@@ -1,3 +1,17 @@
+2019-11-07  Alex Christensen  <achristensen@webkit.org>
+
+        Re-enable NSURLSession isolation after r252116
+        https://bugs.webkit.org/show_bug.cgi?id=203934
+        <rdar://problem/56921584>
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ResourceLoadStatistics.mm:
+        (-[DataTaskIdentifierCollisionDelegate webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:]):
+        (-[DataTaskIdentifierCollisionDelegate waitForMessages:]):
+        (-[DataTaskIdentifierCollisionDelegate webView:didReceiveAuthenticationChallenge:completionHandler:]):
+        (TEST):
+
 2019-11-07  Paulo Matos  <pmatos@igalia.com>
 
         Add support for remotes file for EWS builders
index a721d24..ad25a26 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 
 #import "PlatformUtilities.h"
+#import "TCPServer.h"
 #import "TestNavigationDelegate.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKFoundation.h>
@@ -474,6 +475,105 @@ TEST(ResourceLoadStatistics, NetworkProcessRestart)
     TestWebKitAPI::Util::run(&doneFlag);
 }
 
+@interface DataTaskIdentifierCollisionDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
+- (NSArray<NSString *> *)waitForMessages:(size_t)count;
+@end
+
+@implementation DataTaskIdentifierCollisionDelegate {
+    RetainPtr<NSMutableArray<NSString *>> _messages;
+}
+
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
+{
+    [_messages addObject:message];
+    completionHandler();
+}
+
+- (NSArray<NSString *> *)waitForMessages:(size_t)messageCount
+{
+    _messages = adoptNS([NSMutableArray arrayWithCapacity:messageCount]);
+    while ([_messages count] < messageCount)
+        TestWebKitAPI::Util::spinRunLoop();
+    return _messages.autorelease();
+}
+
+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * credential))completionHandler
+{
+    completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+}
+
+@end
+
+TEST(ResourceLoadStatistics, DataTaskIdentifierCollision)
+{
+    using namespace TestWebKitAPI;
+
+    std::atomic<unsigned> serversConnected { 0 };
+    const char* header = "HTTP/1.1 200 OK\r\nContent-Length: 27\r\n\r\n";
+
+    TCPServer httpsServer(TCPServer::Protocol::HTTPSProxy, [&] (SSL* ssl) {
+        serversConnected++;
+        while (serversConnected < 2)
+            usleep(100000);
+        TCPServer::read(ssl);
+        TCPServer::write(ssl, header, strlen(header));
+        const char* body = "<script>alert('1')</script>";
+        TCPServer::write(ssl, body, strlen(body));
+    });
+
+    TCPServer httpServer([&] (int socket) {
+        serversConnected++;
+        while (serversConnected < 2)
+            usleep(100000);
+        TCPServer::read(socket);
+        TCPServer::write(socket, header, strlen(header));
+        const char* body = "<script>alert('2')</script>";
+        TCPServer::write(socket, body, strlen(body));
+    });
+
+    _WKWebsiteDataStoreConfiguration *storeConfiguration = [[_WKWebsiteDataStoreConfiguration new] autorelease];
+    storeConfiguration.httpsProxy = [NSURL URLWithString:[NSString stringWithFormat:@"https://127.0.0.1:%d/", httpsServer.port()]];
+    WKWebsiteDataStore *dataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:storeConfiguration] autorelease];
+    auto viewConfiguration = adoptNS([WKWebViewConfiguration new]);
+    [viewConfiguration setWebsiteDataStore:dataStore];
+
+    auto webView1 = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:viewConfiguration.get()]);
+    [webView1 synchronouslyLoadHTMLString:@"start network process and initialize data store"];
+    auto delegate = adoptNS([DataTaskIdentifierCollisionDelegate new]);
+    auto webView2 = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:viewConfiguration.get()]);
+    [webView1 setUIDelegate:delegate.get()];
+    [webView1 setNavigationDelegate:delegate.get()];
+    [webView2 setUIDelegate:delegate.get()];
+    [webView2 setNavigationDelegate:delegate.get()];
+    [dataStore _setResourceLoadStatisticsEnabled:YES];
+    [dataStore _setResourceLoadStatisticsDebugMode:YES];
+
+    __block bool isolatedSessionDomain = false;
+    __block NSURL *prevalentExample = [NSURL URLWithString:@"https://prevalent-example.com/"];
+    [dataStore _logUserInteraction:prevalentExample completionHandler:^{
+        [dataStore _setPrevalentDomain:prevalentExample completionHandler: ^(void) {
+            [dataStore _scheduleCookieBlockingUpdate:^{
+                isolatedSessionDomain = true;
+            }];
+        }];
+    }];
+    TestWebKitAPI::Util::run(&isolatedSessionDomain);
+
+    [webView1 loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", httpServer.port()]]]];
+    [webView2 loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://prevalent-example.com/"]]];
+
+    NSArray<NSString *> *messages = [delegate waitForMessages:2];
+    auto contains = [] (NSArray<NSString *> *array, NSString *expected) {
+        for (NSString *s in array) {
+            if ([s isEqualToString:expected])
+                return true;
+        }
+        return false;
+    };
+    EXPECT_TRUE(contains(messages, @"1"));
+    EXPECT_TRUE(contains(messages, @"2"));
+}
+
 TEST(ResourceLoadStatistics, NoMessagesWhenNotTesting)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);