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