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