d3fa7142cb6fc198d3c1f29b429d3a32dcdce495
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2018 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 "SessionTracker.h"
53 #include "StatisticsData.h"
54 #include "WebCookieManager.h"
55 #include "WebCoreArgumentCoders.h"
56 #include "WebPageProxyMessages.h"
57 #include "WebProcessPoolMessages.h"
58 #include "WebSWOriginStore.h"
59 #include "WebSWServerConnection.h"
60 #include "WebSWServerToContextConnection.h"
61 #include "WebsiteData.h"
62 #include "WebsiteDataFetchOption.h"
63 #include "WebsiteDataStore.h"
64 #include "WebsiteDataStoreParameters.h"
65 #include "WebsiteDataType.h"
66 #include <WebCore/DNS.h>
67 #include <WebCore/DeprecatedGlobalSettings.h>
68 #include <WebCore/DiagnosticLoggingClient.h>
69 #include <WebCore/LogInitialization.h>
70 #include <WebCore/MIMETypeRegistry.h>
71 #include <WebCore/NetworkStateNotifier.h>
72 #include <WebCore/NetworkStorageSession.h>
73 #include <WebCore/ResourceRequest.h>
74 #include <WebCore/RuntimeApplicationChecks.h>
75 #include <WebCore/SchemeRegistry.h>
76 #include <WebCore/SecurityOriginData.h>
77 #include <WebCore/SecurityOriginHash.h>
78 #include <WebCore/Settings.h>
79 #include <WebCore/URLParser.h>
80 #include <pal/SessionID.h>
81 #include <wtf/Algorithms.h>
82 #include <wtf/CallbackAggregator.h>
83 #include <wtf/OptionSet.h>
84 #include <wtf/ProcessPrivilege.h>
85 #include <wtf/RunLoop.h>
86 #include <wtf/text/AtomicString.h>
87 #include <wtf/text/CString.h>
88
89 #if ENABLE(SEC_ITEM_SHIM)
90 #include "SecItemShim.h"
91 #endif
92
93 #include "NetworkCache.h"
94 #include "NetworkCacheCoders.h"
95
96 #if ENABLE(NETWORK_CAPTURE)
97 #include "NetworkCaptureManager.h"
98 #endif
99
100 #if PLATFORM(COCOA)
101 #include "NetworkSessionCocoa.h"
102 #endif
103
104 #if ENABLE(SERVICE_WORKER)
105 #include "WebSWServerToContextConnectionMessages.h"
106 #endif
107
108 namespace WebKit {
109 using namespace WebCore;
110
111 static void callExitSoon(IPC::Connection*)
112 {
113     // If the connection has been closed and we haven't responded in the main thread for 10 seconds
114     // the process will exit forcibly.
115     auto watchdogDelay = 10_s;
116
117     WorkQueue::create("com.apple.WebKit.ChildProcess.WatchDogQueue")->dispatchAfter(watchdogDelay, [] {
118         // We use _exit here since the watchdog callback is called from another thread and we don't want
119         // global destructors or atexit handlers to be called from this thread while the main thread is busy
120         // doing its thing.
121         RELEASE_LOG_ERROR(IPC, "Exiting process early due to unacknowledged closed-connection");
122         _exit(EXIT_FAILURE);
123     });
124 }
125
126 NetworkProcess& NetworkProcess::singleton()
127 {
128     static NeverDestroyed<NetworkProcess> networkProcess;
129     return networkProcess;
130 }
131
132 NetworkProcess::NetworkProcess()
133     : m_hasSetCacheModel(false)
134     , m_cacheModel(CacheModelDocumentViewer)
135     , m_diskCacheIsDisabledForTesting(false)
136     , m_canHandleHTTPSServerTrustEvaluation(true)
137 #if PLATFORM(COCOA)
138     , m_clearCacheDispatchGroup(0)
139 #endif
140     , m_storageTaskQueue(WorkQueue::create("com.apple.WebKit.StorageTask"))
141 {
142     NetworkProcessPlatformStrategies::initialize();
143
144     addSupplement<AuthenticationManager>();
145     addSupplement<WebCookieManager>();
146 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
147     addSupplement<LegacyCustomProtocolManager>();
148 #endif
149 #if ENABLE(PROXIMITY_NETWORKING)
150     addSupplement<NetworkProximityManager>();
151 #endif
152
153     NetworkStateNotifier::singleton().addListener([this](bool isOnLine) {
154         auto webProcessConnections = m_webProcessConnections;
155         for (auto& webProcessConnection : webProcessConnections)
156             webProcessConnection->setOnLineState(isOnLine);
157     });
158 }
159
160 NetworkProcess::~NetworkProcess()
161 {
162     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
163         for (auto& callback : callbacks)
164             callback(String { }, 0);
165     }
166 }
167
168 AuthenticationManager& NetworkProcess::authenticationManager()
169 {
170     return *supplement<AuthenticationManager>();
171 }
172
173 DownloadManager& NetworkProcess::downloadManager()
174 {
175     static NeverDestroyed<DownloadManager> downloadManager(*this);
176     return downloadManager;
177 }
178
179 #if ENABLE(PROXIMITY_NETWORKING)
180 NetworkProximityManager& NetworkProcess::proximityManager()
181 {
182     return *supplement<NetworkProximityManager>();
183 }
184 #endif
185
186 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
187 {
188     size_t vectorIndex = m_webProcessConnections.find(connection);
189     ASSERT(vectorIndex != notFound);
190
191     m_webProcessConnections.remove(vectorIndex);
192 }
193
194 bool NetworkProcess::shouldTerminate()
195 {
196     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
197     return false;
198 }
199
200 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
201 {
202     if (messageReceiverMap().dispatchMessage(connection, decoder))
203         return;
204
205     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
206         ChildProcess::didReceiveMessage(connection, decoder);
207         return;
208     }
209
210 #if ENABLE(CONTENT_EXTENSIONS)
211     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
212         m_NetworkContentRuleListManager.didReceiveMessage(connection, decoder);
213         return;
214     }
215 #endif
216
217 #if ENABLE(SERVICE_WORKER)
218     if (decoder.messageReceiverName() == Messages::WebSWServerToContextConnection::messageReceiverName()) {
219         ASSERT(parentProcessHasServiceWorkerEntitlement());
220         if (!parentProcessHasServiceWorkerEntitlement())
221             return;
222         if (auto* webSWConnection = connectionToContextProcessFromIPCConnection(connection)) {
223             webSWConnection->didReceiveMessage(connection, decoder);
224             return;
225         }
226     }
227 #endif
228     didReceiveNetworkProcessMessage(connection, decoder);
229 }
230
231 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
232 {
233     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
234         return;
235
236     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
237 }
238
239 void NetworkProcess::didClose(IPC::Connection&)
240 {
241     ASSERT(RunLoop::isMain());
242
243     // Make sure we flush all cookies to disk before exiting.
244     platformSyncAllCookies([this] {
245         stopRunLoop();
246     });
247 }
248
249 void NetworkProcess::didCreateDownload()
250 {
251     disableTermination();
252 }
253
254 void NetworkProcess::didDestroyDownload()
255 {
256     enableTermination();
257 }
258
259 IPC::Connection* NetworkProcess::downloadProxyConnection()
260 {
261     return parentProcessConnection();
262 }
263
264 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
265 {
266     return authenticationManager();
267 }
268
269 void NetworkProcess::lowMemoryHandler(Critical critical)
270 {
271     if (m_suppressMemoryPressureHandler)
272         return;
273
274     WTF::releaseFastMallocFreeMemory();
275 }
276
277 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
278 {
279 #if HAVE(SEC_KEY_PROXY)
280     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
281 #else
282     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
283 #endif
284     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
285     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
286     platformInitializeNetworkProcess(parameters);
287
288     WTF::Thread::setCurrentThreadIsUserInitiated();
289     AtomicString::init();
290
291     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
292     m_loadThrottleLatency = parameters.loadThrottleLatency;
293     if (!m_suppressMemoryPressureHandler) {
294         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
295         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
296             lowMemoryHandler(critical);
297         });
298         memoryPressureHandler.install();
299     }
300
301 #if ENABLE(NETWORK_CAPTURE)
302     NetworkCapture::Manager::singleton().initialize(
303         parameters.recordReplayMode,
304         parameters.recordReplayCacheLocation);
305 #endif
306
307     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
308
309     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
310     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
311
312     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
313
314     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
315     if (parameters.privateBrowsingEnabled)
316         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
317
318     if (parameters.shouldUseTestingNetworkSession)
319         NetworkStorageSession::switchToNewTestingSession();
320
321 #if ENABLE(RESOURCE_LOAD_STATISTICS) && !RELEASE_LOG_DISABLED
322     m_logCookieInformation = parameters.logCookieInformation;
323 #endif
324
325     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(NetworkSessionCreationParameters()));
326
327 #if ENABLE(INDEXED_DATABASE)
328     addIndexedDatabaseSession(PAL::SessionID::defaultSessionID(), parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
329 #endif
330
331 #if ENABLE(SERVICE_WORKER)
332     if (parentProcessHasServiceWorkerEntitlement()) {
333         addServiceWorkerSession(PAL::SessionID::defaultSessionID(), parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
334
335         for (auto& scheme : parameters.urlSchemesServiceWorkersCanHandle)
336             registerURLSchemeServiceWorkersCanHandle(scheme);
337
338         m_shouldDisableServiceWorkerProcessTerminationDelay = parameters.shouldDisableServiceWorkerProcessTerminationDelay;
339     }
340 #endif
341
342     auto* defaultSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID());
343     for (const auto& cookie : parameters.defaultSessionPendingCookies)
344         defaultSession->networkStorageSession().setCookie(cookie);
345
346     for (auto& supplement : m_supplements.values())
347         supplement->initialize(parameters);
348
349     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
350         registerURLSchemeAsSecure(scheme);
351
352     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
353         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
354
355     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
356         registerURLSchemeAsLocal(scheme);
357
358     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
359         registerURLSchemeAsNoAccess(scheme);
360
361     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
362         registerURLSchemeAsDisplayIsolated(scheme);
363
364     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
365         registerURLSchemeAsCORSEnabled(scheme);
366
367     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
368         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
369
370     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
371 }
372
373 void NetworkProcess::initializeConnection(IPC::Connection* connection)
374 {
375     ChildProcess::initializeConnection(connection);
376
377     // We give a chance for didClose() to get called on the main thread but forcefully call _exit() after a delay
378     // in case the main thread is unresponsive or didClose() takes too long.
379     connection->setDidCloseOnConnectionWorkQueueCallback(callExitSoon);
380
381     for (auto& supplement : m_supplements.values())
382         supplement->initializeConnection(connection);
383 }
384
385 void NetworkProcess::createNetworkConnectionToWebProcess(bool isServiceWorkerProcess, WebCore::SecurityOriginData&& securityOrigin)
386 {
387 #if USE(UNIX_DOMAIN_SOCKETS)
388     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
389
390     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
391     m_webProcessConnections.append(WTFMove(connection));
392
393     IPC::Attachment clientSocket(socketPair.client);
394     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
395 #elif OS(DARWIN)
396     // Create the listening port.
397     mach_port_t listeningPort = MACH_PORT_NULL;
398     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
399     if (kr != KERN_SUCCESS) {
400         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
401         CRASH();
402     }
403     if (!MACH_PORT_VALID(listeningPort)) {
404         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
405         CRASH();
406     }
407
408     // Create a listening connection.
409     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
410     m_webProcessConnections.append(WTFMove(connection));
411
412     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
413     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
414 #elif OS(WINDOWS)
415     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
416     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
417         LOG_ERROR("Failed to create server and client identifiers");
418         CRASH();
419     }
420
421     auto connection = NetworkConnectionToWebProcess::create(serverIdentifier);
422     m_webProcessConnections.append(WTFMove(connection));
423
424     IPC::Attachment clientSocket(clientIdentifier);
425     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
426 #else
427     notImplemented();
428 #endif
429
430     if (!m_webProcessConnections.isEmpty())
431         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
432     
433 #if ENABLE(SERVICE_WORKER)
434     if (isServiceWorkerProcess && !m_webProcessConnections.isEmpty()) {
435         ASSERT(parentProcessHasServiceWorkerEntitlement());
436         ASSERT(m_waitingForServerToContextProcessConnection);
437         auto contextConnection = WebSWServerToContextConnection::create(securityOrigin, m_webProcessConnections.last()->connection());
438         auto addResult = m_serverToContextConnections.add(WTFMove(securityOrigin), contextConnection.copyRef());
439         ASSERT_UNUSED(addResult, addResult.isNewEntry);
440
441         m_waitingForServerToContextProcessConnection = false;
442
443         for (auto* server : SWServer::allServers())
444             server->serverToContextConnectionCreated(contextConnection);
445     }
446 #else
447     UNUSED_PARAM(isServiceWorkerProcess);
448     UNUSED_PARAM(securityOrigin);
449 #endif
450 }
451
452 void NetworkProcess::clearCachedCredentials()
453 {
454     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
455     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
456         networkSession->clearCredentials();
457     else
458         ASSERT_NOT_REACHED();
459 }
460
461 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
462 {
463 #if ENABLE(INDEXED_DATABASE)
464     addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
465 #endif
466
467 #if ENABLE(SERVICE_WORKER)
468     if (parentProcessHasServiceWorkerEntitlement())
469         addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
470 #endif
471
472     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
473 }
474
475 void NetworkProcess::destroySession(PAL::SessionID sessionID)
476 {
477     SessionTracker::destroySession(sessionID);
478     m_sessionsControlledByAutomation.remove(sessionID);
479     CacheStorage::Engine::destroyEngine(sessionID);
480
481 #if ENABLE(SERVICE_WORKER)
482     m_swServers.remove(sessionID);
483     m_swDatabasePaths.remove(sessionID);
484 #endif
485 }
486
487 void NetworkProcess::writeBlobToFilePath(const WebCore::URL& url, const String& path, SandboxExtension::Handle&& handleForWriting, uint64_t requestID)
488 {
489     auto extension = SandboxExtension::create(WTFMove(handleForWriting));
490     if (!extension) {
491         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(false, requestID), 0);
492         return;
493     }
494
495     extension->consume();
496     NetworkBlobRegistry::singleton().writeBlobToFilePath(url, path, [this, extension = WTFMove(extension), requestID] (bool success) {
497         extension->revoke();
498         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(success, requestID), 0);
499     });
500 }
501
502 #if ENABLE(RESOURCE_LOAD_STATISTICS)
503 void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<String>& domainsToBlock, bool shouldClearFirst, uint64_t contextId)
504 {
505     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
506         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock, shouldClearFirst);
507     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdateBlockCookies(contextId), 0);
508 }
509
510 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
511 {
512     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
513         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
514     else
515         ASSERT_NOT_REACHED();
516 }
517
518 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
519 {
520     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
521         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
522     else
523         ASSERT_NOT_REACHED();
524 }
525
526 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
527 {
528     bool isStorageGranted = false;
529     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
530         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
531         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
532         isStorageGranted = true;
533     } else
534         ASSERT_NOT_REACHED();
535
536     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
537 }
538
539 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
540 {
541     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
542         networkStorageSession->removeAllStorageAccess();
543     else
544         ASSERT_NOT_REACHED();
545     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidRemoveAllStorageAccess(contextId), 0);
546 }
547
548 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
549 {
550     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
551         networkStorageSession->removePrevalentDomains(domains);
552 }
553
554 void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, uint64_t contextId)
555 {
556     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
557         networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
558     else
559         ASSERT_NOT_REACHED();
560     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSetCacheMaxAgeCapForPrevalentResources(contextId), 0);
561 }
562
563 void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, uint64_t contextId)
564 {
565     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
566         networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
567     else
568         ASSERT_NOT_REACHED();
569     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidResetCacheMaxAgeCapForPrevalentResources(contextId), 0);
570 }
571 #endif
572
573 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
574 {
575     return m_sessionsControlledByAutomation.contains(sessionID);
576 }
577
578 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
579 {
580     if (controlled)
581         m_sessionsControlledByAutomation.add(sessionID);
582     else
583         m_sessionsControlledByAutomation.remove(sessionID);
584 }
585
586 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
587 {
588     if (auto* cache = NetworkProcess::singleton().cache()) {
589         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
590         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
591             if (!traversalEntry) {
592                 Vector<WebsiteData::Entry> entries;
593
594                 for (auto& originAndSize : originsAndSizes)
595                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
596
597                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
598                     completionHandler(entries);
599                 });
600
601                 return;
602             }
603
604             auto url = traversalEntry->entry.response().url();
605             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
606
607             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
608                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
609         });
610
611         return;
612     }
613
614     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
615         completionHandler({ });
616     });
617 }
618
619 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
620 {
621     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
622         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
623             : m_completionHandler(WTFMove(completionHandler))
624         {
625         }
626
627         ~CallbackAggregator()
628         {
629             ASSERT(RunLoop::isMain());
630
631             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
632                 completionHandler(websiteData);
633             });
634         }
635
636         Function<void (WebsiteData)> m_completionHandler;
637         WebsiteData m_websiteData;
638     };
639
640     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
641         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
642     }));
643
644     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
645         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
646             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
647     }
648
649     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
650         if (NetworkStorageSession::storageSession(sessionID))
651             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
652     }
653
654     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
655         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
656             callbackAggregator->m_websiteData.entries.appendVector(entries);
657         });
658     }
659
660 #if PLATFORM(COCOA)
661     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
662         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
663             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
664     }
665 #endif
666
667 #if ENABLE(INDEXED_DATABASE)
668     auto path = m_idbDatabasePaths.get(sessionID);
669     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
670         // FIXME: Pick the right database store based on the session ID.
671         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
672             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
673                 for (const auto& securityOrigin : securityOrigins)
674                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
675             });
676         }));
677     }
678 #endif
679
680 #if ENABLE(SERVICE_WORKER)
681     path = m_swDatabasePaths.get(sessionID);
682     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
683         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
684             for (auto& origin : securityOrigins)
685                 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
686         });
687     }
688 #endif
689
690     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
691         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
692             callbackAggregator->m_websiteData.entries.appendVector(entries);
693         });
694     }
695 }
696
697 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
698 {
699 #if PLATFORM(COCOA)
700     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
701         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
702             clearHSTSCache(*networkStorageSession, modifiedSince);
703     }
704 #endif
705
706     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
707         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
708             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
709     }
710
711     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
712         if (NetworkStorageSession::storageSession(sessionID))
713             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
714     }
715
716     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
717         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
718     });
719
720     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
721         CacheStorage::Engine::clearAllCaches(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
722
723 #if ENABLE(INDEXED_DATABASE)
724     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
725         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
726 #endif
727
728 #if ENABLE(SERVICE_WORKER)
729     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
730         swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
731 #endif
732
733     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
734         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
735 }
736
737 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
738 {
739     if (auto* cache = NetworkProcess::singleton().cache()) {
740         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
741         for (auto& origin : origins)
742             originsToDelete.add(origin.securityOrigin());
743
744         Vector<NetworkCache::Key> cacheKeysToDelete;
745         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
746             if (traversalEntry) {
747                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
748                     cacheKeysToDelete.append(traversalEntry->entry.key());
749                 return;
750             }
751
752             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
753             return;
754         });
755
756         return;
757     }
758
759     RunLoop::main().dispatch(WTFMove(completionHandler));
760 }
761
762 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
763 {
764     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
765         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
766             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
767     }
768
769 #if PLATFORM(COCOA)
770     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
771         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
772             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
773     }
774 #endif
775
776     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
777         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
778     });
779
780     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
781         for (auto& originData : originDatas)
782             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
783     }
784
785 #if ENABLE(INDEXED_DATABASE)
786     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
787         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
788 #endif
789
790 #if ENABLE(SERVICE_WORKER)
791     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
792         auto& server = swServerForSession(sessionID);
793         for (auto& originData : originDatas)
794             server.clear(originData, [clearTasksHandler = clearTasksHandler.copyRef()] { });
795     }
796 #endif
797
798     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
799         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
800 }
801
802 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
803 {
804     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
805 }
806
807 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
808 {
809     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
810 }
811
812 void NetworkProcess::cancelDownload(DownloadID downloadID)
813 {
814     downloadManager().cancelDownload(downloadID);
815 }
816
817 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
818 {
819     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
820 }
821
822 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
823 {
824     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
825 }
826
827 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
828 {
829     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
830     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
831
832     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
833
834     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
835     // should override the suggested filename from the download attribute.
836     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
837     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
838
839     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
840 }
841
842 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
843 {
844     if (destination.isEmpty())
845         downloadManager().cancelDownload(downloadID);
846     else
847         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
848 }
849
850 void NetworkProcess::setCacheModel(uint32_t cm)
851 {
852     CacheModel cacheModel = static_cast<CacheModel>(cm);
853
854     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
855         return;
856
857     m_hasSetCacheModel = true;
858     m_cacheModel = cacheModel;
859
860     unsigned urlCacheMemoryCapacity = 0;
861     uint64_t urlCacheDiskCapacity = 0;
862     uint64_t diskFreeSize = 0;
863     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
864         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
865         // count doesn't align exactly to a megabyte boundary.
866         diskFreeSize /= KB * 1000;
867         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
868     }
869
870     if (m_diskCacheSizeOverride >= 0)
871         urlCacheDiskCapacity = m_diskCacheSizeOverride;
872
873     if (m_cache)
874         m_cache->setCapacity(urlCacheDiskCapacity);
875 }
876
877 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
878 {
879     m_canHandleHTTPSServerTrustEvaluation = value;
880 }
881
882 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
883 {
884     StatisticsData data;
885
886     auto& networkProcess = NetworkProcess::singleton();
887     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
888     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
889
890     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
891 }
892
893 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
894 {
895     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
896 }
897
898 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
899 {
900     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
901         return;
902
903     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
904 }
905
906 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
907 {
908     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
909         return;
910
911     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
912 }
913
914 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
915 {
916     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
917         return;
918
919     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
920 }
921
922 void NetworkProcess::terminate()
923 {
924 #if ENABLE(NETWORK_CAPTURE)
925     NetworkCapture::Manager::singleton().terminate();
926 #endif
927
928     platformTerminate();
929     ChildProcess::terminate();
930 }
931
932 void NetworkProcess::processDidTransitionToForeground()
933 {
934     platformProcessDidTransitionToForeground();
935 }
936
937 void NetworkProcess::processDidTransitionToBackground()
938 {
939     platformProcessDidTransitionToBackground();
940 }
941
942 // FIXME: We can remove this one by adapting RefCounter.
943 class TaskCounter : public RefCounted<TaskCounter> {
944 public:
945     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
946     ~TaskCounter() { m_callback(); };
947
948 private:
949     Function<void()> m_callback;
950 };
951
952 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
953 {
954     lowMemoryHandler(Critical::Yes);
955
956     RefPtr<TaskCounter> delayedTaskCounter;
957     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
958         delayedTaskCounter = adoptRef(new TaskCounter([this] {
959             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
960             if (parentProcessConnection())
961                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
962         }));
963     }
964
965     platformPrepareToSuspend([delayedTaskCounter] { });
966     platformSyncAllCookies([delayedTaskCounter] { });
967
968     for (auto& connection : m_webProcessConnections)
969         connection->cleanupForSuspension([delayedTaskCounter] { });
970 }
971
972 void NetworkProcess::processWillSuspendImminently(bool& handled)
973 {
974     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
975     handled = true;
976 }
977
978 void NetworkProcess::prepareToSuspend()
979 {
980     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
981     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
982 }
983
984 void NetworkProcess::cancelPrepareToSuspend()
985 {
986     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
987     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
988     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
989     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
990     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
991     platformProcessDidResume();
992     for (auto& connection : m_webProcessConnections)
993         connection->endSuspension();
994 }
995
996 void NetworkProcess::processDidResume()
997 {
998     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
999     platformProcessDidResume();
1000     for (auto& connection : m_webProcessConnections)
1001         connection->endSuspension();
1002 }
1003
1004 void NetworkProcess::prefetchDNS(const String& hostname)
1005 {
1006     WebCore::prefetchDNS(hostname);
1007 }
1008
1009 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
1010 {
1011     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
1012         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
1013         return Vector<CacheStorageParametersCallback> { };
1014     }).iterator->value.append(WTFMove(callback));
1015 }
1016
1017 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
1018 {
1019     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
1020     if (iterator == m_cacheStorageParametersCallbacks.end())
1021         return;
1022
1023     SandboxExtension::consumePermanently(handle);
1024     auto callbacks = WTFMove(iterator->value);
1025     m_cacheStorageParametersCallbacks.remove(iterator);
1026     for (auto& callback : callbacks)
1027         callback(String { cacheStorageDirectory }, quota);
1028 }
1029
1030 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
1031 {
1032 #if ENABLE(SERVER_PRECONNECT)
1033     NetworkLoadParameters parameters;
1034     parameters.request = ResourceRequest { url };
1035     parameters.sessionID = PAL::SessionID::defaultSessionID();
1036     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
1037     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
1038
1039     new PreconnectTask(WTFMove(parameters));
1040 #else
1041     UNUSED_PARAM(url);
1042     UNUSED_PARAM(storedCredentialsPolicy);
1043 #endif
1044 }
1045
1046 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
1047 {
1048     SchemeRegistry::registerURLSchemeAsSecure(scheme);
1049 }
1050
1051 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
1052 {
1053     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1054 }
1055
1056 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
1057 {
1058     SchemeRegistry::registerURLSchemeAsLocal(scheme);
1059 }
1060
1061 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
1062 {
1063     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
1064 }
1065
1066 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
1067 {
1068     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
1069 }
1070
1071 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
1072 {
1073     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
1074 }
1075
1076 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
1077 {
1078     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
1079 }
1080
1081 void NetworkProcess::didSyncAllCookies()
1082 {
1083     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
1084 }
1085
1086 #if ENABLE(INDEXED_DATABASE)
1087 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
1088 {
1089     auto addResult = m_idbServers.add(sessionID, nullptr);
1090     if (!addResult.isNewEntry) {
1091         ASSERT(addResult.iterator->value);
1092         return *addResult.iterator->value;
1093     }
1094     
1095     auto path = m_idbDatabasePaths.get(sessionID);
1096     // There should already be a registered path for this PAL::SessionID.
1097     // If there's not, then where did this PAL::SessionID come from?
1098     ASSERT(!path.isEmpty());
1099     
1100     addResult.iterator->value = IDBServer::IDBServer::create(path, NetworkProcess::singleton());
1101     return *addResult.iterator->value;
1102 }
1103
1104 void NetworkProcess::ensurePathExists(const String& path)
1105 {
1106     ASSERT(!RunLoop::isMain());
1107     
1108     if (!FileSystem::makeAllDirectories(path))
1109         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
1110 }
1111
1112 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
1113 {
1114     ASSERT(RunLoop::isMain());
1115     
1116     LockHolder locker(m_storageTaskMutex);
1117     
1118     m_storageTasks.append(WTFMove(task));
1119     
1120     m_storageTaskQueue->dispatch([this] {
1121         performNextStorageTask();
1122     });
1123 }
1124
1125 void NetworkProcess::performNextStorageTask()
1126 {
1127     ASSERT(!RunLoop::isMain());
1128     
1129     CrossThreadTask task;
1130     {
1131         LockHolder locker(m_storageTaskMutex);
1132         ASSERT(!m_storageTasks.isEmpty());
1133         task = m_storageTasks.takeFirst();
1134     }
1135     
1136     task.performTask();
1137 }
1138
1139 void NetworkProcess::prepareForAccessToTemporaryFile(const String& path)
1140 {
1141     if (auto extension = m_blobTemporaryFileSandboxExtensions.get(path))
1142         extension->consume();
1143 }
1144
1145 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
1146 {
1147     // We've either hard linked the temporary blob file to the database directory, copied it there,
1148     // or the transaction is being aborted.
1149     // In any of those cases, we can delete the temporary blob file now.
1150     FileSystem::deleteFile(path);
1151     
1152     if (auto extension = m_blobTemporaryFileSandboxExtensions.take(path))
1153         extension->revoke();
1154 }
1155
1156 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
1157 {
1158     if (path.isEmpty())
1159         return { };
1160     
1161     HashSet<WebCore::SecurityOriginData> securityOrigins;
1162     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
1163         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
1164         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1165             securityOrigins.add(WTFMove(*securityOrigin));
1166         
1167         for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
1168             databaseIdentifier = FileSystem::pathGetFileName(originPath);
1169             if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1170                 securityOrigins.add(WTFMove(*securityOrigin));
1171         }
1172     }
1173
1174     return securityOrigins;
1175 }
1176
1177 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
1178 {
1179     // *********
1180     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
1181     // *********
1182     auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
1183     if (addResult.isNewEntry) {
1184         SandboxExtension::consumePermanently(handle);
1185         if (!indexedDatabaseDirectory.isEmpty())
1186             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
1187     }
1188 }
1189
1190 #endif // ENABLE(INDEXED_DATABASE)
1191
1192 #if ENABLE(SANDBOX_EXTENSIONS)
1193 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&& completionHandler)
1194 {
1195     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(filenames), WTFMove(completionHandler));
1196 }
1197
1198 void NetworkProcess::updateTemporaryFileSandboxExtensions(const Vector<String>& paths, SandboxExtension::HandleArray& handles)
1199 {
1200     for (size_t i = 0; i < handles.size(); ++i) {
1201         auto result = m_blobTemporaryFileSandboxExtensions.add(paths[i], SandboxExtension::create(WTFMove(handles[i])));
1202         ASSERT_UNUSED(result, result.isNewEntry);
1203     }
1204 }
1205 #endif // ENABLE(SANDBOX_EXTENSIONS)
1206
1207 #if ENABLE(SERVICE_WORKER)
1208 WebSWServerToContextConnection* NetworkProcess::connectionToContextProcessFromIPCConnection(IPC::Connection& connection)
1209 {
1210     for (auto& serverToContextConnection : m_serverToContextConnections.values()) {
1211         if (serverToContextConnection->ipcConnection() == &connection)
1212             return serverToContextConnection.get();
1213     }
1214     return nullptr;
1215 }
1216
1217 void NetworkProcess::connectionToContextProcessWasClosed(Ref<WebSWServerToContextConnection>&& serverToContextConnection)
1218 {
1219     auto& securityOrigin = serverToContextConnection->securityOrigin();
1220     
1221     serverToContextConnection->connectionClosed();
1222     m_serverToContextConnections.remove(securityOrigin);
1223     
1224     for (auto& swServer : m_swServers.values())
1225         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1226     
1227     if (needsServerToContextConnectionForOrigin(securityOrigin)) {
1228         RELEASE_LOG(ServiceWorker, "Connection to service worker process was closed but is still needed, relaunching it");
1229         createServerToContextConnection(securityOrigin, std::nullopt);
1230     }
1231 }
1232
1233 bool NetworkProcess::needsServerToContextConnectionForOrigin(const SecurityOriginData& securityOrigin) const
1234 {
1235     return WTF::anyOf(m_swServers.values(), [&](auto& swServer) {
1236         return swServer->needsServerToContextConnectionForOrigin(securityOrigin);
1237     });
1238 }
1239
1240 SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
1241 {
1242     ASSERT(sessionID.isValid());
1243     
1244     auto result = m_swServers.ensure(sessionID, [&] {
1245         auto path = m_swDatabasePaths.get(sessionID);
1246         // There should already be a registered path for this PAL::SessionID.
1247         // If there's not, then where did this PAL::SessionID come from?
1248         ASSERT(sessionID.isEphemeral() || !path.isEmpty());
1249         
1250         auto value = std::make_unique<SWServer>(makeUniqueRef<WebSWOriginStore>(), WTFMove(path), sessionID);
1251         if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1252             value->disableServiceWorkerProcessTerminationDelay();
1253         return value;
1254     });
1255
1256     return *result.iterator->value;
1257 }
1258
1259 WebSWOriginStore& NetworkProcess::swOriginStoreForSession(PAL::SessionID sessionID)
1260 {
1261     return static_cast<WebSWOriginStore&>(swServerForSession(sessionID).originStore());
1262 }
1263
1264 WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
1265 {
1266     auto* swServer = m_swServers.get(sessionID);
1267     if (!swServer)
1268         return nullptr;
1269     return &static_cast<WebSWOriginStore&>(swServer->originStore());
1270 }
1271
1272 WebSWServerToContextConnection* NetworkProcess::serverToContextConnectionForOrigin(const SecurityOriginData& securityOrigin)
1273 {
1274     return m_serverToContextConnections.get(securityOrigin);
1275 }
1276
1277 void NetworkProcess::createServerToContextConnection(const SecurityOriginData& securityOrigin, std::optional<PAL::SessionID> sessionID)
1278 {
1279     if (m_waitingForServerToContextProcessConnection)
1280         return;
1281     
1282     m_waitingForServerToContextProcessConnection = true;
1283     if (sessionID)
1284         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcessForExplicitSession(securityOrigin, *sessionID), 0);
1285     else
1286         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess(securityOrigin), 0);
1287 }
1288
1289 void NetworkProcess::didFailFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const ResourceError& error)
1290 {
1291     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1292         connection->didFailFetch(fetchIdentifier, error);
1293 }
1294
1295 void NetworkProcess::didNotHandleFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1296 {
1297     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1298         connection->didNotHandleFetch(fetchIdentifier);
1299 }
1300
1301 void NetworkProcess::didReceiveFetchResponse(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const WebCore::ResourceResponse& response)
1302 {
1303     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1304         connection->didReceiveFetchResponse(fetchIdentifier, response);
1305 }
1306
1307 void NetworkProcess::didReceiveFetchData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::DataReference& data, int64_t encodedDataLength)
1308 {
1309     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1310         connection->didReceiveFetchData(fetchIdentifier, data, encodedDataLength);
1311 }
1312
1313 void NetworkProcess::didReceiveFetchFormData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::FormDataReference& formData)
1314 {
1315     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1316         connection->didReceiveFetchFormData(fetchIdentifier, formData);
1317 }
1318
1319 void NetworkProcess::didFinishFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1320 {
1321     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1322         connection->didFinishFetch(fetchIdentifier);
1323 }
1324
1325 void NetworkProcess::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, MessageWithMessagePorts&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
1326 {
1327     if (auto* connection = m_swServerConnections.get(destinationIdentifier.serverConnectionIdentifier))
1328         connection->postMessageToServiceWorkerClient(destinationIdentifier.contextIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
1329 }
1330
1331 void NetworkProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, WebCore::MessageWithMessagePorts&& message, const WebCore::ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
1332 {
1333     if (auto* connection = m_swServerConnections.get(connectionIdentifier))
1334         connection->postMessageToServiceWorker(destination, WTFMove(message), source);
1335 }
1336
1337 void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
1338 {
1339     ASSERT(parentProcessHasServiceWorkerEntitlement());
1340     ASSERT(!m_swServerConnections.contains(connection.identifier()));
1341     m_swServerConnections.add(connection.identifier(), &connection);
1342     swOriginStoreForSession(connection.sessionID()).registerSWServerConnection(connection);
1343 }
1344
1345 void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
1346 {
1347     ASSERT(m_swServerConnections.get(connection.identifier()) == &connection);
1348     m_swServerConnections.remove(connection.identifier());
1349     if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
1350         store->unregisterSWServerConnection(connection);
1351 }
1352
1353 void NetworkProcess::swContextConnectionMayNoLongerBeNeeded(WebSWServerToContextConnection& serverToContextConnection)
1354 {
1355     auto& securityOrigin = serverToContextConnection.securityOrigin();
1356     if (needsServerToContextConnectionForOrigin(securityOrigin))
1357         return;
1358     
1359     RELEASE_LOG(ServiceWorker, "Service worker process is no longer needed, terminating it");
1360     serverToContextConnection.terminate();
1361     
1362     for (auto& swServer : m_swServers.values())
1363         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1364     
1365     serverToContextConnection.connectionClosed();
1366     m_serverToContextConnections.remove(securityOrigin);
1367 }
1368
1369 void NetworkProcess::disableServiceWorkerProcessTerminationDelay()
1370 {
1371     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1372         return;
1373     
1374     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
1375     for (auto& swServer : m_swServers.values())
1376         swServer->disableServiceWorkerProcessTerminationDelay();
1377 }
1378
1379 void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
1380 {
1381     auto addResult = m_swDatabasePaths.add(sessionID, serviceWorkerRegistrationDirectory);
1382     if (addResult.isNewEntry) {
1383         SandboxExtension::consumePermanently(handle);
1384         if (!serviceWorkerRegistrationDirectory.isEmpty())
1385             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
1386     }
1387 }
1388 #endif // ENABLE(SERVICE_WORKER)
1389
1390 #if !PLATFORM(COCOA)
1391 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
1392 {
1393 }
1394
1395 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1396 {
1397 }
1398
1399 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1400 {
1401 }
1402
1403 void NetworkProcess::syncAllCookies()
1404 {
1405 }
1406
1407 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
1408 {
1409     completionHandler();
1410 }
1411
1412 #endif
1413
1414 } // namespace WebKit