API tests using permanent credentials should clear credentials left by previous tests
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2019 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 "AuxiliaryProcessMessages.h"
34 #include "DataReference.h"
35 #include "Download.h"
36 #include "DownloadProxyMessages.h"
37 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
38 #include "LegacyCustomProtocolManager.h"
39 #endif
40 #include "Logging.h"
41 #include "NetworkConnectionToWebProcess.h"
42 #include "NetworkContentRuleListManagerMessages.h"
43 #include "NetworkLoad.h"
44 #include "NetworkProcessCreationParameters.h"
45 #include "NetworkProcessPlatformStrategies.h"
46 #include "NetworkProcessProxyMessages.h"
47 #include "NetworkResourceLoadMap.h"
48 #include "NetworkResourceLoader.h"
49 #include "NetworkSession.h"
50 #include "NetworkSessionCreationParameters.h"
51 #include "PreconnectTask.h"
52 #include "RemoteNetworkingContext.h"
53 #include "ShouldGrandfatherStatistics.h"
54 #include "StatisticsData.h"
55 #include "StorageAccessStatus.h"
56 #include "StorageManager.h"
57 #include "StorageManagerMessages.h"
58 #include "WebCookieManager.h"
59 #include "WebPageProxyMessages.h"
60 #include "WebProcessPoolMessages.h"
61 #include "WebResourceLoadStatisticsStore.h"
62 #include "WebSWOriginStore.h"
63 #include "WebSWServerConnection.h"
64 #include "WebSWServerToContextConnection.h"
65 #include "WebsiteDataFetchOption.h"
66 #include "WebsiteDataStore.h"
67 #include "WebsiteDataStoreParameters.h"
68 #include "WebsiteDataType.h"
69 #include <WebCore/CookieJar.h>
70 #include <WebCore/DNS.h>
71 #include <WebCore/DeprecatedGlobalSettings.h>
72 #include <WebCore/DiagnosticLoggingClient.h>
73 #include <WebCore/LogInitialization.h>
74 #include <WebCore/MIMETypeRegistry.h>
75 #include <WebCore/NetworkStateNotifier.h>
76 #include <WebCore/NetworkStorageSession.h>
77 #include <WebCore/ResourceRequest.h>
78 #include <WebCore/RuntimeApplicationChecks.h>
79 #include <WebCore/RuntimeEnabledFeatures.h>
80 #include <WebCore/SchemeRegistry.h>
81 #include <WebCore/SecurityOriginData.h>
82 #include <WebCore/StorageQuotaManager.h>
83 #include <wtf/Algorithms.h>
84 #include <wtf/CallbackAggregator.h>
85 #include <wtf/OptionSet.h>
86 #include <wtf/ProcessPrivilege.h>
87 #include <wtf/RunLoop.h>
88 #include <wtf/UniqueRef.h>
89 #include <wtf/text/AtomString.h>
90
91 #if ENABLE(SEC_ITEM_SHIM)
92 #include "SecItemShim.h"
93 #endif
94
95 #include "NetworkCache.h"
96 #include "NetworkCacheCoders.h"
97
98 #if PLATFORM(COCOA)
99 #include "NetworkSessionCocoa.h"
100 #endif
101
102 #if USE(SOUP)
103 #include "NetworkSessionSoup.h"
104 #include <WebCore/DNSResolveQueueSoup.h>
105 #include <WebCore/SoupNetworkSession.h>
106 #endif
107
108 #if USE(CURL)
109 #include <WebCore/CurlContext.h>
110 #endif
111
112 #if ENABLE(SERVICE_WORKER)
113 #include "WebSWServerToContextConnectionMessages.h"
114 #endif
115
116 namespace WebKit {
117 using namespace WebCore;
118
119 static void callExitSoon(IPC::Connection*)
120 {
121     // If the connection has been closed and we haven't responded in the main thread for 10 seconds
122     // the process will exit forcibly.
123     auto watchdogDelay = 10_s;
124
125     WorkQueue::create("com.apple.WebKit.NetworkProcess.WatchDogQueue")->dispatchAfter(watchdogDelay, [] {
126         // We use _exit here since the watchdog callback is called from another thread and we don't want
127         // global destructors or atexit handlers to be called from this thread while the main thread is busy
128         // doing its thing.
129         RELEASE_LOG_ERROR(IPC, "Exiting process early due to unacknowledged closed-connection");
130         _exit(EXIT_FAILURE);
131     });
132 }
133
134 NetworkProcess::NetworkProcess(AuxiliaryProcessInitializationParameters&& parameters)
135     : m_downloadManager(*this)
136 #if ENABLE(CONTENT_EXTENSIONS)
137     , m_networkContentRuleListManager(*this)
138 #endif
139 #if PLATFORM(IOS_FAMILY)
140     , m_webSQLiteDatabaseTracker([this](bool isHoldingLockedFiles) { parentProcessConnection()->send(Messages::NetworkProcessProxy::SetIsHoldingLockedFiles(isHoldingLockedFiles), 0); })
141 #endif
142 {
143     NetworkProcessPlatformStrategies::initialize();
144
145     addSupplement<AuthenticationManager>();
146     addSupplement<WebCookieManager>();
147 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
148     addSupplement<LegacyCustomProtocolManager>();
149 #endif
150 #if PLATFORM(COCOA) || USE(SOUP)
151     LegacyCustomProtocolManager::networkProcessCreated(*this);
152 #endif
153
154 #if USE(SOUP)
155     DNSResolveQueueSoup::setGlobalDefaultSoupSessionAccessor([this]() -> SoupSession* {
156         return static_cast<NetworkSessionSoup&>(*networkSession(PAL::SessionID::defaultSessionID())).soupSession();
157     });
158 #endif
159
160     NetworkStateNotifier::singleton().addListener([weakThis = makeWeakPtr(*this)](bool isOnLine) {
161         if (!weakThis)
162             return;
163         for (auto& webProcessConnection : weakThis->m_webProcessConnections)
164             webProcessConnection->setOnLineState(isOnLine);
165     });
166
167     initialize(WTFMove(parameters));
168 }
169
170 NetworkProcess::~NetworkProcess()
171 {
172     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
173         for (auto& callback : callbacks)
174             callback(String { });
175     }
176 }
177
178 AuthenticationManager& NetworkProcess::authenticationManager()
179 {
180     return *supplement<AuthenticationManager>();
181 }
182
183 DownloadManager& NetworkProcess::downloadManager()
184 {
185     return m_downloadManager;
186 }
187
188 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess& connection)
189 {
190     auto count = m_webProcessConnections.removeAllMatching([&] (const auto& c) {
191         return c.ptr() == &connection;
192     });
193     ASSERT_UNUSED(count, count == 1);
194 }
195
196 bool NetworkProcess::shouldTerminate()
197 {
198     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
199     return false;
200 }
201
202 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
203 {
204     if (messageReceiverMap().dispatchMessage(connection, decoder))
205         return;
206
207     if (decoder.messageReceiverName() == Messages::AuxiliaryProcess::messageReceiverName()) {
208         AuxiliaryProcess::didReceiveMessage(connection, decoder);
209         return;
210     }
211
212 #if ENABLE(CONTENT_EXTENSIONS)
213     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
214         m_networkContentRuleListManager.didReceiveMessage(connection, decoder);
215         return;
216     }
217 #endif
218
219 #if ENABLE(SERVICE_WORKER)
220     if (decoder.messageReceiverName() == Messages::WebSWServerToContextConnection::messageReceiverName()) {
221         ASSERT(parentProcessHasServiceWorkerEntitlement());
222         if (!parentProcessHasServiceWorkerEntitlement())
223             return;
224         if (auto* webSWConnection = connectionToContextProcessFromIPCConnection(connection)) {
225             webSWConnection->didReceiveMessage(connection, decoder);
226             return;
227         }
228     }
229 #endif
230     didReceiveNetworkProcessMessage(connection, decoder);
231 }
232
233 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
234 {
235     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
236         return;
237
238     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
239 }
240
241 void NetworkProcess::didClose(IPC::Connection&)
242 {
243     ASSERT(RunLoop::isMain());
244
245     // Make sure we flush all cookies to disk before exiting.
246     platformSyncAllCookies([this] {
247         stopRunLoop();
248     });
249 }
250
251 void NetworkProcess::didCreateDownload()
252 {
253     disableTermination();
254 }
255
256 void NetworkProcess::didDestroyDownload()
257 {
258     enableTermination();
259 }
260
261 IPC::Connection* NetworkProcess::downloadProxyConnection()
262 {
263     return parentProcessConnection();
264 }
265
266 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
267 {
268     return authenticationManager();
269 }
270
271 void NetworkProcess::lowMemoryHandler(Critical critical)
272 {
273     if (m_suppressMemoryPressureHandler)
274         return;
275
276     WTF::releaseFastMallocFreeMemory();
277
278     forEachNetworkSession([](auto& networkSession) {
279         networkSession.clearPrefetchCache();
280     });
281 }
282
283 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
284 {
285 #if HAVE(SEC_KEY_PROXY)
286     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
287 #else
288     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
289 #endif
290     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
291     platformInitializeNetworkProcess(parameters);
292
293     WTF::Thread::setCurrentThreadIsUserInitiated();
294     AtomString::init();
295
296     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
297     if (!m_suppressMemoryPressureHandler) {
298         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
299         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
300             lowMemoryHandler(critical);
301         });
302         memoryPressureHandler.install();
303     }
304
305     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
306
307     setCacheModel(parameters.cacheModel);
308
309     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
310
311     if (parameters.shouldUseTestingNetworkSession)
312         switchToNewTestingSession();
313
314     WebCore::RuntimeEnabledFeatures::sharedFeatures().setIsITPDatabaseEnabled(parameters.shouldEnableITPDatabase);
315
316     WebCore::RuntimeEnabledFeatures::sharedFeatures().setAdClickAttributionDebugModeEnabled(parameters.enableAdClickAttributionDebugMode);
317
318     SandboxExtension::consumePermanently(parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectoryExtensionHandle);
319
320     auto sessionID = parameters.defaultDataStoreParameters.networkSessionParameters.sessionID;
321     setSession(sessionID, NetworkSession::create(*this, WTFMove(parameters.defaultDataStoreParameters.networkSessionParameters)));
322
323 #if ENABLE(INDEXED_DATABASE)
324     addIndexedDatabaseSession(sessionID, parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle);
325 #endif
326
327 #if ENABLE(SERVICE_WORKER)
328     if (parentProcessHasServiceWorkerEntitlement()) {
329         addServiceWorkerSession(PAL::SessionID::defaultSessionID(), parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
330
331         for (auto& scheme : parameters.urlSchemesServiceWorkersCanHandle)
332             registerURLSchemeServiceWorkersCanHandle(scheme);
333
334         m_shouldDisableServiceWorkerProcessTerminationDelay = parameters.shouldDisableServiceWorkerProcessTerminationDelay;
335     }
336 #endif
337     initializeStorageQuota(parameters.defaultDataStoreParameters);
338
339     auto* defaultSession = networkSession(PAL::SessionID::defaultSessionID());
340     auto* defaultStorageSession = defaultSession->networkStorageSession();
341     for (const auto& cookie : parameters.defaultDataStoreParameters.pendingCookies)
342         defaultStorageSession->setCookie(cookie);
343
344     for (auto& supplement : m_supplements.values())
345         supplement->initialize(parameters);
346
347     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
348         registerURLSchemeAsSecure(scheme);
349
350     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
351         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
352
353     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
354         registerURLSchemeAsLocal(scheme);
355
356     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
357         registerURLSchemeAsNoAccess(scheme);
358
359     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
360         registerURLSchemeAsDisplayIsolated(scheme);
361
362     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
363         registerURLSchemeAsCORSEnabled(scheme);
364
365     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
366         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
367     
368     m_downloadMonitorSpeedMultiplier = parameters.downloadMonitorSpeedMultiplier;
369
370     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
371 }
372
373 void NetworkProcess::initializeConnection(IPC::Connection* connection)
374 {
375     AuxiliaryProcess::initializeConnection(connection);
376
377     // We give a chance for didClose() to get called on the main thread but forcefully call _exit() after a delay
378     // in case the main thread is unresponsive or didClose() takes too long.
379     connection->setDidCloseOnConnectionWorkQueueCallback(callExitSoon);
380
381     for (auto& supplement : m_supplements.values())
382         supplement->initializeConnection(connection);
383 }
384
385 void NetworkProcess::createNetworkConnectionToWebProcess(bool isServiceWorkerProcess, WebCore::RegistrableDomain&& registrableDomain)
386 {
387 #if USE(UNIX_DOMAIN_SOCKETS)
388     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
389
390     auto connection = NetworkConnectionToWebProcess::create(*this, socketPair.server);
391     m_webProcessConnections.append(WTFMove(connection));
392
393     IPC::Attachment clientSocket(socketPair.client);
394     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
395 #elif OS(DARWIN)
396     // Create the listening port.
397     mach_port_t listeningPort = MACH_PORT_NULL;
398     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
399     if (kr != KERN_SUCCESS) {
400         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
401         CRASH();
402     }
403     if (!MACH_PORT_VALID(listeningPort)) {
404         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
405         CRASH();
406     }
407
408     // Create a listening connection.
409     auto connection = NetworkConnectionToWebProcess::create(*this, IPC::Connection::Identifier(listeningPort));
410     m_webProcessConnections.append(WTFMove(connection));
411
412     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
413     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
414 #elif OS(WINDOWS)
415     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
416     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
417         LOG_ERROR("Failed to create server and client identifiers");
418         CRASH();
419     }
420
421     auto connection = NetworkConnectionToWebProcess::create(*this, serverIdentifier);
422     m_webProcessConnections.append(WTFMove(connection));
423
424     IPC::Attachment clientSocket(clientIdentifier);
425     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
426 #else
427     notImplemented();
428 #endif
429
430     if (!m_webProcessConnections.isEmpty())
431         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
432     
433 #if ENABLE(SERVICE_WORKER)
434     if (isServiceWorkerProcess && !m_webProcessConnections.isEmpty()) {
435         ASSERT(parentProcessHasServiceWorkerEntitlement());
436         ASSERT(m_waitingForServerToContextProcessConnection);
437         auto contextConnection = WebSWServerToContextConnection::create(*this, registrableDomain, m_webProcessConnections.last()->connection());
438         auto addResult = m_serverToContextConnections.add(WTFMove(registrableDomain), contextConnection.copyRef());
439         ASSERT_UNUSED(addResult, addResult.isNewEntry);
440
441         m_waitingForServerToContextProcessConnection = false;
442
443         for (auto* server : SWServer::allServers())
444             server->serverToContextConnectionCreated(contextConnection);
445     }
446 #else
447     UNUSED_PARAM(isServiceWorkerProcess);
448     UNUSED_PARAM(registrableDomain);
449 #endif
450 }
451
452 void NetworkProcess::clearCachedCredentials()
453 {
454     defaultStorageSession().credentialStorage().clearCredentials();
455     if (auto* networkSession = this->networkSession(PAL::SessionID::defaultSessionID()))
456         networkSession->clearCredentials();
457     else
458         ASSERT_NOT_REACHED();
459 }
460
461 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
462 {
463 #if ENABLE(INDEXED_DATABASE)
464     addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
465 #endif
466
467 #if ENABLE(SERVICE_WORKER)
468     if (parentProcessHasServiceWorkerEntitlement())
469         addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
470 #endif
471
472     initializeStorageQuota(parameters);
473
474     RemoteNetworkingContext::ensureWebsiteDataStoreSession(*this, WTFMove(parameters));
475 }
476
477 void NetworkProcess::initializeStorageQuota(const WebsiteDataStoreParameters& parameters)
478 {
479     auto& managers =  m_storageQuotaManagers.ensure(parameters.networkSessionParameters.sessionID, [] {
480         return StorageQuotaManagers { };
481     }).iterator->value;
482     managers.setDefaultQuotas(parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota);
483 }
484
485 void NetworkProcess::forEachNetworkSession(const Function<void(NetworkSession&)>& functor)
486 {
487     for (auto& session : m_networkSessions.values())
488         functor(*session);
489 }
490
491 void NetworkProcess::switchToNewTestingSession()
492 {
493 #if PLATFORM(COCOA)
494     // Session name should be short enough for shared memory region name to be under the limit, otherwise sandbox rules won't work (see <rdar://problem/13642852>).
495     String sessionName = makeString("WebKit Test-", getCurrentProcessID());
496
497     auto session = adoptCF(WebCore::createPrivateStorageSession(sessionName.createCFString().get()));
498
499     RetainPtr<CFHTTPCookieStorageRef> cookieStorage;
500     if (WebCore::NetworkStorageSession::processMayUseCookieAPI()) {
501         ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
502         if (session)
503             cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, session.get()));
504     }
505
506     m_defaultNetworkStorageSession = std::make_unique<WebCore::NetworkStorageSession>(PAL::SessionID::defaultSessionID(), WTFMove(session), WTFMove(cookieStorage));
507 #elif USE(CURL) || USE(SOUP)
508     m_defaultNetworkStorageSession = std::make_unique<WebCore::NetworkStorageSession>(PAL::SessionID::defaultSessionID());
509 #endif
510 }
511
512 #if PLATFORM(COCOA)
513 void NetworkProcess::ensureSession(const PAL::SessionID& sessionID, const String& identifierBase, RetainPtr<CFHTTPCookieStorageRef>&& cookieStorage)
514 #else
515 void NetworkProcess::ensureSession(const PAL::SessionID& sessionID, const String& identifierBase)
516 #endif
517 {
518     ASSERT(sessionID != PAL::SessionID::defaultSessionID());
519
520     auto addResult = m_networkStorageSessions.add(sessionID, nullptr);
521     if (!addResult.isNewEntry)
522         return;
523
524 #if PLATFORM(COCOA)
525     RetainPtr<CFURLStorageSessionRef> storageSession;
526     RetainPtr<CFStringRef> cfIdentifier = String(identifierBase + ".PrivateBrowsing").createCFString();
527     if (sessionID.isEphemeral())
528         storageSession = adoptCF(createPrivateStorageSession(cfIdentifier.get()));
529     else
530         storageSession = WebCore::NetworkStorageSession::createCFStorageSessionForIdentifier(cfIdentifier.get());
531
532     if (NetworkStorageSession::processMayUseCookieAPI()) {
533         ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
534         if (!cookieStorage && storageSession)
535             cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
536     }
537
538     addResult.iterator->value = std::make_unique<NetworkStorageSession>(sessionID, WTFMove(storageSession), WTFMove(cookieStorage));
539 #elif USE(CURL) || USE(SOUP)
540     addResult.iterator->value = std::make_unique<NetworkStorageSession>(sessionID);
541 #endif
542 }
543
544 WebCore::NetworkStorageSession* NetworkProcess::storageSession(const PAL::SessionID& sessionID) const
545 {
546     if (sessionID == PAL::SessionID::defaultSessionID())
547         return &defaultStorageSession();
548     return m_networkStorageSessions.get(sessionID);
549 }
550
551 WebCore::NetworkStorageSession& NetworkProcess::defaultStorageSession() const
552 {
553     if (!m_defaultNetworkStorageSession)
554         m_defaultNetworkStorageSession = platformCreateDefaultStorageSession();
555     return *m_defaultNetworkStorageSession;
556 }
557
558 void NetworkProcess::forEachNetworkStorageSession(const Function<void(WebCore::NetworkStorageSession&)>& functor)
559 {
560     functor(defaultStorageSession());
561     for (auto& storageSession : m_networkStorageSessions.values())
562         functor(*storageSession);
563 }
564
565 NetworkSession* NetworkProcess::networkSession(const PAL::SessionID& sessionID) const
566 {
567     ASSERT(RunLoop::isMain());
568     ASSERT(sessionID.isValid());
569     return sessionID.isValid() ? m_networkSessions.get(sessionID) : nullptr;
570 }
571
572 NetworkSession* NetworkProcess::networkSessionByConnection(IPC::Connection& connection) const
573 {
574     auto sessionID = m_sessionByConnection.get(connection.uniqueID());
575     return sessionID.isValid() ? networkSession(sessionID) : nullptr;
576 }
577
578 void NetworkProcess::setSession(const PAL::SessionID& sessionID, std::unique_ptr<NetworkSession>&& session)
579 {
580     ASSERT(RunLoop::isMain());
581     ASSERT(sessionID.isValid());
582     if (!sessionID.isValid())
583         return;
584
585     m_networkSessions.set(sessionID, WTFMove(session));
586 }
587
588 void NetworkProcess::destroySession(const PAL::SessionID& sessionID)
589 {
590     ASSERT(RunLoop::isMain());
591     ASSERT(sessionID.isValid());
592     if (!sessionID.isValid())
593         return;
594
595 #if !USE(SOUP)
596     // Soup based ports destroy the default session right before the process exits to avoid leaking
597     // network resources like the cookies database.
598     ASSERT(sessionID != PAL::SessionID::defaultSessionID());
599 #endif
600
601     if (auto session = m_networkSessions.take(sessionID))
602         session->invalidateAndCancel();
603     m_networkStorageSessions.remove(sessionID);
604     m_sessionsControlledByAutomation.remove(sessionID);
605     CacheStorage::Engine::destroyEngine(*this, sessionID);
606
607 #if ENABLE(SERVICE_WORKER)
608     m_swServers.remove(sessionID);
609     m_swDatabasePaths.remove(sessionID);
610 #endif
611
612     m_storageQuotaManagers.remove(sessionID);
613 }
614
615 #if ENABLE(RESOURCE_LOAD_STATISTICS)
616 void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
617 {
618     if (auto* networkSession = this->networkSession(sessionID)) {
619         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
620             resourceLoadStatistics->dumpResourceLoadStatistics(WTFMove(completionHandler));
621         else
622             completionHandler({ });
623     } else {
624         ASSERT_NOT_REACHED();
625         completionHandler({ });
626     }
627 }
628
629 void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
630 {
631     if (auto* networkStorageSession = storageSession(sessionID))
632         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
633     completionHandler();
634 }
635
636 void NetworkProcess::isGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
637 {
638     if (auto* networkSession = this->networkSession(sessionID)) {
639         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
640             resourceLoadStatistics->isGrandfathered(domain, WTFMove(completionHandler));
641         else
642             completionHandler(false);
643     } else {
644         ASSERT_NOT_REACHED();
645         completionHandler(false);
646     }
647 }
648
649 void NetworkProcess::isPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
650 {
651     if (auto* networkSession = this->networkSession(sessionID)) {
652         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
653             resourceLoadStatistics->isPrevalentResource(domain, WTFMove(completionHandler));
654         else
655             completionHandler(false);
656     } else {
657         ASSERT_NOT_REACHED();
658         completionHandler(false);
659     }
660 }
661
662 void NetworkProcess::isVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
663 {
664     if (auto* networkSession = this->networkSession(sessionID)) {
665         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
666             resourceLoadStatistics->isVeryPrevalentResource(domain, WTFMove(completionHandler));
667         else
668             completionHandler(false);
669     } else {
670         ASSERT_NOT_REACHED();
671         completionHandler(false);
672     }
673 }
674
675 void NetworkProcess::setAgeCapForClientSideCookies(PAL::SessionID sessionID, Optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
676 {
677     if (auto* networkStorageSession = storageSession(sessionID))
678         networkStorageSession->setAgeCapForClientSideCookies(seconds);
679     completionHandler();
680 }
681
682 void NetworkProcess::setGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& domain, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
683 {
684     if (auto* networkSession = this->networkSession(sessionID)) {
685         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
686             resourceLoadStatistics->setGrandfathered(domain, isGrandfathered, WTFMove(completionHandler));
687         else
688             completionHandler();
689     } else {
690         ASSERT_NOT_REACHED();
691         completionHandler();
692     }
693 }
694
695 void NetworkProcess::setPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
696 {
697     if (auto* networkSession = this->networkSession(sessionID)) {
698         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
699             resourceLoadStatistics->setPrevalentResource(domain, WTFMove(completionHandler));
700         else
701             completionHandler();
702     } else {
703         ASSERT_NOT_REACHED();
704         completionHandler();
705     }
706 }
707
708 void NetworkProcess::setPrevalentResourceForDebugMode(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
709 {
710     if (auto* networkSession = this->networkSession(sessionID)) {
711         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
712             resourceLoadStatistics->setPrevalentResourceForDebugMode(domain, WTFMove(completionHandler));
713         else
714             completionHandler();
715     } else {
716         ASSERT_NOT_REACHED();
717         completionHandler();
718     }
719 }
720
721 void NetworkProcess::setVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
722 {
723     if (auto* networkSession = this->networkSession(sessionID)) {
724         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
725             resourceLoadStatistics->setVeryPrevalentResource(domain, WTFMove(completionHandler));
726         else
727             completionHandler();
728     } else {
729         ASSERT_NOT_REACHED();
730         completionHandler();
731     }
732 }
733
734 void NetworkProcess::clearPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
735 {
736     if (auto* networkSession = this->networkSession(sessionID)) {
737         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
738             resourceLoadStatistics->clearPrevalentResource(domain, WTFMove(completionHandler));
739         else
740             completionHandler();
741     } else {
742         ASSERT_NOT_REACHED();
743         completionHandler();
744     }
745 }
746
747 void NetworkProcess::submitTelemetry(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
748 {
749     if (auto* networkSession = this->networkSession(sessionID)) {
750         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
751             resourceLoadStatistics->submitTelemetry(WTFMove(completionHandler));
752         else
753             completionHandler();
754     } else {
755         ASSERT_NOT_REACHED();
756         completionHandler();
757     }
758 }
759
760 void NetworkProcess::scheduleCookieBlockingUpdate(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
761 {
762     if (auto* networkSession = this->networkSession(sessionID)) {
763         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
764             resourceLoadStatistics->scheduleCookieBlockingUpdate(WTFMove(completionHandler));
765         else
766             completionHandler();
767     } else {
768         ASSERT_NOT_REACHED();
769         completionHandler();
770     }
771 }
772
773 void NetworkProcess::scheduleClearInMemoryAndPersistent(PAL::SessionID sessionID, Optional<WallTime> modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
774 {
775     if (auto* networkSession = this->networkSession(sessionID)) {
776         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
777             if (modifiedSince)
778                 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince.value(), shouldGrandfather, WTFMove(completionHandler));
779             else
780                 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(shouldGrandfather, WTFMove(completionHandler));
781         } else
782             completionHandler();
783     } else {
784         ASSERT_NOT_REACHED();
785         completionHandler();
786     }
787 }
788
789 void NetworkProcess::resetParametersToDefaultValues(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
790 {
791     if (auto* networkSession = this->networkSession(sessionID)) {
792         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
793             resourceLoadStatistics->resetParametersToDefaultValues(WTFMove(completionHandler));
794         else
795             completionHandler();
796     } else {
797         ASSERT_NOT_REACHED();
798         completionHandler();
799     }
800 }
801
802 void NetworkProcess::scheduleStatisticsAndDataRecordsProcessing(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
803 {
804     if (auto* networkSession = this->networkSession(sessionID)) {
805         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
806             resourceLoadStatistics->scheduleStatisticsAndDataRecordsProcessing(WTFMove(completionHandler));
807         else
808             completionHandler();
809     } else {
810         ASSERT_NOT_REACHED();
811         completionHandler();
812     }
813 }
814
815 void NetworkProcess::setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
816 {
817     if (auto* networkSession = this->networkSession(sessionID)) {
818         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
819             resourceLoadStatistics->setNotifyPagesWhenDataRecordsWereScanned(value, WTFMove(completionHandler));
820         else
821             completionHandler();
822     } else {
823         ASSERT_NOT_REACHED();
824         completionHandler();
825     }
826 }
827
828 void NetworkProcess::setIsRunningResourceLoadStatisticsTest(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
829 {
830     if (auto* networkSession = this->networkSession(sessionID)) {
831         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
832             resourceLoadStatistics->setIsRunningTest(value, WTFMove(completionHandler));
833         else
834             completionHandler();
835     } else {
836         ASSERT_NOT_REACHED();
837         completionHandler();
838     }
839 }
840
841 void NetworkProcess::setNotifyPagesWhenTelemetryWasCaptured(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
842 {
843     if (auto* networkSession = this->networkSession(sessionID)) {
844         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
845             resourceLoadStatistics->setNotifyPagesWhenTelemetryWasCaptured(value, WTFMove(completionHandler));
846         else
847             completionHandler();
848     } else {
849         ASSERT_NOT_REACHED();
850         completionHandler();
851     }
852 }
853
854 void NetworkProcess::setSubframeUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
855 {
856     if (auto* networkSession = this->networkSession(sessionID)) {
857         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
858             resourceLoadStatistics->setSubframeUnderTopFrameDomain(subFrameDomain, topFrameDomain, WTFMove(completionHandler));
859         else
860             completionHandler();
861     } else {
862         ASSERT_NOT_REACHED();
863         completionHandler();
864     }
865 }
866
867 void NetworkProcess::isRegisteredAsRedirectingTo(PAL::SessionID sessionID, const RegistrableDomain& domainRedirectedFrom, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
868 {
869     if (auto* networkSession = this->networkSession(sessionID)) {
870         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
871             resourceLoadStatistics->isRegisteredAsRedirectingTo(domainRedirectedFrom, domainRedirectedTo, WTFMove(completionHandler));
872         else
873             completionHandler(false);
874     } else {
875         ASSERT_NOT_REACHED();
876         completionHandler(false);
877     }
878 }
879
880 void NetworkProcess::isRegisteredAsSubFrameUnder(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
881 {
882     if (auto* networkSession = this->networkSession(sessionID)) {
883         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
884             resourceLoadStatistics->isRegisteredAsSubFrameUnder(subFrameDomain, topFrameDomain, WTFMove(completionHandler));
885         else
886             completionHandler(false);
887     } else {
888         ASSERT_NOT_REACHED();
889         completionHandler(false);
890     }
891 }
892
893 void NetworkProcess::setSubresourceUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
894 {
895     if (auto* networkSession = this->networkSession(sessionID)) {
896         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
897             resourceLoadStatistics->setSubresourceUnderTopFrameDomain(subresourceDomain, topFrameDomain, WTFMove(completionHandler));
898         else
899             completionHandler();
900     } else {
901         ASSERT_NOT_REACHED();
902         completionHandler();
903     }
904 }
905
906 void NetworkProcess::setSubresourceUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
907 {
908     if (auto* networkSession = this->networkSession(sessionID)) {
909         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
910             resourceLoadStatistics->setSubresourceUniqueRedirectTo(subresourceDomain, domainRedirectedTo, WTFMove(completionHandler));
911         else
912             completionHandler();
913     } else {
914         ASSERT_NOT_REACHED();
915         completionHandler();
916     }
917 }
918
919 void NetworkProcess::setSubresourceUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
920 {
921     if (auto* networkSession = this->networkSession(sessionID)) {
922         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
923             resourceLoadStatistics->setSubresourceUniqueRedirectFrom(subresourceDomain, domainRedirectedFrom, WTFMove(completionHandler));
924         else
925             completionHandler();
926     } else {
927         ASSERT_NOT_REACHED();
928         completionHandler();
929     }
930 }
931
932 void NetworkProcess::isRegisteredAsSubresourceUnder(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
933 {
934     if (auto* networkSession = this->networkSession(sessionID)) {
935         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
936             resourceLoadStatistics->isRegisteredAsSubresourceUnder(subresourceDomain, topFrameDomain, WTFMove(completionHandler));
937         else
938             completionHandler(false);
939     } else {
940         ASSERT_NOT_REACHED();
941         completionHandler(false);
942     }
943 }
944
945 void NetworkProcess::setTopFrameUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
946 {
947     if (auto* networkSession = this->networkSession(sessionID)) {
948         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
949             resourceLoadStatistics->setTopFrameUniqueRedirectTo(topFrameDomain, domainRedirectedTo, WTFMove(completionHandler));
950         else
951             completionHandler();
952     } else {
953         ASSERT_NOT_REACHED();
954         completionHandler();
955     }
956 }
957
958 void NetworkProcess::setTopFrameUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
959 {
960     if (auto* networkSession = this->networkSession(sessionID)) {
961         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
962             resourceLoadStatistics->setTopFrameUniqueRedirectFrom(topFrameDomain, domainRedirectedFrom, WTFMove(completionHandler));
963         else
964             completionHandler();
965     } else {
966         ASSERT_NOT_REACHED();
967         completionHandler();
968     }
969 }
970     
971     
972 void NetworkProcess::setLastSeen(PAL::SessionID sessionID, const RegistrableDomain& domain, Seconds seconds, CompletionHandler<void()>&& completionHandler)
973 {
974     if (auto* networkSession = this->networkSession(sessionID)) {
975         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
976             resourceLoadStatistics->setLastSeen(domain, seconds, WTFMove(completionHandler));
977         else
978             completionHandler();
979     } else {
980         ASSERT_NOT_REACHED();
981         completionHandler();
982     }
983 }
984
985 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String> domains)>&& completionHandler)
986 {
987     if (auto* networkStorageSession = storageSession(sessionID))
988         completionHandler(networkStorageSession->getAllStorageAccessEntries());
989     else {
990         ASSERT_NOT_REACHED();
991         completionHandler({ });
992     }
993 }
994
995 void NetworkProcess::logFrameNavigation(PAL::SessionID sessionID, const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, const RegistrableDomain& sourceDomain, bool isRedirect, bool isMainFrame)
996 {
997     if (auto* networkSession = this->networkSession(sessionID)) {
998         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
999             resourceLoadStatistics->logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, isMainFrame);
1000     } else
1001         ASSERT_NOT_REACHED();
1002 }
1003
1004 void NetworkProcess::logUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
1005 {
1006     if (auto* networkSession = this->networkSession(sessionID)) {
1007         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1008             resourceLoadStatistics->logUserInteraction(domain, WTFMove(completionHandler));
1009         else
1010             completionHandler();
1011     } else {
1012         ASSERT_NOT_REACHED();
1013         completionHandler();
1014     }
1015 }
1016
1017 void NetworkProcess::hadUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
1018 {
1019     if (auto* networkSession = this->networkSession(sessionID)) {
1020         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1021             resourceLoadStatistics->hasHadUserInteraction(domain, WTFMove(completionHandler));
1022         else
1023             completionHandler(false);
1024     } else {
1025         ASSERT_NOT_REACHED();
1026         completionHandler(false);
1027     }
1028 }
1029
1030 void NetworkProcess::clearUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
1031 {
1032     if (auto* networkSession = this->networkSession(sessionID)) {
1033         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1034             resourceLoadStatistics->clearUserInteraction(domain, WTFMove(completionHandler));
1035         else
1036             completionHandler();
1037     } else {
1038         ASSERT_NOT_REACHED();
1039         completionHandler();
1040     }
1041 }
1042
1043 void NetworkProcess::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
1044 {
1045     if (auto* session = networkSession(sessionID)) {
1046         session->storageManager().getLocalStorageOrigins([domain, completionHandler = WTFMove(completionHandler)](auto&& origins) mutable {
1047             completionHandler(WTF::anyOf(origins, [&domain](auto& origin) {
1048                 return domain.matches(origin);
1049             }));
1050         });
1051         return;
1052     }
1053     completionHandler(false);
1054 }
1055
1056 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domains)
1057 {
1058     if (auto* networkStorageSession = storageSession(sessionID))
1059         networkStorageSession->removePrevalentDomains(domains);
1060 }
1061
1062 void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1063 {
1064     if (auto* networkStorageSession = storageSession(sessionID))
1065         networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
1066     else
1067         ASSERT_NOT_REACHED();
1068     completionHandler();
1069 }
1070
1071 void NetworkProcess::setGrandfatheringTime(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1072 {
1073     if (auto* networkSession = this->networkSession(sessionID)) {
1074         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1075             resourceLoadStatistics->setGrandfatheringTime(seconds, WTFMove(completionHandler));
1076         else
1077             completionHandler();
1078     } else {
1079         ASSERT_NOT_REACHED();
1080         completionHandler();
1081     }
1082 }
1083
1084 void NetworkProcess::setMaxStatisticsEntries(PAL::SessionID sessionID, uint64_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
1085 {
1086     if (auto* networkSession = this->networkSession(sessionID)) {
1087         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1088             resourceLoadStatistics->setMaxStatisticsEntries(maximumEntryCount, WTFMove(completionHandler));
1089         else
1090             completionHandler();
1091     } else {
1092         ASSERT_NOT_REACHED();
1093         completionHandler();
1094     }
1095 }
1096
1097 void NetworkProcess::setMinimumTimeBetweenDataRecordsRemoval(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1098 {
1099     if (auto* networkSession = this->networkSession(sessionID)) {
1100         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1101             resourceLoadStatistics->setMinimumTimeBetweenDataRecordsRemoval(seconds, WTFMove(completionHandler));
1102         else
1103             completionHandler();
1104     } else {
1105         ASSERT_NOT_REACHED();
1106         completionHandler();
1107     }
1108 }
1109
1110 void NetworkProcess::setPruneEntriesDownTo(PAL::SessionID sessionID, uint64_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
1111 {
1112     if (auto* networkSession = this->networkSession(sessionID)) {
1113         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1114             resourceLoadStatistics->setPruneEntriesDownTo(pruneTargetCount, WTFMove(completionHandler));
1115         else
1116             completionHandler();
1117     } else {
1118         ASSERT_NOT_REACHED();
1119         completionHandler();
1120     }
1121 }
1122
1123 void NetworkProcess::setTimeToLiveUserInteraction(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1124 {
1125     if (auto* networkSession = this->networkSession(sessionID)) {
1126         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1127             resourceLoadStatistics->setTimeToLiveUserInteraction(seconds, WTFMove(completionHandler));
1128         else
1129             completionHandler();
1130     } else {
1131         ASSERT_NOT_REACHED();
1132         completionHandler();
1133     }
1134 }
1135
1136 void NetworkProcess::setShouldClassifyResourcesBeforeDataRecordsRemoval(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
1137 {
1138     if (auto* networkSession = this->networkSession(sessionID)) {
1139         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1140             resourceLoadStatistics->setShouldClassifyResourcesBeforeDataRecordsRemoval(value, WTFMove(completionHandler));
1141         else
1142             completionHandler();
1143     } else {
1144         ASSERT_NOT_REACHED();
1145         completionHandler();
1146     }
1147 }
1148
1149 void NetworkProcess::setResourceLoadStatisticsEnabled(bool enabled)
1150 {
1151     forEachNetworkSession([enabled](auto& networkSession) {
1152         networkSession.setResourceLoadStatisticsEnabled(enabled);
1153     });
1154 }
1155
1156 void NetworkProcess::setResourceLoadStatisticsLogTestingEvent(bool enabled)
1157 {
1158     forEachNetworkSession([enabled](auto& networkSession) {
1159         networkSession.setResourceLoadStatisticsLogTestingEvent(enabled);
1160     });
1161 }
1162
1163 void NetworkProcess::setResourceLoadStatisticsDebugMode(PAL::SessionID sessionID, bool debugMode, CompletionHandler<void()>&& completionHandler)
1164 {
1165     if (auto* networkSession = this->networkSession(sessionID)) {
1166         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1167             resourceLoadStatistics->setResourceLoadStatisticsDebugMode(debugMode, WTFMove(completionHandler));
1168         else
1169             completionHandler();
1170     } else {
1171         ASSERT_NOT_REACHED();
1172         completionHandler();
1173     }
1174 }
1175
1176 void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1177 {
1178     if (auto* networkStorageSession = storageSession(sessionID))
1179         networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
1180     else
1181         ASSERT_NOT_REACHED();
1182     completionHandler();
1183 }
1184
1185 void NetworkProcess::didCommitCrossSiteLoadWithDataTransfer(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, OptionSet<WebCore::CrossSiteNavigationDataTransfer::Flag> navigationDataTransfer, WebCore::PageIdentifier pageID)
1186 {
1187     ASSERT(!navigationDataTransfer.isEmpty());
1188
1189     if (auto* networkStorageSession = storageSession(sessionID)) {
1190         if (!networkStorageSession->shouldBlockThirdPartyCookies(fromDomain))
1191             return;
1192
1193         if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration))
1194             networkStorageSession->didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(toDomain, pageID);
1195
1196         if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::ReferrerLinkDecoration))
1197             parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCommitCrossSiteLoadWithDataTransferFromPrevalentResource(pageID), 0);
1198     } else
1199         ASSERT_NOT_REACHED();
1200
1201     if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration)) {
1202         if (auto* networkSession = this->networkSession(sessionID)) {
1203             if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1204                 resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, [] { });
1205         } else
1206             ASSERT_NOT_REACHED();
1207     }
1208 }
1209
1210 void NetworkProcess::setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
1211 {
1212     if (auto* networkSession = this->networkSession(sessionID)) {
1213         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1214             resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, WTFMove(completionHandler));
1215         else
1216             completionHandler();
1217     } else {
1218         ASSERT_NOT_REACHED();
1219         completionHandler();
1220     }
1221 }
1222
1223 void NetworkProcess::resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1224 {
1225     if (auto* networkStorageSession = storageSession(sessionID))
1226         networkStorageSession->resetCrossSiteLoadsWithLinkDecorationForTesting();
1227     else
1228         ASSERT_NOT_REACHED();
1229     completionHandler();
1230 }
1231 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1232
1233 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
1234 {
1235     return m_sessionsControlledByAutomation.contains(sessionID);
1236 }
1237
1238 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
1239 {
1240     if (controlled)
1241         m_sessionsControlledByAutomation.add(sessionID);
1242     else
1243         m_sessionsControlledByAutomation.remove(sessionID);
1244 }
1245
1246 static void fetchDiskCacheEntries(NetworkCache::Cache* cache, PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void(Vector<WebsiteData::Entry>)>&& completionHandler)
1247 {
1248     if (!cache) {
1249         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
1250             completionHandler({ });
1251         });
1252         return;
1253     }
1254     
1255     HashMap<SecurityOriginData, uint64_t> originsAndSizes;
1256     cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
1257         if (!traversalEntry) {
1258             Vector<WebsiteData::Entry> entries;
1259
1260             for (auto& originAndSize : originsAndSizes)
1261                 entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
1262
1263             RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] () mutable {
1264                 completionHandler(entries);
1265             });
1266
1267             return;
1268         }
1269
1270         auto url = traversalEntry->entry.response().url();
1271         auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
1272
1273         if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
1274             result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
1275     });
1276 }
1277
1278 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
1279 {
1280     ASSERT(sessionID.isValid());
1281     if (!sessionID.isValid())
1282         return;
1283
1284     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1285         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
1286             : m_completionHandler(WTFMove(completionHandler))
1287         {
1288         }
1289
1290         ~CallbackAggregator()
1291         {
1292             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1293                 completionHandler(websiteData);
1294             });
1295         }
1296
1297         CompletionHandler<void(WebsiteData)> m_completionHandler;
1298         WebsiteData m_websiteData;
1299     };
1300
1301     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
1302         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1303     }));
1304
1305     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1306         if (auto* networkStorageSession = storageSession(sessionID))
1307             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
1308     }
1309
1310     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1311         if (storageSession(sessionID)) {
1312             auto securityOrigins = storageSession(sessionID)->credentialStorage().originsWithCredentials();
1313             for (auto& securityOrigin : securityOrigins)
1314                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1315         }
1316         auto securityOrigins = WebCore::CredentialStorage::originsWithSessionCredentials();
1317         for (auto& securityOrigin : securityOrigins)
1318             callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1319     }
1320
1321     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1322         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1323             callbackAggregator->m_websiteData.entries.appendVector(entries);
1324         });
1325     }
1326
1327     auto* session = networkSession(sessionID);
1328     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session) {
1329         session->storageManager().getSessionStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1330             while (!origins.isEmpty())
1331                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 });
1332         });
1333     }
1334
1335     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session) {
1336         session->storageManager().getLocalStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1337             while (!origins.isEmpty())
1338                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 });
1339         });
1340     }
1341
1342 #if PLATFORM(COCOA)
1343     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1344         if (auto* networkStorageSession = storageSession(sessionID))
1345             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
1346     }
1347 #endif
1348
1349 #if ENABLE(INDEXED_DATABASE)
1350     auto path = m_idbDatabasePaths.get(sessionID);
1351     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1352         // FIXME: Pick the right database store based on the session ID.
1353         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
1354             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
1355                 for (const auto& securityOrigin : securityOrigins)
1356                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1357             });
1358         }));
1359     }
1360 #endif
1361
1362 #if ENABLE(SERVICE_WORKER)
1363     path = m_swDatabasePaths.get(sessionID);
1364     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1365         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1366             for (auto& origin : securityOrigins)
1367                 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1368         });
1369     }
1370 #endif
1371     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1372         forEachNetworkSession([sessionID, fetchOptions, &callbackAggregator](auto& session) {
1373             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1374                 callbackAggregator->m_websiteData.entries.appendVector(entries);
1375             });
1376         });
1377     }
1378 }
1379
1380 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
1381 {
1382     ASSERT(sessionID.isValid());
1383     if (!sessionID.isValid())
1384         return;
1385
1386 #if PLATFORM(COCOA)
1387     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1388         if (auto* networkStorageSession = storageSession(sessionID))
1389             clearHSTSCache(*networkStorageSession, modifiedSince);
1390     }
1391 #endif
1392
1393     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1394         if (auto* networkStorageSession = storageSession(sessionID))
1395             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
1396     }
1397
1398     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1399         if (auto* session = storageSession(sessionID))
1400             session->credentialStorage().clearCredentials();
1401         WebCore::CredentialStorage::clearSessionCredentials();
1402     }
1403
1404     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1405         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1406     });
1407
1408     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
1409         CacheStorage::Engine::clearAllCaches(*this, sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1410
1411     auto* session = networkSession(sessionID);
1412     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
1413         session->storageManager().deleteSessionStorageOrigins([clearTasksHandler = clearTasksHandler.copyRef()] { });
1414
1415     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
1416         session->storageManager().deleteLocalStorageOriginsModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1417
1418 #if ENABLE(INDEXED_DATABASE)
1419     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1420         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1421 #endif
1422
1423 #if ENABLE(SERVICE_WORKER)
1424     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
1425         swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
1426 #endif
1427
1428 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1429     if (websiteDataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
1430         if (auto* networkSession = this->networkSession(sessionID)) {
1431             if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
1432                 auto deletedTypesRaw = websiteDataTypes.toRaw();
1433                 auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
1434                 
1435                 // If we are deleting all of the data types that the resource load statistics store monitors
1436                 // we do not need to re-grandfather old data.
1437                 auto shouldGrandfather = ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw) ? ShouldGrandfatherStatistics::No : ShouldGrandfatherStatistics::Yes;
1438                 
1439                 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, shouldGrandfather, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1440             }
1441         }
1442     }
1443 #endif
1444
1445     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
1446         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
1447
1448     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) || websiteDataTypes.contains(WebsiteDataType::DOMCache))
1449         clearStorageQuota(sessionID);
1450
1451     if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1452         if (auto* networkSession = this->networkSession(sessionID))
1453             networkSession->clearAdClickAttribution();
1454     }
1455 }
1456
1457 static void clearDiskCacheEntries(NetworkCache::Cache* cache, const Vector<SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
1458 {
1459     if (!cache) {
1460         RunLoop::main().dispatch(WTFMove(completionHandler));
1461         return;
1462     }
1463
1464     HashSet<RefPtr<SecurityOrigin>> originsToDelete;
1465     for (auto& origin : origins)
1466         originsToDelete.add(origin.securityOrigin());
1467
1468     Vector<NetworkCache::Key> cacheKeysToDelete;
1469     cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
1470         if (traversalEntry) {
1471             if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
1472                 cacheKeysToDelete.append(traversalEntry->entry.key());
1473             return;
1474         }
1475
1476         cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
1477         return;
1478     });
1479 }
1480
1481 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
1482 {
1483     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1484         if (auto* networkStorageSession = storageSession(sessionID))
1485             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
1486     }
1487
1488 #if PLATFORM(COCOA)
1489     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1490         if (auto* networkStorageSession = storageSession(sessionID))
1491             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
1492     }
1493 #endif
1494
1495     if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1496         if (auto* networkSession = this->networkSession(sessionID)) {
1497             for (auto& originData : originDatas)
1498                 networkSession->clearAdClickAttributionForRegistrableDomain(RegistrableDomain::uncheckedCreateFromHost(originData.host));
1499         }
1500     }
1501     
1502     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1503         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1504     });
1505
1506     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1507         for (auto& originData : originDatas)
1508             CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1509     }
1510
1511     auto* session = networkSession(sessionID);
1512     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
1513         session->storageManager().deleteSessionStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1514
1515     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
1516         session->storageManager().deleteLocalStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1517
1518 #if ENABLE(INDEXED_DATABASE)
1519     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1520         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1521 #endif
1522
1523 #if ENABLE(SERVICE_WORKER)
1524     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
1525         auto& server = swServerForSession(sessionID);
1526         for (auto& originData : originDatas)
1527             server.clear(originData, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1528     }
1529 #endif
1530
1531     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral()) {
1532         forEachNetworkSession([originDatas, &clearTasksHandler](auto& session) {
1533             clearDiskCacheEntries(session.cache(), originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1534         });
1535     }
1536
1537     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1538         if (auto* session = storageSession(sessionID)) {
1539             for (auto& originData : originDatas)
1540                 session->credentialStorage().removeCredentialsWithOrigin(originData);
1541         }
1542         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originDatas);
1543     }
1544
1545     // FIXME: Implement storage quota clearing for these origins.
1546 }
1547
1548 void NetworkProcess::clearStorageQuota(PAL::SessionID sessionID)
1549 {
1550     auto iterator = m_storageQuotaManagers.find(sessionID);
1551     if (iterator == m_storageQuotaManagers.end())
1552         return;
1553
1554     auto& managers = iterator->value;
1555     for (auto& manager : managers.managersPerOrigin())
1556         manager.value->resetQuota(managers.defaultQuota(manager.key));
1557 }
1558
1559 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1560 static Vector<String> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const HashSet<String>& foundValues)
1561 {
1562     Vector<String> result;
1563     for (const auto& value : foundValues) {
1564         if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value)))
1565             result.append(value);
1566     }
1567     
1568     return result;
1569 }
1570
1571 static Vector<WebsiteData::Entry> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const Vector<WebsiteData::Entry>& foundValues)
1572 {
1573     Vector<WebsiteData::Entry> result;
1574     for (const auto& value : foundValues) {
1575         if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value.origin.host)))
1576             result.append(value);
1577     }
1578     
1579     return result;
1580 }
1581
1582 static Vector<WebCore::SecurityOriginData> filterForRegistrableDomains(const HashSet<WebCore::SecurityOriginData>& origins, const Vector<RegistrableDomain>& domainsToDelete, HashSet<RegistrableDomain>& domainsDeleted)
1583 {
1584     Vector<SecurityOriginData> originsDeleted;
1585     for (const auto& origin : origins) {
1586         auto domain = RegistrableDomain::uncheckedCreateFromHost(origin.host);
1587         if (!domainsToDelete.contains(domain))
1588             continue;
1589         originsDeleted.append(origin);
1590         domainsDeleted.add(domain);
1591     }
1592
1593     return originsDeleted;
1594 }
1595
1596 void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1597 {
1598     ASSERT(sessionID.isValid());
1599     if (!sessionID.isValid())
1600         return;
1601
1602     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1603
1604     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1605         explicit CallbackAggregator(CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1606             : m_completionHandler(WTFMove(completionHandler))
1607         {
1608         }
1609         
1610         ~CallbackAggregator()
1611         {
1612             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), domains = WTFMove(m_domains)] () mutable {
1613                 completionHandler(domains);
1614             });
1615         }
1616         
1617         CompletionHandler<void(const HashSet<RegistrableDomain>&)> m_completionHandler;
1618         HashSet<RegistrableDomain> m_domains;
1619     };
1620     
1621     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (const HashSet<RegistrableDomain>& domainsWithData) mutable {
1622         if (shouldNotifyPage)
1623             parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataDeletionForRegistrableDomainsFinished(), 0);
1624         
1625         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1626             completionHandler(domainsWithData);
1627         });
1628     }));
1629
1630     HashSet<String> hostNamesWithCookies;
1631     HashSet<String> hostNamesWithHSTSCache;
1632
1633     Vector<RegistrableDomain> domainsToDeleteCookiesFor;
1634     Vector<RegistrableDomain> domainsToDeleteAllButHttpOnlyCookiesFor;
1635     Vector<RegistrableDomain> domainsToDeleteAllButCookiesFor;
1636     Vector<String> hostnamesWithCookiesToDelete;
1637     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1638         for (auto& domain : domains.keys()) {
1639             domainsToDeleteAllButCookiesFor.append(domain);
1640             switch (domains.get(domain)) {
1641             case WebsiteDataToRemove::All:
1642                 domainsToDeleteCookiesFor.append(domain);
1643                 break;
1644             case WebsiteDataToRemove::AllButHttpOnlyCookies:
1645                 domainsToDeleteAllButHttpOnlyCookiesFor.append(domain);
1646                 break;
1647             case WebsiteDataToRemove::AllButCookies:
1648                 // Already added.
1649                 break;
1650             }
1651         }
1652         if (auto* networkStorageSession = storageSession(sessionID)) {
1653             networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
1654
1655             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, hostNamesWithCookies);
1656             networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes);
1657
1658             for (const auto& host : hostnamesWithCookiesToDelete)
1659                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1660
1661             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
1662             networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No);
1663
1664             for (const auto& host : hostnamesWithCookiesToDelete)
1665                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1666         }
1667     } else {
1668         for (auto& domain : domains.keys())
1669             domainsToDeleteAllButCookiesFor.append(domain);
1670     }
1671
1672     Vector<String> hostnamesWithHSTSToDelete;
1673 #if PLATFORM(COCOA)
1674     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1675         if (auto* networkStorageSession = storageSession(sessionID)) {
1676             getHostNamesWithHSTSCache(*networkStorageSession, hostNamesWithHSTSCache);
1677             hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, hostNamesWithHSTSCache);
1678
1679             for (const auto& host : hostnamesWithHSTSToDelete)
1680                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1681
1682             deleteHSTSCacheForHostNames(*networkStorageSession, hostnamesWithHSTSToDelete);
1683         }
1684     }
1685 #endif
1686
1687     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1688         if (auto* session = storageSession(sessionID)) {
1689             auto origins = session->credentialStorage().originsWithCredentials();
1690             auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1691             for (auto& origin : originsToDelete)
1692                 session->credentialStorage().removeCredentialsWithOrigin(origin);
1693         }
1694
1695         auto origins = WebCore::CredentialStorage::originsWithSessionCredentials();
1696         auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1697         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originsToDelete);
1698     }
1699     
1700     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1701         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [this, domainsToDeleteAllButCookiesFor, sessionID, callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1702             
1703             auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, entries);
1704
1705             for (const auto& entry : entriesToDelete)
1706                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1707
1708             for (auto& entry : entriesToDelete)
1709                 CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { });
1710         });
1711     }
1712
1713     auto* session = networkSession(sessionID);
1714     if (session) {
1715         auto& storageManager = session->storageManager();
1716         if (websiteDataTypes.contains(WebsiteDataType::SessionStorage)) {
1717             storageManager.getSessionStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1718                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1719                 storageManager->deleteSessionStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1720             });
1721         }
1722
1723         if (websiteDataTypes.contains(WebsiteDataType::LocalStorage)) {
1724             storageManager.getLocalStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1725                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1726                 storageManager->deleteLocalStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1727             });
1728         }
1729     }
1730
1731 #if ENABLE(INDEXED_DATABASE)
1732     auto path = m_idbDatabasePaths.get(sessionID);
1733     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1734         // FIXME: Pick the right database store based on the session ID.
1735         postStorageTask(CrossThreadTask([this, sessionID, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path), domainsToDeleteAllButCookiesFor]() mutable {
1736             RunLoop::main().dispatch([this, sessionID, domainsToDeleteAllButCookiesFor = crossThreadCopy(domainsToDeleteAllButCookiesFor), callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1737                 Vector<SecurityOriginData> entriesToDelete;
1738                 for (const auto& securityOrigin : securityOrigins) {
1739                     auto domain = RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host);
1740                     if (!domainsToDeleteAllButCookiesFor.contains(domain))
1741                         continue;
1742
1743                     entriesToDelete.append(securityOrigin);
1744                     callbackAggregator->m_domains.add(domain);
1745                 }
1746
1747                 idbServer(sessionID).closeAndDeleteDatabasesForOrigins(entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1748             });
1749         }));
1750     }
1751 #endif
1752     
1753 #if ENABLE(SERVICE_WORKER)
1754     path = m_swDatabasePaths.get(sessionID);
1755     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1756         swServerForSession(sessionID).getOriginsWithRegistrations([this, sessionID, domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1757             for (auto& securityOrigin : securityOrigins) {
1758                 if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
1759                     continue;
1760                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
1761                 swServerForSession(sessionID).clear(securityOrigin, [callbackAggregator = callbackAggregator.copyRef()] { });
1762             }
1763         });
1764     }
1765 #endif
1766
1767     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1768         forEachNetworkSession([sessionID, fetchOptions, &domainsToDeleteAllButCookiesFor, &callbackAggregator](auto& session) {
1769             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef(), session = makeWeakPtr(&session)](auto entries) mutable {
1770                 if (!session)
1771                     return;
1772
1773                 Vector<SecurityOriginData> entriesToDelete;
1774                 for (auto& entry : entries) {
1775                     if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
1776                         continue;
1777                     entriesToDelete.append(entry.origin);
1778                     callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1779                 }
1780                 clearDiskCacheEntries(session->cache(), entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1781             });
1782         });
1783     }
1784
1785     auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
1786     if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllButCookiesFor.isEmpty()) {
1787         CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator = callbackAggregator.copyRef()] (const HashSet<RegistrableDomain>& domains) {
1788             for (auto& domain : domains)
1789                 callbackAggregator->m_domains.add(domain);
1790         };
1791         parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllButCookiesFor), WTFMove(completionHandler));
1792     }
1793 }
1794
1795 void NetworkProcess::deleteCookiesForTesting(PAL::SessionID sessionID, RegistrableDomain domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1796 {
1797     OptionSet<WebsiteDataType> cookieType = WebsiteDataType::Cookies;
1798     HashMap<RegistrableDomain, WebsiteDataToRemove> toDeleteFor;
1799     toDeleteFor.add(domain, includeHttpOnlyCookies ? WebsiteDataToRemove::All : WebsiteDataToRemove::AllButHttpOnlyCookies);
1800     deleteWebsiteDataForRegistrableDomains(sessionID, cookieType, WTFMove(toDeleteFor), true, [completionHandler = WTFMove(completionHandler)] (const HashSet<RegistrableDomain>& domainsDeletedFor) mutable {
1801         UNUSED_PARAM(domainsDeletedFor);
1802         completionHandler();
1803     });
1804 }
1805
1806 void NetworkProcess::registrableDomainsWithWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1807 {
1808     ASSERT(sessionID.isValid());
1809     if (!sessionID.isValid())
1810         return;
1811
1812     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1813     
1814     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1815         explicit CallbackAggregator(CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1816             : m_completionHandler(WTFMove(completionHandler))
1817         {
1818         }
1819         
1820         ~CallbackAggregator()
1821         {
1822             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1823                 HashSet<RegistrableDomain> domains;
1824                 for (const auto& hostnameWithCookies : websiteData.hostNamesWithCookies)
1825                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithCookies));
1826
1827                 for (const auto& hostnameWithHSTS : websiteData.hostNamesWithHSTSCache)
1828                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithHSTS));
1829
1830                 for (const auto& entry : websiteData.entries)
1831                     domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1832
1833                 completionHandler(WTFMove(domains));
1834             });
1835         }
1836         
1837         CompletionHandler<void(HashSet<RegistrableDomain>&&)> m_completionHandler;
1838         WebsiteData m_websiteData;
1839     };
1840     
1841     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (HashSet<RegistrableDomain>&& domainsWithData) mutable {
1842         if (shouldNotifyPage)
1843             parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataScanForRegistrableDomainsFinished(), 0);
1844
1845         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1846             completionHandler(WTFMove(domainsWithData));
1847         });
1848     }));
1849     
1850     auto& websiteDataStore = callbackAggregator->m_websiteData;
1851     
1852     Vector<String> hostnamesWithCookiesToDelete;
1853     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1854         if (auto* networkStorageSession = storageSession(sessionID))
1855             networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
1856     }
1857     
1858     Vector<String> hostnamesWithHSTSToDelete;
1859 #if PLATFORM(COCOA)
1860     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1861         if (auto* networkStorageSession = storageSession(sessionID))
1862             getHostNamesWithHSTSCache(*networkStorageSession, websiteDataStore.hostNamesWithHSTSCache);
1863     }
1864 #endif
1865
1866     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1867         if (auto* networkStorageSession = storageSession(sessionID)) {
1868             auto securityOrigins = networkStorageSession->credentialStorage().originsWithCredentials();
1869             for (auto& securityOrigin : securityOrigins)
1870                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1871         }
1872     }
1873     
1874     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1875         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1876             callbackAggregator->m_websiteData.entries.appendVector(entries);
1877         });
1878     }
1879     
1880 #if ENABLE(INDEXED_DATABASE)
1881     auto path = m_idbDatabasePaths.get(sessionID);
1882     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1883         // FIXME: Pick the right database store based on the session ID.
1884         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
1885             RunLoop::main().dispatch([callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1886                 for (const auto& securityOrigin : securityOrigins)
1887                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1888             });
1889         }));
1890     }
1891 #endif
1892     
1893 #if ENABLE(SERVICE_WORKER)
1894     path = m_swDatabasePaths.get(sessionID);
1895     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1896         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1897             for (auto& securityOrigin : securityOrigins)
1898                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1899         });
1900     }
1901 #endif
1902     
1903     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1904         forEachNetworkSession([sessionID, fetchOptions, &callbackAggregator](auto& session) {
1905             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1906                 callbackAggregator->m_websiteData.entries.appendVector(entries);
1907             });
1908         });
1909     }
1910 }
1911 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1912
1913 CacheStorage::Engine* NetworkProcess::findCacheEngine(const PAL::SessionID& sessionID)
1914 {
1915     return m_cacheEngines.get(sessionID);
1916 }
1917
1918 CacheStorage::Engine& NetworkProcess::ensureCacheEngine(const PAL::SessionID& sessionID, Function<Ref<CacheStorage::Engine>()>&& functor)
1919 {
1920     return m_cacheEngines.ensure(sessionID, WTFMove(functor)).iterator->value;
1921 }
1922
1923 void NetworkProcess::removeCacheEngine(const PAL::SessionID& sessionID)
1924 {
1925     m_cacheEngines.remove(sessionID);
1926 }
1927
1928 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
1929 {
1930     downloadManager().startDownload(sessionID, downloadID, request, suggestedFilename);
1931 }
1932
1933 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
1934 {
1935     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
1936 }
1937
1938 void NetworkProcess::cancelDownload(DownloadID downloadID)
1939 {
1940     downloadManager().cancelDownload(downloadID);
1941 }
1942
1943 #if PLATFORM(COCOA)
1944 void NetworkProcess::publishDownloadProgress(DownloadID downloadID, const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
1945 {
1946     downloadManager().publishDownloadProgress(downloadID, url, WTFMove(sandboxExtensionHandle));
1947 }
1948 #endif
1949
1950 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
1951 {
1952     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
1953 }
1954
1955 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
1956 {
1957     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
1958 }
1959
1960 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
1961 {
1962     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
1963     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
1964
1965     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
1966
1967     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
1968     // should override the suggested filename from the download attribute.
1969     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
1970     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
1971
1972     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
1973 }
1974
1975 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
1976 {
1977     if (destination.isEmpty())
1978         downloadManager().cancelDownload(downloadID);
1979     else
1980         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
1981 }
1982
1983 void NetworkProcess::setCacheModel(CacheModel cacheModel)
1984 {
1985     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
1986         return;
1987
1988     m_hasSetCacheModel = true;
1989     m_cacheModel = cacheModel;
1990
1991     unsigned urlCacheMemoryCapacity = 0;
1992     uint64_t urlCacheDiskCapacity = 0;
1993     uint64_t diskFreeSize = 0;
1994     if (FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
1995         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
1996         // count doesn't align exactly to a megabyte boundary.
1997         diskFreeSize /= KB * 1000;
1998         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
1999     }
2000
2001     forEachNetworkSession([urlCacheDiskCapacity](auto& session) {
2002         if (auto* cache = session.cache())
2003             cache->setCapacity(urlCacheDiskCapacity);
2004     });
2005 }
2006
2007 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
2008 {
2009     m_canHandleHTTPSServerTrustEvaluation = value;
2010 }
2011
2012 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
2013 {
2014     StatisticsData data;
2015
2016     data.statisticsNumbers.set("DownloadsActiveCount", downloadManager().activeDownloadCount());
2017     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", authenticationManager().outstandingAuthenticationChallengeCount());
2018
2019     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
2020 }
2021
2022 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows, CompletionHandler<void()>&& completionHandler)
2023 {
2024     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
2025     completionHandler();
2026 }
2027
2028 void NetworkProcess::logDiagnosticMessage(PageIdentifier webPageID, const String& message, const String& description, ShouldSample shouldSample)
2029 {
2030     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2031         return;
2032
2033     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
2034 }
2035
2036 void NetworkProcess::logDiagnosticMessageWithResult(PageIdentifier webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
2037 {
2038     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2039         return;
2040
2041     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
2042 }
2043
2044 void NetworkProcess::logDiagnosticMessageWithValue(PageIdentifier webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
2045 {
2046     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2047         return;
2048
2049     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
2050 }
2051
2052 void NetworkProcess::terminate()
2053 {
2054     platformTerminate();
2055     AuxiliaryProcess::terminate();
2056 }
2057
2058 void NetworkProcess::processDidTransitionToForeground()
2059 {
2060     platformProcessDidTransitionToForeground();
2061 }
2062
2063 void NetworkProcess::processDidTransitionToBackground()
2064 {
2065     platformProcessDidTransitionToBackground();
2066 }
2067
2068 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
2069 {
2070 #if PLATFORM(IOS_FAMILY)
2071     m_webSQLiteDatabaseTracker.setIsSuspended(true);
2072 #endif
2073
2074     lowMemoryHandler(Critical::Yes);
2075
2076     RefPtr<CallbackAggregator> callbackAggregator;
2077     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
2078         callbackAggregator = CallbackAggregator::create([this] {
2079             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
2080             if (parentProcessConnection())
2081                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
2082         });
2083     }
2084
2085     platformPrepareToSuspend([callbackAggregator] { });
2086     platformSyncAllCookies([callbackAggregator] { });
2087
2088     for (auto& connection : m_webProcessConnections)
2089         connection->cleanupForSuspension([callbackAggregator] { });
2090
2091 #if ENABLE(SERVICE_WORKER)
2092     for (auto& server : m_swServers.values()) {
2093         ASSERT(m_swServers.get(server->sessionID()) == server.get());
2094         server->startSuspension([callbackAggregator] { });
2095     }
2096 #endif
2097
2098     forEachNetworkSession([&callbackAggregator](auto& session) {
2099         session.storageManager().suspend([callbackAggregator] { });
2100     });
2101 }
2102
2103 void NetworkProcess::processWillSuspendImminently()
2104 {
2105     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() BEGIN", this);
2106 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2107     for (auto& server : m_idbServers.values())
2108         server->tryStop(IDBServer::ShouldForceStop::Yes);
2109 #endif
2110     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
2111     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() END", this);
2112 }
2113
2114 void NetworkProcess::processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&& completionHandler)
2115 {
2116     processWillSuspendImminently();
2117     completionHandler();
2118 }
2119
2120 void NetworkProcess::prepareToSuspend()
2121 {
2122     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
2123
2124 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2125     for (auto& server : m_idbServers.values())
2126         server->tryStop(IDBServer::ShouldForceStop::No);
2127 #endif
2128     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
2129 }
2130
2131 void NetworkProcess::cancelPrepareToSuspend()
2132 {
2133     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
2134     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
2135     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
2136     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
2137     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
2138     resume();
2139 }
2140
2141 void NetworkProcess::applicationDidEnterBackground()
2142 {
2143     m_downloadManager.applicationDidEnterBackground();
2144 }
2145
2146 void NetworkProcess::applicationWillEnterForeground()
2147 {
2148     m_downloadManager.applicationWillEnterForeground();
2149 }
2150
2151 void NetworkProcess::processDidResume()
2152 {
2153     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
2154     resume();
2155 }
2156
2157 void NetworkProcess::resume()
2158 {
2159 #if PLATFORM(IOS_FAMILY)
2160     m_webSQLiteDatabaseTracker.setIsSuspended(false);
2161 #endif
2162
2163     platformProcessDidResume();
2164     for (auto& connection : m_webProcessConnections)
2165         connection->endSuspension();
2166
2167 #if ENABLE(SERVICE_WORKER)
2168     for (auto& server : m_swServers.values())
2169         server->endSuspension();
2170 #endif
2171 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2172     for (auto& server : m_idbServers.values())
2173         server->resume();
2174 #endif
2175
2176     forEachNetworkSession([](auto& session) {
2177         session.storageManager().resume();
2178     });
2179 }
2180
2181 void NetworkProcess::prefetchDNS(const String& hostname)
2182 {
2183     WebCore::prefetchDNS(hostname);
2184 }
2185
2186 void NetworkProcess::cacheStorageRootPath(PAL::SessionID sessionID, CacheStorageRootPathCallback&& callback)
2187 {
2188     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
2189         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
2190         return Vector<CacheStorageRootPathCallback> { };
2191     }).iterator->value.append(WTFMove(callback));
2192 }
2193
2194 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
2195 {
2196     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
2197     if (iterator == m_cacheStorageParametersCallbacks.end())
2198         return;
2199
2200     SandboxExtension::consumePermanently(handle);
2201     auto callbacks = WTFMove(iterator->value);
2202     m_cacheStorageParametersCallbacks.remove(iterator);
2203     for (auto& callback : callbacks)
2204         callback(String { cacheStorageDirectory });
2205 }
2206
2207 void NetworkProcess::preconnectTo(const URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
2208 {
2209 #if ENABLE(SERVER_PRECONNECT)
2210     NetworkLoadParameters parameters;
2211     parameters.request = ResourceRequest { url };
2212     parameters.sessionID = PAL::SessionID::defaultSessionID();
2213     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
2214     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
2215
2216     new PreconnectTask(*this, WTFMove(parameters));
2217 #else
2218     UNUSED_PARAM(url);
2219     UNUSED_PARAM(storedCredentialsPolicy);
2220 #endif
2221 }
2222
2223 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
2224 {
2225     SchemeRegistry::registerURLSchemeAsSecure(scheme);
2226 }
2227
2228 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
2229 {
2230     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2231 }
2232
2233 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
2234 {
2235     SchemeRegistry::registerURLSchemeAsLocal(scheme);
2236 }
2237
2238 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
2239 {
2240     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
2241 }
2242
2243 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
2244 {
2245     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
2246 }
2247
2248 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
2249 {
2250     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
2251 }
2252
2253 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
2254 {
2255     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
2256 }
2257
2258 void NetworkProcess::didSyncAllCookies()
2259 {
2260     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
2261 }
2262
2263 #if ENABLE(INDEXED_DATABASE)
2264 Ref<IDBServer::IDBServer> NetworkProcess::createIDBServer(PAL::SessionID sessionID)
2265 {
2266     String path;
2267     if (!sessionID.isEphemeral()) {
2268         ASSERT(m_idbDatabasePaths.contains(sessionID));
2269         path = m_idbDatabasePaths.get(sessionID);
2270     }
2271
2272     auto server = IDBServer::IDBServer::create(sessionID, path, *this, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* {
2273         if (!weakThis)
2274             return nullptr;
2275         return &this->storageQuotaManager(sessionID, origin);
2276     });
2277     server->setPerOriginQuota(m_idbPerOriginQuota);
2278     return server;
2279 }
2280
2281 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
2282 {
2283     return *m_idbServers.ensure(sessionID, [this, sessionID] {
2284         return this->createIDBServer(sessionID);
2285     }).iterator->value;
2286 }
2287
2288 void NetworkProcess::ensurePathExists(const String& path)
2289 {
2290     ASSERT(!RunLoop::isMain());
2291     
2292     if (!FileSystem::makeAllDirectories(path))
2293         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
2294 }
2295
2296 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
2297 {
2298     ASSERT(RunLoop::isMain());
2299     
2300     LockHolder locker(m_storageTaskMutex);
2301     
2302     m_storageTasks.append(WTFMove(task));
2303     
2304     m_storageTaskQueue->dispatch([this] {
2305         performNextStorageTask();
2306     });
2307 }
2308
2309 void NetworkProcess::performNextStorageTask()
2310 {
2311     ASSERT(!RunLoop::isMain());
2312     
2313     CrossThreadTask task;
2314     {
2315         LockHolder locker(m_storageTaskMutex);
2316         ASSERT(!m_storageTasks.isEmpty());
2317         task = m_storageTasks.takeFirst();
2318     }
2319     
2320     task.performTask();
2321 }
2322
2323 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
2324 {
2325     // We've either hard linked the temporary blob file to the database directory, copied it there,
2326     // or the transaction is being aborted.
2327     // In any of those cases, we can delete the temporary blob file now.
2328     FileSystem::deleteFile(path);
2329 }
2330
2331 void NetworkProcess::collectIndexedDatabaseOriginsForVersion(const String& path, HashSet<WebCore::SecurityOriginData>& securityOrigins)
2332 {
2333     if (path.isEmpty())
2334         return;
2335
2336     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
2337         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
2338         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier)) {
2339             securityOrigins.add(WTFMove(*securityOrigin));
2340         
2341             for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
2342                 databaseIdentifier = FileSystem::pathGetFileName(originPath);
2343                 if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
2344                     securityOrigins.add(WTFMove(*securityOrigin));
2345             }
2346         }
2347     }
2348 }
2349
2350 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
2351 {
2352     if (path.isEmpty())
2353         return { };
2354     
2355     HashSet<WebCore::SecurityOriginData> securityOrigins;
2356     collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v0"), securityOrigins);
2357     collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v1"), securityOrigins);
2358
2359     return securityOrigins;
2360 }
2361
2362 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
2363 {
2364     // *********
2365     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
2366     // *********
2367     auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
2368     if (addResult.isNewEntry) {
2369         SandboxExtension::consumePermanently(handle);
2370         if (!indexedDatabaseDirectory.isEmpty())
2371             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
2372     }
2373 }
2374
2375 void NetworkProcess::setIDBPerOriginQuota(uint64_t quota)
2376 {
2377     m_idbPerOriginQuota = quota;
2378     
2379     for (auto& server : m_idbServers.values())
2380         server->setPerOriginQuota(quota);
2381 }
2382 #endif // ENABLE(INDEXED_DATABASE)
2383
2384 void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
2385 {
2386     auto& manager = storageQuotaManager(sessionID, origin);
2387     manager.resetQuota(m_storageQuotaManagers.find(sessionID)->value.defaultQuota(origin));
2388     manager.updateQuotaBasedOnSpaceUsage();
2389 }
2390
2391 #if ENABLE(SANDBOX_EXTENSIONS)
2392 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&& completionHandler)
2393 {
2394     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(filenames), WTFMove(completionHandler));
2395 }
2396 #endif // ENABLE(SANDBOX_EXTENSIONS)
2397
2398 #if ENABLE(SERVICE_WORKER)
2399 WebSWServerToContextConnection* NetworkProcess::connectionToContextProcessFromIPCConnection(IPC::Connection& connection)
2400 {
2401     for (auto& serverToContextConnection : m_serverToContextConnections.values()) {
2402         if (serverToContextConnection->ipcConnection() == &connection)
2403             return serverToContextConnection.get();
2404     }
2405     return nullptr;
2406 }
2407
2408 void NetworkProcess::connectionToContextProcessWasClosed(Ref<WebSWServerToContextConnection>&& serverToContextConnection)
2409 {
2410     auto& registrableDomain = serverToContextConnection->registrableDomain();
2411     
2412     serverToContextConnection->connectionClosed();
2413     m_serverToContextConnections.remove(registrableDomain);
2414     
2415     for (auto& swServer : m_swServers.values())
2416         swServer->markAllWorkersForRegistrableDomainAsTerminated(registrableDomain);
2417     
2418     if (needsServerToContextConnectionForRegistrableDomain(registrableDomain)) {
2419         RELEASE_LOG(ServiceWorker, "Connection to service worker process was closed but is still needed, relaunching it");
2420         createServerToContextConnection(registrableDomain, WTF::nullopt);
2421     }
2422 }
2423
2424 bool NetworkProcess::needsServerToContextConnectionForRegistrableDomain(const RegistrableDomain& registrableDomain) const
2425 {
2426     return WTF::anyOf(m_swServers.values(), [&](auto& swServer) {
2427         return swServer->needsServerToContextConnectionForRegistrableDomain(registrableDomain);
2428     });
2429 }
2430
2431 SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
2432 {
2433     ASSERT(sessionID.isValid());
2434
2435     auto result = m_swServers.ensure(sessionID, [&] {
2436         auto path = m_swDatabasePaths.get(sessionID);
2437         // There should already be a registered path for this PAL::SessionID.
2438         // If there's not, then where did this PAL::SessionID come from?
2439         ASSERT(sessionID.isEphemeral() || !path.isEmpty());
2440         
2441         auto value = std::make_unique<SWServer>(makeUniqueRef<WebSWOriginStore>(), WTFMove(path), sessionID);
2442         if (m_shouldDisableServiceWorkerProcessTerminationDelay)
2443             value->disableServiceWorkerProcessTerminationDelay();
2444         return value;
2445     });
2446
2447     return *result.iterator->value;
2448 }
2449
2450 WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
2451 {
2452     ASSERT(sessionID.isValid());
2453     if (!sessionID.isValid())
2454         return nullptr;
2455
2456     auto* swServer = m_swServers.get(sessionID);
2457     if (!swServer)
2458         return nullptr;
2459     return &static_cast<WebSWOriginStore&>(swServer->originStore());
2460 }
2461
2462 WebSWServerToContextConnection* NetworkProcess::serverToContextConnectionForRegistrableDomain(const RegistrableDomain& registrableDomain)
2463 {
2464     return m_serverToContextConnections.get(registrableDomain);
2465 }
2466
2467 void NetworkProcess::createServerToContextConnection(const RegistrableDomain& registrableDomain, Optional<PAL::SessionID> sessionID)
2468 {
2469     if (m_waitingForServerToContextProcessConnection)
2470         return;
2471     
2472     m_waitingForServerToContextProcessConnection = true;
2473     if (sessionID)
2474         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcessForExplicitSession(registrableDomain, *sessionID), 0);
2475     else
2476         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess(registrableDomain), 0);
2477 }
2478
2479 void NetworkProcess::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, MessageWithMessagePorts&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
2480 {
2481     if (auto* connection = m_swServerConnections.get(destinationIdentifier.serverConnectionIdentifier))
2482         connection->postMessageToServiceWorkerClient(destinationIdentifier.contextIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
2483 }
2484
2485 void NetworkProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, WebCore::MessageWithMessagePorts&& message, const WebCore::ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
2486 {
2487     if (auto* connection = m_swServerConnections.get(connectionIdentifier))
2488         connection->postMessageToServiceWorker(destination, WTFMove(message), source);
2489 }
2490
2491 void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
2492 {
2493     ASSERT(parentProcessHasServiceWorkerEntitlement());
2494     ASSERT(!m_swServerConnections.contains(connection.identifier()));
2495     m_swServerConnections.add(connection.identifier(), &connection);
2496     auto* store = existingSWOriginStoreForSession(connection.sessionID());
2497     ASSERT(store);
2498     if (store)
2499         store->registerSWServerConnection(connection);
2500 }
2501
2502 void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
2503 {
2504     ASSERT(m_swServerConnections.get(connection.identifier()) == &connection);
2505     m_swServerConnections.remove(connection.identifier());
2506     if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
2507         store->unregisterSWServerConnection(connection);
2508 }
2509
2510 void NetworkProcess::swContextConnectionMayNoLongerBeNeeded(WebSWServerToContextConnection& serverToContextConnection)
2511 {
2512     auto& registrableDomain = serverToContextConnection.registrableDomain();
2513     if (needsServerToContextConnectionForRegistrableDomain(registrableDomain))
2514         return;
2515     
2516     RELEASE_LOG(ServiceWorker, "Service worker process is no longer needed, terminating it");
2517     serverToContextConnection.terminate();
2518     
2519     for (auto& swServer : m_swServers.values())
2520         swServer->markAllWorkersForRegistrableDomainAsTerminated(registrableDomain);
2521     
2522     serverToContextConnection.connectionClosed();
2523     m_serverToContextConnections.remove(registrableDomain);
2524 }
2525
2526 void NetworkProcess::disableServiceWorkerProcessTerminationDelay()
2527 {
2528     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
2529         return;
2530     
2531     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
2532     for (auto& swServer : m_swServers.values())
2533         swServer->disableServiceWorkerProcessTerminationDelay();
2534 }
2535
2536 void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
2537 {
2538     auto addResult = m_swDatabasePaths.add(sessionID, serviceWorkerRegistrationDirectory);
2539     if (addResult.isNewEntry) {
2540         SandboxExtension::consumePermanently(handle);
2541         if (!serviceWorkerRegistrationDirectory.isEmpty())
2542             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
2543     }
2544 }
2545 #endif // ENABLE(SERVICE_WORKER)
2546
2547 void NetworkProcess::requestStorageSpace(PAL::SessionID sessionID, const ClientOrigin& origin, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(Optional<uint64_t>)>&& callback)
2548 {
2549     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageSpace { sessionID, origin, quota, currentSize, spaceRequired }, WTFMove(callback), 0);
2550 }
2551
2552 class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
2553 public:
2554     explicit QuotaUserInitializer(StorageQuotaManager& manager)
2555         : m_manager(makeWeakPtr(manager))
2556     {
2557         manager.addUser(*this);
2558     }
2559
2560     ~QuotaUserInitializer()
2561     {
2562         if (m_manager)
2563             m_manager->removeUser(*this);
2564         if (m_callback)
2565             m_callback();
2566     }
2567
2568 private:
2569     // StorageQuotaUser API.
2570     uint64_t spaceUsed() const final
2571     {
2572         ASSERT_NOT_REACHED();
2573         return 0;
2574     }
2575
2576     void whenInitialized(CompletionHandler<void()>&& callback) final
2577     {
2578         m_callback = WTFMove(callback);
2579     }
2580
2581     WeakPtr<StorageQuotaManager> m_manager;
2582     CompletionHandler<void()> m_callback;
2583 };
2584
2585 void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
2586 {
2587     RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = std::make_unique<QuotaUserInitializer>(manager)]() mutable {
2588         if (!weakThis)
2589             return;
2590         this->idbServer(sessionID).initializeQuotaUser(origin);
2591         CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
2592     });
2593 }
2594
2595 StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
2596 {
2597     auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
2598         return StorageQuotaManagers { };
2599     }).iterator->value;
2600     return *storageQuotaManagers.managersPerOrigin().ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
2601         auto manager = std::make_unique<StorageQuotaManager>(storageQuotaManagers.defaultQuota(origin), [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
2602             this->requestStorageSpace(sessionID, origin, quota, currentSpace, spaceIncrease, WTFMove(callback));
2603         });
2604         initializeQuotaUsers(*manager, sessionID, origin);
2605         return manager;
2606     }).iterator->value;
2607 }
2608
2609 #if !PLATFORM(COCOA)
2610 void NetworkProcess::initializeProcess(const AuxiliaryProcessInitializationParameters&)
2611 {
2612 }
2613
2614 void NetworkProcess::initializeProcessName(const AuxiliaryProcessInitializationParameters&)
2615 {
2616 }
2617
2618 void NetworkProcess::initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&)
2619 {
2620 }
2621
2622 void NetworkProcess::syncAllCookies()
2623 {
2624 }
2625
2626 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
2627 {
2628     completionHandler();
2629 }
2630
2631 #endif
2632
2633 void NetworkProcess::storeAdClickAttribution(PAL::SessionID sessionID, WebCore::AdClickAttribution&& adClickAttribution)
2634 {
2635     if (auto* session = networkSession(sessionID))
2636         session->storeAdClickAttribution(WTFMove(adClickAttribution));
2637 }
2638
2639 void NetworkProcess::dumpAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
2640 {
2641     if (auto* session = networkSession(sessionID))
2642         return session->dumpAdClickAttribution(WTFMove(completionHandler));
2643
2644     completionHandler({ });
2645 }
2646
2647 void NetworkProcess::clearAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2648 {
2649     if (auto* session = networkSession(sessionID))
2650         session->clearAdClickAttribution();
2651     
2652     completionHandler();
2653 }
2654
2655 void NetworkProcess::setAdClickAttributionOverrideTimerForTesting(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
2656 {
2657     if (auto* session = networkSession(sessionID))
2658         session->setAdClickAttributionOverrideTimerForTesting(value);
2659     
2660     completionHandler();
2661 }
2662
2663 void NetworkProcess::setAdClickAttributionConversionURLForTesting(PAL::SessionID sessionID, URL&& url, CompletionHandler<void()>&& completionHandler)
2664 {
2665     if (auto* session = networkSession(sessionID))
2666         session->setAdClickAttributionConversionURLForTesting(WTFMove(url));
2667     
2668     completionHandler();
2669 }
2670
2671 void NetworkProcess::markAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2672 {
2673     if (auto* session = networkSession(sessionID))
2674         session->markAdClickAttributionsAsExpiredForTesting();
2675
2676     completionHandler();
2677 }
2678
2679 void NetworkProcess::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
2680 {
2681     if (auto* session = networkSession(loader->sessionID()))
2682         session->addKeptAliveLoad(WTFMove(loader));
2683 }
2684
2685 void NetworkProcess::removeKeptAliveLoad(NetworkResourceLoader& loader)
2686 {
2687     if (auto* session = networkSession(loader.sessionID()))
2688         session->removeKeptAliveLoad(loader);
2689 }
2690
2691 void NetworkProcess::webPageWasAdded(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID, PageIdentifier oldPageID)
2692 {
2693     if (!pageID || !oldPageID) {
2694         LOG_ERROR("Cannot add page with invalid id");
2695         return;
2696     }
2697
2698     auto* session = networkSession(sessionID);
2699     if (!session) {
2700         LOG_ERROR("Cannot add page to an unknown session");
2701         return;
2702     }
2703     auto& storageManager = session->storageManager();
2704
2705     auto addResult = m_sessionByConnection.add(connection.uniqueID(), sessionID);
2706     ASSERT_UNUSED(addResult, addResult.iterator->value == sessionID);
2707
2708     storageManager.createSessionStorageNamespace(pageID.toUInt64(), std::numeric_limits<unsigned>::max());
2709     storageManager.addAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
2710     if (pageID != oldPageID)
2711         storageManager.cloneSessionStorageNamespace(oldPageID.toUInt64(), pageID.toUInt64());
2712 }
2713
2714 void NetworkProcess::webPageWasRemoved(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID)
2715 {
2716     if (!pageID) {
2717         LOG_ERROR("Cannot remove page with invalid id");
2718         return;
2719     }
2720
2721     auto* session = networkSession(sessionID);
2722     // Session can be destroyed before page gets removed.
2723     if (!session)
2724         return;
2725
2726     auto& storageManager = session->storageManager();
2727     storageManager.removeAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
2728     storageManager.destroySessionStorageNamespace(pageID.toUInt64());
2729 }
2730
2731 void NetworkProcess::webProcessWasDisconnected(IPC::Connection& connection)
2732 {
2733     auto sessionID = m_sessionByConnection.take(connection.uniqueID());
2734     if (!sessionID.isValid())
2735         return;
2736
2737     if (auto* session = networkSession(sessionID))
2738         session->storageManager().processDidCloseConnection(connection);
2739 }
2740
2741 void NetworkProcess::webProcessSessionChanged(IPC::Connection& connection, PAL::SessionID newSessionID, const Vector<PageIdentifier>& pageIDs)
2742 {
2743     auto connectionID = connection.uniqueID();
2744     ASSERT(m_sessionByConnection.contains(connectionID));
2745     if (m_sessionByConnection.get(connectionID) == newSessionID)
2746         return;
2747
2748     webProcessWasDisconnected(connection);
2749     for (auto& pageID : pageIDs)
2750         webPageWasAdded(connection, newSessionID, pageID, pageID);
2751 }
2752
2753 void NetworkProcess::getLocalStorageOriginDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2754 {
2755     auto* session = networkSession(sessionID);
2756     if (!session) {
2757         LOG_ERROR("Cannot get local storage information for an unknown session");
2758         return;
2759     }
2760
2761     auto& storageManager = session->storageManager();
2762     storageManager.getLocalStorageOriginDetails([completionHandler = WTFMove(completionHandler)](auto&& details) mutable {
2763         completionHandler(WTFMove(details));
2764     });
2765 }
2766
2767 } // namespace WebKit