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