dc25c6bf00a35d74bb80f588b5c9728c1686ccf1
[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::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String> domains)>&& completionHandler)
978 {
979     if (auto* networkStorageSession = storageSession(sessionID))
980         completionHandler(networkStorageSession->getAllStorageAccessEntries());
981     else {
982         ASSERT_NOT_REACHED();
983         completionHandler({ });
984     }
985 }
986
987 void NetworkProcess::logFrameNavigation(PAL::SessionID sessionID, const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, const RegistrableDomain& sourceDomain, bool isRedirect, bool isMainFrame)
988 {
989     if (auto* networkSession = this->networkSession(sessionID)) {
990         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
991             resourceLoadStatistics->logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, isMainFrame);
992     } else
993         ASSERT_NOT_REACHED();
994 }
995
996 void NetworkProcess::logUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
997 {
998     if (auto* networkSession = this->networkSession(sessionID)) {
999         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1000             resourceLoadStatistics->logUserInteraction(domain, WTFMove(completionHandler));
1001         else
1002             completionHandler();
1003     } else {
1004         ASSERT_NOT_REACHED();
1005         completionHandler();
1006     }
1007 }
1008
1009 void NetworkProcess::hadUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
1010 {
1011     if (auto* networkSession = this->networkSession(sessionID)) {
1012         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1013             resourceLoadStatistics->hasHadUserInteraction(domain, WTFMove(completionHandler));
1014         else
1015             completionHandler(false);
1016     } else {
1017         ASSERT_NOT_REACHED();
1018         completionHandler(false);
1019     }
1020 }
1021
1022 void NetworkProcess::clearUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
1023 {
1024     if (auto* networkSession = this->networkSession(sessionID)) {
1025         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1026             resourceLoadStatistics->clearUserInteraction(domain, WTFMove(completionHandler));
1027         else
1028             completionHandler();
1029     } else {
1030         ASSERT_NOT_REACHED();
1031         completionHandler();
1032     }
1033 }
1034
1035 void NetworkProcess::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
1036 {
1037     if (m_storageManagerSet->contains(sessionID)) {
1038         m_storageManagerSet->getLocalStorageOrigins(sessionID, [domain, completionHandler = WTFMove(completionHandler)](auto&& origins) mutable {
1039             completionHandler(WTF::anyOf(origins, [&domain](auto& origin) {
1040                 return domain.matches(origin);
1041             }));
1042         });
1043         return;
1044     }
1045     completionHandler(false);
1046 }
1047
1048 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domains)
1049 {
1050     if (auto* networkStorageSession = storageSession(sessionID))
1051         networkStorageSession->removePrevalentDomains(domains);
1052 }
1053
1054 void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1055 {
1056     if (auto* networkStorageSession = storageSession(sessionID))
1057         networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
1058     else
1059         ASSERT_NOT_REACHED();
1060     completionHandler();
1061 }
1062
1063 void NetworkProcess::setGrandfatheringTime(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1064 {
1065     if (auto* networkSession = this->networkSession(sessionID)) {
1066         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1067             resourceLoadStatistics->setGrandfatheringTime(seconds, WTFMove(completionHandler));
1068         else
1069             completionHandler();
1070     } else {
1071         ASSERT_NOT_REACHED();
1072         completionHandler();
1073     }
1074 }
1075
1076 void NetworkProcess::setMaxStatisticsEntries(PAL::SessionID sessionID, uint64_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
1077 {
1078     if (auto* networkSession = this->networkSession(sessionID)) {
1079         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1080             resourceLoadStatistics->setMaxStatisticsEntries(maximumEntryCount, WTFMove(completionHandler));
1081         else
1082             completionHandler();
1083     } else {
1084         ASSERT_NOT_REACHED();
1085         completionHandler();
1086     }
1087 }
1088
1089 void NetworkProcess::setMinimumTimeBetweenDataRecordsRemoval(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1090 {
1091     if (auto* networkSession = this->networkSession(sessionID)) {
1092         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1093             resourceLoadStatistics->setMinimumTimeBetweenDataRecordsRemoval(seconds, WTFMove(completionHandler));
1094         else
1095             completionHandler();
1096     } else {
1097         ASSERT_NOT_REACHED();
1098         completionHandler();
1099     }
1100 }
1101
1102 void NetworkProcess::setPruneEntriesDownTo(PAL::SessionID sessionID, uint64_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
1103 {
1104     if (auto* networkSession = this->networkSession(sessionID)) {
1105         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1106             resourceLoadStatistics->setPruneEntriesDownTo(pruneTargetCount, WTFMove(completionHandler));
1107         else
1108             completionHandler();
1109     } else {
1110         ASSERT_NOT_REACHED();
1111         completionHandler();
1112     }
1113 }
1114
1115 void NetworkProcess::setTimeToLiveUserInteraction(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1116 {
1117     if (auto* networkSession = this->networkSession(sessionID)) {
1118         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1119             resourceLoadStatistics->setTimeToLiveUserInteraction(seconds, WTFMove(completionHandler));
1120         else
1121             completionHandler();
1122     } else {
1123         ASSERT_NOT_REACHED();
1124         completionHandler();
1125     }
1126 }
1127
1128 void NetworkProcess::setShouldClassifyResourcesBeforeDataRecordsRemoval(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
1129 {
1130     if (auto* networkSession = this->networkSession(sessionID)) {
1131         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1132             resourceLoadStatistics->setShouldClassifyResourcesBeforeDataRecordsRemoval(value, WTFMove(completionHandler));
1133         else
1134             completionHandler();
1135     } else {
1136         ASSERT_NOT_REACHED();
1137         completionHandler();
1138     }
1139 }
1140
1141 void NetworkProcess::setResourceLoadStatisticsEnabled(PAL::SessionID sessionID, bool enabled)
1142 {
1143     if (auto* networkSession = this->networkSession(sessionID))
1144         networkSession->setResourceLoadStatisticsEnabled(enabled);
1145 }
1146
1147 void NetworkProcess::setResourceLoadStatisticsLogTestingEvent(bool enabled)
1148 {
1149     forEachNetworkSession([enabled](auto& networkSession) {
1150         networkSession.setResourceLoadStatisticsLogTestingEvent(enabled);
1151     });
1152 }
1153
1154 void NetworkProcess::setResourceLoadStatisticsDebugMode(PAL::SessionID sessionID, bool debugMode, CompletionHandler<void()>&& completionHandler)
1155 {
1156     if (auto* networkSession = this->networkSession(sessionID)) {
1157         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1158             resourceLoadStatistics->setResourceLoadStatisticsDebugMode(debugMode, WTFMove(completionHandler));
1159         else
1160             completionHandler();
1161     } else {
1162         ASSERT_NOT_REACHED();
1163         completionHandler();
1164     }
1165 }
1166
1167 void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1168 {
1169     if (auto* networkStorageSession = storageSession(sessionID))
1170         networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
1171     else
1172         ASSERT_NOT_REACHED();
1173     completionHandler();
1174 }
1175
1176 void NetworkProcess::didCommitCrossSiteLoadWithDataTransfer(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, OptionSet<WebCore::CrossSiteNavigationDataTransfer::Flag> navigationDataTransfer, WebPageProxyIdentifier webPageProxyID, WebCore::PageIdentifier webPageID)
1177 {
1178     ASSERT(!navigationDataTransfer.isEmpty());
1179
1180     if (auto* networkStorageSession = storageSession(sessionID)) {
1181         if (!networkStorageSession->shouldBlockThirdPartyCookies(fromDomain))
1182             return;
1183
1184         if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration))
1185             networkStorageSession->didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(toDomain, webPageID);
1186
1187         if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::ReferrerLinkDecoration))
1188             parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCommitCrossSiteLoadWithDataTransferFromPrevalentResource(webPageProxyID), 0);
1189     } else
1190         ASSERT_NOT_REACHED();
1191
1192     if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration)) {
1193         if (auto* networkSession = this->networkSession(sessionID)) {
1194             if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1195                 resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, [] { });
1196         } else
1197             ASSERT_NOT_REACHED();
1198     }
1199 }
1200
1201 void NetworkProcess::setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
1202 {
1203     if (auto* networkSession = this->networkSession(sessionID)) {
1204         if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1205             resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, WTFMove(completionHandler));
1206         else
1207             completionHandler();
1208     } else {
1209         ASSERT_NOT_REACHED();
1210         completionHandler();
1211     }
1212 }
1213
1214 void NetworkProcess::resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1215 {
1216     if (auto* networkStorageSession = storageSession(sessionID))
1217         networkStorageSession->resetCrossSiteLoadsWithLinkDecorationForTesting();
1218     else
1219         ASSERT_NOT_REACHED();
1220     completionHandler();
1221 }
1222
1223 void NetworkProcess::hasIsolatedSession(PAL::SessionID sessionID, const WebCore::RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler) const
1224 {
1225     bool result = false;
1226     if (auto* networkSession = this->networkSession(sessionID))
1227         result = networkSession->hasIsolatedSession(domain);
1228     completionHandler(result);
1229 }
1230
1231 void NetworkProcess::setShouldDowngradeReferrerForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
1232 {
1233     forEachNetworkSession([enabled](auto& networkSession) {
1234         networkSession.setShouldDowngradeReferrerForTesting(enabled);
1235     });
1236     completionHandler();
1237 }
1238 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1239
1240 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
1241 {
1242     return m_sessionsControlledByAutomation.contains(sessionID);
1243 }
1244
1245 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
1246 {
1247     if (controlled)
1248         m_sessionsControlledByAutomation.add(sessionID);
1249     else
1250         m_sessionsControlledByAutomation.remove(sessionID);
1251 }
1252
1253 static void fetchDiskCacheEntries(NetworkCache::Cache* cache, PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void(Vector<WebsiteData::Entry>)>&& completionHandler)
1254 {
1255     if (!cache) {
1256         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
1257             completionHandler({ });
1258         });
1259         return;
1260     }
1261     
1262     HashMap<SecurityOriginData, uint64_t> originsAndSizes;
1263     cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
1264         if (!traversalEntry) {
1265             Vector<WebsiteData::Entry> entries;
1266
1267             for (auto& originAndSize : originsAndSizes)
1268                 entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
1269
1270             RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] () mutable {
1271                 completionHandler(entries);
1272             });
1273
1274             return;
1275         }
1276
1277         auto url = traversalEntry->entry.response().url();
1278         auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
1279
1280         if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
1281             result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
1282     });
1283 }
1284
1285 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
1286 {
1287     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1288         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
1289             : m_completionHandler(WTFMove(completionHandler))
1290         {
1291         }
1292
1293         ~CallbackAggregator()
1294         {
1295             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1296                 completionHandler(websiteData);
1297             });
1298         }
1299
1300         CompletionHandler<void(WebsiteData)> m_completionHandler;
1301         WebsiteData m_websiteData;
1302     };
1303
1304     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
1305         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1306     }));
1307
1308     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1309         if (auto* networkStorageSession = storageSession(sessionID))
1310             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
1311     }
1312
1313     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1314         if (storageSession(sessionID)) {
1315             auto securityOrigins = storageSession(sessionID)->credentialStorage().originsWithCredentials();
1316             for (auto& securityOrigin : securityOrigins)
1317                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1318         }
1319         auto securityOrigins = WebCore::CredentialStorage::originsWithSessionCredentials();
1320         for (auto& securityOrigin : securityOrigins)
1321             callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1322     }
1323
1324     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1325         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1326             callbackAggregator->m_websiteData.entries.appendVector(entries);
1327         });
1328     }
1329
1330     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID)) {
1331         m_storageManagerSet->getSessionStorageOrigins(sessionID, [callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1332             while (!origins.isEmpty())
1333                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 });
1334         });
1335     }
1336
1337     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID)) {
1338         m_storageManagerSet->getLocalStorageOrigins(sessionID, [callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1339             while (!origins.isEmpty())
1340                 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 });
1341         });
1342     }
1343
1344 #if PLATFORM(COCOA) || USE(SOUP)
1345     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1346         if (auto* networkStorageSession = storageSession(sessionID))
1347             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
1348     }
1349 #endif
1350
1351 #if ENABLE(INDEXED_DATABASE)
1352     auto path = m_idbDatabasePaths.get(sessionID);
1353     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1354         // FIXME: Pick the right database store based on the session ID.
1355         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = crossThreadCopy(path)]() mutable {
1356             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
1357                 for (const auto& securityOrigin : securityOrigins)
1358                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1359             });
1360         }));
1361     }
1362 #endif
1363
1364 #if ENABLE(SERVICE_WORKER)
1365     path = m_serviceWorkerInfo.get(sessionID).databasePath;
1366     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1367         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1368             for (auto& origin : securityOrigins)
1369                 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1370         });
1371     }
1372 #endif
1373     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1374         forEachNetworkSession([sessionID, fetchOptions, &callbackAggregator](auto& session) {
1375             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1376                 callbackAggregator->m_websiteData.entries.appendVector(entries);
1377             });
1378         });
1379     }
1380 }
1381
1382 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
1383 {
1384 #if PLATFORM(COCOA) || USE(SOUP)
1385     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1386         if (auto* networkStorageSession = storageSession(sessionID))
1387             clearHSTSCache(*networkStorageSession, modifiedSince);
1388     }
1389 #endif
1390
1391     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1392         if (auto* networkStorageSession = storageSession(sessionID))
1393             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
1394     }
1395
1396     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1397         if (auto* session = storageSession(sessionID))
1398             session->credentialStorage().clearCredentials();
1399         WebCore::CredentialStorage::clearSessionCredentials();
1400     }
1401
1402     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1403         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1404     });
1405
1406     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
1407         CacheStorage::Engine::clearAllCaches(*this, sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1408
1409     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID))
1410         m_storageManagerSet->deleteSessionStorage(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1411
1412     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID))
1413         m_storageManagerSet->deleteLocalStorageModifiedSince(sessionID, modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1414
1415 #if ENABLE(INDEXED_DATABASE)
1416     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1417         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1418 #endif
1419
1420 #if ENABLE(SERVICE_WORKER)
1421     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
1422         swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
1423 #endif
1424
1425 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1426     if (websiteDataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
1427         if (auto* networkSession = this->networkSession(sessionID)) {
1428             if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
1429                 auto deletedTypesRaw = websiteDataTypes.toRaw();
1430                 auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
1431                 
1432                 // If we are deleting all of the data types that the resource load statistics store monitors
1433                 // we do not need to re-grandfather old data.
1434                 auto shouldGrandfather = ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw) ? ShouldGrandfatherStatistics::No : ShouldGrandfatherStatistics::Yes;
1435                 
1436                 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, shouldGrandfather, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1437             }
1438         }
1439     }
1440 #endif
1441
1442     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
1443         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
1444
1445     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) || websiteDataTypes.contains(WebsiteDataType::DOMCache))
1446         clearStorageQuota(sessionID);
1447
1448     if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1449         if (auto* networkSession = this->networkSession(sessionID))
1450             networkSession->clearAdClickAttribution();
1451     }
1452 }
1453
1454 static void clearDiskCacheEntries(NetworkCache::Cache* cache, const Vector<SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
1455 {
1456     if (!cache) {
1457         RunLoop::main().dispatch(WTFMove(completionHandler));
1458         return;
1459     }
1460
1461     HashSet<RefPtr<SecurityOrigin>> originsToDelete;
1462     for (auto& origin : origins)
1463         originsToDelete.add(origin.securityOrigin());
1464
1465     Vector<NetworkCache::Key> cacheKeysToDelete;
1466     cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
1467         if (traversalEntry) {
1468             if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
1469                 cacheKeysToDelete.append(traversalEntry->entry.key());
1470             return;
1471         }
1472
1473         cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
1474         return;
1475     });
1476 }
1477
1478 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
1479 {
1480     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1481         if (auto* networkStorageSession = storageSession(sessionID))
1482             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
1483     }
1484
1485 #if PLATFORM(COCOA) || USE(SOUP)
1486     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1487         if (auto* networkStorageSession = storageSession(sessionID))
1488             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
1489     }
1490 #endif
1491
1492     if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1493         if (auto* networkSession = this->networkSession(sessionID)) {
1494             for (auto& originData : originDatas)
1495                 networkSession->clearAdClickAttributionForRegistrableDomain(RegistrableDomain::uncheckedCreateFromHost(originData.host));
1496         }
1497     }
1498     
1499     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1500         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1501     });
1502
1503     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1504         for (auto& originData : originDatas)
1505             CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1506     }
1507
1508     if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManagerSet->contains(sessionID))
1509         m_storageManagerSet->deleteSessionStorageForOrigins(sessionID, originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1510
1511     if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManagerSet->contains(sessionID))
1512         m_storageManagerSet->deleteLocalStorageForOrigins(sessionID, originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1513
1514 #if ENABLE(INDEXED_DATABASE)
1515     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1516         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1517 #endif
1518
1519 #if ENABLE(SERVICE_WORKER)
1520     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
1521         auto& server = swServerForSession(sessionID);
1522         for (auto& originData : originDatas)
1523             server.clear(originData, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1524     }
1525 #endif
1526
1527     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral()) {
1528         forEachNetworkSession([originDatas, &clearTasksHandler](auto& session) {
1529             clearDiskCacheEntries(session.cache(), originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1530         });
1531     }
1532
1533     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1534         if (auto* session = storageSession(sessionID)) {
1535             for (auto& originData : originDatas)
1536                 session->credentialStorage().removeCredentialsWithOrigin(originData);
1537         }
1538         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originDatas);
1539     }
1540
1541     // FIXME: Implement storage quota clearing for these origins.
1542 }
1543
1544 void NetworkProcess::clearStorageQuota(PAL::SessionID sessionID)
1545 {
1546     auto iterator = m_storageQuotaManagers.find(sessionID);
1547     if (iterator == m_storageQuotaManagers.end())
1548         return;
1549
1550     auto& managers = iterator->value;
1551     for (auto& manager : managers.managersPerOrigin())
1552         manager.value->resetQuota(managers.defaultQuota(manager.key));
1553 }
1554
1555 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1556 static Vector<String> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const HashSet<String>& foundValues)
1557 {
1558     Vector<String> result;
1559     for (const auto& value : foundValues) {
1560         if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value)))
1561             result.append(value);
1562     }
1563     
1564     return result;
1565 }
1566
1567 static Vector<WebsiteData::Entry> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const Vector<WebsiteData::Entry>& foundValues)
1568 {
1569     Vector<WebsiteData::Entry> result;
1570     for (const auto& value : foundValues) {
1571         if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value.origin.host)))
1572             result.append(value);
1573     }
1574     
1575     return result;
1576 }
1577
1578 static Vector<WebCore::SecurityOriginData> filterForRegistrableDomains(const HashSet<WebCore::SecurityOriginData>& origins, const Vector<RegistrableDomain>& domainsToDelete, HashSet<RegistrableDomain>& domainsDeleted)
1579 {
1580     Vector<SecurityOriginData> originsDeleted;
1581     for (const auto& origin : origins) {
1582         auto domain = RegistrableDomain::uncheckedCreateFromHost(origin.host);
1583         if (!domainsToDelete.contains(domain))
1584             continue;
1585         originsDeleted.append(origin);
1586         domainsDeleted.add(domain);
1587     }
1588
1589     return originsDeleted;
1590 }
1591
1592 void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1593 {
1594     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1595
1596     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1597         explicit CallbackAggregator(CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1598             : m_completionHandler(WTFMove(completionHandler))
1599         {
1600         }
1601         
1602         ~CallbackAggregator()
1603         {
1604             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), domains = WTFMove(m_domains)] () mutable {
1605                 completionHandler(domains);
1606             });
1607         }
1608         
1609         CompletionHandler<void(const HashSet<RegistrableDomain>&)> m_completionHandler;
1610         HashSet<RegistrableDomain> m_domains;
1611     };
1612     
1613     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (const HashSet<RegistrableDomain>& domainsWithData) mutable {
1614         if (shouldNotifyPage)
1615             parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataDeletionForRegistrableDomainsFinished(), 0);
1616         
1617         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1618             completionHandler(domainsWithData);
1619         });
1620     }));
1621
1622     HashSet<String> hostNamesWithCookies;
1623     HashSet<String> hostNamesWithHSTSCache;
1624
1625     Vector<RegistrableDomain> domainsToDeleteCookiesFor;
1626     Vector<RegistrableDomain> domainsToDeleteAllButHttpOnlyCookiesFor;
1627     Vector<RegistrableDomain> domainsToDeleteAllButCookiesFor;
1628     Vector<String> hostnamesWithCookiesToDelete;
1629     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1630         for (auto& pair : domains) {
1631             auto& domain = pair.first;
1632             auto& dataToRemove = pair.second;
1633             domainsToDeleteAllButCookiesFor.append(domain);
1634             switch (dataToRemove) {
1635             case WebsiteDataToRemove::All:
1636                 domainsToDeleteCookiesFor.append(domain);
1637                 break;
1638             case WebsiteDataToRemove::AllButHttpOnlyCookies:
1639                 domainsToDeleteAllButHttpOnlyCookiesFor.append(domain);
1640                 break;
1641             case WebsiteDataToRemove::AllButCookies:
1642                 // Already added.
1643                 break;
1644             }
1645         }
1646         if (auto* networkStorageSession = storageSession(sessionID)) {
1647             networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
1648
1649             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, hostNamesWithCookies);
1650             networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes);
1651
1652             for (const auto& host : hostnamesWithCookiesToDelete)
1653                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1654
1655             hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
1656             networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No);
1657
1658             for (const auto& host : hostnamesWithCookiesToDelete)
1659                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1660         }
1661     } else {
1662         for (auto& domain : domains)
1663             domainsToDeleteAllButCookiesFor.append(domain.first);
1664     }
1665
1666     Vector<String> hostnamesWithHSTSToDelete;
1667 #if PLATFORM(COCOA) || USE(SOUP)
1668     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1669         if (auto* networkStorageSession = storageSession(sessionID)) {
1670             getHostNamesWithHSTSCache(*networkStorageSession, hostNamesWithHSTSCache);
1671             hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, hostNamesWithHSTSCache);
1672
1673             for (const auto& host : hostnamesWithHSTSToDelete)
1674                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1675
1676             deleteHSTSCacheForHostNames(*networkStorageSession, hostnamesWithHSTSToDelete);
1677         }
1678     }
1679 #endif
1680
1681     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1682         if (auto* session = storageSession(sessionID)) {
1683             auto origins = session->credentialStorage().originsWithCredentials();
1684             auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1685             for (auto& origin : originsToDelete)
1686                 session->credentialStorage().removeCredentialsWithOrigin(origin);
1687         }
1688
1689         auto origins = WebCore::CredentialStorage::originsWithSessionCredentials();
1690         auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1691         WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originsToDelete);
1692     }
1693     
1694     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1695         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [this, domainsToDeleteAllButCookiesFor, sessionID, callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1696             
1697             auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, entries);
1698
1699             for (const auto& entry : entriesToDelete)
1700                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1701
1702             for (auto& entry : entriesToDelete)
1703                 CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { });
1704         });
1705     }
1706
1707     if (m_storageManagerSet->contains(sessionID)) {
1708         if (websiteDataTypes.contains(WebsiteDataType::SessionStorage)) {
1709             m_storageManagerSet->getSessionStorageOrigins(sessionID, [protectedThis = makeRef(*this), this, sessionID, callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1710                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1711                 m_storageManagerSet->deleteSessionStorageForOrigins(sessionID, originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1712             });
1713         }
1714
1715         if (websiteDataTypes.contains(WebsiteDataType::LocalStorage)) {
1716             m_storageManagerSet->getLocalStorageOrigins(sessionID, [protectedThis = makeRef(*this), this, sessionID, callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1717                 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1718                 m_storageManagerSet->deleteLocalStorageForOrigins(sessionID, originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1719             });
1720         }
1721     }
1722
1723 #if ENABLE(INDEXED_DATABASE)
1724     auto path = m_idbDatabasePaths.get(sessionID);
1725     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1726         // FIXME: Pick the right database store based on the session ID.
1727         postStorageTask(CrossThreadTask([this, sessionID, callbackAggregator = callbackAggregator.copyRef(), path = crossThreadCopy(path), domainsToDeleteAllButCookiesFor = crossThreadCopy(domainsToDeleteAllButCookiesFor)]() mutable {
1728             RunLoop::main().dispatch([this, sessionID, domainsToDeleteAllButCookiesFor = WTFMove(domainsToDeleteAllButCookiesFor), callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1729                 Vector<SecurityOriginData> entriesToDelete;
1730                 for (const auto& securityOrigin : securityOrigins) {
1731                     auto domain = RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host);
1732                     if (!domainsToDeleteAllButCookiesFor.contains(domain))
1733                         continue;
1734
1735                     entriesToDelete.append(securityOrigin);
1736                     callbackAggregator->m_domains.add(domain);
1737                 }
1738
1739                 idbServer(sessionID).closeAndDeleteDatabasesForOrigins(entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1740             });
1741         }));
1742     }
1743 #endif
1744     
1745 #if ENABLE(SERVICE_WORKER)
1746     path = m_serviceWorkerInfo.get(sessionID).databasePath;
1747     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1748         swServerForSession(sessionID).getOriginsWithRegistrations([this, sessionID, domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1749             for (auto& securityOrigin : securityOrigins) {
1750                 if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
1751                     continue;
1752                 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
1753                 swServerForSession(sessionID).clear(securityOrigin, [callbackAggregator = callbackAggregator.copyRef()] { });
1754             }
1755         });
1756     }
1757 #endif
1758
1759     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1760         forEachNetworkSession([sessionID, fetchOptions, &domainsToDeleteAllButCookiesFor, &callbackAggregator](auto& session) {
1761             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef(), session = makeWeakPtr(&session)](auto entries) mutable {
1762                 if (!session)
1763                     return;
1764
1765                 Vector<SecurityOriginData> entriesToDelete;
1766                 for (auto& entry : entries) {
1767                     if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
1768                         continue;
1769                     entriesToDelete.append(entry.origin);
1770                     callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1771                 }
1772                 clearDiskCacheEntries(session->cache(), entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1773             });
1774         });
1775     }
1776
1777     auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
1778     if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllButCookiesFor.isEmpty()) {
1779         CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator = callbackAggregator.copyRef()] (const HashSet<RegistrableDomain>& domains) {
1780             for (auto& domain : domains)
1781                 callbackAggregator->m_domains.add(domain);
1782         };
1783         parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllButCookiesFor), WTFMove(completionHandler));
1784     }
1785 }
1786
1787 void NetworkProcess::deleteCookiesForTesting(PAL::SessionID sessionID, RegistrableDomain domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1788 {
1789     OptionSet<WebsiteDataType> cookieType = WebsiteDataType::Cookies;
1790     Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>> toDeleteFor = {
1791         std::make_pair(domain, includeHttpOnlyCookies ? WebsiteDataToRemove::All : WebsiteDataToRemove::AllButHttpOnlyCookies)
1792     };
1793     deleteWebsiteDataForRegistrableDomains(sessionID, cookieType, WTFMove(toDeleteFor), true, [completionHandler = WTFMove(completionHandler)] (const HashSet<RegistrableDomain>& domainsDeletedFor) mutable {
1794         UNUSED_PARAM(domainsDeletedFor);
1795         completionHandler();
1796     });
1797 }
1798
1799 void NetworkProcess::registrableDomainsWithWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1800 {
1801     OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1802     
1803     struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1804         explicit CallbackAggregator(CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1805             : m_completionHandler(WTFMove(completionHandler))
1806         {
1807         }
1808         
1809         ~CallbackAggregator()
1810         {
1811             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1812                 HashSet<RegistrableDomain> domains;
1813                 for (const auto& hostnameWithCookies : websiteData.hostNamesWithCookies)
1814                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithCookies));
1815
1816                 for (const auto& hostnameWithHSTS : websiteData.hostNamesWithHSTSCache)
1817                     domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithHSTS));
1818
1819                 for (const auto& entry : websiteData.entries)
1820                     domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1821
1822                 completionHandler(WTFMove(domains));
1823             });
1824         }
1825         
1826         CompletionHandler<void(HashSet<RegistrableDomain>&&)> m_completionHandler;
1827         WebsiteData m_websiteData;
1828     };
1829     
1830     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (HashSet<RegistrableDomain>&& domainsWithData) mutable {
1831         if (shouldNotifyPage)
1832             parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataScanForRegistrableDomainsFinished(), 0);
1833
1834         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1835             completionHandler(WTFMove(domainsWithData));
1836         });
1837     }));
1838     
1839     auto& websiteDataStore = callbackAggregator->m_websiteData;
1840     
1841     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1842         if (auto* networkStorageSession = storageSession(sessionID))
1843             networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
1844     }
1845     
1846 #if PLATFORM(COCOA) || USE(SOUP)
1847     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1848         if (auto* networkStorageSession = storageSession(sessionID))
1849             getHostNamesWithHSTSCache(*networkStorageSession, websiteDataStore.hostNamesWithHSTSCache);
1850     }
1851 #endif
1852
1853     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1854         if (auto* networkStorageSession = storageSession(sessionID)) {
1855             auto securityOrigins = networkStorageSession->credentialStorage().originsWithCredentials();
1856             for (auto& securityOrigin : securityOrigins)
1857                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1858         }
1859     }
1860     
1861     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1862         CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1863             callbackAggregator->m_websiteData.entries.appendVector(entries);
1864         });
1865     }
1866     
1867 #if ENABLE(INDEXED_DATABASE)
1868     auto path = m_idbDatabasePaths.get(sessionID);
1869     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1870         // FIXME: Pick the right database store based on the session ID.
1871         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = crossThreadCopy(path)]() mutable {
1872             RunLoop::main().dispatch([callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1873                 for (const auto& securityOrigin : securityOrigins)
1874                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1875             });
1876         }));
1877     }
1878 #endif
1879     
1880 #if ENABLE(SERVICE_WORKER)
1881     path = m_serviceWorkerInfo.get(sessionID).databasePath;
1882     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1883         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1884             for (auto& securityOrigin : securityOrigins)
1885                 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1886         });
1887     }
1888 #endif
1889     
1890     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1891         forEachNetworkSession([sessionID, fetchOptions, &callbackAggregator](auto& session) {
1892             fetchDiskCacheEntries(session.cache(), sessionID, fetchOptions, [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1893                 callbackAggregator->m_websiteData.entries.appendVector(entries);
1894             });
1895         });
1896     }
1897 }
1898 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1899
1900 CacheStorage::Engine* NetworkProcess::findCacheEngine(const PAL::SessionID& sessionID)
1901 {
1902     return m_cacheEngines.get(sessionID);
1903 }
1904
1905 CacheStorage::Engine& NetworkProcess::ensureCacheEngine(const PAL::SessionID& sessionID, Function<Ref<CacheStorage::Engine>()>&& functor)
1906 {
1907     return m_cacheEngines.ensure(sessionID, WTFMove(functor)).iterator->value;
1908 }
1909
1910 void NetworkProcess::removeCacheEngine(const PAL::SessionID& sessionID)
1911 {
1912     m_cacheEngines.remove(sessionID);
1913 }
1914
1915 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
1916 {
1917     downloadManager().startDownload(sessionID, downloadID, request, suggestedFilename);
1918 }
1919
1920 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
1921 {
1922     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
1923 }
1924
1925 void NetworkProcess::cancelDownload(DownloadID downloadID)
1926 {
1927     downloadManager().cancelDownload(downloadID);
1928 }
1929
1930 #if PLATFORM(COCOA)
1931 void NetworkProcess::publishDownloadProgress(DownloadID downloadID, const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
1932 {
1933     downloadManager().publishDownloadProgress(downloadID, url, WTFMove(sandboxExtensionHandle));
1934 }
1935 #endif
1936
1937 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
1938 {
1939     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
1940 }
1941
1942 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
1943 {
1944     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
1945 }
1946
1947 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
1948 {
1949     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
1950     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
1951
1952     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
1953
1954     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
1955     // should override the suggested filename from the download attribute.
1956     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
1957     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
1958
1959     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
1960 }
1961
1962 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
1963 {
1964     if (destination.isEmpty())
1965         downloadManager().cancelDownload(downloadID);
1966     else
1967         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
1968 }
1969
1970 void NetworkProcess::setCacheModel(CacheModel cacheModel, String cacheStorageDirectory)
1971 {
1972     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
1973         return;
1974
1975     m_hasSetCacheModel = true;
1976     m_cacheModel = cacheModel;
1977
1978     unsigned urlCacheMemoryCapacity = 0;
1979     uint64_t urlCacheDiskCapacity = 0;
1980     uint64_t diskFreeSize = 0;
1981
1982     // 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.
1983     forEachNetworkSession([&](auto& session) {
1984         if (!cacheStorageDirectory.isNull())
1985             return;
1986         if (auto* cache = session.cache())
1987             cacheStorageDirectory = cache->storageDirectory();
1988     });
1989
1990     if (FileSystem::getVolumeFreeSpace(cacheStorageDirectory, diskFreeSize)) {
1991         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
1992         // count doesn't align exactly to a megabyte boundary.
1993         diskFreeSize /= KB * 1000;
1994         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
1995     }
1996
1997     forEachNetworkSession([urlCacheDiskCapacity](auto& session) {
1998         if (auto* cache = session.cache())
1999             cache->setCapacity(urlCacheDiskCapacity);
2000     });
2001 }
2002
2003 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
2004 {
2005     StatisticsData data;
2006
2007     data.statisticsNumbers.set("DownloadsActiveCount", downloadManager().activeDownloadCount());
2008     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", authenticationManager().outstandingAuthenticationChallengeCount());
2009
2010     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
2011 }
2012
2013 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows, CompletionHandler<void()>&& completionHandler)
2014 {
2015     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
2016     completionHandler();
2017 }
2018
2019 void NetworkProcess::logDiagnosticMessage(WebPageProxyIdentifier webPageProxyID, const String& message, const String& description, ShouldSample shouldSample)
2020 {
2021     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2022         return;
2023
2024     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageProxyID, message, description, ShouldSample::No), 0);
2025 }
2026
2027 void NetworkProcess::logDiagnosticMessageWithResult(WebPageProxyIdentifier webPageProxyID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
2028 {
2029     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2030         return;
2031
2032     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageProxyID, message, description, result, ShouldSample::No), 0);
2033 }
2034
2035 void NetworkProcess::logDiagnosticMessageWithValue(WebPageProxyIdentifier webPageProxyID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
2036 {
2037     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
2038         return;
2039
2040     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageProxyID, message, description, value, significantFigures, ShouldSample::No), 0);
2041 }
2042
2043 void NetworkProcess::terminate()
2044 {
2045     platformTerminate();
2046     AuxiliaryProcess::terminate();
2047 }
2048
2049 void NetworkProcess::processDidTransitionToForeground()
2050 {
2051     platformProcessDidTransitionToForeground();
2052 }
2053
2054 void NetworkProcess::processDidTransitionToBackground()
2055 {
2056     platformProcessDidTransitionToBackground();
2057 }
2058
2059 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
2060 {
2061 #if PLATFORM(IOS_FAMILY)
2062     m_webSQLiteDatabaseTracker.setIsSuspended(true);
2063 #endif
2064
2065     lowMemoryHandler(Critical::Yes);
2066
2067     RefPtr<CallbackAggregator> callbackAggregator;
2068     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
2069         callbackAggregator = CallbackAggregator::create([this] {
2070             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
2071             if (parentProcessConnection())
2072                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
2073         });
2074     }
2075
2076     platformPrepareToSuspend([callbackAggregator] { });
2077     platformSyncAllCookies([callbackAggregator] { });
2078
2079     for (auto& connection : m_webProcessConnections.values())
2080         connection->cleanupForSuspension([callbackAggregator] { });
2081
2082 #if ENABLE(SERVICE_WORKER)
2083     for (auto& server : m_swServers.values()) {
2084         ASSERT(m_swServers.get(server->sessionID()) == server.get());
2085         server->startSuspension([callbackAggregator] { });
2086     }
2087 #endif
2088
2089     m_storageManagerSet->suspend([callbackAggregator] { });
2090 }
2091
2092 void NetworkProcess::processWillSuspendImminently()
2093 {
2094     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() BEGIN", this);
2095 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2096     for (auto& server : m_idbServers.values())
2097         server->tryStop(IDBServer::ShouldForceStop::Yes);
2098 #endif
2099     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
2100     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() END", this);
2101 }
2102
2103 void NetworkProcess::processWillSuspendImminentlyForTestingSync(CompletionHandler<void()>&& completionHandler)
2104 {
2105     processWillSuspendImminently();
2106     completionHandler();
2107 }
2108
2109 void NetworkProcess::prepareToSuspend()
2110 {
2111     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
2112
2113 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2114     for (auto& server : m_idbServers.values())
2115         server->tryStop(IDBServer::ShouldForceStop::No);
2116 #endif
2117     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
2118 }
2119
2120 void NetworkProcess::cancelPrepareToSuspend()
2121 {
2122     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
2123     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
2124     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
2125     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
2126     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
2127     resume();
2128 }
2129
2130 void NetworkProcess::applicationDidEnterBackground()
2131 {
2132     m_downloadManager.applicationDidEnterBackground();
2133 }
2134
2135 void NetworkProcess::applicationWillEnterForeground()
2136 {
2137     m_downloadManager.applicationWillEnterForeground();
2138 }
2139
2140 void NetworkProcess::processDidResume()
2141 {
2142     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
2143     resume();
2144 }
2145
2146 void NetworkProcess::resume()
2147 {
2148 #if PLATFORM(IOS_FAMILY)
2149     m_webSQLiteDatabaseTracker.setIsSuspended(false);
2150 #endif
2151
2152     platformProcessDidResume();
2153     for (auto& connection : m_webProcessConnections.values())
2154         connection->endSuspension();
2155
2156 #if ENABLE(SERVICE_WORKER)
2157     for (auto& server : m_swServers.values())
2158         server->endSuspension();
2159 #endif
2160 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2161     for (auto& server : m_idbServers.values())
2162         server->resume();
2163 #endif
2164
2165     m_storageManagerSet->resume();
2166 }
2167
2168 void NetworkProcess::prefetchDNS(const String& hostname)
2169 {
2170     WebCore::prefetchDNS(hostname);
2171 }
2172
2173 void NetworkProcess::cacheStorageRootPath(PAL::SessionID sessionID, CacheStorageRootPathCallback&& callback)
2174 {
2175     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
2176         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
2177         return Vector<CacheStorageRootPathCallback> { };
2178     }).iterator->value.append(WTFMove(callback));
2179 }
2180
2181 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
2182 {
2183     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
2184     if (iterator == m_cacheStorageParametersCallbacks.end())
2185         return;
2186
2187     SandboxExtension::consumePermanently(handle);
2188     auto callbacks = WTFMove(iterator->value);
2189     m_cacheStorageParametersCallbacks.remove(iterator);
2190     for (auto& callback : callbacks)
2191         callback(String { cacheStorageDirectory });
2192 }
2193
2194 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
2195 {
2196     SchemeRegistry::registerURLSchemeAsSecure(scheme);
2197 }
2198
2199 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
2200 {
2201     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2202 }
2203
2204 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
2205 {
2206     SchemeRegistry::registerURLSchemeAsLocal(scheme);
2207 }
2208
2209 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
2210 {
2211     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
2212 }
2213
2214 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
2215 {
2216     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
2217 }
2218
2219 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
2220 {
2221     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
2222 }
2223
2224 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
2225 {
2226     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
2227 }
2228
2229 void NetworkProcess::didSyncAllCookies()
2230 {
2231     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
2232 }
2233
2234 #if ENABLE(INDEXED_DATABASE)
2235 Ref<IDBServer::IDBServer> NetworkProcess::createIDBServer(PAL::SessionID sessionID)
2236 {
2237     String path;
2238     if (!sessionID.isEphemeral()) {
2239         ASSERT(m_idbDatabasePaths.contains(sessionID));
2240         path = m_idbDatabasePaths.get(sessionID);
2241     }
2242
2243     return IDBServer::IDBServer::create(sessionID, path, *this, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* {
2244         if (!weakThis)
2245             return nullptr;
2246         return &this->storageQuotaManager(sessionID, origin);
2247     });
2248 }
2249
2250 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
2251 {
2252     return *m_idbServers.ensure(sessionID, [this, sessionID] {
2253         return this->createIDBServer(sessionID);
2254     }).iterator->value;
2255 }
2256
2257 void NetworkProcess::ensurePathExists(const String& path)
2258 {
2259     ASSERT(!RunLoop::isMain());
2260     
2261     if (!FileSystem::makeAllDirectories(path))
2262         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
2263 }
2264
2265 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
2266 {
2267     ASSERT(RunLoop::isMain());
2268     
2269     LockHolder locker(m_storageTaskMutex);
2270     
2271     m_storageTasks.append(WTFMove(task));
2272     
2273     m_storageTaskQueue->dispatch([this] {
2274         performNextStorageTask();
2275     });
2276 }
2277
2278 void NetworkProcess::performNextStorageTask()
2279 {
2280     ASSERT(!RunLoop::isMain());
2281     
2282     CrossThreadTask task;
2283     {
2284         LockHolder locker(m_storageTaskMutex);
2285         ASSERT(!m_storageTasks.isEmpty());
2286         task = m_storageTasks.takeFirst();
2287     }
2288     
2289     task.performTask();
2290 }
2291
2292 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
2293 {
2294     // We've either hard linked the temporary blob file to the database directory, copied it there,
2295     // or the transaction is being aborted.
2296     // In any of those cases, we can delete the temporary blob file now.
2297     FileSystem::deleteFile(path);
2298 }
2299
2300 void NetworkProcess::collectIndexedDatabaseOriginsForVersion(const String& path, HashSet<WebCore::SecurityOriginData>& securityOrigins)
2301 {
2302     if (path.isEmpty())
2303         return;
2304
2305     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
2306         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
2307         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier)) {
2308             securityOrigins.add(WTFMove(*securityOrigin));
2309         
2310             for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
2311                 databaseIdentifier = FileSystem::pathGetFileName(originPath);
2312                 if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
2313                     securityOrigins.add(WTFMove(*securityOrigin));
2314             }
2315         }
2316     }
2317 }
2318
2319 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
2320 {
2321     if (path.isEmpty())
2322         return { };
2323     
2324     HashSet<WebCore::SecurityOriginData> securityOrigins;
2325     collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v0"), securityOrigins);
2326     collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v1"), securityOrigins);
2327
2328     return securityOrigins;
2329 }
2330
2331 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
2332 {
2333     // *********
2334     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
2335     // *********
2336     auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
2337     if (addResult.isNewEntry) {
2338         SandboxExtension::consumePermanently(handle);
2339         if (!indexedDatabaseDirectory.isEmpty())
2340             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
2341     }
2342 }
2343 #endif // ENABLE(INDEXED_DATABASE)
2344
2345 void NetworkProcess::syncLocalStorage(CompletionHandler<void()>&& completionHandler)
2346 {
2347     m_storageManagerSet->waitUntilSyncingLocalStorageFinished();
2348     completionHandler();
2349 }
2350
2351 void NetworkProcess::clearLegacyPrivateBrowsingLocalStorage()
2352 {
2353     if (m_storageManagerSet->contains(PAL::SessionID::legacyPrivateSessionID()))
2354         m_storageManagerSet->deleteLocalStorageModifiedSince(PAL::SessionID::legacyPrivateSessionID(), -WallTime::infinity(), []() { });
2355 }
2356
2357 void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
2358 {
2359     auto& manager = storageQuotaManager(sessionID, origin);
2360     manager.resetQuota(m_storageQuotaManagers.find(sessionID)->value.defaultQuota(origin));
2361     manager.updateQuotaBasedOnSpaceUsage();
2362 }
2363
2364 #if ENABLE(SANDBOX_EXTENSIONS)
2365 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&& completionHandler)
2366 {
2367     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(filenames), WTFMove(completionHandler));
2368 }
2369 #endif // ENABLE(SANDBOX_EXTENSIONS)
2370
2371 #if ENABLE(SERVICE_WORKER)
2372 void NetworkProcess::forEachSWServer(const Function<void(SWServer&)>& callback)
2373 {
2374     for (auto& server : m_swServers.values())
2375         callback(*server);
2376 }
2377
2378 SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
2379 {
2380     auto result = m_swServers.ensure(sessionID, [&] {
2381         auto info = m_serviceWorkerInfo.get(sessionID);
2382         auto path = info.databasePath;
2383         // There should already be a registered path for this PAL::SessionID.
2384         // If there's not, then where did this PAL::SessionID come from?
2385         ASSERT(sessionID.isEphemeral() || !path.isEmpty());
2386
2387         return makeUnique<SWServer>(makeUniqueRef<WebSWOriginStore>(), info.processTerminationDelayEnabled, WTFMove(path), sessionID, [this, sessionID](auto& registrableDomain) {
2388             ASSERT(!registrableDomain.isEmpty());
2389             parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess { registrableDomain, sessionID }, 0);
2390         });
2391     });
2392     return *result.iterator->value;
2393 }
2394
2395 WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
2396 {
2397     auto* swServer = m_swServers.get(sessionID);
2398     if (!swServer)
2399         return nullptr;
2400     return &static_cast<WebSWOriginStore&>(swServer->originStore());
2401 }
2402
2403 void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
2404 {
2405     ASSERT(parentProcessHasServiceWorkerEntitlement());
2406     auto* store = existingSWOriginStoreForSession(connection.sessionID());
2407     ASSERT(store);
2408     if (store)
2409         store->registerSWServerConnection(connection);
2410 }
2411
2412 void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
2413 {
2414     if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
2415         store->unregisterSWServerConnection(connection);
2416 }
2417
2418 void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, bool processTerminationDelayEnabled, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
2419 {
2420     ServiceWorkerInfo info {
2421         serviceWorkerRegistrationDirectory,
2422         processTerminationDelayEnabled,
2423     };
2424     auto addResult = m_serviceWorkerInfo.add(sessionID, WTFMove(info));
2425     if (addResult.isNewEntry) {
2426         SandboxExtension::consumePermanently(handle);
2427         if (!serviceWorkerRegistrationDirectory.isEmpty())
2428             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
2429     }
2430 }
2431 #endif // ENABLE(SERVICE_WORKER)
2432
2433 void NetworkProcess::requestStorageSpace(PAL::SessionID sessionID, const ClientOrigin& origin, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(Optional<uint64_t>)>&& callback)
2434 {
2435     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageSpace { sessionID, origin, quota, currentSize, spaceRequired }, WTFMove(callback), 0);
2436 }
2437
2438 class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
2439     WTF_MAKE_FAST_ALLOCATED;
2440 public:
2441     explicit QuotaUserInitializer(StorageQuotaManager& manager)
2442         : m_manager(makeWeakPtr(manager))
2443     {
2444         manager.addUser(*this);
2445     }
2446
2447     ~QuotaUserInitializer()
2448     {
2449         if (m_manager)
2450             m_manager->removeUser(*this);
2451         if (m_callback)
2452             m_callback();
2453     }
2454
2455 private:
2456     // StorageQuotaUser API.
2457     uint64_t spaceUsed() const final
2458     {
2459         ASSERT_NOT_REACHED();
2460         return 0;
2461     }
2462
2463     void whenInitialized(CompletionHandler<void()>&& callback) final
2464     {
2465         m_callback = WTFMove(callback);
2466     }
2467
2468     WeakPtr<StorageQuotaManager> m_manager;
2469     CompletionHandler<void()> m_callback;
2470 };
2471
2472 void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
2473 {
2474     RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = makeUnique<QuotaUserInitializer>(manager)]() mutable {
2475         if (!weakThis)
2476             return;
2477         this->idbServer(sessionID).initializeQuotaUser(origin);
2478         CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
2479     });
2480 }
2481
2482 StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
2483 {
2484     auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
2485         return StorageQuotaManagers { };
2486     }).iterator->value;
2487     return *storageQuotaManagers.managersPerOrigin().ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
2488         auto manager = makeUnique<StorageQuotaManager>(storageQuotaManagers.defaultQuota(origin), [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
2489             this->requestStorageSpace(sessionID, origin, quota, currentSpace, spaceIncrease, WTFMove(callback));
2490         });
2491         initializeQuotaUsers(*manager, sessionID, origin);
2492         return manager;
2493     }).iterator->value;
2494 }
2495
2496 #if !PLATFORM(COCOA)
2497 void NetworkProcess::initializeProcess(const AuxiliaryProcessInitializationParameters&)
2498 {
2499 }
2500
2501 void NetworkProcess::initializeProcessName(const AuxiliaryProcessInitializationParameters&)
2502 {
2503 }
2504
2505 void NetworkProcess::initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&)
2506 {
2507 }
2508
2509 void NetworkProcess::syncAllCookies()
2510 {
2511 }
2512
2513 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
2514 {
2515     completionHandler();
2516 }
2517
2518 #endif
2519
2520 void NetworkProcess::storeAdClickAttribution(PAL::SessionID sessionID, WebCore::AdClickAttribution&& adClickAttribution)
2521 {
2522     if (auto* session = networkSession(sessionID))
2523         session->storeAdClickAttribution(WTFMove(adClickAttribution));
2524 }
2525
2526 void NetworkProcess::dumpAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
2527 {
2528     if (auto* session = networkSession(sessionID))
2529         return session->dumpAdClickAttribution(WTFMove(completionHandler));
2530
2531     completionHandler({ });
2532 }
2533
2534 void NetworkProcess::clearAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2535 {
2536     if (auto* session = networkSession(sessionID))
2537         session->clearAdClickAttribution();
2538     
2539     completionHandler();
2540 }
2541
2542 void NetworkProcess::setAdClickAttributionOverrideTimerForTesting(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
2543 {
2544     if (auto* session = networkSession(sessionID))
2545         session->setAdClickAttributionOverrideTimerForTesting(value);
2546     
2547     completionHandler();
2548 }
2549
2550 void NetworkProcess::setAdClickAttributionConversionURLForTesting(PAL::SessionID sessionID, URL&& url, CompletionHandler<void()>&& completionHandler)
2551 {
2552     if (auto* session = networkSession(sessionID))
2553         session->setAdClickAttributionConversionURLForTesting(WTFMove(url));
2554     
2555     completionHandler();
2556 }
2557
2558 void NetworkProcess::markAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2559 {
2560     if (auto* session = networkSession(sessionID))
2561         session->markAdClickAttributionsAsExpiredForTesting();
2562
2563     completionHandler();
2564 }
2565
2566 void NetworkProcess::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
2567 {
2568     if (auto* session = networkSession(loader->sessionID()))
2569         session->addKeptAliveLoad(WTFMove(loader));
2570 }
2571
2572 void NetworkProcess::removeKeptAliveLoad(NetworkResourceLoader& loader)
2573 {
2574     if (auto* session = networkSession(loader.sessionID()))
2575         session->removeKeptAliveLoad(loader);
2576 }
2577
2578 void NetworkProcess::getLocalStorageOriginDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2579 {
2580     if (!m_storageManagerSet->contains(sessionID)) {
2581         LOG_ERROR("Cannot get local storage information for an unknown session");
2582         return;
2583     }
2584
2585     m_storageManagerSet->getLocalStorageOriginDetails(sessionID, [completionHandler = WTFMove(completionHandler)](auto&& details) mutable {
2586         completionHandler(WTFMove(details));
2587     });
2588 }
2589
2590 void NetworkProcess::connectionToWebProcessClosed(IPC::Connection& connection)
2591 {
2592     m_storageManagerSet->removeConnection(connection);
2593 }
2594
2595 NetworkConnectionToWebProcess* NetworkProcess::webProcessConnection(ProcessIdentifier identifier) const
2596 {
2597     return m_webProcessConnections.get(identifier);
2598 }
2599
2600 } // namespace WebKit