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