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