Replace SessionTracker with HashMap member of NetworkProcess
[WebKit-https.git] / Source / WebKit / NetworkProcess / cocoa / NetworkSessionCocoa.mm
1 /*
2  * Copyright (C) 2015-2018 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 "NetworkSessionCocoa.h"
28
29 #import "AuthenticationChallengeDisposition.h"
30 #import "AuthenticationManager.h"
31 #import "DataReference.h"
32 #import "Download.h"
33 #import "LegacyCustomProtocolManager.h"
34 #import "Logging.h"
35 #import "NetworkLoad.h"
36 #import "NetworkProcess.h"
37 #import "NetworkSessionCreationParameters.h"
38 #import <Foundation/NSURLSession.h>
39 #import <WebCore/Credential.h>
40 #import <WebCore/FormDataStreamMac.h>
41 #import <WebCore/FrameLoaderTypes.h>
42 #import <WebCore/NetworkStorageSession.h>
43 #import <WebCore/NotImplemented.h>
44 #import <WebCore/ResourceError.h>
45 #import <WebCore/ResourceRequest.h>
46 #import <WebCore/ResourceResponse.h>
47 #import <WebCore/SharedBuffer.h>
48 #import <WebCore/WebCoreURLResponse.h>
49 #import <pal/spi/cf/CFNetworkSPI.h>
50 #import <wtf/MainThread.h>
51 #import <wtf/NeverDestroyed.h>
52 #import <wtf/ProcessPrivilege.h>
53 #import <wtf/URL.h>
54 #import <wtf/text/WTFString.h>
55
56 using namespace WebKit;
57
58 CFStringRef const WebKit2HTTPProxyDefaultsKey = static_cast<CFStringRef>(@"WebKit2HTTPProxy");
59 CFStringRef const WebKit2HTTPSProxyDefaultsKey = static_cast<CFStringRef>(@"WebKit2HTTPSProxy");
60
61 static NSURLSessionResponseDisposition toNSURLSessionResponseDisposition(WebCore::PolicyAction disposition)
62 {
63     switch (disposition) {
64     case WebCore::PolicyAction::Ignore:
65         return NSURLSessionResponseCancel;
66     case WebCore::PolicyAction::Use:
67         return NSURLSessionResponseAllow;
68     case WebCore::PolicyAction::Download:
69         return NSURLSessionResponseBecomeDownload;
70     }
71 }
72
73 static NSURLSessionAuthChallengeDisposition toNSURLSessionAuthChallengeDisposition(WebKit::AuthenticationChallengeDisposition disposition)
74 {
75     switch (disposition) {
76     case WebKit::AuthenticationChallengeDisposition::UseCredential:
77         return NSURLSessionAuthChallengeUseCredential;
78     case WebKit::AuthenticationChallengeDisposition::PerformDefaultHandling:
79         return NSURLSessionAuthChallengePerformDefaultHandling;
80     case WebKit::AuthenticationChallengeDisposition::Cancel:
81         return NSURLSessionAuthChallengeCancelAuthenticationChallenge;
82     case WebKit::AuthenticationChallengeDisposition::RejectProtectionSpaceAndContinue:
83         return NSURLSessionAuthChallengeRejectProtectionSpace;
84     }
85 }
86
87 static WebCore::NetworkLoadPriority toNetworkLoadPriority(float priority)
88 {
89     if (priority <= NSURLSessionTaskPriorityLow)
90         return WebCore::NetworkLoadPriority::Low;
91     if (priority >= NSURLSessionTaskPriorityHigh)
92         return WebCore::NetworkLoadPriority::High;
93     return WebCore::NetworkLoadPriority::Medium;
94 }
95
96 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
97 static String stringForSSLProtocol(SSLProtocol protocol)
98 {
99     switch (protocol) {
100     case kDTLSProtocol1:
101         return "DTLS 1.0"_s;
102     case kSSLProtocol2:
103         return "SSL 2.0"_s;
104     case kSSLProtocol3:
105         return "SSL 3.0"_s;
106     case kSSLProtocol3Only:
107         return "SSL 3.0 (Only)"_s;
108     case kTLSProtocol1:
109         return "TLS 1.0"_s;
110     case kTLSProtocol1Only:
111         return "TLS 1.0 (Only)"_s;
112     case kTLSProtocol11:
113         return "TLS 1.1"_s;
114     case kTLSProtocol12:
115         return "TLS 1.2"_s;
116     case kTLSProtocol13:
117         return "TLS 1.3"_s;
118     case kSSLProtocolAll:
119         return "All";
120     case kSSLProtocolUnknown:
121         return "Unknown";
122     case kTLSProtocolMaxSupported:
123     default:
124         ASSERT_NOT_REACHED();
125         return emptyString();
126     }
127 }
128
129 static String stringForSSLCipher(SSLCipherSuite cipher)
130 {
131 #define STRINGIFY_CIPHER(cipher) \
132     case cipher: \
133         return "" #cipher ""_s
134
135     switch (cipher) {
136     STRINGIFY_CIPHER(SSL_RSA_EXPORT_WITH_RC4_40_MD5);
137     STRINGIFY_CIPHER(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
138     STRINGIFY_CIPHER(SSL_RSA_WITH_IDEA_CBC_SHA);
139     STRINGIFY_CIPHER(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA);
140     STRINGIFY_CIPHER(SSL_RSA_WITH_DES_CBC_SHA);
141     STRINGIFY_CIPHER(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
142     STRINGIFY_CIPHER(SSL_DH_DSS_WITH_DES_CBC_SHA);
143     STRINGIFY_CIPHER(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
144     STRINGIFY_CIPHER(SSL_DH_RSA_WITH_DES_CBC_SHA);
145     STRINGIFY_CIPHER(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
146     STRINGIFY_CIPHER(SSL_DHE_DSS_WITH_DES_CBC_SHA);
147     STRINGIFY_CIPHER(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
148     STRINGIFY_CIPHER(SSL_DHE_RSA_WITH_DES_CBC_SHA);
149     STRINGIFY_CIPHER(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5);
150     STRINGIFY_CIPHER(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
151     STRINGIFY_CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA);
152     STRINGIFY_CIPHER(SSL_FORTEZZA_DMS_WITH_NULL_SHA);
153     STRINGIFY_CIPHER(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA);
154     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA);
155     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_128_CBC_SHA);
156     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_128_CBC_SHA);
157     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
158     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
159     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA);
160     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA);
161     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_256_CBC_SHA);
162     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_256_CBC_SHA);
163     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
164     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
165     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA);
166     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_NULL_SHA);
167     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
168     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
169     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
170     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA);
171     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_NULL_SHA);
172     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA);
173     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA);
174     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
175     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
176     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_NULL_SHA);
177     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_RC4_128_SHA);
178     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA);
179     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
180     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
181     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_NULL_SHA);
182     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_RC4_128_SHA);
183     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
184     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
185     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
186     STRINGIFY_CIPHER(TLS_ECDH_anon_WITH_NULL_SHA);
187     STRINGIFY_CIPHER(TLS_ECDH_anon_WITH_RC4_128_SHA);
188     STRINGIFY_CIPHER(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA);
189     STRINGIFY_CIPHER(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
190     STRINGIFY_CIPHER(TLS_ECDH_anon_WITH_AES_256_CBC_SHA);
191     // STRINGIFY_CIPHER(SSL_NULL_WITH_NULL_NULL);
192     STRINGIFY_CIPHER(TLS_NULL_WITH_NULL_NULL);
193     // STRINGIFY_CIPHER(SSL_RSA_WITH_NULL_MD5);
194     STRINGIFY_CIPHER(TLS_RSA_WITH_NULL_MD5);
195     // STRINGIFY_CIPHER(SSL_RSA_WITH_NULL_SHA);
196     STRINGIFY_CIPHER(TLS_RSA_WITH_NULL_SHA);
197     // STRINGIFY_CIPHER(SSL_RSA_WITH_RC4_128_MD5);
198     STRINGIFY_CIPHER(TLS_RSA_WITH_RC4_128_MD5);
199     // STRINGIFY_CIPHER(SSL_RSA_WITH_RC4_128_SHA);
200     STRINGIFY_CIPHER(TLS_RSA_WITH_RC4_128_SHA);
201     // STRINGIFY_CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA);
202     STRINGIFY_CIPHER(TLS_RSA_WITH_3DES_EDE_CBC_SHA);
203     STRINGIFY_CIPHER(TLS_RSA_WITH_NULL_SHA256);
204     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA256);
205     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA256);
206     // STRINGIFY_CIPHER(SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA);
207     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
208     // STRINGIFY_CIPHER(SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA);
209     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
210     // STRINGIFY_CIPHER(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
211     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
212     // STRINGIFY_CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
213     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
214     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_128_CBC_SHA256);
215     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_128_CBC_SHA256);
216     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256);
217     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256);
218     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_256_CBC_SHA256);
219     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_256_CBC_SHA256);
220     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
221     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256);
222     // STRINGIFY_CIPHER(SSL_DH_anon_WITH_RC4_128_MD5);
223     STRINGIFY_CIPHER(TLS_DH_anon_WITH_RC4_128_MD5);
224     // STRINGIFY_CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA);
225     STRINGIFY_CIPHER(TLS_DH_anon_WITH_3DES_EDE_CBC_SHA);
226     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA256);
227     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA256);
228     STRINGIFY_CIPHER(TLS_PSK_WITH_RC4_128_SHA);
229     STRINGIFY_CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA);
230     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA);
231     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA);
232     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_RC4_128_SHA);
233     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA);
234     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_128_CBC_SHA);
235     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_256_CBC_SHA);
236     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_RC4_128_SHA);
237     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA);
238     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_128_CBC_SHA);
239     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_256_CBC_SHA);
240     STRINGIFY_CIPHER(TLS_PSK_WITH_NULL_SHA);
241     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_NULL_SHA);
242     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_NULL_SHA);
243     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_128_GCM_SHA256);
244     STRINGIFY_CIPHER(TLS_RSA_WITH_AES_256_GCM_SHA384);
245     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256);
246     STRINGIFY_CIPHER(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384);
247     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_128_GCM_SHA256);
248     STRINGIFY_CIPHER(TLS_DH_RSA_WITH_AES_256_GCM_SHA384);
249     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256);
250     STRINGIFY_CIPHER(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384);
251     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_128_GCM_SHA256);
252     STRINGIFY_CIPHER(TLS_DH_DSS_WITH_AES_256_GCM_SHA384);
253     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_128_GCM_SHA256);
254     STRINGIFY_CIPHER(TLS_DH_anon_WITH_AES_256_GCM_SHA384);
255     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_128_GCM_SHA256);
256     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_256_GCM_SHA384);
257     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256);
258     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384);
259     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256);
260     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384);
261     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256);
262     STRINGIFY_CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384);
263     STRINGIFY_CIPHER(TLS_PSK_WITH_NULL_SHA256);
264     STRINGIFY_CIPHER(TLS_PSK_WITH_NULL_SHA384);
265     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256);
266     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384);
267     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_NULL_SHA256);
268     STRINGIFY_CIPHER(TLS_DHE_PSK_WITH_NULL_SHA384);
269     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256);
270     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384);
271     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_NULL_SHA256);
272     STRINGIFY_CIPHER(TLS_RSA_PSK_WITH_NULL_SHA384);
273     STRINGIFY_CIPHER(TLS_AES_128_GCM_SHA256);
274     STRINGIFY_CIPHER(TLS_AES_256_GCM_SHA384);
275     STRINGIFY_CIPHER(TLS_CHACHA20_POLY1305_SHA256);
276     STRINGIFY_CIPHER(TLS_AES_128_CCM_SHA256);
277     STRINGIFY_CIPHER(TLS_AES_128_CCM_8_SHA256);
278     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
279     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384);
280     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256);
281     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384);
282     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256);
283     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
284     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256);
285     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384);
286     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
287     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
288     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256);
289     STRINGIFY_CIPHER(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384);
290     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
291     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
292     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256);
293     STRINGIFY_CIPHER(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384);
294     STRINGIFY_CIPHER(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
295     STRINGIFY_CIPHER(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
296     STRINGIFY_CIPHER(TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
297     STRINGIFY_CIPHER(SSL_RSA_WITH_RC2_CBC_MD5);
298     STRINGIFY_CIPHER(SSL_RSA_WITH_IDEA_CBC_MD5);
299     STRINGIFY_CIPHER(SSL_RSA_WITH_DES_CBC_MD5);
300     STRINGIFY_CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_MD5);
301     STRINGIFY_CIPHER(SSL_NO_SUCH_CIPHERSUITE);
302     default:
303         ASSERT_NOT_REACHED();
304         return emptyString();
305     }
306
307 #undef STRINGIFY_CIPHER
308 }
309 #endif
310
311 @interface WKNetworkSessionDelegate : NSObject <NSURLSessionDataDelegate> {
312     RefPtr<WebKit::NetworkSessionCocoa> _session;
313     bool _withCredentials;
314 }
315
316 - (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session withCredentials:(bool)withCredentials;
317 - (void)sessionInvalidated;
318
319 @end
320
321 @implementation WKNetworkSessionDelegate
322
323 - (id)initWithNetworkSession:(WebKit::NetworkSessionCocoa&)session withCredentials:(bool)withCredentials
324 {
325     self = [super init];
326     if (!self)
327         return nil;
328
329     _session = &session;
330     _withCredentials = withCredentials;
331
332     return self;
333 }
334
335 - (void)sessionInvalidated
336 {
337     _session = nullptr;
338 }
339
340 - (NetworkDataTaskCocoa*)existingTask:(NSURLSessionTask *)task
341 {
342     if (!_session)
343         return nullptr;
344
345     if (!task)
346         return nullptr;
347
348     auto storedCredentialsPolicy = _withCredentials ? WebCore::StoredCredentialsPolicy::Use : WebCore::StoredCredentialsPolicy::DoNotUse;
349     return _session->dataTaskForIdentifier(task.taskIdentifier, storedCredentialsPolicy);
350 }
351
352 - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
353 {
354     ASSERT(!_session);
355 }
356
357 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
358 {
359     if (auto* networkDataTask = [self existingTask:task])
360         networkDataTask->didSendData(totalBytesSent, totalBytesExpectedToSend);
361 }
362
363 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
364 {
365     auto* networkDataTask = [self existingTask:task];
366     if (!networkDataTask) {
367         completionHandler(nil);
368         return;
369     }
370
371     auto* body = networkDataTask->firstRequest().httpBody();
372     if (!body) {
373         completionHandler(nil);
374         return;
375     }
376
377     completionHandler(WebCore::createHTTPBodyNSInputStream(*body).get());
378 }
379
380 #if HAVE(CFNETWORK_WITH_IGNORE_HSTS)
381 static NSURLRequest* downgradeRequest(NSURLRequest *request)
382 {
383     NSMutableURLRequest *nsMutableRequest = [[request mutableCopy] autorelease];
384     if ([nsMutableRequest.URL.scheme isEqualToString:@"https"]) {
385         NSURLComponents *components = [NSURLComponents componentsWithURL:nsMutableRequest.URL resolvingAgainstBaseURL:NO];
386         components.scheme = @"http";
387         [nsMutableRequest setURL:components.URL];
388         ASSERT([nsMutableRequest.URL.scheme isEqualToString:@"http"]);
389         return nsMutableRequest;
390     }
391
392     ASSERT_NOT_REACHED();
393     return request;
394 }
395
396 static bool schemeWasUpgradedDueToDynamicHSTS(NSURLRequest *request)
397 {
398     return [request respondsToSelector:@selector(_schemeWasUpgradedDueToDynamicHSTS)]
399         && [request _schemeWasUpgradedDueToDynamicHSTS];
400 }
401
402 static void setIgnoreHSTS(NSMutableURLRequest *request, bool ignoreHSTS)
403 {
404     if ([request respondsToSelector:@selector(_setIgnoreHSTS:)])
405         [request _setIgnoreHSTS:ignoreHSTS];
406 }
407
408 static bool ignoreHSTS(NSURLRequest *request)
409 {
410     return [request respondsToSelector:@selector(_ignoreHSTS)]
411         && [request _ignoreHSTS];
412 }
413 #endif
414
415 static NSURLRequest* updateIgnoreStrictTransportSecuritySettingIfNecessary(NSURLRequest *request, bool shouldIgnoreHSTS)
416 {
417 #if HAVE(CFNETWORK_WITH_IGNORE_HSTS)
418     if ([request.URL.scheme isEqualToString:@"https"] && shouldIgnoreHSTS && ignoreHSTS(request)) {
419         // The request was upgraded for some other reason than HSTS.
420         // Don't ignore HSTS to avoid the risk of another downgrade.
421         NSMutableURLRequest *nsMutableRequest = [[request mutableCopy] autorelease];
422         setIgnoreHSTS(nsMutableRequest, false);
423         return nsMutableRequest;
424     }
425     
426     if ([request.URL.scheme isEqualToString:@"http"] && ignoreHSTS(request) != shouldIgnoreHSTS) {
427         NSMutableURLRequest *nsMutableRequest = [[request mutableCopy] autorelease];
428         setIgnoreHSTS(nsMutableRequest, shouldIgnoreHSTS);
429         return nsMutableRequest;
430     }
431 #else
432     UNUSED_PARAM(shouldIgnoreHSTS);
433 #endif
434
435     return request;
436 }
437
438 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler
439 {
440     auto taskIdentifier = task.taskIdentifier;
441     LOG(NetworkSession, "%llu willPerformHTTPRedirection from %s to %s", taskIdentifier, response.URL.absoluteString.UTF8String, request.URL.absoluteString.UTF8String);
442
443     if (auto* networkDataTask = [self existingTask:task]) {
444         auto completionHandlerCopy = Block_copy(completionHandler);
445
446         bool shouldIgnoreHSTS = false;
447 #if HAVE(CFNETWORK_WITH_IGNORE_HSTS)
448         shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && WebCore::NetworkStorageSession::storageSession(_session->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
449         if (shouldIgnoreHSTS) {
450             request = downgradeRequest(request);
451             ASSERT([request.URL.scheme isEqualToString:@"http"]);
452             LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
453         }
454 #endif
455
456         networkDataTask->willPerformHTTPRedirection(response, request, [completionHandlerCopy, taskIdentifier, shouldIgnoreHSTS](auto&& request) {
457 #if !LOG_DISABLED
458             LOG(NetworkSession, "%llu willPerformHTTPRedirection completionHandler (%s)", taskIdentifier, request.url().string().utf8().data());
459 #else
460             UNUSED_PARAM(taskIdentifier);
461 #endif
462             auto nsRequest = request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
463             nsRequest = updateIgnoreStrictTransportSecuritySettingIfNecessary(nsRequest, shouldIgnoreHSTS);
464             completionHandlerCopy(nsRequest);
465             Block_release(completionHandlerCopy);
466         });
467     } else {
468         LOG(NetworkSession, "%llu willPerformHTTPRedirection completionHandler (nil)", taskIdentifier);
469         completionHandler(nil);
470     }
471 }
472
473 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask*)task _schemeUpgraded:(NSURLRequest*)request completionHandler:(void (^)(NSURLRequest*))completionHandler
474 {
475     auto taskIdentifier = task.taskIdentifier;
476     LOG(NetworkSession, "%llu _schemeUpgraded %s", taskIdentifier, request.URL.absoluteString.UTF8String);
477
478     if (auto* networkDataTask = [self existingTask:task]) {
479         bool shouldIgnoreHSTS = false;
480 #if HAVE(CFNETWORK_WITH_IGNORE_HSTS)
481         shouldIgnoreHSTS = schemeWasUpgradedDueToDynamicHSTS(request) && WebCore::NetworkStorageSession::storageSession(_session->sessionID())->shouldBlockCookies(request, networkDataTask->frameID(), networkDataTask->pageID());
482         if (shouldIgnoreHSTS) {
483             request = downgradeRequest(request);
484             ASSERT([request.URL.scheme isEqualToString:@"http"]);
485             LOG(NetworkSession, "%llu Downgraded %s from https to http", taskIdentifier, request.URL.absoluteString.UTF8String);
486         }
487 #endif
488
489         auto completionHandlerCopy = Block_copy(completionHandler);
490         networkDataTask->willPerformHTTPRedirection(WebCore::synthesizeRedirectResponseIfNecessary([task currentRequest], request, nil), request, [completionHandlerCopy, taskIdentifier, shouldIgnoreHSTS](auto&& request) {
491 #if !LOG_DISABLED
492             LOG(NetworkSession, "%llu _schemeUpgraded completionHandler (%s)", taskIdentifier, request.url().string().utf8().data());
493 #else
494             UNUSED_PARAM(taskIdentifier);
495 #endif
496             auto nsRequest = request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
497             nsRequest = updateIgnoreStrictTransportSecuritySettingIfNecessary(nsRequest, shouldIgnoreHSTS);
498             completionHandlerCopy(nsRequest);
499             Block_release(completionHandlerCopy);
500         });
501     } else {
502         LOG(NetworkSession, "%llu _schemeUpgraded completionHandler (nil)", taskIdentifier);
503         completionHandler(nil);
504     }
505 }
506
507 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler
508 {
509     if (!_session) {
510         completionHandler(nil);
511         return;
512     }
513
514     // FIXME: remove if <rdar://problem/20001985> is ever resolved.
515     if ([proposedResponse.response respondsToSelector:@selector(allHeaderFields)]
516         && [[(id)proposedResponse.response allHeaderFields] objectForKey:@"Content-Range"])
517         completionHandler(nil);
518     else
519         completionHandler(proposedResponse);
520 }
521
522 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
523 {
524     if (!_session) {
525         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
526         return;
527     }
528
529     auto taskIdentifier = task.taskIdentifier;
530     LOG(NetworkSession, "%llu didReceiveChallenge", taskIdentifier);
531     
532     // Proxy authentication is handled by CFNetwork internally. We can get here if the user cancels
533     // CFNetwork authentication dialog, and we shouldn't ask the client to display another one in that case.
534     if (challenge.protectionSpace.isProxy) {
535         completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
536         return;
537     }
538
539     if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
540         if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge))
541             return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
542
543         // Handle server trust evaluation at platform-level if requested, for performance reasons and to use ATS defaults.
544         if (!_session->networkProcess().canHandleHTTPSServerTrustEvaluation())
545             return completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
546     }
547
548     if (auto* networkDataTask = [self existingTask:task]) {
549         WebCore::AuthenticationChallenge authenticationChallenge(challenge);
550         auto completionHandlerCopy = Block_copy(completionHandler);
551         auto sessionID = _session->sessionID();
552         auto challengeCompletionHandler = [completionHandlerCopy, sessionID, authenticationChallenge, taskIdentifier, partition = networkDataTask->partition()](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential)
553         {
554 #if !LOG_DISABLED
555             LOG(NetworkSession, "%llu didReceiveChallenge completionHandler %d", taskIdentifier, disposition);
556 #else
557             UNUSED_PARAM(taskIdentifier);
558 #endif
559 #if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
560             UNUSED_PARAM(sessionID);
561             UNUSED_PARAM(authenticationChallenge);
562 #else
563             if (credential.persistence() == WebCore::CredentialPersistenceForSession && authenticationChallenge.protectionSpace().isPasswordBased()) {
564
565                 WebCore::Credential nonPersistentCredential(credential.user(), credential.password(), WebCore::CredentialPersistenceNone);
566                 URL urlToStore;
567                 if (authenticationChallenge.failureResponse().httpStatusCode() == 401)
568                     urlToStore = authenticationChallenge.failureResponse().url();
569                 if (auto storageSession = WebCore::NetworkStorageSession::storageSession(sessionID))
570                     storageSession->credentialStorage().set(partition, nonPersistentCredential, authenticationChallenge.protectionSpace(), urlToStore);
571                 else
572                     ASSERT_NOT_REACHED();
573
574                 completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), nonPersistentCredential.nsCredential());
575             } else
576 #endif
577                 completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
578             Block_release(completionHandlerCopy);
579         };
580         networkDataTask->didReceiveChallenge(challenge, WTFMove(challengeCompletionHandler));
581     } else {
582         auto downloadID = _session->downloadID(taskIdentifier);
583         if (downloadID.downloadID()) {
584             if (auto* download = _session->networkProcess().downloadManager().download(downloadID)) {
585                 // Received an authentication challenge for a download being resumed.
586                 WebCore::AuthenticationChallenge authenticationChallenge { challenge };
587                 auto completionHandlerCopy = Block_copy(completionHandler);
588                 auto challengeCompletionHandler = [completionHandlerCopy, authenticationChallenge](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) {
589                     completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
590                     Block_release(completionHandlerCopy);
591                 };
592                 download->didReceiveChallenge(challenge, WTFMove(challengeCompletionHandler));
593                 return;
594             }
595         }
596         LOG(NetworkSession, "%llu didReceiveChallenge completionHandler (cancel)", taskIdentifier);
597         completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
598     }
599 }
600
601 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
602 {
603     if (!_session)
604         return;
605
606     LOG(NetworkSession, "%llu didCompleteWithError %@", task.taskIdentifier, error);
607     if (auto* networkDataTask = [self existingTask:task])
608         networkDataTask->didCompleteWithError(error, networkDataTask->networkLoadMetrics());
609     else if (error) {
610         auto downloadID = _session->takeDownloadID(task.taskIdentifier);
611         if (downloadID.downloadID()) {
612             if (auto* download = _session->networkProcess().downloadManager().download(downloadID)) {
613                 NSData *resumeData = nil;
614                 if (id userInfo = error.userInfo) {
615                     if ([userInfo isKindOfClass:[NSDictionary class]])
616                         resumeData = userInfo[@"NSURLSessionDownloadTaskResumeData"];
617                 }
618                 
619                 if (resumeData && [resumeData isKindOfClass:[NSData class]])
620                     download->didFail(error, { static_cast<const uint8_t*>(resumeData.bytes), resumeData.length });
621                 else
622                     download->didFail(error, { });
623             }
624         }
625     }
626 }
627
628 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
629 {
630     LOG(NetworkSession, "%llu didFinishCollectingMetrics", task.taskIdentifier);
631     if (auto* networkDataTask = [self existingTask:task]) {
632         NSURLSessionTaskTransactionMetrics *m = metrics.transactionMetrics.lastObject;
633         NSDate *fetchStartDate = m.fetchStartDate;
634         NSTimeInterval domainLookupStartInterval = m.domainLookupStartDate ? [m.domainLookupStartDate timeIntervalSinceDate:fetchStartDate] : -1;
635         NSTimeInterval domainLookupEndInterval = m.domainLookupEndDate ? [m.domainLookupEndDate timeIntervalSinceDate:fetchStartDate] : -1;
636         NSTimeInterval connectStartInterval = m.connectStartDate ? [m.connectStartDate timeIntervalSinceDate:fetchStartDate] : -1;
637         NSTimeInterval secureConnectionStartInterval = m.secureConnectionStartDate ? [m.secureConnectionStartDate timeIntervalSinceDate:fetchStartDate] : -1;
638         NSTimeInterval connectEndInterval = m.connectEndDate ? [m.connectEndDate timeIntervalSinceDate:fetchStartDate] : -1;
639         NSTimeInterval requestStartInterval = [m.requestStartDate timeIntervalSinceDate:fetchStartDate];
640         NSTimeInterval responseStartInterval = [m.responseStartDate timeIntervalSinceDate:fetchStartDate];
641         NSTimeInterval responseEndInterval = [m.responseEndDate timeIntervalSinceDate:fetchStartDate];
642
643         auto& networkLoadMetrics = networkDataTask->networkLoadMetrics();
644         networkLoadMetrics.domainLookupStart = Seconds(domainLookupStartInterval);
645         networkLoadMetrics.domainLookupEnd = Seconds(domainLookupEndInterval);
646         networkLoadMetrics.connectStart = Seconds(connectStartInterval);
647         networkLoadMetrics.secureConnectionStart = Seconds(secureConnectionStartInterval);
648         networkLoadMetrics.connectEnd = Seconds(connectEndInterval);
649         networkLoadMetrics.requestStart = Seconds(requestStartInterval);
650         networkLoadMetrics.responseStart = Seconds(responseStartInterval);
651         networkLoadMetrics.responseEnd = Seconds(responseEndInterval);
652         networkLoadMetrics.markComplete();
653         networkLoadMetrics.protocol = String(m.networkProtocolName);
654
655         if (networkDataTask->shouldCaptureExtraNetworkLoadMetrics()) {
656             networkLoadMetrics.priority = toNetworkLoadPriority(task.priority);
657
658 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
659             networkLoadMetrics.remoteAddress = String(m._remoteAddressAndPort);
660             networkLoadMetrics.connectionIdentifier = String([m._connectionIdentifier UUIDString]);
661 #endif
662
663 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
664             networkLoadMetrics.tlsProtocol = stringForSSLProtocol(m._negotiatedTLSProtocol);
665             networkLoadMetrics.tlsCipher = stringForSSLCipher(m._negotiatedTLSCipher);
666 #endif
667
668             __block WebCore::HTTPHeaderMap requestHeaders;
669             [m.request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *) {
670                 requestHeaders.set(String(name), String(value));
671             }];
672             networkLoadMetrics.requestHeaders = WTFMove(requestHeaders);
673
674 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
675             uint64_t requestHeaderBytesSent = 0;
676             uint64_t responseHeaderBytesReceived = 0;
677             uint64_t responseBodyBytesReceived = 0;
678             uint64_t responseBodyDecodedSize = 0;
679
680             for (NSURLSessionTaskTransactionMetrics *transactionMetrics in metrics.transactionMetrics) {
681                 requestHeaderBytesSent += transactionMetrics._requestHeaderBytesSent;
682                 responseHeaderBytesReceived += transactionMetrics._responseHeaderBytesReceived;
683                 responseBodyBytesReceived += transactionMetrics._responseBodyBytesReceived;
684                 responseBodyDecodedSize += transactionMetrics._responseBodyBytesDecoded ? transactionMetrics._responseBodyBytesDecoded : transactionMetrics._responseBodyBytesReceived;
685             }
686
687             networkLoadMetrics.requestHeaderBytesSent = requestHeaderBytesSent;
688             networkLoadMetrics.requestBodyBytesSent = task.countOfBytesSent;
689             networkLoadMetrics.responseHeaderBytesReceived = responseHeaderBytesReceived;
690             networkLoadMetrics.responseBodyBytesReceived = responseBodyBytesReceived;
691             networkLoadMetrics.responseBodyDecodedSize = responseBodyDecodedSize;
692 #endif
693         }
694     }
695 }
696
697 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
698 {
699     auto taskIdentifier = dataTask.taskIdentifier;
700     LOG(NetworkSession, "%llu didReceiveResponse", taskIdentifier);
701     if (auto* networkDataTask = [self existingTask:dataTask]) {
702         ASSERT(RunLoop::isMain());
703         
704         // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
705         int statusCode = [response respondsToSelector:@selector(statusCode)] ? [(id)response statusCode] : 0;
706         if (statusCode != 304) {
707             bool isMainResourceLoad = networkDataTask->firstRequest().requester() == WebCore::ResourceRequest::Requester::Main;
708             WebCore::adjustMIMETypeIfNecessary(response._CFURLResponse, isMainResourceLoad);
709         }
710
711         WebCore::ResourceResponse resourceResponse(response);
712         // Lazy initialization is not helpful in the WebKit2 case because we always end up initializing
713         // all the fields when sending the response to the WebContent process over IPC.
714         resourceResponse.disableLazyInitialization();
715
716         // FIXME: This cannot be eliminated until other code no longer relies on ResourceResponse's
717         // NetworkLoadMetrics. For example, PerformanceTiming.
718         copyTimingData([dataTask _timingData], resourceResponse.deprecatedNetworkLoadMetrics());
719
720         auto completionHandlerCopy = Block_copy(completionHandler);
721         networkDataTask->didReceiveResponse(WTFMove(resourceResponse), [completionHandlerCopy, taskIdentifier](WebCore::PolicyAction policyAction) {
722 #if !LOG_DISABLED
723             LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%d)", taskIdentifier, policyAction);
724 #else
725             UNUSED_PARAM(taskIdentifier);
726 #endif
727             completionHandlerCopy(toNSURLSessionResponseDisposition(policyAction));
728             Block_release(completionHandlerCopy);
729         });
730     } else {
731         LOG(NetworkSession, "%llu didReceiveResponse completionHandler (cancel)", taskIdentifier);
732         completionHandler(NSURLSessionResponseCancel);
733     }
734 }
735
736 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
737 {
738     if (auto* networkDataTask = [self existingTask:dataTask])
739         networkDataTask->didReceiveData(WebCore::SharedBuffer::create(data));
740 }
741
742 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
743 {
744     if (!_session)
745         return;
746
747     auto downloadID = _session->takeDownloadID([downloadTask taskIdentifier]);
748     if (auto* download = _session->networkProcess().downloadManager().download(downloadID))
749         download->didFinish();
750 }
751
752 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
753 {
754     if (!_session)
755         return;
756
757     ASSERT_WITH_MESSAGE(![self existingTask:downloadTask], "The NetworkDataTask should be destroyed immediately after didBecomeDownloadTask returns");
758
759     auto downloadID = _session->downloadID([downloadTask taskIdentifier]);
760     if (auto* download = _session->networkProcess().downloadManager().download(downloadID))
761         download->didReceiveData(bytesWritten);
762 }
763
764 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
765 {
766     if (!_session)
767         return;
768
769     notImplemented();
770 }
771
772 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask
773 {
774     if (auto* networkDataTask = [self existingTask:dataTask]) {
775         Ref<NetworkDataTaskCocoa> protectedNetworkDataTask(*networkDataTask);
776         auto downloadID = networkDataTask->pendingDownloadID();
777         auto& downloadManager = _session->networkProcess().downloadManager();
778         auto download = std::make_unique<WebKit::Download>(downloadManager, downloadID, downloadTask, _session->sessionID(), networkDataTask->suggestedFilename());
779         networkDataTask->transferSandboxExtensionToDownload(*download);
780         ASSERT(WebCore::FileSystem::fileExists(networkDataTask->pendingDownloadLocation()));
781         download->didCreateDestination(networkDataTask->pendingDownloadLocation());
782         downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
783
784         _session->addDownloadID([downloadTask taskIdentifier], downloadID);
785     }
786 }
787
788 @end
789
790 namespace WebKit {
791
792 #if !ASSERT_DISABLED
793 static bool sessionsCreated = false;
794 #endif
795
796 static NSURLSessionConfiguration *configurationForSessionID(const PAL::SessionID& session)
797 {
798     if (session.isEphemeral()) {
799         NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
800         configuration._shouldSkipPreferredClientCertificateLookup = YES;
801         return configuration;
802     }
803     return [NSURLSessionConfiguration defaultSessionConfiguration];
804 }
805
806 #if PLATFORM(IOS_FAMILY)
807 static String& globalCTDataConnectionServiceType()
808 {
809     static NeverDestroyed<String> ctDataConnectionServiceType;
810     return ctDataConnectionServiceType.get();
811 }
812 #endif
813
814 #if PLATFORM(IOS_FAMILY)
815 void NetworkSessionCocoa::setCTDataConnectionServiceType(const String& type)
816 {
817     ASSERT(!sessionsCreated);
818     globalCTDataConnectionServiceType() = type;
819 }
820 #endif
821
822 Ref<NetworkSession> NetworkSessionCocoa::create(NetworkProcess& networkProcess, NetworkSessionCreationParameters&& parameters)
823 {
824     return adoptRef(*new NetworkSessionCocoa(networkProcess, WTFMove(parameters)));
825 }
826
827 static NSDictionary *proxyDictionary(const URL& httpProxy, const URL& httpsProxy)
828 {
829     if (!httpProxy.isValid() && !httpsProxy.isValid())
830         return nil;
831
832     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
833
834     NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease];
835     if (httpProxy.isValid()) {
836         [dictionary setObject:httpProxy.host().toString() forKey:(NSString *)kCFStreamPropertyHTTPProxyHost];
837         if (auto port = httpProxy.port())
838             [dictionary setObject:@(*port) forKey:(NSString *)kCFStreamPropertyHTTPProxyPort];
839     }
840     if (httpsProxy.isValid()) {
841         [dictionary setObject:httpsProxy.host().toString() forKey:(NSString *)kCFStreamPropertyHTTPSProxyHost];
842         if (auto port = httpsProxy.port())
843             [dictionary setObject:@(*port) forKey:(NSString *)kCFStreamPropertyHTTPSProxyPort];
844     }
845     return dictionary;
846
847     ALLOW_DEPRECATED_DECLARATIONS_END
848 }
849
850 NetworkSessionCocoa::NetworkSessionCocoa(NetworkProcess& networkProcess, NetworkSessionCreationParameters&& parameters)
851     : NetworkSession(networkProcess, parameters.sessionID)
852     , m_boundInterfaceIdentifier(parameters.boundInterfaceIdentifier)
853     , m_proxyConfiguration(parameters.proxyConfiguration)
854     , m_shouldLogCookieInformation(parameters.shouldLogCookieInformation)
855     , m_loadThrottleLatency(parameters.loadThrottleLatency)
856 {
857     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
858
859     relaxAdoptionRequirement();
860
861 #if !ASSERT_DISABLED
862     sessionsCreated = true;
863 #endif
864
865     NSURLSessionConfiguration *configuration = configurationForSessionID(m_sessionID);
866
867 #if USE(CFNETWORK_AUTO_ADDED_HTTP_HEADER_SUPPRESSION)
868     // Without this, CFNetwork would sometimes add a Content-Type header to our requests (rdar://problem/34748470).
869     configuration._suppressedAutoAddedHTTPHeaders = [NSSet setWithObject:@"Content-Type"];
870 #endif
871
872     if (parameters.allowsCellularAccess == AllowsCellularAccess::No)
873         configuration.allowsCellularAccess = NO;
874
875     // The WebKit network cache was already queried.
876     configuration.URLCache = nil;
877
878     if (auto data = networkProcess.sourceApplicationAuditData())
879         configuration._sourceApplicationAuditTokenData = (__bridge NSData *)data.get();
880
881     if (!parameters.sourceApplicationBundleIdentifier.isEmpty()) {
882         configuration._sourceApplicationBundleIdentifier = parameters.sourceApplicationBundleIdentifier;
883         configuration._sourceApplicationAuditTokenData = nil;
884     }
885
886     if (!parameters.sourceApplicationSecondaryIdentifier.isEmpty())
887         configuration._sourceApplicationSecondaryIdentifier = parameters.sourceApplicationSecondaryIdentifier;
888
889     configuration.connectionProxyDictionary = proxyDictionary(parameters.httpProxy, parameters.httpsProxy);
890
891 #if PLATFORM(IOS_FAMILY)
892     auto& ctDataConnectionServiceType = globalCTDataConnectionServiceType();
893     if (!ctDataConnectionServiceType.isEmpty())
894         configuration._CTDataConnectionServiceType = ctDataConnectionServiceType;
895 #endif
896
897 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
898     networkProcess.supplement<LegacyCustomProtocolManager>()->registerProtocolClass(configuration);
899 #endif
900
901 #if HAVE(TIMINGDATAOPTIONS)
902     configuration._timingDataOptions = _TimingDataOptionsEnableW3CNavigationTiming;
903 #else
904     setCollectsTimingData();
905 #endif
906
907 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
908     // FIXME: Replace @"kCFStreamPropertyAutoErrorOnSystemChange" with a constant from the SDK once rdar://problem/40650244 is in a build.
909     if (networkProcess.suppressesConnectionTerminationOnSystemChange())
910         configuration._socketStreamProperties = @{ @"kCFStreamPropertyAutoErrorOnSystemChange" : @(NO) };
911 #endif
912
913 #if PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MIN_REQUIRED >= 60000
914     configuration._companionProxyPreference = NSURLSessionCompanionProxyPreferencePreferDirectToCloud;
915 #endif
916
917     auto* storageSession = WebCore::NetworkStorageSession::storageSession(parameters.sessionID);
918     RELEASE_ASSERT(storageSession);
919     if (CFHTTPCookieStorageRef storage = storageSession->cookieStorage().get())
920         configuration.HTTPCookieStorage = [[[NSHTTPCookieStorage alloc] _initWithCFHTTPCookieStorage:storage] autorelease];
921
922     m_sessionWithCredentialStorageDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:true]);
923     m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
924     LOG(NetworkSession, "Created NetworkSession with cookieAcceptPolicy %lu", configuration.HTTPCookieStorage.cookieAcceptPolicy);
925
926     configuration.URLCredentialStorage = nil;
927     configuration._shouldSkipPreferredClientCertificateLookup = YES;
928     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=177394
929     // configuration.HTTPCookieStorage = nil;
930     // configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;
931
932     m_statelessSessionDelegate = adoptNS([[WKNetworkSessionDelegate alloc] initWithNetworkSession:*this withCredentials:false]);
933     m_statelessSession = [NSURLSession sessionWithConfiguration:configuration delegate:static_cast<id>(m_statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
934 }
935
936 NetworkSessionCocoa::~NetworkSessionCocoa()
937 {
938 }
939
940 void NetworkSessionCocoa::invalidateAndCancel()
941 {
942     NetworkSession::invalidateAndCancel();
943
944     [m_sessionWithCredentialStorage invalidateAndCancel];
945     [m_statelessSession invalidateAndCancel];
946     [m_sessionWithCredentialStorageDelegate sessionInvalidated];
947     [m_statelessSessionDelegate sessionInvalidated];
948 }
949
950 void NetworkSessionCocoa::clearCredentials()
951 {
952 #if !USE(CREDENTIAL_STORAGE_WITH_NETWORK_SESSION)
953     ASSERT(m_dataTaskMapWithCredentials.isEmpty());
954     ASSERT(m_dataTaskMapWithoutState.isEmpty());
955     ASSERT(m_downloadMap.isEmpty());
956     // FIXME: Use resetWithCompletionHandler instead.
957     m_sessionWithCredentialStorage = [NSURLSession sessionWithConfiguration:m_sessionWithCredentialStorage.get().configuration delegate:static_cast<id>(m_sessionWithCredentialStorageDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
958     m_statelessSession = [NSURLSession sessionWithConfiguration:m_statelessSession.get().configuration delegate:static_cast<id>(m_statelessSessionDelegate.get()) delegateQueue:[NSOperationQueue mainQueue]];
959 #endif
960 }
961
962 NetworkDataTaskCocoa* NetworkSessionCocoa::dataTaskForIdentifier(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
963 {
964     ASSERT(RunLoop::isMain());
965     if (storedCredentialsPolicy == WebCore::StoredCredentialsPolicy::Use)
966         return m_dataTaskMapWithCredentials.get(taskIdentifier);
967     return m_dataTaskMapWithoutState.get(taskIdentifier);
968 }
969
970 NSURLSessionDownloadTask* NetworkSessionCocoa::downloadTaskWithResumeData(NSData* resumeData)
971 {
972     return [m_sessionWithCredentialStorage downloadTaskWithResumeData:resumeData];
973 }
974
975 void NetworkSessionCocoa::addDownloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, DownloadID downloadID)
976 {
977 #ifndef NDEBUG
978     ASSERT(!m_downloadMap.contains(taskIdentifier));
979     for (auto idInMap : m_downloadMap.values())
980         ASSERT(idInMap != downloadID);
981 #endif
982     m_downloadMap.add(taskIdentifier, downloadID);
983 }
984
985 DownloadID NetworkSessionCocoa::downloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier)
986 {
987     ASSERT(m_downloadMap.get(taskIdentifier).downloadID());
988     return m_downloadMap.get(taskIdentifier);
989 }
990
991 DownloadID NetworkSessionCocoa::takeDownloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier)
992 {
993     auto downloadID = m_downloadMap.take(taskIdentifier);
994     return downloadID;
995 }
996
997 static bool certificatesMatch(SecTrustRef trust1, SecTrustRef trust2)
998 {
999     if (!trust1 || !trust2)
1000         return false;
1001
1002     CFIndex count1 = SecTrustGetCertificateCount(trust1);
1003     CFIndex count2 = SecTrustGetCertificateCount(trust2);
1004     if (count1 != count2)
1005         return false;
1006
1007     for (CFIndex i = 0; i < count1; i++) {
1008         auto cert1 = SecTrustGetCertificateAtIndex(trust1, i);
1009         auto cert2 = SecTrustGetCertificateAtIndex(trust2, i);
1010         RELEASE_ASSERT(cert1);
1011         RELEASE_ASSERT(cert2);
1012         if (!CFEqual(cert1, cert2))
1013             return false;
1014     }
1015
1016     return true;
1017 }
1018
1019 bool NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(const WebCore::AuthenticationChallenge& challenge)
1020 {
1021     const String& host = challenge.protectionSpace().host();
1022     NSArray *certificates = [NSURLRequest allowsSpecificHTTPSCertificateForHost:host];
1023     if (!certificates)
1024         return false;
1025
1026     bool requireServerCertificates = challenge.protectionSpace().authenticationScheme() == WebCore::ProtectionSpaceAuthenticationScheme::ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested;
1027     RetainPtr<SecPolicyRef> policy = adoptCF(SecPolicyCreateSSL(requireServerCertificates, host.createCFString().get()));
1028
1029     SecTrustRef trustRef = nullptr;
1030     if (SecTrustCreateWithCertificates((CFArrayRef)certificates, policy.get(), &trustRef) != noErr)
1031         return false;
1032     RetainPtr<SecTrustRef> trust = adoptCF(trustRef);
1033
1034     return certificatesMatch(trust.get(), challenge.nsURLAuthenticationChallenge().protectionSpace.serverTrust);
1035 }
1036
1037 }