Move Service Worker Management from Storage Process to Network Process
[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 "NetworkProximityManager.h"
47 #include "NetworkResourceLoader.h"
48 #include "NetworkSession.h"
49 #include "NetworkSessionCreationParameters.h"
50 #include "PreconnectTask.h"
51 #include "RemoteNetworkingContext.h"
52 #include "SessionTracker.h"
53 #include "StatisticsData.h"
54 #include "WebCookieManager.h"
55 #include "WebCoreArgumentCoders.h"
56 #include "WebPageProxyMessages.h"
57 #include "WebProcessPoolMessages.h"
58 #include "WebSWOriginStore.h"
59 #include "WebSWServerConnection.h"
60 #include "WebSWServerToContextConnection.h"
61 #include "WebsiteData.h"
62 #include "WebsiteDataFetchOption.h"
63 #include "WebsiteDataStore.h"
64 #include "WebsiteDataStoreParameters.h"
65 #include "WebsiteDataType.h"
66 #include <WebCore/DNS.h>
67 #include <WebCore/DeprecatedGlobalSettings.h>
68 #include <WebCore/DiagnosticLoggingClient.h>
69 #include <WebCore/LogInitialization.h>
70 #include <WebCore/MIMETypeRegistry.h>
71 #include <WebCore/NetworkStateNotifier.h>
72 #include <WebCore/NetworkStorageSession.h>
73 #include <WebCore/ResourceRequest.h>
74 #include <WebCore/RuntimeApplicationChecks.h>
75 #include <WebCore/SchemeRegistry.h>
76 #include <WebCore/SecurityOriginData.h>
77 #include <WebCore/SecurityOriginHash.h>
78 #include <WebCore/Settings.h>
79 #include <WebCore/URLParser.h>
80 #include <pal/SessionID.h>
81 #include <wtf/Algorithms.h>
82 #include <wtf/CallbackAggregator.h>
83 #include <wtf/OptionSet.h>
84 #include <wtf/ProcessPrivilege.h>
85 #include <wtf/RunLoop.h>
86 #include <wtf/text/AtomicString.h>
87 #include <wtf/text/CString.h>
88
89 #if ENABLE(SEC_ITEM_SHIM)
90 #include "SecItemShim.h"
91 #endif
92
93 #include "NetworkCache.h"
94 #include "NetworkCacheCoders.h"
95
96 #if ENABLE(NETWORK_CAPTURE)
97 #include "NetworkCaptureManager.h"
98 #endif
99
100 #if PLATFORM(COCOA)
101 #include "NetworkSessionCocoa.h"
102 #endif
103
104 #if ENABLE(SERVICE_WORKER)
105 #include "WebSWServerToContextConnectionMessages.h"
106 #endif
107
108 namespace WebKit {
109 using namespace WebCore;
110
111 NetworkProcess& NetworkProcess::singleton()
112 {
113     static NeverDestroyed<NetworkProcess> networkProcess;
114     return networkProcess;
115 }
116
117 NetworkProcess::NetworkProcess()
118     : m_hasSetCacheModel(false)
119     , m_cacheModel(CacheModelDocumentViewer)
120     , m_diskCacheIsDisabledForTesting(false)
121     , m_canHandleHTTPSServerTrustEvaluation(true)
122 #if PLATFORM(COCOA)
123     , m_clearCacheDispatchGroup(0)
124 #endif
125     , m_storageTaskQueue(WorkQueue::create("com.apple.WebKit.StorageTask"))
126 {
127     NetworkProcessPlatformStrategies::initialize();
128
129     addSupplement<AuthenticationManager>();
130     addSupplement<WebCookieManager>();
131 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
132     addSupplement<LegacyCustomProtocolManager>();
133 #endif
134 #if ENABLE(PROXIMITY_NETWORKING)
135     addSupplement<NetworkProximityManager>();
136 #endif
137
138     NetworkStateNotifier::singleton().addListener([this](bool isOnLine) {
139         auto webProcessConnections = m_webProcessConnections;
140         for (auto& webProcessConnection : webProcessConnections)
141             webProcessConnection->setOnLineState(isOnLine);
142     });
143 }
144
145 NetworkProcess::~NetworkProcess()
146 {
147     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
148         for (auto& callback : callbacks)
149             callback(String { }, 0);
150     }
151 }
152
153 AuthenticationManager& NetworkProcess::authenticationManager()
154 {
155     return *supplement<AuthenticationManager>();
156 }
157
158 DownloadManager& NetworkProcess::downloadManager()
159 {
160     static NeverDestroyed<DownloadManager> downloadManager(*this);
161     return downloadManager;
162 }
163
164 #if ENABLE(PROXIMITY_NETWORKING)
165 NetworkProximityManager& NetworkProcess::proximityManager()
166 {
167     return *supplement<NetworkProximityManager>();
168 }
169 #endif
170
171 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
172 {
173     size_t vectorIndex = m_webProcessConnections.find(connection);
174     ASSERT(vectorIndex != notFound);
175
176     m_webProcessConnections.remove(vectorIndex);
177 }
178
179 bool NetworkProcess::shouldTerminate()
180 {
181     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
182     return false;
183 }
184
185 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
186 {
187     if (messageReceiverMap().dispatchMessage(connection, decoder))
188         return;
189
190     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
191         ChildProcess::didReceiveMessage(connection, decoder);
192         return;
193     }
194
195 #if ENABLE(CONTENT_EXTENSIONS)
196     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
197         m_NetworkContentRuleListManager.didReceiveMessage(connection, decoder);
198         return;
199     }
200 #endif
201
202 #if ENABLE(SERVICE_WORKER)
203     if (decoder.messageReceiverName() == Messages::WebSWServerToContextConnection::messageReceiverName()) {
204         ASSERT(parentProcessHasServiceWorkerEntitlement());
205         if (!parentProcessHasServiceWorkerEntitlement())
206             return;
207         if (auto* webSWConnection = connectionToContextProcessFromIPCConnection(connection)) {
208             webSWConnection->didReceiveMessage(connection, decoder);
209             return;
210         }
211     }
212 #endif
213     didReceiveNetworkProcessMessage(connection, decoder);
214 }
215
216 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
217 {
218     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
219         return;
220
221     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
222 }
223
224 void NetworkProcess::didClose(IPC::Connection&)
225 {
226     ASSERT(RunLoop::isMain());
227
228     // Make sure we flush all cookies to disk before exiting.
229     platformSyncAllCookies([this] {
230         stopRunLoop();
231     });
232 }
233
234 void NetworkProcess::didCreateDownload()
235 {
236     disableTermination();
237 }
238
239 void NetworkProcess::didDestroyDownload()
240 {
241     enableTermination();
242 }
243
244 IPC::Connection* NetworkProcess::downloadProxyConnection()
245 {
246     return parentProcessConnection();
247 }
248
249 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
250 {
251     return authenticationManager();
252 }
253
254 void NetworkProcess::lowMemoryHandler(Critical critical)
255 {
256     if (m_suppressMemoryPressureHandler)
257         return;
258
259     WTF::releaseFastMallocFreeMemory();
260 }
261
262 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
263 {
264 #if HAVE(SEC_KEY_PROXY)
265     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
266 #else
267     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
268 #endif
269     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
270     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
271     platformInitializeNetworkProcess(parameters);
272
273     WTF::Thread::setCurrentThreadIsUserInitiated();
274     AtomicString::init();
275
276     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
277     m_loadThrottleLatency = parameters.loadThrottleLatency;
278     if (!m_suppressMemoryPressureHandler) {
279         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
280         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
281             lowMemoryHandler(critical);
282         });
283         memoryPressureHandler.install();
284     }
285
286 #if ENABLE(NETWORK_CAPTURE)
287     NetworkCapture::Manager::singleton().initialize(
288         parameters.recordReplayMode,
289         parameters.recordReplayCacheLocation);
290 #endif
291
292     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
293
294     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
295     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
296
297     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
298
299     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
300     if (parameters.privateBrowsingEnabled)
301         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
302
303     if (parameters.shouldUseTestingNetworkSession)
304         NetworkStorageSession::switchToNewTestingSession();
305
306 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
307     m_logCookieInformation = parameters.logCookieInformation;
308 #endif
309
310     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(NetworkSessionCreationParameters()));
311
312 #if ENABLE(INDEXED_DATABASE)
313     addIndexedDatabaseSession(PAL::SessionID::defaultSessionID(), parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
314 #endif
315
316 #if ENABLE(SERVICE_WORKER)
317     if (parentProcessHasServiceWorkerEntitlement()) {
318         addServiceWorkerSession(PAL::SessionID::defaultSessionID(), parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
319
320         for (auto& scheme : parameters.urlSchemesServiceWorkersCanHandle)
321             registerURLSchemeServiceWorkersCanHandle(scheme);
322
323         m_shouldDisableServiceWorkerProcessTerminationDelay = parameters.shouldDisableServiceWorkerProcessTerminationDelay;
324     }
325 #endif
326
327     auto* defaultSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID());
328     for (const auto& cookie : parameters.defaultSessionPendingCookies)
329         defaultSession->networkStorageSession().setCookie(cookie);
330
331     for (auto& supplement : m_supplements.values())
332         supplement->initialize(parameters);
333
334     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
335         registerURLSchemeAsSecure(scheme);
336
337     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
338         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
339
340     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
341         registerURLSchemeAsLocal(scheme);
342
343     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
344         registerURLSchemeAsNoAccess(scheme);
345
346     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
347         registerURLSchemeAsDisplayIsolated(scheme);
348
349     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
350         registerURLSchemeAsCORSEnabled(scheme);
351
352     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
353         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
354
355     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
356 }
357
358 void NetworkProcess::initializeConnection(IPC::Connection* connection)
359 {
360     ChildProcess::initializeConnection(connection);
361
362     for (auto& supplement : m_supplements.values())
363         supplement->initializeConnection(connection);
364 }
365
366 void NetworkProcess::createNetworkConnectionToWebProcess(bool isServiceWorkerProcess, WebCore::SecurityOriginData&& securityOrigin)
367 {
368 #if USE(UNIX_DOMAIN_SOCKETS)
369     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
370
371     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
372     m_webProcessConnections.append(WTFMove(connection));
373
374     IPC::Attachment clientSocket(socketPair.client);
375     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
376 #elif OS(DARWIN)
377     // Create the listening port.
378     mach_port_t listeningPort = MACH_PORT_NULL;
379     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
380     if (kr != KERN_SUCCESS) {
381         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
382         CRASH();
383     }
384     if (!MACH_PORT_VALID(listeningPort)) {
385         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
386         CRASH();
387     }
388
389     // Create a listening connection.
390     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
391     m_webProcessConnections.append(WTFMove(connection));
392
393     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
394     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
395 #elif OS(WINDOWS)
396     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
397     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
398         LOG_ERROR("Failed to create server and client identifiers");
399         CRASH();
400     }
401
402     auto connection = NetworkConnectionToWebProcess::create(serverIdentifier);
403     m_webProcessConnections.append(WTFMove(connection));
404
405     IPC::Attachment clientSocket(clientIdentifier);
406     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
407 #else
408     notImplemented();
409 #endif
410
411     if (!m_webProcessConnections.isEmpty())
412         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
413     
414 #if ENABLE(SERVICE_WORKER)
415     if (isServiceWorkerProcess && !m_webProcessConnections.isEmpty()) {
416         ASSERT(parentProcessHasServiceWorkerEntitlement());
417         ASSERT(m_waitingForServerToContextProcessConnection);
418         auto contextConnection = WebSWServerToContextConnection::create(securityOrigin, m_webProcessConnections.last()->connection());
419         auto addResult = m_serverToContextConnections.add(WTFMove(securityOrigin), contextConnection.copyRef());
420         ASSERT_UNUSED(addResult, addResult.isNewEntry);
421
422         m_waitingForServerToContextProcessConnection = false;
423
424         for (auto* server : SWServer::allServers())
425             server->serverToContextConnectionCreated(contextConnection);
426     }
427 #else
428     UNUSED_PARAM(isServiceWorkerProcess);
429     UNUSED_PARAM(securityOrigin);
430 #endif
431 }
432
433 void NetworkProcess::clearCachedCredentials()
434 {
435     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
436     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
437         networkSession->clearCredentials();
438     else
439         ASSERT_NOT_REACHED();
440 }
441
442 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
443 {
444 #if ENABLE(INDEXED_DATABASE)
445     addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
446 #endif
447
448 #if ENABLE(SERVICE_WORKER)
449     if (parentProcessHasServiceWorkerEntitlement())
450         addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
451 #endif
452
453     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
454 }
455
456 void NetworkProcess::destroySession(PAL::SessionID sessionID)
457 {
458     SessionTracker::destroySession(sessionID);
459     m_sessionsControlledByAutomation.remove(sessionID);
460     CacheStorage::Engine::destroyEngine(sessionID);
461
462 #if ENABLE(SERVICE_WORKER)
463     m_swServers.remove(sessionID);
464     m_swDatabasePaths.remove(sessionID);
465 #endif
466 }
467
468 void NetworkProcess::writeBlobToFilePath(const WebCore::URL& url, const String& path, SandboxExtension::Handle&& handleForWriting, uint64_t requestID)
469 {
470     auto extension = SandboxExtension::create(WTFMove(handleForWriting));
471     if (!extension) {
472         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(false, requestID), 0);
473         return;
474     }
475
476     extension->consume();
477     NetworkBlobRegistry::singleton().writeBlobToFilePath(url, path, [this, extension = WTFMove(extension), requestID] (bool success) {
478         extension->revoke();
479         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(success, requestID), 0);
480     });
481 }
482
483 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
484 void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<String>& domainsToBlock, bool shouldClearFirst, uint64_t contextId)
485 {
486     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
487         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock, shouldClearFirst);
488     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdateBlockCookies(contextId), 0);
489 }
490
491 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
492 {
493     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
494         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
495     else
496         ASSERT_NOT_REACHED();
497 }
498
499 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
500 {
501     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
502         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
503     else
504         ASSERT_NOT_REACHED();
505 }
506
507 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
508 {
509     bool isStorageGranted = false;
510     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
511         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
512         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
513         isStorageGranted = true;
514     } else
515         ASSERT_NOT_REACHED();
516
517     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
518 }
519
520 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
521 {
522     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
523         networkStorageSession->removeAllStorageAccess();
524     else
525         ASSERT_NOT_REACHED();
526     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidRemoveAllStorageAccess(contextId), 0);
527 }
528
529 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
530 {
531     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
532         networkStorageSession->removePrevalentDomains(domains);
533 }
534
535 void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, uint64_t contextId)
536 {
537     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
538         networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
539     else
540         ASSERT_NOT_REACHED();
541     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSetCacheMaxAgeCapForPrevalentResources(contextId), 0);
542 }
543
544 void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, uint64_t contextId)
545 {
546     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
547         networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
548     else
549         ASSERT_NOT_REACHED();
550     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidResetCacheMaxAgeCapForPrevalentResources(contextId), 0);
551 }
552 #endif
553
554 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
555 {
556     return m_sessionsControlledByAutomation.contains(sessionID);
557 }
558
559 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
560 {
561     if (controlled)
562         m_sessionsControlledByAutomation.add(sessionID);
563     else
564         m_sessionsControlledByAutomation.remove(sessionID);
565 }
566
567 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
568 {
569     if (auto* cache = NetworkProcess::singleton().cache()) {
570         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
571         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
572             if (!traversalEntry) {
573                 Vector<WebsiteData::Entry> entries;
574
575                 for (auto& originAndSize : originsAndSizes)
576                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
577
578                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
579                     completionHandler(entries);
580                 });
581
582                 return;
583             }
584
585             auto url = traversalEntry->entry.response().url();
586             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
587
588             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
589                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
590         });
591
592         return;
593     }
594
595     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
596         completionHandler({ });
597     });
598 }
599
600 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
601 {
602     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
603         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
604             : m_completionHandler(WTFMove(completionHandler))
605         {
606         }
607
608         ~CallbackAggregator()
609         {
610             ASSERT(RunLoop::isMain());
611
612             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
613                 completionHandler(websiteData);
614             });
615         }
616
617         Function<void (WebsiteData)> m_completionHandler;
618         WebsiteData m_websiteData;
619     };
620
621     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
622         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
623     }));
624
625     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
626         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
627             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
628     }
629
630     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
631         if (NetworkStorageSession::storageSession(sessionID))
632             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
633     }
634
635     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
636         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
637             callbackAggregator->m_websiteData.entries.appendVector(entries);
638         });
639     }
640
641 #if PLATFORM(COCOA)
642     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
643         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
644             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
645     }
646 #endif
647
648 #if ENABLE(INDEXED_DATABASE)
649     auto path = m_idbDatabasePaths.get(sessionID);
650     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
651         // FIXME: Pick the right database store based on the session ID.
652         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
653             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
654                 for (const auto& securityOrigin : securityOrigins)
655                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
656             });
657         }));
658     }
659 #endif
660
661 #if ENABLE(SERVICE_WORKER)
662     path = m_swDatabasePaths.get(sessionID);
663     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
664         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
665             for (auto& origin : securityOrigins)
666                 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
667         });
668     }
669 #endif
670
671     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
672         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
673             callbackAggregator->m_websiteData.entries.appendVector(entries);
674         });
675     }
676 }
677
678 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
679 {
680 #if PLATFORM(COCOA)
681     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
682         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
683             clearHSTSCache(*networkStorageSession, modifiedSince);
684     }
685 #endif
686
687     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
688         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
689             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
690     }
691
692     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
693         if (NetworkStorageSession::storageSession(sessionID))
694             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
695     }
696
697     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
698         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
699     });
700
701     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
702         CacheStorage::Engine::clearAllCaches(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
703
704 #if ENABLE(INDEXED_DATABASE)
705     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
706         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
707 #endif
708
709 #if ENABLE(SERVICE_WORKER)
710     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
711         swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
712 #endif
713
714     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
715         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
716 }
717
718 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
719 {
720     if (auto* cache = NetworkProcess::singleton().cache()) {
721         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
722         for (auto& origin : origins)
723             originsToDelete.add(origin.securityOrigin());
724
725         Vector<NetworkCache::Key> cacheKeysToDelete;
726         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
727             if (traversalEntry) {
728                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
729                     cacheKeysToDelete.append(traversalEntry->entry.key());
730                 return;
731             }
732
733             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
734             return;
735         });
736
737         return;
738     }
739
740     RunLoop::main().dispatch(WTFMove(completionHandler));
741 }
742
743 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
744 {
745     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
746         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
747             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
748     }
749
750 #if PLATFORM(COCOA)
751     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
752         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
753             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
754     }
755 #endif
756
757     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
758         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
759     });
760
761     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
762         for (auto& originData : originDatas)
763             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
764     }
765
766 #if ENABLE(INDEXED_DATABASE)
767     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
768         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
769 #endif
770
771 #if ENABLE(SERVICE_WORKER)
772     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
773         auto& server = swServerForSession(sessionID);
774         for (auto& originData : originDatas)
775             server.clear(originData, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
776     }
777 #endif
778
779     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
780         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
781 }
782
783 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
784 {
785     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
786 }
787
788 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
789 {
790     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
791 }
792
793 void NetworkProcess::cancelDownload(DownloadID downloadID)
794 {
795     downloadManager().cancelDownload(downloadID);
796 }
797
798 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
799 {
800     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
801 }
802
803 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
804 {
805     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
806 }
807
808 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
809 {
810     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
811     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
812
813     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
814
815     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
816     // should override the suggested filename from the download attribute.
817     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
818     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
819
820     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
821 }
822
823 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
824 {
825     if (destination.isEmpty())
826         downloadManager().cancelDownload(downloadID);
827     else
828         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
829 }
830
831 void NetworkProcess::setCacheModel(uint32_t cm)
832 {
833     CacheModel cacheModel = static_cast<CacheModel>(cm);
834
835     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
836         return;
837
838     m_hasSetCacheModel = true;
839     m_cacheModel = cacheModel;
840
841     unsigned urlCacheMemoryCapacity = 0;
842     uint64_t urlCacheDiskCapacity = 0;
843     uint64_t diskFreeSize = 0;
844     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
845         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
846         // count doesn't align exactly to a megabyte boundary.
847         diskFreeSize /= KB * 1000;
848         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
849     }
850
851     if (m_diskCacheSizeOverride >= 0)
852         urlCacheDiskCapacity = m_diskCacheSizeOverride;
853
854     if (m_cache)
855         m_cache->setCapacity(urlCacheDiskCapacity);
856 }
857
858 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
859 {
860     m_canHandleHTTPSServerTrustEvaluation = value;
861 }
862
863 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
864 {
865     StatisticsData data;
866
867     auto& networkProcess = NetworkProcess::singleton();
868     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
869     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
870
871     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
872 }
873
874 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
875 {
876     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
877 }
878
879 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
880 {
881     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
882         return;
883
884     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
885 }
886
887 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
888 {
889     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
890         return;
891
892     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
893 }
894
895 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
896 {
897     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
898         return;
899
900     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
901 }
902
903 void NetworkProcess::terminate()
904 {
905 #if ENABLE(NETWORK_CAPTURE)
906     NetworkCapture::Manager::singleton().terminate();
907 #endif
908
909     platformTerminate();
910     ChildProcess::terminate();
911 }
912
913 void NetworkProcess::processDidTransitionToForeground()
914 {
915     platformProcessDidTransitionToForeground();
916 }
917
918 void NetworkProcess::processDidTransitionToBackground()
919 {
920     platformProcessDidTransitionToBackground();
921 }
922
923 // FIXME: We can remove this one by adapting RefCounter.
924 class TaskCounter : public RefCounted<TaskCounter> {
925 public:
926     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
927     ~TaskCounter() { m_callback(); };
928
929 private:
930     Function<void()> m_callback;
931 };
932
933 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
934 {
935     lowMemoryHandler(Critical::Yes);
936
937     RefPtr<TaskCounter> delayedTaskCounter;
938     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
939         delayedTaskCounter = adoptRef(new TaskCounter([this] {
940             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
941             if (parentProcessConnection())
942                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
943         }));
944     }
945
946     platformPrepareToSuspend([delayedTaskCounter] { });
947     platformSyncAllCookies([delayedTaskCounter] { });
948
949     for (auto& connection : m_webProcessConnections)
950         connection->cleanupForSuspension([delayedTaskCounter] { });
951 }
952
953 void NetworkProcess::processWillSuspendImminently(bool& handled)
954 {
955     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
956     handled = true;
957 }
958
959 void NetworkProcess::prepareToSuspend()
960 {
961     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
962     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
963 }
964
965 void NetworkProcess::cancelPrepareToSuspend()
966 {
967     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
968     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
969     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
970     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
971     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
972     platformProcessDidResume();
973     for (auto& connection : m_webProcessConnections)
974         connection->endSuspension();
975 }
976
977 void NetworkProcess::processDidResume()
978 {
979     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
980     platformProcessDidResume();
981     for (auto& connection : m_webProcessConnections)
982         connection->endSuspension();
983 }
984
985 void NetworkProcess::prefetchDNS(const String& hostname)
986 {
987     WebCore::prefetchDNS(hostname);
988 }
989
990 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
991 {
992     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
993         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
994         return Vector<CacheStorageParametersCallback> { };
995     }).iterator->value.append(WTFMove(callback));
996 }
997
998 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
999 {
1000     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
1001     if (iterator == m_cacheStorageParametersCallbacks.end())
1002         return;
1003
1004     SandboxExtension::consumePermanently(handle);
1005     auto callbacks = WTFMove(iterator->value);
1006     m_cacheStorageParametersCallbacks.remove(iterator);
1007     for (auto& callback : callbacks)
1008         callback(String { cacheStorageDirectory }, quota);
1009 }
1010
1011 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
1012 {
1013 #if ENABLE(SERVER_PRECONNECT)
1014     NetworkLoadParameters parameters;
1015     parameters.request = ResourceRequest { url };
1016     parameters.sessionID = PAL::SessionID::defaultSessionID();
1017     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
1018     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
1019
1020     new PreconnectTask(WTFMove(parameters));
1021 #else
1022     UNUSED_PARAM(url);
1023     UNUSED_PARAM(storedCredentialsPolicy);
1024 #endif
1025 }
1026
1027 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
1028 {
1029     SchemeRegistry::registerURLSchemeAsSecure(scheme);
1030 }
1031
1032 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
1033 {
1034     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1035 }
1036
1037 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
1038 {
1039     SchemeRegistry::registerURLSchemeAsLocal(scheme);
1040 }
1041
1042 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
1043 {
1044     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
1045 }
1046
1047 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
1048 {
1049     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
1050 }
1051
1052 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
1053 {
1054     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
1055 }
1056
1057 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
1058 {
1059     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
1060 }
1061
1062 void NetworkProcess::didSyncAllCookies()
1063 {
1064     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
1065 }
1066
1067 #if ENABLE(INDEXED_DATABASE)
1068 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
1069 {
1070     auto addResult = m_idbServers.add(sessionID, nullptr);
1071     if (!addResult.isNewEntry) {
1072         ASSERT(addResult.iterator->value);
1073         return *addResult.iterator->value;
1074     }
1075     
1076     auto path = m_idbDatabasePaths.get(sessionID);
1077     // There should already be a registered path for this PAL::SessionID.
1078     // If there's not, then where did this PAL::SessionID come from?
1079     ASSERT(!path.isEmpty());
1080     
1081     addResult.iterator->value = IDBServer::IDBServer::create(path, NetworkProcess::singleton());
1082     return *addResult.iterator->value;
1083 }
1084
1085 void NetworkProcess::ensurePathExists(const String& path)
1086 {
1087     ASSERT(!RunLoop::isMain());
1088     
1089     if (!FileSystem::makeAllDirectories(path))
1090         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
1091 }
1092
1093 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
1094 {
1095     ASSERT(RunLoop::isMain());
1096     
1097     LockHolder locker(m_storageTaskMutex);
1098     
1099     m_storageTasks.append(WTFMove(task));
1100     
1101     m_storageTaskQueue->dispatch([this] {
1102         performNextStorageTask();
1103     });
1104 }
1105
1106 void NetworkProcess::performNextStorageTask()
1107 {
1108     ASSERT(!RunLoop::isMain());
1109     
1110     CrossThreadTask task;
1111     {
1112         LockHolder locker(m_storageTaskMutex);
1113         ASSERT(!m_storageTasks.isEmpty());
1114         task = m_storageTasks.takeFirst();
1115     }
1116     
1117     task.performTask();
1118 }
1119
1120 void NetworkProcess::prepareForAccessToTemporaryFile(const String& path)
1121 {
1122     if (auto extension = m_blobTemporaryFileSandboxExtensions.get(path))
1123         extension->consume();
1124 }
1125
1126 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
1127 {
1128     // We've either hard linked the temporary blob file to the database directory, copied it there,
1129     // or the transaction is being aborted.
1130     // In any of those cases, we can delete the temporary blob file now.
1131     FileSystem::deleteFile(path);
1132     
1133     if (auto extension = m_blobTemporaryFileSandboxExtensions.take(path))
1134         extension->revoke();
1135 }
1136
1137 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
1138 {
1139     if (path.isEmpty())
1140         return { };
1141     
1142     HashSet<WebCore::SecurityOriginData> securityOrigins;
1143     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
1144         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
1145         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1146             securityOrigins.add(WTFMove(*securityOrigin));
1147         
1148         for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
1149             databaseIdentifier = FileSystem::pathGetFileName(originPath);
1150             if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1151                 securityOrigins.add(WTFMove(*securityOrigin));
1152         }
1153     }
1154
1155     return securityOrigins;
1156 }
1157
1158 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
1159 {
1160     // *********
1161     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
1162     // *********
1163     auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
1164     if (addResult.isNewEntry) {
1165         SandboxExtension::consumePermanently(handle);
1166         if (!indexedDatabaseDirectory.isEmpty())
1167             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
1168     }
1169 }
1170
1171 #endif // ENABLE(INDEXED_DATABASE)
1172
1173 #if ENABLE(SANDBOX_EXTENSIONS)
1174 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, Function<void(SandboxExtension::HandleArray&&)>&& completionHandler)
1175 {
1176     static uint64_t lastRequestID;
1177     
1178     uint64_t requestID = ++lastRequestID;
1179     m_sandboxExtensionForBlobsCompletionHandlersStorageForNetworkProcess.set(requestID, WTFMove(completionHandler));
1180     parentProcessConnection()->send(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(requestID, filenames), 0);
1181 }
1182
1183 void NetworkProcess::didGetSandboxExtensionsForBlobFiles(uint64_t requestID, SandboxExtension::HandleArray&& handles)
1184 {
1185     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlersStorageForNetworkProcess.take(requestID))
1186         handler(WTFMove(handles));
1187 }
1188     
1189 void NetworkProcess::updateTemporaryFileSandboxExtensions(const Vector<String>& paths, SandboxExtension::HandleArray& handles)
1190 {
1191     for (size_t i = 0; i < handles.size(); ++i) {
1192         auto result = m_blobTemporaryFileSandboxExtensions.add(paths[i], SandboxExtension::create(WTFMove(handles[i])));
1193         ASSERT_UNUSED(result, result.isNewEntry);
1194     }
1195 }
1196 #endif // ENABLE(SANDBOX_EXTENSIONS)
1197
1198 #if ENABLE(SERVICE_WORKER)
1199 WebSWServerToContextConnection* NetworkProcess::connectionToContextProcessFromIPCConnection(IPC::Connection& connection)
1200 {
1201     for (auto& serverToContextConnection : m_serverToContextConnections.values()) {
1202         if (serverToContextConnection->ipcConnection() == &connection)
1203             return serverToContextConnection.get();
1204     }
1205     return nullptr;
1206 }
1207
1208 void NetworkProcess::connectionToContextProcessWasClosed(Ref<WebSWServerToContextConnection>&& serverToContextConnection)
1209 {
1210     auto& securityOrigin = serverToContextConnection->securityOrigin();
1211     
1212     serverToContextConnection->connectionClosed();
1213     m_serverToContextConnections.remove(securityOrigin);
1214     
1215     for (auto& swServer : m_swServers.values())
1216         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1217     
1218     if (needsServerToContextConnectionForOrigin(securityOrigin)) {
1219         RELEASE_LOG(ServiceWorker, "Connection to service worker process was closed but is still needed, relaunching it");
1220         createServerToContextConnection(securityOrigin, std::nullopt);
1221     }
1222 }
1223
1224 bool NetworkProcess::needsServerToContextConnectionForOrigin(const SecurityOriginData& securityOrigin) const
1225 {
1226     return WTF::anyOf(m_swServers.values(), [&](auto& swServer) {
1227         return swServer->needsServerToContextConnectionForOrigin(securityOrigin);
1228     });
1229 }
1230
1231 SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
1232 {
1233     ASSERT(sessionID.isValid());
1234     
1235     auto result = m_swServers.ensure(sessionID, [&] {
1236         auto path = m_swDatabasePaths.get(sessionID);
1237         // There should already be a registered path for this PAL::SessionID.
1238         // If there's not, then where did this PAL::SessionID come from?
1239         ASSERT(sessionID.isEphemeral() || !path.isEmpty());
1240         
1241         auto value = std::make_unique<SWServer>(makeUniqueRef<WebSWOriginStore>(), WTFMove(path), sessionID);
1242         if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1243             value->disableServiceWorkerProcessTerminationDelay();
1244         return value;
1245     });
1246
1247     return *result.iterator->value;
1248 }
1249
1250 WebSWOriginStore& NetworkProcess::swOriginStoreForSession(PAL::SessionID sessionID)
1251 {
1252     return static_cast<WebSWOriginStore&>(swServerForSession(sessionID).originStore());
1253 }
1254
1255 WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
1256 {
1257     auto* swServer = m_swServers.get(sessionID);
1258     if (!swServer)
1259         return nullptr;
1260     return &static_cast<WebSWOriginStore&>(swServer->originStore());
1261 }
1262
1263 WebSWServerToContextConnection* NetworkProcess::serverToContextConnectionForOrigin(const SecurityOriginData& securityOrigin)
1264 {
1265     return m_serverToContextConnections.get(securityOrigin);
1266 }
1267
1268 void NetworkProcess::createServerToContextConnection(const SecurityOriginData& securityOrigin, std::optional<PAL::SessionID> sessionID)
1269 {
1270     if (m_waitingForServerToContextProcessConnection)
1271         return;
1272     
1273     m_waitingForServerToContextProcessConnection = true;
1274     if (sessionID)
1275         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcessForExplicitSession(securityOrigin, *sessionID), 0);
1276     else
1277         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess(securityOrigin), 0);
1278 }
1279
1280 void NetworkProcess::didFailFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const ResourceError& error)
1281 {
1282     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1283         connection->didFailFetch(fetchIdentifier, error);
1284 }
1285
1286 void NetworkProcess::didNotHandleFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1287 {
1288     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1289         connection->didNotHandleFetch(fetchIdentifier);
1290 }
1291
1292 void NetworkProcess::didReceiveFetchResponse(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const WebCore::ResourceResponse& response)
1293 {
1294     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1295         connection->didReceiveFetchResponse(fetchIdentifier, response);
1296 }
1297
1298 void NetworkProcess::didReceiveFetchData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::DataReference& data, int64_t encodedDataLength)
1299 {
1300     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1301         connection->didReceiveFetchData(fetchIdentifier, data, encodedDataLength);
1302 }
1303
1304 void NetworkProcess::didReceiveFetchFormData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::FormDataReference& formData)
1305 {
1306     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1307         connection->didReceiveFetchFormData(fetchIdentifier, formData);
1308 }
1309
1310 void NetworkProcess::didFinishFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1311 {
1312     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1313         connection->didFinishFetch(fetchIdentifier);
1314 }
1315
1316 void NetworkProcess::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, MessageWithMessagePorts&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
1317 {
1318     if (auto* connection = m_swServerConnections.get(destinationIdentifier.serverConnectionIdentifier))
1319         connection->postMessageToServiceWorkerClient(destinationIdentifier.contextIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
1320 }
1321
1322 void NetworkProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, WebCore::MessageWithMessagePorts&& message, const WebCore::ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
1323 {
1324     if (auto* connection = m_swServerConnections.get(connectionIdentifier))
1325         connection->postMessageToServiceWorker(destination, WTFMove(message), source);
1326 }
1327
1328 void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
1329 {
1330     ASSERT(parentProcessHasServiceWorkerEntitlement());
1331     ASSERT(!m_swServerConnections.contains(connection.identifier()));
1332     m_swServerConnections.add(connection.identifier(), &connection);
1333     swOriginStoreForSession(connection.sessionID()).registerSWServerConnection(connection);
1334 }
1335
1336 void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
1337 {
1338     ASSERT(m_swServerConnections.get(connection.identifier()) == &connection);
1339     m_swServerConnections.remove(connection.identifier());
1340     if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
1341         store->unregisterSWServerConnection(connection);
1342 }
1343
1344 void NetworkProcess::swContextConnectionMayNoLongerBeNeeded(WebSWServerToContextConnection& serverToContextConnection)
1345 {
1346     auto& securityOrigin = serverToContextConnection.securityOrigin();
1347     if (needsServerToContextConnectionForOrigin(securityOrigin))
1348         return;
1349     
1350     RELEASE_LOG(ServiceWorker, "Service worker process is no longer needed, terminating it");
1351     serverToContextConnection.terminate();
1352     
1353     for (auto& swServer : m_swServers.values())
1354         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1355     
1356     serverToContextConnection.connectionClosed();
1357     m_serverToContextConnections.remove(securityOrigin);
1358 }
1359
1360 void NetworkProcess::disableServiceWorkerProcessTerminationDelay()
1361 {
1362     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1363         return;
1364     
1365     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
1366     for (auto& swServer : m_swServers.values())
1367         swServer->disableServiceWorkerProcessTerminationDelay();
1368 }
1369
1370 void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
1371 {
1372     auto addResult = m_swDatabasePaths.add(sessionID, serviceWorkerRegistrationDirectory);
1373     if (addResult.isNewEntry) {
1374         SandboxExtension::consumePermanently(handle);
1375         if (!serviceWorkerRegistrationDirectory.isEmpty())
1376             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
1377     }
1378 }
1379 #endif // ENABLE(SERVICE_WORKER)
1380
1381 #if !PLATFORM(COCOA)
1382 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
1383 {
1384 }
1385
1386 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1387 {
1388 }
1389
1390 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1391 {
1392 }
1393
1394 void NetworkProcess::syncAllCookies()
1395 {
1396 }
1397
1398 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
1399 {
1400     completionHandler();
1401 }
1402
1403 #endif
1404
1405 } // namespace WebKit