Only cap lifetime of persistent cookies created client-side through document.cookie...
[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, uint64_t contextId)
504 {
505     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
506         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
507     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdateBlockCookies(contextId), 0);
508 }
509
510 void NetworkProcess::setShouldCapLifetimeForClientSideCookies(PAL::SessionID sessionID, bool value, uint64_t contextId)
511 {
512     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
513         networkStorageSession->setShouldCapLifetimeForClientSideCookies(value);
514     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSetShouldCapLifetimeForClientSideCookies(contextId), 0);
515 }
516
517 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
518 {
519     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
520         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
521     else
522         ASSERT_NOT_REACHED();
523 }
524
525 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
526 {
527     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
528         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
529     else
530         ASSERT_NOT_REACHED();
531 }
532
533 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
534 {
535     bool isStorageGranted = false;
536     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
537         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
538         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
539         isStorageGranted = true;
540     } else
541         ASSERT_NOT_REACHED();
542
543     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
544 }
545
546 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
547 {
548     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
549         networkStorageSession->removeAllStorageAccess();
550     else
551         ASSERT_NOT_REACHED();
552     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidRemoveAllStorageAccess(contextId), 0);
553 }
554
555 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
556 {
557     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
558         networkStorageSession->removePrevalentDomains(domains);
559 }
560
561 void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, uint64_t contextId)
562 {
563     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
564         networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
565     else
566         ASSERT_NOT_REACHED();
567     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSetCacheMaxAgeCapForPrevalentResources(contextId), 0);
568 }
569
570 void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, uint64_t contextId)
571 {
572     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
573         networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
574     else
575         ASSERT_NOT_REACHED();
576     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidResetCacheMaxAgeCapForPrevalentResources(contextId), 0);
577 }
578 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
579
580 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
581 {
582     return m_sessionsControlledByAutomation.contains(sessionID);
583 }
584
585 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
586 {
587     if (controlled)
588         m_sessionsControlledByAutomation.add(sessionID);
589     else
590         m_sessionsControlledByAutomation.remove(sessionID);
591 }
592
593 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
594 {
595     if (auto* cache = NetworkProcess::singleton().cache()) {
596         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
597         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
598             if (!traversalEntry) {
599                 Vector<WebsiteData::Entry> entries;
600
601                 for (auto& originAndSize : originsAndSizes)
602                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
603
604                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
605                     completionHandler(entries);
606                 });
607
608                 return;
609             }
610
611             auto url = traversalEntry->entry.response().url();
612             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
613
614             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
615                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
616         });
617
618         return;
619     }
620
621     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
622         completionHandler({ });
623     });
624 }
625
626 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
627 {
628     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
629         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
630             : m_completionHandler(WTFMove(completionHandler))
631         {
632         }
633
634         ~CallbackAggregator()
635         {
636             ASSERT(RunLoop::isMain());
637
638             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
639                 completionHandler(websiteData);
640             });
641         }
642
643         Function<void (WebsiteData)> m_completionHandler;
644         WebsiteData m_websiteData;
645     };
646
647     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
648         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
649     }));
650
651     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
652         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
653             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
654     }
655
656     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
657         if (NetworkStorageSession::storageSession(sessionID))
658             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
659     }
660
661     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
662         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
663             callbackAggregator->m_websiteData.entries.appendVector(entries);
664         });
665     }
666
667 #if PLATFORM(COCOA)
668     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
669         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
670             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
671     }
672 #endif
673
674 #if ENABLE(INDEXED_DATABASE)
675     auto path = m_idbDatabasePaths.get(sessionID);
676     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
677         // FIXME: Pick the right database store based on the session ID.
678         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
679             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
680                 for (const auto& securityOrigin : securityOrigins)
681                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
682             });
683         }));
684     }
685 #endif
686
687 #if ENABLE(SERVICE_WORKER)
688     path = m_swDatabasePaths.get(sessionID);
689     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
690         swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
691             for (auto& origin : securityOrigins)
692                 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
693         });
694     }
695 #endif
696
697     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
698         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
699             callbackAggregator->m_websiteData.entries.appendVector(entries);
700         });
701     }
702 }
703
704 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
705 {
706 #if PLATFORM(COCOA)
707     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
708         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
709             clearHSTSCache(*networkStorageSession, modifiedSince);
710     }
711 #endif
712
713     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
714         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
715             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
716     }
717
718     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
719         if (NetworkStorageSession::storageSession(sessionID))
720             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
721     }
722
723     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
724         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
725     });
726
727     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
728         CacheStorage::Engine::clearAllCaches(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
729
730 #if ENABLE(INDEXED_DATABASE)
731     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
732         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
733 #endif
734
735 #if ENABLE(SERVICE_WORKER)
736     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
737         swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
738 #endif
739
740     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
741         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
742 }
743
744 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
745 {
746     if (auto* cache = NetworkProcess::singleton().cache()) {
747         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
748         for (auto& origin : origins)
749             originsToDelete.add(origin.securityOrigin());
750
751         Vector<NetworkCache::Key> cacheKeysToDelete;
752         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
753             if (traversalEntry) {
754                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
755                     cacheKeysToDelete.append(traversalEntry->entry.key());
756                 return;
757             }
758
759             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
760             return;
761         });
762
763         return;
764     }
765
766     RunLoop::main().dispatch(WTFMove(completionHandler));
767 }
768
769 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
770 {
771     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
772         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
773             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
774     }
775
776 #if PLATFORM(COCOA)
777     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
778         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
779             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
780     }
781 #endif
782
783     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
784         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
785     });
786
787     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
788         for (auto& originData : originDatas)
789             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
790     }
791
792 #if ENABLE(INDEXED_DATABASE)
793     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
794         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
795 #endif
796
797 #if ENABLE(SERVICE_WORKER)
798     if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
799         auto& server = swServerForSession(sessionID);
800         for (auto& originData : originDatas)
801             server.clear(originData, [clearTasksHandler = clearTasksHandler.copyRef()] { });
802     }
803 #endif
804
805     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
806         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
807 }
808
809 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
810 {
811     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
812 }
813
814 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
815 {
816     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
817 }
818
819 void NetworkProcess::cancelDownload(DownloadID downloadID)
820 {
821     downloadManager().cancelDownload(downloadID);
822 }
823
824 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
825 {
826     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
827 }
828
829 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
830 {
831     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
832 }
833
834 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
835 {
836     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
837     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
838
839     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
840
841     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
842     // should override the suggested filename from the download attribute.
843     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
844     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
845
846     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
847 }
848
849 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
850 {
851     if (destination.isEmpty())
852         downloadManager().cancelDownload(downloadID);
853     else
854         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
855 }
856
857 void NetworkProcess::setCacheModel(uint32_t cm)
858 {
859     CacheModel cacheModel = static_cast<CacheModel>(cm);
860
861     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
862         return;
863
864     m_hasSetCacheModel = true;
865     m_cacheModel = cacheModel;
866
867     unsigned urlCacheMemoryCapacity = 0;
868     uint64_t urlCacheDiskCapacity = 0;
869     uint64_t diskFreeSize = 0;
870     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
871         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
872         // count doesn't align exactly to a megabyte boundary.
873         diskFreeSize /= KB * 1000;
874         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
875     }
876
877     if (m_diskCacheSizeOverride >= 0)
878         urlCacheDiskCapacity = m_diskCacheSizeOverride;
879
880     if (m_cache)
881         m_cache->setCapacity(urlCacheDiskCapacity);
882 }
883
884 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
885 {
886     m_canHandleHTTPSServerTrustEvaluation = value;
887 }
888
889 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
890 {
891     StatisticsData data;
892
893     auto& networkProcess = NetworkProcess::singleton();
894     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
895     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
896
897     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
898 }
899
900 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
901 {
902     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
903 }
904
905 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
906 {
907     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
908         return;
909
910     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
911 }
912
913 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
914 {
915     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
916         return;
917
918     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
919 }
920
921 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
922 {
923     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
924         return;
925
926     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
927 }
928
929 void NetworkProcess::terminate()
930 {
931 #if ENABLE(NETWORK_CAPTURE)
932     NetworkCapture::Manager::singleton().terminate();
933 #endif
934
935     platformTerminate();
936     ChildProcess::terminate();
937 }
938
939 void NetworkProcess::processDidTransitionToForeground()
940 {
941     platformProcessDidTransitionToForeground();
942 }
943
944 void NetworkProcess::processDidTransitionToBackground()
945 {
946     platformProcessDidTransitionToBackground();
947 }
948
949 // FIXME: We can remove this one by adapting RefCounter.
950 class TaskCounter : public RefCounted<TaskCounter> {
951 public:
952     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
953     ~TaskCounter() { m_callback(); };
954
955 private:
956     Function<void()> m_callback;
957 };
958
959 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
960 {
961     lowMemoryHandler(Critical::Yes);
962
963     RefPtr<TaskCounter> delayedTaskCounter;
964     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
965         delayedTaskCounter = adoptRef(new TaskCounter([this] {
966             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
967             if (parentProcessConnection())
968                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
969         }));
970     }
971
972     platformPrepareToSuspend([delayedTaskCounter] { });
973     platformSyncAllCookies([delayedTaskCounter] { });
974
975     for (auto& connection : m_webProcessConnections)
976         connection->cleanupForSuspension([delayedTaskCounter] { });
977 }
978
979 void NetworkProcess::processWillSuspendImminently(bool& handled)
980 {
981     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
982     handled = true;
983 }
984
985 void NetworkProcess::prepareToSuspend()
986 {
987     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
988     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
989 }
990
991 void NetworkProcess::cancelPrepareToSuspend()
992 {
993     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
994     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
995     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
996     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
997     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
998     platformProcessDidResume();
999     for (auto& connection : m_webProcessConnections)
1000         connection->endSuspension();
1001 }
1002
1003 void NetworkProcess::processDidResume()
1004 {
1005     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
1006     platformProcessDidResume();
1007     for (auto& connection : m_webProcessConnections)
1008         connection->endSuspension();
1009 }
1010
1011 void NetworkProcess::prefetchDNS(const String& hostname)
1012 {
1013     WebCore::prefetchDNS(hostname);
1014 }
1015
1016 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
1017 {
1018     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
1019         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
1020         return Vector<CacheStorageParametersCallback> { };
1021     }).iterator->value.append(WTFMove(callback));
1022 }
1023
1024 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
1025 {
1026     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
1027     if (iterator == m_cacheStorageParametersCallbacks.end())
1028         return;
1029
1030     SandboxExtension::consumePermanently(handle);
1031     auto callbacks = WTFMove(iterator->value);
1032     m_cacheStorageParametersCallbacks.remove(iterator);
1033     for (auto& callback : callbacks)
1034         callback(String { cacheStorageDirectory }, quota);
1035 }
1036
1037 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
1038 {
1039 #if ENABLE(SERVER_PRECONNECT)
1040     NetworkLoadParameters parameters;
1041     parameters.request = ResourceRequest { url };
1042     parameters.sessionID = PAL::SessionID::defaultSessionID();
1043     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
1044     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
1045
1046     new PreconnectTask(WTFMove(parameters));
1047 #else
1048     UNUSED_PARAM(url);
1049     UNUSED_PARAM(storedCredentialsPolicy);
1050 #endif
1051 }
1052
1053 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
1054 {
1055     SchemeRegistry::registerURLSchemeAsSecure(scheme);
1056 }
1057
1058 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
1059 {
1060     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1061 }
1062
1063 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
1064 {
1065     SchemeRegistry::registerURLSchemeAsLocal(scheme);
1066 }
1067
1068 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
1069 {
1070     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
1071 }
1072
1073 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
1074 {
1075     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
1076 }
1077
1078 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
1079 {
1080     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
1081 }
1082
1083 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
1084 {
1085     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
1086 }
1087
1088 void NetworkProcess::didSyncAllCookies()
1089 {
1090     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
1091 }
1092
1093 #if ENABLE(INDEXED_DATABASE)
1094 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
1095 {
1096     auto addResult = m_idbServers.add(sessionID, nullptr);
1097     if (!addResult.isNewEntry) {
1098         ASSERT(addResult.iterator->value);
1099         return *addResult.iterator->value;
1100     }
1101     
1102     auto path = m_idbDatabasePaths.get(sessionID);
1103     // There should already be a registered path for this PAL::SessionID.
1104     // If there's not, then where did this PAL::SessionID come from?
1105     ASSERT(!path.isEmpty());
1106     
1107     addResult.iterator->value = IDBServer::IDBServer::create(path, NetworkProcess::singleton());
1108     return *addResult.iterator->value;
1109 }
1110
1111 void NetworkProcess::ensurePathExists(const String& path)
1112 {
1113     ASSERT(!RunLoop::isMain());
1114     
1115     if (!FileSystem::makeAllDirectories(path))
1116         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
1117 }
1118
1119 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
1120 {
1121     ASSERT(RunLoop::isMain());
1122     
1123     LockHolder locker(m_storageTaskMutex);
1124     
1125     m_storageTasks.append(WTFMove(task));
1126     
1127     m_storageTaskQueue->dispatch([this] {
1128         performNextStorageTask();
1129     });
1130 }
1131
1132 void NetworkProcess::performNextStorageTask()
1133 {
1134     ASSERT(!RunLoop::isMain());
1135     
1136     CrossThreadTask task;
1137     {
1138         LockHolder locker(m_storageTaskMutex);
1139         ASSERT(!m_storageTasks.isEmpty());
1140         task = m_storageTasks.takeFirst();
1141     }
1142     
1143     task.performTask();
1144 }
1145
1146 void NetworkProcess::prepareForAccessToTemporaryFile(const String& path)
1147 {
1148     if (auto extension = m_blobTemporaryFileSandboxExtensions.get(path))
1149         extension->consume();
1150 }
1151
1152 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
1153 {
1154     // We've either hard linked the temporary blob file to the database directory, copied it there,
1155     // or the transaction is being aborted.
1156     // In any of those cases, we can delete the temporary blob file now.
1157     FileSystem::deleteFile(path);
1158     
1159     if (auto extension = m_blobTemporaryFileSandboxExtensions.take(path))
1160         extension->revoke();
1161 }
1162
1163 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
1164 {
1165     if (path.isEmpty())
1166         return { };
1167     
1168     HashSet<WebCore::SecurityOriginData> securityOrigins;
1169     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
1170         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
1171         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1172             securityOrigins.add(WTFMove(*securityOrigin));
1173         
1174         for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
1175             databaseIdentifier = FileSystem::pathGetFileName(originPath);
1176             if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1177                 securityOrigins.add(WTFMove(*securityOrigin));
1178         }
1179     }
1180
1181     return securityOrigins;
1182 }
1183
1184 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
1185 {
1186     // *********
1187     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
1188     // *********
1189     auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
1190     if (addResult.isNewEntry) {
1191         SandboxExtension::consumePermanently(handle);
1192         if (!indexedDatabaseDirectory.isEmpty())
1193             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
1194     }
1195 }
1196
1197 #endif // ENABLE(INDEXED_DATABASE)
1198
1199 #if ENABLE(SANDBOX_EXTENSIONS)
1200 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&& completionHandler)
1201 {
1202     parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(filenames), WTFMove(completionHandler));
1203 }
1204
1205 void NetworkProcess::updateTemporaryFileSandboxExtensions(const Vector<String>& paths, SandboxExtension::HandleArray& handles)
1206 {
1207     for (size_t i = 0; i < handles.size(); ++i) {
1208         auto result = m_blobTemporaryFileSandboxExtensions.add(paths[i], SandboxExtension::create(WTFMove(handles[i])));
1209         ASSERT_UNUSED(result, result.isNewEntry);
1210     }
1211 }
1212 #endif // ENABLE(SANDBOX_EXTENSIONS)
1213
1214 #if ENABLE(SERVICE_WORKER)
1215 WebSWServerToContextConnection* NetworkProcess::connectionToContextProcessFromIPCConnection(IPC::Connection& connection)
1216 {
1217     for (auto& serverToContextConnection : m_serverToContextConnections.values()) {
1218         if (serverToContextConnection->ipcConnection() == &connection)
1219             return serverToContextConnection.get();
1220     }
1221     return nullptr;
1222 }
1223
1224 void NetworkProcess::connectionToContextProcessWasClosed(Ref<WebSWServerToContextConnection>&& serverToContextConnection)
1225 {
1226     auto& securityOrigin = serverToContextConnection->securityOrigin();
1227     
1228     serverToContextConnection->connectionClosed();
1229     m_serverToContextConnections.remove(securityOrigin);
1230     
1231     for (auto& swServer : m_swServers.values())
1232         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1233     
1234     if (needsServerToContextConnectionForOrigin(securityOrigin)) {
1235         RELEASE_LOG(ServiceWorker, "Connection to service worker process was closed but is still needed, relaunching it");
1236         createServerToContextConnection(securityOrigin, std::nullopt);
1237     }
1238 }
1239
1240 bool NetworkProcess::needsServerToContextConnectionForOrigin(const SecurityOriginData& securityOrigin) const
1241 {
1242     return WTF::anyOf(m_swServers.values(), [&](auto& swServer) {
1243         return swServer->needsServerToContextConnectionForOrigin(securityOrigin);
1244     });
1245 }
1246
1247 SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
1248 {
1249     ASSERT(sessionID.isValid());
1250     
1251     auto result = m_swServers.ensure(sessionID, [&] {
1252         auto path = m_swDatabasePaths.get(sessionID);
1253         // There should already be a registered path for this PAL::SessionID.
1254         // If there's not, then where did this PAL::SessionID come from?
1255         ASSERT(sessionID.isEphemeral() || !path.isEmpty());
1256         
1257         auto value = std::make_unique<SWServer>(makeUniqueRef<WebSWOriginStore>(), WTFMove(path), sessionID);
1258         if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1259             value->disableServiceWorkerProcessTerminationDelay();
1260         return value;
1261     });
1262
1263     return *result.iterator->value;
1264 }
1265
1266 WebSWOriginStore& NetworkProcess::swOriginStoreForSession(PAL::SessionID sessionID)
1267 {
1268     return static_cast<WebSWOriginStore&>(swServerForSession(sessionID).originStore());
1269 }
1270
1271 WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
1272 {
1273     auto* swServer = m_swServers.get(sessionID);
1274     if (!swServer)
1275         return nullptr;
1276     return &static_cast<WebSWOriginStore&>(swServer->originStore());
1277 }
1278
1279 WebSWServerToContextConnection* NetworkProcess::serverToContextConnectionForOrigin(const SecurityOriginData& securityOrigin)
1280 {
1281     return m_serverToContextConnections.get(securityOrigin);
1282 }
1283
1284 void NetworkProcess::createServerToContextConnection(const SecurityOriginData& securityOrigin, std::optional<PAL::SessionID> sessionID)
1285 {
1286     if (m_waitingForServerToContextProcessConnection)
1287         return;
1288     
1289     m_waitingForServerToContextProcessConnection = true;
1290     if (sessionID)
1291         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcessForExplicitSession(securityOrigin, *sessionID), 0);
1292     else
1293         parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess(securityOrigin), 0);
1294 }
1295
1296 void NetworkProcess::didFailFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const ResourceError& error)
1297 {
1298     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1299         connection->didFailFetch(fetchIdentifier, error);
1300 }
1301
1302 void NetworkProcess::didNotHandleFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1303 {
1304     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1305         connection->didNotHandleFetch(fetchIdentifier);
1306 }
1307
1308 void NetworkProcess::didReceiveFetchResponse(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const WebCore::ResourceResponse& response)
1309 {
1310     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1311         connection->didReceiveFetchResponse(fetchIdentifier, response);
1312 }
1313
1314 void NetworkProcess::didReceiveFetchData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::DataReference& data, int64_t encodedDataLength)
1315 {
1316     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1317         connection->didReceiveFetchData(fetchIdentifier, data, encodedDataLength);
1318 }
1319
1320 void NetworkProcess::didReceiveFetchFormData(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier, const IPC::FormDataReference& formData)
1321 {
1322     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1323         connection->didReceiveFetchFormData(fetchIdentifier, formData);
1324 }
1325
1326 void NetworkProcess::didFinishFetch(SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier fetchIdentifier)
1327 {
1328     if (auto* connection = m_swServerConnections.get(serverConnectionIdentifier))
1329         connection->didFinishFetch(fetchIdentifier);
1330 }
1331
1332 void NetworkProcess::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, MessageWithMessagePorts&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
1333 {
1334     if (auto* connection = m_swServerConnections.get(destinationIdentifier.serverConnectionIdentifier))
1335         connection->postMessageToServiceWorkerClient(destinationIdentifier.contextIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
1336 }
1337
1338 void NetworkProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, WebCore::MessageWithMessagePorts&& message, const WebCore::ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
1339 {
1340     if (auto* connection = m_swServerConnections.get(connectionIdentifier))
1341         connection->postMessageToServiceWorker(destination, WTFMove(message), source);
1342 }
1343
1344 void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
1345 {
1346     ASSERT(parentProcessHasServiceWorkerEntitlement());
1347     ASSERT(!m_swServerConnections.contains(connection.identifier()));
1348     m_swServerConnections.add(connection.identifier(), &connection);
1349     swOriginStoreForSession(connection.sessionID()).registerSWServerConnection(connection);
1350 }
1351
1352 void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
1353 {
1354     ASSERT(m_swServerConnections.get(connection.identifier()) == &connection);
1355     m_swServerConnections.remove(connection.identifier());
1356     if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
1357         store->unregisterSWServerConnection(connection);
1358 }
1359
1360 void NetworkProcess::swContextConnectionMayNoLongerBeNeeded(WebSWServerToContextConnection& serverToContextConnection)
1361 {
1362     auto& securityOrigin = serverToContextConnection.securityOrigin();
1363     if (needsServerToContextConnectionForOrigin(securityOrigin))
1364         return;
1365     
1366     RELEASE_LOG(ServiceWorker, "Service worker process is no longer needed, terminating it");
1367     serverToContextConnection.terminate();
1368     
1369     for (auto& swServer : m_swServers.values())
1370         swServer->markAllWorkersForOriginAsTerminated(securityOrigin);
1371     
1372     serverToContextConnection.connectionClosed();
1373     m_serverToContextConnections.remove(securityOrigin);
1374 }
1375
1376 void NetworkProcess::disableServiceWorkerProcessTerminationDelay()
1377 {
1378     if (m_shouldDisableServiceWorkerProcessTerminationDelay)
1379         return;
1380     
1381     m_shouldDisableServiceWorkerProcessTerminationDelay = true;
1382     for (auto& swServer : m_swServers.values())
1383         swServer->disableServiceWorkerProcessTerminationDelay();
1384 }
1385
1386 void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
1387 {
1388     auto addResult = m_swDatabasePaths.add(sessionID, serviceWorkerRegistrationDirectory);
1389     if (addResult.isNewEntry) {
1390         SandboxExtension::consumePermanently(handle);
1391         if (!serviceWorkerRegistrationDirectory.isEmpty())
1392             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
1393     }
1394 }
1395 #endif // ENABLE(SERVICE_WORKER)
1396
1397 #if !PLATFORM(COCOA)
1398 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
1399 {
1400 }
1401
1402 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1403 {
1404 }
1405
1406 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1407 {
1408 }
1409
1410 void NetworkProcess::syncAllCookies()
1411 {
1412 }
1413
1414 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
1415 {
1416     completionHandler();
1417 }
1418
1419 #endif
1420
1421 } // namespace WebKit