cedfc398df0c0509b7f5f95ed49d81f5224ff230
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cocoa / NetworkSessionCocoa.mm
1 /*
2  * Copyright (C) 2015 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 #import "config.h"
27 #import "NetworkSession.h"
28
29 #if USE(NETWORK_SESSION)
30
31 #import "CustomProtocolManager.h"
32 #import "DataReference.h"
33 #import "Download.h"
34 #import "Logging.h"
35 #import "NetworkCache.h"
36 #import "NetworkLoad.h"
37 #import "NetworkProcess.h"
38 #import "SessionTracker.h"
39 #import <Foundation/NSURLSession.h>
40 #import <WebCore/CFNetworkSPI.h>
41 #import <WebCore/Credential.h>
42 #import <WebCore/FrameLoaderTypes.h>
43 #import <WebCore/NetworkLoadTiming.h>
44 #import <WebCore/NetworkStorageSession.h>
45 #import <WebCore/NotImplemented.h>
46 #import <WebCore/ResourceError.h>
47 #import <WebCore/ResourceRequest.h>
48 #import <WebCore/ResourceResponse.h>
49 #import <WebCore/SharedBuffer.h>
50 #import <WebCore/URL.h>
51 #import <WebCore/WebCoreURLResponse.h>
52 #import <wtf/MainThread.h>
53 #import <wtf/NeverDestroyed.h>
54
55 using namespace WebKit;
56
57 static NSURLSessionResponseDisposition toNSURLSessionResponseDisposition(WebCore::PolicyAction disposition)
58 {
59     switch (disposition) {
60     case WebCore::PolicyAction::PolicyIgnore:
61         return NSURLSessionResponseCancel;
62     case WebCore::PolicyAction::PolicyUse:
63         return NSURLSessionResponseAllow;
64     case WebCore::PolicyAction::PolicyDownload:
65         return NSURLSessionResponseBecomeDownload;
66     }
67 }
68
69 static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDisposition(WebKit::AuthenticationChallengeDisposition disposition)
70 {
71     switch (disposition) {
72     case WebKit::AuthenticationChallengeDisposition::UseCredential:
73         return NSURLSessionAuthChallengeUseCredential;
74     case WebKit::AuthenticationChallengeDisposition::PerformDefaultHandling:
75         return NSURLSessionAuthChallengePerformDefaultHandling;
76     case WebKit::AuthenticationChallengeDisposition::Cancel:
77         return NSURLSessionAuthChallengeCancelAuthenticationChallenge;
78     case WebKit::AuthenticationChallengeDisposition::RejectProtectionSpace:
79         return NSURLSessionAuthChallengeRejectProtectionSpace;
80     }
81 }
82
83 @interface WKNetworkSessionDelegate : NSObject <NSURLSessionDataDelegate> {
84     RefPtr<WebKit::NetworkSession> _session;
85     bool _withCredentials;
86 }
87
88 - (id)initWithNetworkSession:(WebKit::NetworkSession&)session withCredentials:(bool)withCredentials;
89
90 @end
91
92 @implementation WKNetworkSessionDelegate
93
94 - (id)initWithNetworkSession:(WebKit::NetworkSession&)session withCredentials:(bool)withCredentials
95 {
96     self = [super init];
97     if (!self)
98         return nil;
99
100     _session = &session;
101     _withCredentials = withCredentials;
102
103     return self;
104 }
105
106 - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
107 {
108     _session = nullptr;
109 }
110
111 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
112 {
113     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
114     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials))
115         networkDataTask->didSendData(totalBytesSent, totalBytesExpectedToSend);
116 }
117
118 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler
119 {
120     auto taskIdentifier = task.taskIdentifier;
121     LOG(NetworkSession, "%llu willPerformHTTPRedirection from %s to %s", taskIdentifier, response.URL.absoluteString.UTF8String, request.URL.absoluteString.UTF8String);
122     
123     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
124     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials)) {
125         auto completionHandlerCopy = Block_copy(completionHandler);
126         networkDataTask->willPerformHTTPRedirection(response, request, [completionHandlerCopy, taskIdentifier](auto& request) {
127             LOG(NetworkSession, "%llu willPerformHTTPRedirection completionHandler (%s)", taskIdentifier, request.url().string().utf8().data());
128             completionHandlerCopy(request.nsURLRequest(WebCore::UpdateHTTPBody));
129             Block_release(completionHandlerCopy);
130         });
131     } else {
132         LOG(NetworkSession, "%llu willPerformHTTPRedirection completionHandler (nil)", taskIdentifier);
133         completionHandler(nil);
134     }
135 }
136
137 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask*)task _schemeUpgraded:(NSURLRequest*)request completionHandler:(void (^)(NSURLRequest*))completionHandler
138 {
139     auto taskIdentifier = task.taskIdentifier;
140     LOG(NetworkSession, "%llu _schemeUpgraded %s", taskIdentifier, request.URL.absoluteString.UTF8String);
141     
142     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
143     if (auto* networkDataTask = _session->dataTaskForIdentifier(taskIdentifier, storedCredentials)) {
144         auto completionHandlerCopy = Block_copy(completionHandler);
145         networkDataTask->willPerformHTTPRedirection(WebCore::synthesizeRedirectResponseIfNecessary([task currentRequest], request, nil), request, [completionHandlerCopy, taskIdentifier](auto& request) {
146             LOG(NetworkSession, "%llu _schemeUpgraded completionHandler (%s)", taskIdentifier, request.url().string().utf8().data());
147             completionHandlerCopy(request.nsURLRequest(WebCore::UpdateHTTPBody));
148             Block_release(completionHandlerCopy);
149         });
150     } else {
151         LOG(NetworkSession, "%llu _schemeUpgraded completionHandler (nil)", taskIdentifier);
152         completionHandler(nil);
153     }
154 }
155
156 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler
157 {
158     // FIXME: remove if <rdar://problem/20001985> is ever resolved.
159     if ([proposedResponse.response respondsToSelector:@selector(allHeaderFields)]
160         && [[(id)proposedResponse.response allHeaderFields] objectForKey:@"Content-Range"])
161         completionHandler(nil);
162     else
163         completionHandler(proposedResponse);
164 }
165
166 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
167 {
168     auto taskIdentifier = task.taskIdentifier;
169     LOG(NetworkSession, "%llu didReceiveChallenge", taskIdentifier);
170     
171     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
172     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials)) {
173         WebCore::AuthenticationChallenge authenticationChallenge(challenge);
174         auto completionHandlerCopy = Block_copy(completionHandler);
175         auto sessionID = _session->sessionID();
176         auto challengeCompletionHandler = [completionHandlerCopy, sessionID, authenticationChallenge, taskIdentifier](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential)
177         {
178             LOG(NetworkSession, "%llu didReceiveChallenge completionHandler", taskIdentifier);
179 #if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
180             UNUSED_PARAM(sessionID);
181             UNUSED_PARAM(authenticationChallenge);
182 #else
183             if (credential.persistence() == WebCore::CredentialPersistenceForSession && authenticationChallenge.protectionSpace().isPasswordBased()) {
184
185                 WebCore::Credential nonPersistentCredential(credential.user(), credential.password(), WebCore::CredentialPersistenceNone);
186                 WebCore::URL urlToStore;
187                 if (authenticationChallenge.failureResponse().httpStatusCode() == 401)
188                     urlToStore = authenticationChallenge.failureResponse().url();
189                 if (auto storageSession = WebCore::NetworkStorageSession::storageSession(sessionID))
190                     storageSession->credentialStorage().set(nonPersistentCredential, authenticationChallenge.protectionSpace(), urlToStore);
191                 else
192                     ASSERT_NOT_REACHED();
193
194                 completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), nonPersistentCredential.nsCredential());
195             } else
196 #endif
197                 completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
198             Block_release(completionHandlerCopy);
199         };
200         networkDataTask->didReceiveChallenge(challenge, WTFMove(challengeCompletionHandler));
201     } else {
202         LOG(NetworkSession, "%llu didReceiveChallenge completionHandler (cancel)", taskIdentifier);
203         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
204     }
205 }
206
207 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
208 {
209     LOG(NetworkSession, "%llu didCompleteWithError", task.taskIdentifier);
210     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
211     if (auto* networkDataTask = _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentials))
212         networkDataTask->didCompleteWithError(error);
213     else if (error) {
214         auto downloadID = _session->takeDownloadID(task.taskIdentifier);
215         if (downloadID.downloadID()) {
216             if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID)) {
217                 NSData *resumeData = nil;
218                 if (id userInfo = error.userInfo) {
219                     if ([userInfo isKindOfClass:[NSDictionary class]])
220                         resumeData = userInfo[@"NSURLSessionDownloadTaskResumeData"];
221                 }
222                 
223                 if (resumeData && [resumeData isKindOfClass:[NSData class]])
224                     download->didFail(error, { static_cast<const uint8_t*>(resumeData.bytes), resumeData.length });
225                 else
226                     download->didFail(error, { });
227             }
228         }
229     }
230 }
231
232 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
233 {
234     auto taskIdentifier = dataTask.taskIdentifier;
235     LOG(NetworkSession, "%llu didReceiveResponse", taskIdentifier);
236     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
237     if (auto* networkDataTask = _session->dataTaskForIdentifier(taskIdentifier, storedCredentials)) {
238         ASSERT(isMainThread());
239         
240         // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
241         int statusCode = [response respondsToSelector:@selector(statusCode)] ? [(id)response statusCode] : 0;
242         if (statusCode != 304) {
243             bool isMainResourceLoad = networkDataTask->firstRequest().requester() == WebCore::ResourceRequest::Requester::Main;
244             WebCore::adjustMIMETypeIfNecessary(response._CFURLResponse, isMainResourceLoad);
245         }
246
247         WebCore::ResourceResponse resourceResponse(response);
248         // Lazy initialization is not helpful in the WebKit2 case because we always end up initializing
249         // all the fields when sending the response to the WebContent process over IPC.
250         resourceResponse.disableLazyInitialization();
251
252         copyTimingData([dataTask _timingData], resourceResponse.networkLoadTiming());
253         auto completionHandlerCopy = Block_copy(completionHandler);
254         networkDataTask->didReceiveResponse(WTFMove(resourceResponse), [completionHandlerCopy, taskIdentifier](WebCore::PolicyAction policyAction) {
255             LOG(NetworkSession, "%llu didReceiveResponse completionHandler (cancel)", taskIdentifier);
256             completionHandlerCopy(toNSURLSessionResponseDisposition(policyAction));
257             Block_release(completionHandlerCopy);
258         });
259     } else {
260         LOG(NetworkSession, "%llu didReceiveResponse completionHandler (cancel)", taskIdentifier);
261         completionHandler(NSURLSessionResponseCancel);
262     }
263 }
264
265 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
266 {
267     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
268     if (auto* networkDataTask = _session->dataTaskForIdentifier(dataTask.taskIdentifier, storedCredentials))
269         networkDataTask->didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
270 }
271
272 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
273 {
274     auto downloadID = _session->takeDownloadID([downloadTask taskIdentifier]);
275     if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID))
276         download->didFinish();
277 }
278
279 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
280 {
281     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
282     ASSERT_WITH_MESSAGE_UNUSED(storedCredentials, !_session->dataTaskForIdentifier([downloadTask taskIdentifier], storedCredentials), "The NetworkDataTask should be destroyed immediately after didBecomeDownloadTask returns");
283
284     auto downloadID = _session->downloadID([downloadTask taskIdentifier]);
285     if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID))
286         download->didReceiveData(bytesWritten);
287 }
288
289 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
290 {
291     notImplemented();
292 }
293
294 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
295 {
296     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
297     if (auto* networkDataTask = _session->dataTaskForIdentifier([dataTask taskIdentifier], storedCredentials)) {
298         Ref<NetworkDataTask> protectedNetworkDataTask(*networkDataTask);
299         auto downloadID = networkDataTask->pendingDownloadID();
300         auto& downloadManager = WebKit::NetworkProcess::singleton().downloadManager();
301         auto download = std::make_unique<WebKit::Download>(downloadManager, downloadID, downloadTask, _session->sessionID(), networkDataTask->suggestedFilename());
302         networkDataTask->transferSandboxExtensionToDownload(*download);
303         ASSERT(WebCore::fileExists(networkDataTask->pendingDownloadLocation()));
304         download->didCreateDestination(networkDataTask->pendingDownloadLocation());
305         downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
306         networkDataTask->didBecomeDownload();
307
308         _session->addDownloadID([downloadTask taskIdentifier], downloadID);
309     }
310 }
311
312 @end
313
314 namespace WebKit {
315     
316 static NSURLSessionConfiguration *configurationForType(NetworkSession::Type type)
317 {
318     switch (type) {
319     case NetworkSession::Type::Normal:
320         return [NSURLSessionConfiguration defaultSessionConfiguration];
321     case NetworkSession::Type::Ephemeral:
322         return [NSURLSessionConfiguration ephemeralSessionConfiguration];
323     }
324 }
325
326 static RefPtr<CustomProtocolManager>& globalCustomProtocolManager()
327 {
328     static NeverDestroyed<RefPtr<CustomProtocolManager>> customProtocolManager;
329     return customProtocolManager.get();
330 }
331
332 static RetainPtr<CFDataRef>& globalSourceApplicationAuditTokenData()
333 {
334     static NeverDestroyed<RetainPtr<CFDataRef>> sourceApplicationAuditTokenData;
335     return sourceApplicationAuditTokenData.get();
336 }
337
338 static String& globalSourceApplicationBundleIdentifier()
339 {
340     static NeverDestroyed<String> sourceApplicationBundleIdentifier;
341     return sourceApplicationBundleIdentifier.get();
342 }
343
344 static String& globalSourceApplicationSecondaryIdentifier()
345 {
346     static NeverDestroyed<String> sourceApplicationSecondaryIdentifier;
347     return sourceApplicationSecondaryIdentifier.get();
348 }
349
350 #if PLATFORM(IOS)
351 static String& globalCTDataConnectionServiceType()
352 {
353     static NeverDestroyed<String> ctDataConnectionServiceType;
354     return ctDataConnectionServiceType.get();
355 }
356 #endif
357
358 #if !ASSERT_DISABLED
359 static bool sessionsCreated = false;
360 #endif
361
362 void NetworkSession::setCustomProtocolManager(CustomProtocolManager* customProtocolManager)
363 {
364     ASSERT(!sessionsCreated);
365     globalCustomProtocolManager() = customProtocolManager;
366 }
367     
368 void NetworkSession::setSourceApplicationAuditTokenData(RetainPtr<CFDataRef>&& data)
369 {
370     ASSERT(!sessionsCreated);
371     globalSourceApplicationAuditTokenData() = data;
372 }
373
374 void NetworkSession::setSourceApplicationBundleIdentifier(const String& identifier)
375 {
376     ASSERT(!sessionsCreated);
377     globalSourceApplicationBundleIdentifier() = identifier;
378 }
379
380 void NetworkSession::setSourceApplicationSecondaryIdentifier(const String& identifier)
381 {
382     ASSERT(!sessionsCreated);
383     globalSourceApplicationSecondaryIdentifier() = identifier;
384 }
385
386 #if PLATFORM(IOS)
387 void NetworkSession::setCTDataConnectionServiceType(const String& type)
388 {
389     ASSERT(!sessionsCreated);
390     globalCTDataConnectionServiceType() = type;
391 }
392 #endif
393
394 Ref<NetworkSession> NetworkSession::create(Type type, WebCore::SessionID sessionID, CustomProtocolManager* customProtocolManager)
395 {
396     return adoptRef(*new NetworkSession(type, sessionID, customProtocolManager));
397 }
398
399 NetworkSession& NetworkSession::defaultSession()
400 {
401     ASSERT(isMainThread());
402     static NetworkSession* session = &NetworkSession::create(NetworkSession::Type::Normal, WebCore::SessionID::defaultSessionID(), globalCustomProtocolManager().get()).leakRef();
403     return *session;
404 }
405
406 NetworkSession::NetworkSession(Type type, WebCore::SessionID sessionID, CustomProtocolManager* customProtocolManager)
407     : m_sessionID(sessionID)
408 {
409     relaxAdoptionRequirement();
410
411 #if !ASSERT_DISABLED
412     sessionsCreated = true;
413 #endif
414
415     NSURLSessionConfiguration *configuration = configurationForType(type);
416
417     if (NetworkCache::singleton().isEnabled())
418         configuration.URLCache = nil;
419     
420     if (auto& data = globalSourceApplicationAuditTokenData())
421         configuration._sourceApplicationAuditTokenData = (NSData *)data.get();
422
423     auto& sourceApplicationBundleIdentifier = globalSourceApplicationBundleIdentifier();
424     if (!sourceApplicationBundleIdentifier.isEmpty())
425         configuration._sourceApplicationBundleIdentifier = sourceApplicationBundleIdentifier;
426
427     auto& sourceApplicationSecondaryIdentifier = globalSourceApplicationSecondaryIdentifier();
428     if (!sourceApplicationSecondaryIdentifier.isEmpty())
429         configuration._sourceApplicationSecondaryIdentifier = sourceApplicationSecondaryIdentifier;
430
431 #if PLATFORM(IOS)
432     auto& ctDataConnectionServiceType = globalCTDataConnectionServiceType();
433     if (!ctDataConnectionServiceType.isEmpty())
434         configuration._CTDataConnectionServiceType = ctDataConnectionServiceType;
435 #endif
436
437     if (customProtocolManager)
438         customProtocolManager->registerProtocolClass(configuration);
439     
440 #if HAVE(TIMINGDATAOPTIONS)
441     configuration._timingDataOptions = _TimingDataOptionsEnableW3CNavigationTiming;
442 #else
443     setCollectsTimingData();
444 #endif
445
446     if (sessionID == WebCore::SessionID::defaultSessionID()) {
447         ASSERT(type == Type::Normal);
448         if (CFHTTPCookieStorageRef storage = WebCore::NetworkStorageSession::defaultStorageSession().cookieStorage().get())
449             configuration.HTTPCookieStorage = [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:storage] autorelease];
450     } else {
451         ASSERT(type == Type::Ephemeral);
452         auto* storageSession = WebCore::NetworkStorageSession::storageSession(sessionID);
453         RELEASE_ASSERT(storageSession);
454         if (CFHTTPCookieStorageRef storage = storageSession->cookieStorage().get())
455             configuration.HTTPCookieStorage = [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:storage] autorelease];
456     }
457
458     m_sessionWithCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:true]);
459     m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
460
461     configuration.URLCredentialStorage = nil;
462     m_sessionWithoutCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
463     m_sessionWithoutCredentialStorage = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_sessionWithoutCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
464     LOG(NetworkSession, "Created NetworkSession with cookieAcceptPolicy %lu", configuration.HTTPCookieStorage.cookieAcceptPolicy);
465 }
466
467 NetworkSession::~NetworkSession()
468 {
469 }
470
471 void NetworkSession::invalidateAndCancel()
472 {
473     [m_sessionWithCredentialStorage invalidateAndCancel];
474     [m_sessionWithoutCredentialStorage invalidateAndCancel];
475 }
476
477
478 WebCore::NetworkStorageSession& NetworkSession::networkStorageSession()
479 {
480     auto* storageSession = WebCore::NetworkStorageSession::storageSession(m_sessionID);
481     RELEASE_ASSERT(storageSession);
482     return *storageSession;
483 }
484
485 void NetworkSession::clearCredentials()
486 {
487 #if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
488     ASSERT(m_dataTaskMapWithCredentials.isEmpty());
489     ASSERT(m_dataTaskMapWithoutCredentials.isEmpty());
490     ASSERT(m_downloadMap.isEmpty());
491     // FIXME: Use resetWithCompletionHandler instead.
492     m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
493     m_sessionWithoutCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithoutCredentialStorage.get().configuration delegate:static_cast<id>(m_sessionWithoutCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
494 #endif
495 }
496
497 NetworkDataTask* NetworkSession::dataTaskForIdentifier(NetworkDataTask::TaskIdentifier taskIdentifier, WebCore::StoredCredentials storedCredentials)
498 {
499     ASSERT(isMainThread());
500     if (storedCredentials == WebCore::StoredCredentials::AllowStoredCredentials)
501         return m_dataTaskMapWithCredentials.get(taskIdentifier);
502     return m_dataTaskMapWithoutCredentials.get(taskIdentifier);
503 }
504
505 void NetworkSession::addDownloadID(NetworkDataTask::TaskIdentifier taskIdentifier, DownloadID downloadID)
506 {
507 #ifndef NDEBUG
508     ASSERT(!m_downloadMap.contains(taskIdentifier));
509     for (auto idInMap : m_downloadMap.values())
510         ASSERT(idInMap != downloadID);
511 #endif
512     m_downloadMap.add(taskIdentifier, downloadID);
513 }
514
515 DownloadID NetworkSession::downloadID(NetworkDataTask::TaskIdentifier taskIdentifier)
516 {
517     ASSERT(m_downloadMap.get(taskIdentifier).downloadID());
518     return m_downloadMap.get(taskIdentifier);
519 }
520
521 DownloadID NetworkSession::takeDownloadID(NetworkDataTask::TaskIdentifier taskIdentifier)
522 {
523     auto downloadID = m_downloadMap.take(taskIdentifier);
524     return downloadID;
525 }
526
527 }
528
529 #endif