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