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