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