67bc9e1dbe6f50a288dd765d413405ac5f5aa7b1
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "NetworkProcess.h"
29
30 #include "ArgumentCoders.h"
31 #include "Attachment.h"
32 #include "AuthenticationManager.h"
33 #include "ChildProcessMessages.h"
34 #include "DataReference.h"
35 #include "DownloadProxyMessages.h"
36 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
37 #include "LegacyCustomProtocolManager.h"
38 #endif
39 #include "Logging.h"
40 #include "NetworkBlobRegistry.h"
41 #include "NetworkConnectionToWebProcess.h"
42 #include "NetworkContentRuleListManagerMessages.h"
43 #include "NetworkProcessCreationParameters.h"
44 #include "NetworkProcessPlatformStrategies.h"
45 #include "NetworkProcessProxyMessages.h"
46 #include "NetworkResourceLoader.h"
47 #include "NetworkSession.h"
48 #include "PreconnectTask.h"
49 #include "RemoteNetworkingContext.h"
50 #include "SessionTracker.h"
51 #include "StatisticsData.h"
52 #include "WebCookieManager.h"
53 #include "WebCoreArgumentCoders.h"
54 #include "WebPageProxyMessages.h"
55 #include "WebProcessPoolMessages.h"
56 #include "WebsiteData.h"
57 #include "WebsiteDataFetchOption.h"
58 #include "WebsiteDataStore.h"
59 #include "WebsiteDataStoreParameters.h"
60 #include "WebsiteDataType.h"
61 #include <WebCore/DNS.h>
62 #include <WebCore/DeprecatedGlobalSettings.h>
63 #include <WebCore/DiagnosticLoggingClient.h>
64 #include <WebCore/LogInitialization.h>
65 #include <WebCore/MIMETypeRegistry.h>
66 #include <WebCore/NetworkStateNotifier.h>
67 #include <WebCore/NetworkStorageSession.h>
68 #include <WebCore/PlatformCookieJar.h>
69 #include <WebCore/ResourceRequest.h>
70 #include <WebCore/RuntimeApplicationChecks.h>
71 #include <WebCore/SchemeRegistry.h>
72 #include <WebCore/SecurityOriginData.h>
73 #include <WebCore/SecurityOriginHash.h>
74 #include <WebCore/Settings.h>
75 #include <WebCore/URLParser.h>
76 #include <pal/SessionID.h>
77 #include <wtf/CallbackAggregator.h>
78 #include <wtf/OptionSet.h>
79 #include <wtf/ProcessPrivilege.h>
80 #include <wtf/RunLoop.h>
81 #include <wtf/text/AtomicString.h>
82 #include <wtf/text/CString.h>
83
84 #if ENABLE(SEC_ITEM_SHIM)
85 #include "SecItemShim.h"
86 #endif
87
88 #include "NetworkCache.h"
89 #include "NetworkCacheCoders.h"
90
91 #if ENABLE(NETWORK_CAPTURE)
92 #include "NetworkCaptureManager.h"
93 #endif
94
95 #if PLATFORM(COCOA)
96 #include "NetworkSessionCocoa.h"
97 #endif
98
99 using namespace WebCore;
100
101 namespace WebKit {
102
103 NetworkProcess& NetworkProcess::singleton()
104 {
105     static NeverDestroyed<NetworkProcess> networkProcess;
106     return networkProcess;
107 }
108
109 NetworkProcess::NetworkProcess()
110     : m_hasSetCacheModel(false)
111     , m_cacheModel(CacheModelDocumentViewer)
112     , m_diskCacheIsDisabledForTesting(false)
113     , m_canHandleHTTPSServerTrustEvaluation(true)
114 #if PLATFORM(COCOA)
115     , m_clearCacheDispatchGroup(0)
116 #endif
117 {
118     NetworkProcessPlatformStrategies::initialize();
119
120     addSupplement<AuthenticationManager>();
121     addSupplement<WebCookieManager>();
122 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
123     addSupplement<LegacyCustomProtocolManager>();
124 #endif
125
126     NetworkStateNotifier::singleton().addListener([this](bool isOnLine) {
127         auto webProcessConnections = m_webProcessConnections;
128         for (auto& webProcessConnection : webProcessConnections)
129             webProcessConnection->setOnLineState(isOnLine);
130     });
131 }
132
133 NetworkProcess::~NetworkProcess()
134 {
135     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
136         for (auto& callback : callbacks)
137             callback(String { }, 0);
138     }
139 }
140
141 AuthenticationManager& NetworkProcess::authenticationManager()
142 {
143     return *supplement<AuthenticationManager>();
144 }
145
146 DownloadManager& NetworkProcess::downloadManager()
147 {
148     static NeverDestroyed<DownloadManager> downloadManager(*this);
149     return downloadManager;
150 }
151
152 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
153 {
154     size_t vectorIndex = m_webProcessConnections.find(connection);
155     ASSERT(vectorIndex != notFound);
156
157     m_webProcessConnections.remove(vectorIndex);
158 }
159
160 bool NetworkProcess::shouldTerminate()
161 {
162     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
163     return false;
164 }
165
166 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
167 {
168     if (messageReceiverMap().dispatchMessage(connection, decoder))
169         return;
170
171     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
172         ChildProcess::didReceiveMessage(connection, decoder);
173         return;
174     }
175
176 #if ENABLE(CONTENT_EXTENSIONS)
177     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
178         m_NetworkContentRuleListManager.didReceiveMessage(connection, decoder);
179         return;
180     }
181 #endif
182
183     didReceiveNetworkProcessMessage(connection, decoder);
184 }
185
186 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
187 {
188     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
189         return;
190
191     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
192 }
193
194 void NetworkProcess::didCreateDownload()
195 {
196     disableTermination();
197 }
198
199 void NetworkProcess::didDestroyDownload()
200 {
201     enableTermination();
202 }
203
204 IPC::Connection* NetworkProcess::downloadProxyConnection()
205 {
206     return parentProcessConnection();
207 }
208
209 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
210 {
211     return authenticationManager();
212 }
213
214 void NetworkProcess::lowMemoryHandler(Critical critical)
215 {
216     if (m_suppressMemoryPressureHandler)
217         return;
218
219     WTF::releaseFastMallocFreeMemory();
220 }
221
222 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
223 {
224 #if HAVE(SEC_KEY_PROXY)
225     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
226 #else
227     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
228 #endif
229     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
230     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
231     platformInitializeNetworkProcess(parameters);
232
233     WTF::Thread::setCurrentThreadIsUserInitiated();
234     AtomicString::init();
235
236     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
237     m_loadThrottleLatency = parameters.loadThrottleLatency;
238     if (!m_suppressMemoryPressureHandler) {
239         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
240         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
241             lowMemoryHandler(critical);
242         });
243         memoryPressureHandler.install();
244     }
245
246 #if ENABLE(NETWORK_CAPTURE)
247     NetworkCapture::Manager::singleton().initialize(
248         parameters.recordReplayMode,
249         parameters.recordReplayCacheLocation);
250 #endif
251
252     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
253
254     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
255     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
256
257     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
258
259     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
260     if (parameters.privateBrowsingEnabled)
261         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
262
263     if (parameters.shouldUseTestingNetworkSession)
264         NetworkStorageSession::switchToNewTestingSession();
265
266 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
267     m_logCookieInformation = parameters.logCookieInformation;
268 #endif
269
270     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(WTFMove(parameters.defaultSessionParameters)));
271
272     auto* defaultSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID());
273     for (const auto& cookie : parameters.defaultSessionPendingCookies)
274         defaultSession->networkStorageSession().setCookie(cookie);
275
276     for (auto& supplement : m_supplements.values())
277         supplement->initialize(parameters);
278
279     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
280         registerURLSchemeAsSecure(scheme);
281
282     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
283         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
284
285     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
286         registerURLSchemeAsLocal(scheme);
287
288     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
289         registerURLSchemeAsNoAccess(scheme);
290
291     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
292         registerURLSchemeAsDisplayIsolated(scheme);
293
294     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
295         registerURLSchemeAsCORSEnabled(scheme);
296
297     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
298         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
299
300     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
301 }
302
303 void NetworkProcess::initializeConnection(IPC::Connection* connection)
304 {
305     ChildProcess::initializeConnection(connection);
306
307     for (auto& supplement : m_supplements.values())
308         supplement->initializeConnection(connection);
309 }
310
311 void NetworkProcess::createNetworkConnectionToWebProcess()
312 {
313 #if USE(UNIX_DOMAIN_SOCKETS)
314     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
315
316     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
317     m_webProcessConnections.append(WTFMove(connection));
318
319     IPC::Attachment clientSocket(socketPair.client);
320     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
321 #elif OS(DARWIN)
322     // Create the listening port.
323     mach_port_t listeningPort = MACH_PORT_NULL;
324     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
325     if (kr != KERN_SUCCESS) {
326         LOG_ERROR("Could not allocate mach port, error %x", kr);
327         CRASH();
328     }
329
330     // Create a listening connection.
331     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
332     m_webProcessConnections.append(WTFMove(connection));
333
334     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
335     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
336 #elif OS(WINDOWS)
337     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
338     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier))
339         return;
340
341     auto connection = NetworkConnectionToWebProcess::create(serverIdentifier);
342     m_webProcessConnections.append(WTFMove(connection));
343
344     IPC::Attachment clientSocket(clientIdentifier);
345     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
346 #else
347     notImplemented();
348 #endif
349
350     if (!m_webProcessConnections.isEmpty())
351         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
352 }
353
354 void NetworkProcess::clearCachedCredentials()
355 {
356     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
357     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
358         networkSession->clearCredentials();
359     else
360         ASSERT_NOT_REACHED();
361 }
362
363 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
364 {
365     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
366 }
367
368 void NetworkProcess::destroySession(PAL::SessionID sessionID)
369 {
370     SessionTracker::destroySession(sessionID);
371     m_sessionsControlledByAutomation.remove(sessionID);
372     CacheStorage::Engine::destroyEngine(sessionID);
373 }
374
375 void NetworkProcess::grantSandboxExtensionsToStorageProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler)
376 {
377     static uint64_t lastRequestID;
378
379     uint64_t requestID = ++lastRequestID;
380     m_sandboxExtensionForBlobsCompletionHandlers.set(requestID, WTFMove(completionHandler));
381     parentProcessConnection()->send(Messages::NetworkProcessProxy::GrantSandboxExtensionsToStorageProcessForBlobs(requestID, filenames), 0);
382 }
383
384 void NetworkProcess::didGrantSandboxExtensionsToStorageProcessForBlobs(uint64_t requestID)
385 {
386     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlers.take(requestID))
387         handler();
388 }
389
390 void NetworkProcess::writeBlobToFilePath(const WebCore::URL& url, const String& path, SandboxExtension::Handle&& handleForWriting, uint64_t requestID)
391 {
392     auto extension = SandboxExtension::create(WTFMove(handleForWriting));
393     if (!extension) {
394         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(false, requestID), 0);
395         return;
396     }
397
398     extension->consume();
399     NetworkBlobRegistry::singleton().writeBlobToFilePath(url, path, [this, extension = WTFMove(extension), requestID] (bool success) {
400         extension->revoke();
401         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(success, requestID), 0);
402     });
403 }
404
405 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
406 void NetworkProcess::updatePrevalentDomainsToPartitionOrBlockCookies(PAL::SessionID sessionID, const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, bool shouldClearFirst, uint64_t callbackId)
407 {
408     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
409         networkStorageSession->setPrevalentDomainsToPartitionOrBlockCookies(domainsToPartition, domainsToBlock, domainsToNeitherPartitionNorBlock, shouldClearFirst);
410     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdatePartitionOrBlockCookies(callbackId), 0);
411 }
412
413 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
414 {
415     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
416         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
417     else
418         ASSERT_NOT_REACHED();
419 }
420
421 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
422 {
423     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
424         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
425     else
426         ASSERT_NOT_REACHED();
427 }
428
429 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
430 {
431     bool isStorageGranted = false;
432     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
433         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
434         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
435         isStorageGranted = true;
436     } else
437         ASSERT_NOT_REACHED();
438
439     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
440 }
441
442 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID)
443 {
444     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
445         networkStorageSession->removeAllStorageAccess();
446     else
447         ASSERT_NOT_REACHED();
448 }
449
450 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
451 {
452     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
453         networkStorageSession->removePrevalentDomains(domains);
454 }
455 #endif
456
457 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
458 {
459     return m_sessionsControlledByAutomation.contains(sessionID);
460 }
461
462 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
463 {
464     if (controlled)
465         m_sessionsControlledByAutomation.add(sessionID);
466     else
467         m_sessionsControlledByAutomation.remove(sessionID);
468 }
469
470 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
471 {
472     if (auto* cache = NetworkProcess::singleton().cache()) {
473         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
474         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
475             if (!traversalEntry) {
476                 Vector<WebsiteData::Entry> entries;
477
478                 for (auto& originAndSize : originsAndSizes)
479                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
480
481                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
482                     completionHandler(entries);
483                 });
484
485                 return;
486             }
487
488             auto url = traversalEntry->entry.response().url();
489             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
490
491             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
492                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
493         });
494
495         return;
496     }
497
498     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
499         completionHandler({ });
500     });
501 }
502
503 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
504 {
505     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
506         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
507             : m_completionHandler(WTFMove(completionHandler))
508         {
509         }
510
511         ~CallbackAggregator()
512         {
513             ASSERT(RunLoop::isMain());
514
515             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
516                 completionHandler(websiteData);
517             });
518         }
519
520         Function<void (WebsiteData)> m_completionHandler;
521         WebsiteData m_websiteData;
522     };
523
524     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
525         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
526     }));
527
528     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
529         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
530             getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies);
531     }
532
533     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
534         if (NetworkStorageSession::storageSession(sessionID))
535             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
536     }
537
538     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
539         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
540             callbackAggregator->m_websiteData.entries.appendVector(entries);
541         });
542     }
543
544     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
545         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
546             callbackAggregator->m_websiteData.entries.appendVector(entries);
547         });
548     }
549 }
550
551 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
552 {
553 #if PLATFORM(COCOA)
554     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
555         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
556             clearHSTSCache(*networkStorageSession, modifiedSince);
557     }
558 #endif
559
560     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
561         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
562             deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince);
563     }
564
565     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
566         if (NetworkStorageSession::storageSession(sessionID))
567             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
568     }
569
570     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
571         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
572     });
573
574     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
575         CacheStorage::Engine::clearAllCaches(sessionID, clearTasksHandler.copyRef());
576
577     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
578         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
579 }
580
581 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
582 {
583     if (auto* cache = NetworkProcess::singleton().cache()) {
584         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
585         for (auto& origin : origins)
586             originsToDelete.add(origin.securityOrigin());
587
588         Vector<NetworkCache::Key> cacheKeysToDelete;
589         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
590             if (traversalEntry) {
591                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
592                     cacheKeysToDelete.append(traversalEntry->entry.key());
593                 return;
594             }
595
596             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
597             return;
598         });
599
600         return;
601     }
602
603     RunLoop::main().dispatch(WTFMove(completionHandler));
604 }
605
606 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, uint64_t callbackID)
607 {
608     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
609         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
610             deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
611     }
612
613     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
614         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
615     });
616
617     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
618         for (auto& originData : originDatas)
619             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, clearTasksHandler.copyRef());
620     }
621
622     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
623         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
624 }
625
626 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
627 {
628     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
629 }
630
631 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
632 {
633     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
634 }
635
636 void NetworkProcess::cancelDownload(DownloadID downloadID)
637 {
638     downloadManager().cancelDownload(downloadID);
639 }
640     
641 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
642 static uint64_t generateCanAuthenticateIdentifier()
643 {
644     static uint64_t lastLoaderID = 0;
645     return ++lastLoaderID;
646 }
647
648 void NetworkProcess::canAuthenticateAgainstProtectionSpace(NetworkResourceLoader& loader, const WebCore::ProtectionSpace& protectionSpace)
649 {
650     uint64_t loaderID = generateCanAuthenticateIdentifier();
651     m_waitingNetworkResourceLoaders.set(loaderID, loader);
652     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, loader.pageID(), loader.frameID(), protectionSpace), 0);
653 }
654
655 #if ENABLE(SERVER_PRECONNECT)
656 void NetworkProcess::canAuthenticateAgainstProtectionSpace(PreconnectTask& preconnectTask, const WebCore::ProtectionSpace& protectionSpace)
657 {
658     uint64_t loaderID = generateCanAuthenticateIdentifier();
659     m_waitingPreconnectTasks.set(loaderID, makeWeakPtr(preconnectTask));
660     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, preconnectTask.pageID(), preconnectTask.frameID(), protectionSpace), 0);
661 }
662 #endif
663
664 void NetworkProcess::continueCanAuthenticateAgainstProtectionSpace(uint64_t loaderID, bool canAuthenticate)
665 {
666     if (auto resourceLoader = m_waitingNetworkResourceLoaders.take(loaderID)) {
667         resourceLoader.value()->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
668         return;
669     }
670 #if ENABLE(SERVER_PRECONNECT)
671     if (auto preconnectTask = m_waitingPreconnectTasks.take(loaderID)) {
672         preconnectTask->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
673         return;
674     }
675 #endif
676 }
677
678 #endif
679
680 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
681 {
682     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
683 }
684
685 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
686 {
687     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
688 }
689
690 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
691 {
692     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
693     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
694
695     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
696
697     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
698     // should override the suggested filename from the download attribute.
699     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
700     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
701
702     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
703 }
704
705 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
706 {
707     if (destination.isEmpty())
708         downloadManager().cancelDownload(downloadID);
709     else
710         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
711 }
712
713 void NetworkProcess::setCacheModel(uint32_t cm)
714 {
715     CacheModel cacheModel = static_cast<CacheModel>(cm);
716
717     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
718         return;
719
720     m_hasSetCacheModel = true;
721     m_cacheModel = cacheModel;
722
723     unsigned urlCacheMemoryCapacity = 0;
724     uint64_t urlCacheDiskCapacity = 0;
725     uint64_t diskFreeSize = 0;
726     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
727         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
728         // count doesn't align exactly to a megabyte boundary.
729         diskFreeSize /= KB * 1000;
730         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
731     }
732
733     if (m_diskCacheSizeOverride >= 0)
734         urlCacheDiskCapacity = m_diskCacheSizeOverride;
735
736     if (m_cache)
737         m_cache->setCapacity(urlCacheDiskCapacity);
738 }
739
740 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
741 {
742     m_canHandleHTTPSServerTrustEvaluation = value;
743 }
744
745 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
746 {
747     StatisticsData data;
748
749     auto& networkProcess = NetworkProcess::singleton();
750     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
751     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
752
753     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
754 }
755
756 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
757 {
758     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
759 }
760
761 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
762 {
763     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
764         return;
765
766     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
767 }
768
769 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
770 {
771     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
772         return;
773
774     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
775 }
776
777 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
778 {
779     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
780         return;
781
782     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
783 }
784
785 void NetworkProcess::terminate()
786 {
787 #if ENABLE(NETWORK_CAPTURE)
788     NetworkCapture::Manager::singleton().terminate();
789 #endif
790
791     platformTerminate();
792     ChildProcess::terminate();
793 }
794
795 // FIXME: We can remove this one by adapting RefCounter.
796 class TaskCounter : public RefCounted<TaskCounter> {
797 public:
798     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
799     ~TaskCounter() { m_callback(); };
800
801 private:
802     Function<void()> m_callback;
803 };
804
805 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
806 {
807     platformPrepareToSuspend();
808     lowMemoryHandler(Critical::Yes);
809
810     RefPtr<TaskCounter> delayedTaskCounter;
811     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
812         delayedTaskCounter = adoptRef(new TaskCounter([this] {
813             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
814             if (parentProcessConnection())
815                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
816         }));
817     }
818
819     for (auto& connection : m_webProcessConnections)
820         connection->cleanupForSuspension([delayedTaskCounter] { });
821 }
822
823 void NetworkProcess::processWillSuspendImminently(bool& handled)
824 {
825     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
826     handled = true;
827 }
828
829 void NetworkProcess::prepareToSuspend()
830 {
831     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
832     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
833 }
834
835 void NetworkProcess::cancelPrepareToSuspend()
836 {
837     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
838     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
839     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
840     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
841     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
842     platformProcessDidResume();
843     for (auto& connection : m_webProcessConnections)
844         connection->endSuspension();
845 }
846
847 void NetworkProcess::processDidResume()
848 {
849     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
850     platformProcessDidResume();
851     for (auto& connection : m_webProcessConnections)
852         connection->endSuspension();
853 }
854
855 void NetworkProcess::prefetchDNS(const String& hostname)
856 {
857     WebCore::prefetchDNS(hostname);
858 }
859
860 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
861 {
862     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
863         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
864         return Vector<CacheStorageParametersCallback> { };
865     }).iterator->value.append(WTFMove(callback));
866 }
867
868 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
869 {
870     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
871     if (iterator == m_cacheStorageParametersCallbacks.end())
872         return;
873
874     SandboxExtension::consumePermanently(handle);
875     auto callbacks = WTFMove(iterator->value);
876     m_cacheStorageParametersCallbacks.remove(iterator);
877     for (auto& callback : callbacks)
878         callback(String { cacheStorageDirectory }, quota);
879 }
880
881 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
882 {
883 #if ENABLE(SERVER_PRECONNECT)
884     NetworkLoadParameters parameters;
885     parameters.request = ResourceRequest { url };
886     parameters.sessionID = PAL::SessionID::defaultSessionID();
887     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
888     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
889
890     new PreconnectTask(WTFMove(parameters));
891 #else
892     UNUSED_PARAM(url);
893     UNUSED_PARAM(storedCredentialsPolicy);
894 #endif
895 }
896
897 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
898 {
899     SchemeRegistry::registerURLSchemeAsSecure(scheme);
900 }
901
902 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
903 {
904     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
905 }
906
907 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
908 {
909     SchemeRegistry::registerURLSchemeAsLocal(scheme);
910 }
911
912 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
913 {
914     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
915 }
916
917 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
918 {
919     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
920 }
921
922 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
923 {
924     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
925 }
926
927 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
928 {
929     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
930 }
931
932 void NetworkProcess::didSyncAllCookies()
933 {
934     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
935 }
936
937 #if !PLATFORM(COCOA)
938 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
939 {
940 }
941
942 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
943 {
944 }
945
946 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
947 {
948 }
949
950 void NetworkProcess::syncAllCookies()
951 {
952 }
953
954 #endif
955
956 } // namespace WebKit