Use unified build for NetworkProcess
[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 "PreconnectTask.h"
50 #include "RemoteNetworkingContext.h"
51 #include "SessionTracker.h"
52 #include "StatisticsData.h"
53 #include "WebCookieManager.h"
54 #include "WebCoreArgumentCoders.h"
55 #include "WebPageProxyMessages.h"
56 #include "WebProcessPoolMessages.h"
57 #include "WebsiteData.h"
58 #include "WebsiteDataFetchOption.h"
59 #include "WebsiteDataStore.h"
60 #include "WebsiteDataStoreParameters.h"
61 #include "WebsiteDataType.h"
62 #include <WebCore/DNS.h>
63 #include <WebCore/DeprecatedGlobalSettings.h>
64 #include <WebCore/DiagnosticLoggingClient.h>
65 #include <WebCore/LogInitialization.h>
66 #include <WebCore/MIMETypeRegistry.h>
67 #include <WebCore/NetworkStateNotifier.h>
68 #include <WebCore/NetworkStorageSession.h>
69 #include <WebCore/ResourceRequest.h>
70 #include <WebCore/RuntimeApplicationChecks.h>
71 #include <WebCore/SchemeRegistry.h>
72 #include <WebCore/SecurityOriginData.h>
73 #include <WebCore/SecurityOriginHash.h>
74 #include <WebCore/Settings.h>
75 #include <WebCore/URLParser.h>
76 #include <pal/SessionID.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 #include <wtf/text/CString.h>
83
84 #if ENABLE(SEC_ITEM_SHIM)
85 #include "SecItemShim.h"
86 #endif
87
88 #include "NetworkCache.h"
89 #include "NetworkCacheCoders.h"
90
91 #if ENABLE(NETWORK_CAPTURE)
92 #include "NetworkCaptureManager.h"
93 #endif
94
95 #if PLATFORM(COCOA)
96 #include "NetworkSessionCocoa.h"
97 #endif
98
99 namespace WebKit {
100 using namespace WebCore;
101
102 NetworkProcess& NetworkProcess::singleton()
103 {
104     static NeverDestroyed<NetworkProcess> networkProcess;
105     return networkProcess;
106 }
107
108 NetworkProcess::NetworkProcess()
109     : m_hasSetCacheModel(false)
110     , m_cacheModel(CacheModelDocumentViewer)
111     , m_diskCacheIsDisabledForTesting(false)
112     , m_canHandleHTTPSServerTrustEvaluation(true)
113 #if PLATFORM(COCOA)
114     , m_clearCacheDispatchGroup(0)
115 #endif
116 {
117     NetworkProcessPlatformStrategies::initialize();
118
119     addSupplement<AuthenticationManager>();
120     addSupplement<WebCookieManager>();
121 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
122     addSupplement<LegacyCustomProtocolManager>();
123 #endif
124 #if ENABLE(PROXIMITY_NETWORKING)
125     addSupplement<NetworkProximityManager>();
126 #endif
127
128     NetworkStateNotifier::singleton().addListener([this](bool isOnLine) {
129         auto webProcessConnections = m_webProcessConnections;
130         for (auto& webProcessConnection : webProcessConnections)
131             webProcessConnection->setOnLineState(isOnLine);
132     });
133 }
134
135 NetworkProcess::~NetworkProcess()
136 {
137     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
138         for (auto& callback : callbacks)
139             callback(String { }, 0);
140     }
141 }
142
143 AuthenticationManager& NetworkProcess::authenticationManager()
144 {
145     return *supplement<AuthenticationManager>();
146 }
147
148 DownloadManager& NetworkProcess::downloadManager()
149 {
150     static NeverDestroyed<DownloadManager> downloadManager(*this);
151     return downloadManager;
152 }
153
154 #if ENABLE(PROXIMITY_NETWORKING)
155 NetworkProximityManager& NetworkProcess::proximityManager()
156 {
157     return *supplement<NetworkProximityManager>();
158 }
159 #endif
160
161 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
162 {
163     size_t vectorIndex = m_webProcessConnections.find(connection);
164     ASSERT(vectorIndex != notFound);
165
166     m_webProcessConnections.remove(vectorIndex);
167 }
168
169 bool NetworkProcess::shouldTerminate()
170 {
171     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
172     return false;
173 }
174
175 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
176 {
177     if (messageReceiverMap().dispatchMessage(connection, decoder))
178         return;
179
180     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
181         ChildProcess::didReceiveMessage(connection, decoder);
182         return;
183     }
184
185 #if ENABLE(CONTENT_EXTENSIONS)
186     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
187         m_NetworkContentRuleListManager.didReceiveMessage(connection, decoder);
188         return;
189     }
190 #endif
191
192     didReceiveNetworkProcessMessage(connection, decoder);
193 }
194
195 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
196 {
197     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
198         return;
199
200     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
201 }
202
203 void NetworkProcess::didClose(IPC::Connection&)
204 {
205     ASSERT(RunLoop::isMain());
206
207     // Make sure we flush all cookies to disk before exiting.
208     platformSyncAllCookies([this] {
209         stopRunLoop();
210     });
211 }
212
213 void NetworkProcess::didCreateDownload()
214 {
215     disableTermination();
216 }
217
218 void NetworkProcess::didDestroyDownload()
219 {
220     enableTermination();
221 }
222
223 IPC::Connection* NetworkProcess::downloadProxyConnection()
224 {
225     return parentProcessConnection();
226 }
227
228 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
229 {
230     return authenticationManager();
231 }
232
233 void NetworkProcess::lowMemoryHandler(Critical critical)
234 {
235     if (m_suppressMemoryPressureHandler)
236         return;
237
238     WTF::releaseFastMallocFreeMemory();
239 }
240
241 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
242 {
243 #if HAVE(SEC_KEY_PROXY)
244     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
245 #else
246     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
247 #endif
248     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
249     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
250     platformInitializeNetworkProcess(parameters);
251
252     WTF::Thread::setCurrentThreadIsUserInitiated();
253     AtomicString::init();
254
255     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
256     m_loadThrottleLatency = parameters.loadThrottleLatency;
257     if (!m_suppressMemoryPressureHandler) {
258         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
259         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
260             lowMemoryHandler(critical);
261         });
262         memoryPressureHandler.install();
263     }
264
265 #if ENABLE(NETWORK_CAPTURE)
266     NetworkCapture::Manager::singleton().initialize(
267         parameters.recordReplayMode,
268         parameters.recordReplayCacheLocation);
269 #endif
270
271     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
272
273     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
274     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
275
276     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
277
278     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
279     if (parameters.privateBrowsingEnabled)
280         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
281
282     if (parameters.shouldUseTestingNetworkSession)
283         NetworkStorageSession::switchToNewTestingSession();
284
285 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
286     m_logCookieInformation = parameters.logCookieInformation;
287 #endif
288
289     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(WTFMove(parameters.defaultSessionParameters)));
290
291     auto* defaultSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID());
292     for (const auto& cookie : parameters.defaultSessionPendingCookies)
293         defaultSession->networkStorageSession().setCookie(cookie);
294
295     for (auto& supplement : m_supplements.values())
296         supplement->initialize(parameters);
297
298     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
299         registerURLSchemeAsSecure(scheme);
300
301     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
302         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
303
304     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
305         registerURLSchemeAsLocal(scheme);
306
307     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
308         registerURLSchemeAsNoAccess(scheme);
309
310     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
311         registerURLSchemeAsDisplayIsolated(scheme);
312
313     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
314         registerURLSchemeAsCORSEnabled(scheme);
315
316     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
317         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
318
319     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
320 }
321
322 void NetworkProcess::initializeConnection(IPC::Connection* connection)
323 {
324     ChildProcess::initializeConnection(connection);
325
326     for (auto& supplement : m_supplements.values())
327         supplement->initializeConnection(connection);
328 }
329
330 void NetworkProcess::createNetworkConnectionToWebProcess()
331 {
332 #if USE(UNIX_DOMAIN_SOCKETS)
333     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
334
335     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
336     m_webProcessConnections.append(WTFMove(connection));
337
338     IPC::Attachment clientSocket(socketPair.client);
339     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
340 #elif OS(DARWIN)
341     // Create the listening port.
342     mach_port_t listeningPort = MACH_PORT_NULL;
343     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
344     if (kr != KERN_SUCCESS) {
345         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
346         CRASH();
347     }
348     if (!MACH_PORT_VALID(listeningPort)) {
349         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
350         CRASH();
351     }
352
353     // Create a listening connection.
354     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
355     m_webProcessConnections.append(WTFMove(connection));
356
357     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
358     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
359 #elif OS(WINDOWS)
360     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
361     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
362         LOG_ERROR("Failed to create server and client identifiers");
363         CRASH();
364     }
365
366     auto connection = NetworkConnectionToWebProcess::create(serverIdentifier);
367     m_webProcessConnections.append(WTFMove(connection));
368
369     IPC::Attachment clientSocket(clientIdentifier);
370     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
371 #else
372     notImplemented();
373 #endif
374
375     if (!m_webProcessConnections.isEmpty())
376         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
377 }
378
379 void NetworkProcess::clearCachedCredentials()
380 {
381     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
382     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
383         networkSession->clearCredentials();
384     else
385         ASSERT_NOT_REACHED();
386 }
387
388 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
389 {
390     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
391 }
392
393 void NetworkProcess::destroySession(PAL::SessionID sessionID)
394 {
395     SessionTracker::destroySession(sessionID);
396     m_sessionsControlledByAutomation.remove(sessionID);
397     CacheStorage::Engine::destroyEngine(sessionID);
398 }
399
400 void NetworkProcess::grantSandboxExtensionsToStorageProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler)
401 {
402     static uint64_t lastRequestID;
403
404     uint64_t requestID = ++lastRequestID;
405     m_sandboxExtensionForBlobsCompletionHandlers.set(requestID, WTFMove(completionHandler));
406     parentProcessConnection()->send(Messages::NetworkProcessProxy::GrantSandboxExtensionsToStorageProcessForBlobs(requestID, filenames), 0);
407 }
408
409 void NetworkProcess::didGrantSandboxExtensionsToStorageProcessForBlobs(uint64_t requestID)
410 {
411     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlers.take(requestID))
412         handler();
413 }
414
415 void NetworkProcess::writeBlobToFilePath(const WebCore::URL& url, const String& path, SandboxExtension::Handle&& handleForWriting, uint64_t requestID)
416 {
417     auto extension = SandboxExtension::create(WTFMove(handleForWriting));
418     if (!extension) {
419         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(false, requestID), 0);
420         return;
421     }
422
423     extension->consume();
424     NetworkBlobRegistry::singleton().writeBlobToFilePath(url, path, [this, extension = WTFMove(extension), requestID] (bool success) {
425         extension->revoke();
426         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(success, requestID), 0);
427     });
428 }
429
430 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
431 void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<String>& domainsToBlock, bool shouldClearFirst, uint64_t contextId)
432 {
433     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
434         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock, shouldClearFirst);
435     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdateBlockCookies(contextId), 0);
436 }
437
438 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
439 {
440     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
441         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
442     else
443         ASSERT_NOT_REACHED();
444 }
445
446 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
447 {
448     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
449         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
450     else
451         ASSERT_NOT_REACHED();
452 }
453
454 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
455 {
456     bool isStorageGranted = false;
457     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
458         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
459         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
460         isStorageGranted = true;
461     } else
462         ASSERT_NOT_REACHED();
463
464     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
465 }
466
467 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
468 {
469     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
470         networkStorageSession->removeAllStorageAccess();
471     else
472         ASSERT_NOT_REACHED();
473     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidRemoveAllStorageAccess(contextId), 0);
474 }
475
476 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
477 {
478     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
479         networkStorageSession->removePrevalentDomains(domains);
480 }
481 #endif
482
483 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
484 {
485     return m_sessionsControlledByAutomation.contains(sessionID);
486 }
487
488 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
489 {
490     if (controlled)
491         m_sessionsControlledByAutomation.add(sessionID);
492     else
493         m_sessionsControlledByAutomation.remove(sessionID);
494 }
495
496 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
497 {
498     if (auto* cache = NetworkProcess::singleton().cache()) {
499         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
500         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
501             if (!traversalEntry) {
502                 Vector<WebsiteData::Entry> entries;
503
504                 for (auto& originAndSize : originsAndSizes)
505                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
506
507                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
508                     completionHandler(entries);
509                 });
510
511                 return;
512             }
513
514             auto url = traversalEntry->entry.response().url();
515             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
516
517             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
518                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
519         });
520
521         return;
522     }
523
524     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
525         completionHandler({ });
526     });
527 }
528
529 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
530 {
531     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
532         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
533             : m_completionHandler(WTFMove(completionHandler))
534         {
535         }
536
537         ~CallbackAggregator()
538         {
539             ASSERT(RunLoop::isMain());
540
541             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
542                 completionHandler(websiteData);
543             });
544         }
545
546         Function<void (WebsiteData)> m_completionHandler;
547         WebsiteData m_websiteData;
548     };
549
550     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
551         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
552     }));
553
554     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
555         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
556             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
557     }
558
559     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
560         if (NetworkStorageSession::storageSession(sessionID))
561             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
562     }
563
564     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
565         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
566             callbackAggregator->m_websiteData.entries.appendVector(entries);
567         });
568     }
569
570 #if PLATFORM(COCOA)
571     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
572         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
573             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
574     }
575 #endif
576
577     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
578         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
579             callbackAggregator->m_websiteData.entries.appendVector(entries);
580         });
581     }
582 }
583
584 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
585 {
586 #if PLATFORM(COCOA)
587     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
588         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
589             clearHSTSCache(*networkStorageSession, modifiedSince);
590     }
591 #endif
592
593     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
594         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
595             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
596     }
597
598     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
599         if (NetworkStorageSession::storageSession(sessionID))
600             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
601     }
602
603     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
604         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
605     });
606
607     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
608         CacheStorage::Engine::clearAllCaches(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
609
610     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
611         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
612 }
613
614 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
615 {
616     if (auto* cache = NetworkProcess::singleton().cache()) {
617         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
618         for (auto& origin : origins)
619             originsToDelete.add(origin.securityOrigin());
620
621         Vector<NetworkCache::Key> cacheKeysToDelete;
622         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
623             if (traversalEntry) {
624                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
625                     cacheKeysToDelete.append(traversalEntry->entry.key());
626                 return;
627             }
628
629             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
630             return;
631         });
632
633         return;
634     }
635
636     RunLoop::main().dispatch(WTFMove(completionHandler));
637 }
638
639 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
640 {
641     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
642         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
643             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
644     }
645
646 #if PLATFORM(COCOA)
647     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
648         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
649             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
650     }
651 #endif
652
653     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
654         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
655     });
656
657     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
658         for (auto& originData : originDatas)
659             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
660     }
661
662     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
663         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
664 }
665
666 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
667 {
668     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
669 }
670
671 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
672 {
673     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
674 }
675
676 void NetworkProcess::cancelDownload(DownloadID downloadID)
677 {
678     downloadManager().cancelDownload(downloadID);
679 }
680
681 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
682 {
683     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
684 }
685
686 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
687 {
688     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
689 }
690
691 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
692 {
693     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
694     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
695
696     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
697
698     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
699     // should override the suggested filename from the download attribute.
700     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
701     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
702
703     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
704 }
705
706 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
707 {
708     if (destination.isEmpty())
709         downloadManager().cancelDownload(downloadID);
710     else
711         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
712 }
713
714 void NetworkProcess::setCacheModel(uint32_t cm)
715 {
716     CacheModel cacheModel = static_cast<CacheModel>(cm);
717
718     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
719         return;
720
721     m_hasSetCacheModel = true;
722     m_cacheModel = cacheModel;
723
724     unsigned urlCacheMemoryCapacity = 0;
725     uint64_t urlCacheDiskCapacity = 0;
726     uint64_t diskFreeSize = 0;
727     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
728         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
729         // count doesn't align exactly to a megabyte boundary.
730         diskFreeSize /= KB * 1000;
731         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
732     }
733
734     if (m_diskCacheSizeOverride >= 0)
735         urlCacheDiskCapacity = m_diskCacheSizeOverride;
736
737     if (m_cache)
738         m_cache->setCapacity(urlCacheDiskCapacity);
739 }
740
741 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
742 {
743     m_canHandleHTTPSServerTrustEvaluation = value;
744 }
745
746 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
747 {
748     StatisticsData data;
749
750     auto& networkProcess = NetworkProcess::singleton();
751     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
752     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
753
754     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
755 }
756
757 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
758 {
759     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
760 }
761
762 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
763 {
764     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
765         return;
766
767     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
768 }
769
770 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
771 {
772     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
773         return;
774
775     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
776 }
777
778 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
779 {
780     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
781         return;
782
783     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
784 }
785
786 void NetworkProcess::terminate()
787 {
788 #if ENABLE(NETWORK_CAPTURE)
789     NetworkCapture::Manager::singleton().terminate();
790 #endif
791
792     platformTerminate();
793     ChildProcess::terminate();
794 }
795
796 void NetworkProcess::processDidTransitionToForeground()
797 {
798     platformProcessDidTransitionToForeground();
799 }
800
801 void NetworkProcess::processDidTransitionToBackground()
802 {
803     platformProcessDidTransitionToBackground();
804 }
805
806 // FIXME: We can remove this one by adapting RefCounter.
807 class TaskCounter : public RefCounted<TaskCounter> {
808 public:
809     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
810     ~TaskCounter() { m_callback(); };
811
812 private:
813     Function<void()> m_callback;
814 };
815
816 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
817 {
818     lowMemoryHandler(Critical::Yes);
819
820     RefPtr<TaskCounter> delayedTaskCounter;
821     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
822         delayedTaskCounter = adoptRef(new TaskCounter([this] {
823             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
824             if (parentProcessConnection())
825                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
826         }));
827     }
828
829     platformPrepareToSuspend([delayedTaskCounter] { });
830     platformSyncAllCookies([delayedTaskCounter] { });
831
832     for (auto& connection : m_webProcessConnections)
833         connection->cleanupForSuspension([delayedTaskCounter] { });
834 }
835
836 void NetworkProcess::processWillSuspendImminently(bool& handled)
837 {
838     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
839     handled = true;
840 }
841
842 void NetworkProcess::prepareToSuspend()
843 {
844     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
845     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
846 }
847
848 void NetworkProcess::cancelPrepareToSuspend()
849 {
850     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
851     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
852     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
853     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
854     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
855     platformProcessDidResume();
856     for (auto& connection : m_webProcessConnections)
857         connection->endSuspension();
858 }
859
860 void NetworkProcess::processDidResume()
861 {
862     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
863     platformProcessDidResume();
864     for (auto& connection : m_webProcessConnections)
865         connection->endSuspension();
866 }
867
868 void NetworkProcess::prefetchDNS(const String& hostname)
869 {
870     WebCore::prefetchDNS(hostname);
871 }
872
873 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
874 {
875     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
876         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
877         return Vector<CacheStorageParametersCallback> { };
878     }).iterator->value.append(WTFMove(callback));
879 }
880
881 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
882 {
883     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
884     if (iterator == m_cacheStorageParametersCallbacks.end())
885         return;
886
887     SandboxExtension::consumePermanently(handle);
888     auto callbacks = WTFMove(iterator->value);
889     m_cacheStorageParametersCallbacks.remove(iterator);
890     for (auto& callback : callbacks)
891         callback(String { cacheStorageDirectory }, quota);
892 }
893
894 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
895 {
896 #if ENABLE(SERVER_PRECONNECT)
897     NetworkLoadParameters parameters;
898     parameters.request = ResourceRequest { url };
899     parameters.sessionID = PAL::SessionID::defaultSessionID();
900     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
901     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
902
903     new PreconnectTask(WTFMove(parameters));
904 #else
905     UNUSED_PARAM(url);
906     UNUSED_PARAM(storedCredentialsPolicy);
907 #endif
908 }
909
910 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
911 {
912     SchemeRegistry::registerURLSchemeAsSecure(scheme);
913 }
914
915 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
916 {
917     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
918 }
919
920 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
921 {
922     SchemeRegistry::registerURLSchemeAsLocal(scheme);
923 }
924
925 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
926 {
927     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
928 }
929
930 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
931 {
932     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
933 }
934
935 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
936 {
937     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
938 }
939
940 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
941 {
942     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
943 }
944
945 void NetworkProcess::didSyncAllCookies()
946 {
947     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
948 }
949
950 #if !PLATFORM(COCOA)
951 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
952 {
953 }
954
955 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
956 {
957 }
958
959 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
960 {
961 }
962
963 void NetworkProcess::syncAllCookies()
964 {
965 }
966
967 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
968 {
969     completionHandler();
970 }
971
972 #endif
973
974 } // namespace WebKit