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