5a1b3acdeb4260b0b8ac7faa19b6f071bd00bcee
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "NetworkProcess.h"
28
29 #include "ArgumentCoders.h"
30 #include "Attachment.h"
31 #include "AuthenticationManager.h"
32 #include "ChildProcessMessages.h"
33 #include "DataReference.h"
34 #include "DownloadProxyMessages.h"
35 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
36 #include "LegacyCustomProtocolManager.h"
37 #endif
38 #include "Logging.h"
39 #include "NetworkConnectionToWebProcess.h"
40 #include "NetworkProcessCreationParameters.h"
41 #include "NetworkProcessPlatformStrategies.h"
42 #include "NetworkProcessProxyMessages.h"
43 #include "NetworkResourceLoader.h"
44 #include "NetworkSession.h"
45 #include "PreconnectTask.h"
46 #include "RemoteNetworkingContext.h"
47 #include "SessionTracker.h"
48 #include "StatisticsData.h"
49 #include "WebCookieManager.h"
50 #include "WebCoreArgumentCoders.h"
51 #include "WebPageProxyMessages.h"
52 #include "WebProcessPoolMessages.h"
53 #include "WebsiteData.h"
54 #include "WebsiteDataFetchOption.h"
55 #include "WebsiteDataStore.h"
56 #include "WebsiteDataStoreParameters.h"
57 #include "WebsiteDataType.h"
58 #include <WebCore/DNS.h>
59 #include <WebCore/DeprecatedGlobalSettings.h>
60 #include <WebCore/DiagnosticLoggingClient.h>
61 #include <WebCore/LogInitialization.h>
62 #include <WebCore/MIMETypeRegistry.h>
63 #include <WebCore/NetworkStorageSession.h>
64 #include <WebCore/PlatformCookieJar.h>
65 #include <WebCore/ResourceRequest.h>
66 #include <WebCore/RuntimeApplicationChecks.h>
67 #include <WebCore/SecurityOriginData.h>
68 #include <WebCore/SecurityOriginHash.h>
69 #include <WebCore/Settings.h>
70 #include <WebCore/URLParser.h>
71 #include <pal/SessionID.h>
72 #include <wtf/CallbackAggregator.h>
73 #include <wtf/OptionSet.h>
74 #include <wtf/RunLoop.h>
75 #include <wtf/text/AtomicString.h>
76 #include <wtf/text/CString.h>
77
78 #if ENABLE(SEC_ITEM_SHIM)
79 #include "SecItemShim.h"
80 #endif
81
82 #include "NetworkCache.h"
83 #include "NetworkCacheCoders.h"
84
85 #if ENABLE(NETWORK_CAPTURE)
86 #include "NetworkCaptureManager.h"
87 #endif
88
89 #if PLATFORM(COCOA)
90 #include "NetworkSessionCocoa.h"
91 #endif
92
93 using namespace WebCore;
94
95 namespace WebKit {
96
97 NetworkProcess& NetworkProcess::singleton()
98 {
99     static NeverDestroyed<NetworkProcess> networkProcess;
100     return networkProcess;
101 }
102
103 NetworkProcess::NetworkProcess()
104     : m_hasSetCacheModel(false)
105     , m_cacheModel(CacheModelDocumentViewer)
106     , m_diskCacheIsDisabledForTesting(false)
107     , m_canHandleHTTPSServerTrustEvaluation(true)
108 #if PLATFORM(COCOA)
109     , m_clearCacheDispatchGroup(0)
110 #endif
111 #if PLATFORM(IOS)
112     , m_webSQLiteDatabaseTracker(*this)
113 #endif
114 {
115     NetworkProcessPlatformStrategies::initialize();
116
117     addSupplement<AuthenticationManager>();
118     addSupplement<WebCookieManager>();
119 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
120     addSupplement<LegacyCustomProtocolManager>();
121 #endif
122 }
123
124 NetworkProcess::~NetworkProcess()
125 {
126 }
127
128 AuthenticationManager& NetworkProcess::authenticationManager()
129 {
130     return *supplement<AuthenticationManager>();
131 }
132
133 DownloadManager& NetworkProcess::downloadManager()
134 {
135     static NeverDestroyed<DownloadManager> downloadManager(*this);
136     return downloadManager;
137 }
138
139 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
140 {
141     size_t vectorIndex = m_webProcessConnections.find(connection);
142     ASSERT(vectorIndex != notFound);
143
144     m_webProcessConnections.remove(vectorIndex);
145 }
146
147 bool NetworkProcess::shouldTerminate()
148 {
149     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
150     return false;
151 }
152
153 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
154 {
155     if (messageReceiverMap().dispatchMessage(connection, decoder))
156         return;
157
158     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
159         ChildProcess::didReceiveMessage(connection, decoder);
160         return;
161     }
162
163     didReceiveNetworkProcessMessage(connection, decoder);
164 }
165
166 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
167 {
168     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
169         return;
170
171     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
172 }
173
174 void NetworkProcess::didClose(IPC::Connection&)
175 {
176     // The UIProcess just exited.
177     stopRunLoop();
178 }
179
180 void NetworkProcess::didCreateDownload()
181 {
182     disableTermination();
183 }
184
185 void NetworkProcess::didDestroyDownload()
186 {
187     enableTermination();
188 }
189
190 IPC::Connection* NetworkProcess::downloadProxyConnection()
191 {
192     return parentProcessConnection();
193 }
194
195 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
196 {
197     return authenticationManager();
198 }
199
200 void NetworkProcess::lowMemoryHandler(Critical critical)
201 {
202     if (m_suppressMemoryPressureHandler)
203         return;
204
205     WTF::releaseFastMallocFreeMemory();
206 }
207
208 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
209 {
210     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
211     platformInitializeNetworkProcess(parameters);
212
213     WTF::Thread::setCurrentThreadIsUserInitiated();
214     AtomicString::init();
215
216     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
217     m_loadThrottleLatency = parameters.loadThrottleLatency;
218     if (!m_suppressMemoryPressureHandler) {
219         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
220 #if OS(LINUX)
221         if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
222             memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
223 #endif
224         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
225             lowMemoryHandler(critical);
226         });
227         memoryPressureHandler.install();
228     }
229
230 #if ENABLE(NETWORK_CAPTURE)
231     NetworkCapture::Manager::singleton().initialize(
232         parameters.recordReplayMode,
233         parameters.recordReplayCacheLocation);
234 #endif
235
236     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
237
238     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
239     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
240
241     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
242
243     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
244     if (parameters.privateBrowsingEnabled)
245         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
246
247     if (parameters.shouldUseTestingNetworkSession)
248         NetworkStorageSession::switchToNewTestingSession();
249
250 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
251     m_logCookieInformation = parameters.logCookieInformation;
252 #endif
253
254 #if USE(NETWORK_SESSION)
255 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
256     parameters.defaultSessionParameters.legacyCustomProtocolManager = supplement<LegacyCustomProtocolManager>();
257 #endif
258     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(WTFMove(parameters.defaultSessionParameters)));
259 #endif
260
261     for (auto& supplement : m_supplements.values())
262         supplement->initialize(parameters);
263 }
264
265 void NetworkProcess::initializeConnection(IPC::Connection* connection)
266 {
267     ChildProcess::initializeConnection(connection);
268
269     for (auto& supplement : m_supplements.values())
270         supplement->initializeConnection(connection);
271 }
272
273 void NetworkProcess::createNetworkConnectionToWebProcess()
274 {
275 #if USE(UNIX_DOMAIN_SOCKETS)
276     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
277
278     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
279     m_webProcessConnections.append(WTFMove(connection));
280
281     IPC::Attachment clientSocket(socketPair.client);
282     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
283 #elif OS(DARWIN)
284     // Create the listening port.
285     mach_port_t listeningPort;
286     mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
287
288     // Create a listening connection.
289     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
290     m_webProcessConnections.append(WTFMove(connection));
291
292     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
293     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
294 #else
295     notImplemented();
296 #endif
297 }
298
299 void NetworkProcess::clearCachedCredentials()
300 {
301     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
302 #if USE(NETWORK_SESSION)
303     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
304         networkSession->clearCredentials();
305     else
306         ASSERT_NOT_REACHED();
307 #endif
308 }
309
310 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
311 {
312     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
313 }
314
315 void NetworkProcess::destroySession(PAL::SessionID sessionID)
316 {
317     SessionTracker::destroySession(sessionID);
318 }
319
320 void NetworkProcess::grantSandboxExtensionsToStorageProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler)
321 {
322     static uint64_t lastRequestID;
323
324     uint64_t requestID = ++lastRequestID;
325     m_sandboxExtensionForBlobsCompletionHandlers.set(requestID, WTFMove(completionHandler));
326     parentProcessConnection()->send(Messages::NetworkProcessProxy::GrantSandboxExtensionsToStorageProcessForBlobs(requestID, filenames), 0);
327 }
328
329 void NetworkProcess::didGrantSandboxExtensionsToStorageProcessForBlobs(uint64_t requestID)
330 {
331     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlers.take(requestID))
332         handler();
333 }
334
335 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
336 void NetworkProcess::updatePrevalentDomainsToPartitionOrBlockCookies(PAL::SessionID sessionID, const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, bool shouldClearFirst)
337 {
338     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
339         networkStorageSession->setPrevalentDomainsToPartitionOrBlockCookies(domainsToPartition, domainsToBlock, domainsToNeitherPartitionNorBlock, shouldClearFirst);
340 }
341
342 void NetworkProcess::hasStorageAccessForPrevalentDomains(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
343 {
344     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
345         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->isStorageAccessGranted(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
346     else
347         ASSERT_NOT_REACHED();
348 }
349
350 void NetworkProcess::updateStorageAccessForPrevalentDomains(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, bool shouldGrantStorage, uint64_t contextId)
351 {
352     bool isStorageGranted = false;
353     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
354         networkStorageSession->setStorageAccessGranted(resourceDomain, firstPartyDomain, frameID, pageID, shouldGrantStorage);
355         ASSERT(networkStorageSession->isStorageAccessGranted(resourceDomain, firstPartyDomain, frameID, pageID) == shouldGrantStorage);
356         isStorageGranted = shouldGrantStorage;
357     } else
358         ASSERT_NOT_REACHED();
359
360     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
361 }
362
363 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
364 {
365     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
366         networkStorageSession->removePrevalentDomains(domains);
367 }
368 #endif
369
370 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
371 {
372     if (auto* cache = NetworkProcess::singleton().cache()) {
373         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
374         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
375             if (!traversalEntry) {
376                 Vector<WebsiteData::Entry> entries;
377
378                 for (auto& originAndSize : originsAndSizes)
379                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
380
381                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
382                     completionHandler(entries);
383                 });
384
385                 return;
386             }
387
388             auto url = traversalEntry->entry.response().url();
389             auto result = originsAndSizes.add({url.protocol().toString(), url.host(), url.port()}, 0);
390
391             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
392                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
393         });
394
395         return;
396     }
397
398     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
399         completionHandler({ });
400     });
401 }
402
403 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
404 {
405     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
406         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
407             : m_completionHandler(WTFMove(completionHandler))
408         {
409         }
410
411         ~CallbackAggregator()
412         {
413             ASSERT(RunLoop::isMain());
414
415             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
416                 completionHandler(websiteData);
417             });
418         }
419
420         Function<void (WebsiteData)> m_completionHandler;
421         WebsiteData m_websiteData;
422     };
423
424     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
425         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
426     }));
427
428     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
429         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
430             getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies);
431     }
432
433     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
434         if (NetworkStorageSession::storageSession(sessionID))
435             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
436     }
437
438     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
439         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
440             callbackAggregator->m_websiteData.entries.appendVector(entries);
441         });
442     }
443
444     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
445         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
446             callbackAggregator->m_websiteData.entries.appendVector(entries);
447         });
448     }
449 }
450
451 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
452 {
453 #if PLATFORM(COCOA)
454     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
455         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
456             clearHSTSCache(*networkStorageSession, modifiedSince);
457     }
458 #endif
459
460     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
461         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
462             deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince);
463     }
464
465     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
466         if (NetworkStorageSession::storageSession(sessionID))
467             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
468     }
469
470     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
471         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
472     });
473
474     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
475         CacheStorage::Engine::from(sessionID).clearAllCaches(clearTasksHandler);
476
477     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
478         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
479 }
480
481 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
482 {
483     if (auto* cache = NetworkProcess::singleton().cache()) {
484         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
485         for (auto& origin : origins)
486             originsToDelete.add(origin.securityOrigin());
487
488         Vector<NetworkCache::Key> cacheKeysToDelete;
489         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
490             if (traversalEntry) {
491                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
492                     cacheKeysToDelete.append(traversalEntry->entry.key());
493                 return;
494             }
495
496             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
497             return;
498         });
499
500         return;
501     }
502
503     RunLoop::main().dispatch(WTFMove(completionHandler));
504 }
505
506 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, uint64_t callbackID)
507 {
508     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
509         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
510             deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
511     }
512
513     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
514         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
515     });
516
517     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
518         for (auto& originData : originDatas) {
519             auto origin = originData.securityOrigin()->toString();
520             CacheStorage::Engine::from(sessionID).clearCachesForOrigin(origin, clearTasksHandler);
521         }
522     }
523
524     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
525         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
526 }
527
528 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
529 {
530     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
531 }
532
533 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
534 {
535     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
536 }
537
538 void NetworkProcess::cancelDownload(DownloadID downloadID)
539 {
540     downloadManager().cancelDownload(downloadID);
541 }
542     
543 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
544 static uint64_t generateCanAuthenticateIdentifier()
545 {
546     static uint64_t lastLoaderID = 0;
547     return ++lastLoaderID;
548 }
549
550 void NetworkProcess::canAuthenticateAgainstProtectionSpace(NetworkResourceLoader& loader, const WebCore::ProtectionSpace& protectionSpace)
551 {
552     uint64_t loaderID = generateCanAuthenticateIdentifier();
553     m_waitingNetworkResourceLoaders.set(loaderID, loader);
554     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, loader.pageID(), loader.frameID(), protectionSpace), 0);
555 }
556
557 #if ENABLE(SERVER_PRECONNECT)
558 void NetworkProcess::canAuthenticateAgainstProtectionSpace(PreconnectTask& preconnectTask, const WebCore::ProtectionSpace& protectionSpace)
559 {
560     uint64_t loaderID = generateCanAuthenticateIdentifier();
561     m_waitingPreconnectTasks.set(loaderID, preconnectTask.createWeakPtr());
562     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, preconnectTask.pageID(), preconnectTask.frameID(), protectionSpace), 0);
563 }
564 #endif
565
566 void NetworkProcess::continueCanAuthenticateAgainstProtectionSpace(uint64_t loaderID, bool canAuthenticate)
567 {
568     if (auto resourceLoader = m_waitingNetworkResourceLoaders.take(loaderID)) {
569         resourceLoader.value()->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
570         return;
571     }
572 #if ENABLE(SERVER_PRECONNECT)
573     if (auto preconnectTask = m_waitingPreconnectTasks.take(loaderID)) {
574         preconnectTask->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
575         return;
576     }
577 #endif
578 }
579
580 #endif
581
582 #if USE(NETWORK_SESSION)
583 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
584 {
585     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
586 }
587
588 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
589 {
590     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
591 }
592
593 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
594 {
595     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
596     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
597
598     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
599
600     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
601     // should override the suggested filename from the download attribute.
602     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
603     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
604
605     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
606 }
607 #endif
608
609 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
610 {
611     if (destination.isEmpty())
612         downloadManager().cancelDownload(downloadID);
613     else
614         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
615 }
616
617 void NetworkProcess::setCacheModel(uint32_t cm)
618 {
619     CacheModel cacheModel = static_cast<CacheModel>(cm);
620
621     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
622         return;
623
624     m_hasSetCacheModel = true;
625     m_cacheModel = cacheModel;
626
627     unsigned urlCacheMemoryCapacity = 0;
628     uint64_t urlCacheDiskCapacity = 0;
629     uint64_t diskFreeSize = 0;
630     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
631         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
632         // count doesn't align exactly to a megabyte boundary.
633         diskFreeSize /= KB * 1000;
634         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
635     }
636
637     if (m_diskCacheSizeOverride >= 0)
638         urlCacheDiskCapacity = m_diskCacheSizeOverride;
639
640     if (m_cache) {
641         m_cache->setCapacity(urlCacheDiskCapacity);
642         return;
643     }
644
645     platformSetURLCacheSize(urlCacheMemoryCapacity, urlCacheDiskCapacity);
646 }
647
648 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
649 {
650     m_canHandleHTTPSServerTrustEvaluation = value;
651 }
652
653 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
654 {
655     StatisticsData data;
656
657     auto& networkProcess = NetworkProcess::singleton();
658     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
659     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
660
661     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
662 }
663
664 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
665 {
666     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
667 }
668
669 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
670 {
671     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
672         return;
673
674     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
675 }
676
677 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
678 {
679     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
680         return;
681
682     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
683 }
684
685 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
686 {
687     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
688         return;
689
690     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
691 }
692
693 void NetworkProcess::terminate()
694 {
695 #if ENABLE(NETWORK_CAPTURE)
696     NetworkCapture::Manager::singleton().terminate();
697 #endif
698
699     platformTerminate();
700     ChildProcess::terminate();
701 }
702
703 // FIXME: We can remove this one by adapting RefCounter.
704 class TaskCounter : public RefCounted<TaskCounter> {
705 public:
706     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
707     ~TaskCounter() { m_callback(); };
708
709 private:
710     Function<void()> m_callback;
711 };
712
713 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
714 {
715     lowMemoryHandler(Critical::Yes);
716
717     RefPtr<TaskCounter> delayedTaskCounter;
718     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
719         delayedTaskCounter = adoptRef(new TaskCounter([this] {
720             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
721             if (parentProcessConnection())
722                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
723         }));
724     }
725
726     for (auto& connection : m_webProcessConnections)
727         connection->cleanupForSuspension([delayedTaskCounter] { });
728 }
729
730 void NetworkProcess::processWillSuspendImminently(bool& handled)
731 {
732     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
733     handled = true;
734 }
735
736 void NetworkProcess::prepareToSuspend()
737 {
738     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
739     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
740 }
741
742 void NetworkProcess::cancelPrepareToSuspend()
743 {
744     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
745     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
746     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
747     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
748     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
749     for (auto& connection : m_webProcessConnections)
750         connection->endSuspension();
751 }
752
753 void NetworkProcess::processDidResume()
754 {
755     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
756     for (auto& connection : m_webProcessConnections)
757         connection->endSuspension();
758 }
759
760 void NetworkProcess::prefetchDNS(const String& hostname)
761 {
762     WebCore::prefetchDNS(hostname);
763 }
764
765 String NetworkProcess::cacheStorageDirectory(PAL::SessionID sessionID) const
766 {
767     if (sessionID.isEphemeral())
768         return { };
769
770     if (sessionID == PAL::SessionID::defaultSessionID())
771         return m_cacheStorageDirectory;
772
773     auto* session = NetworkStorageSession::storageSession(sessionID);
774     if (!session)
775         return { };
776
777     return session->cacheStorageDirectory();
778 }
779
780 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
781 {
782 #if ENABLE(SERVER_PRECONNECT)
783     NetworkLoadParameters parameters;
784     parameters.request = ResourceRequest { url };
785     parameters.sessionID = PAL::SessionID::defaultSessionID();
786     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
787     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
788
789     new PreconnectTask(WTFMove(parameters));
790 #else
791     UNUSED_PARAM(url);
792     UNUSED_PARAM(storedCredentialsPolicy);
793 #endif
794 }
795
796 uint64_t NetworkProcess::cacheStoragePerOriginQuota() const
797 {
798     return m_cacheStoragePerOriginQuota;
799 }
800
801 #if !PLATFORM(COCOA)
802 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
803 {
804 }
805
806 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
807 {
808 }
809
810 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
811 {
812 }
813
814 void NetworkProcess::syncAllCookies()
815 {
816 }
817
818 #endif
819
820 } // namespace WebKit