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