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