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