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