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