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