Clearing WebSite data on iOS does not clear the Fetch Cache
[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 USE(NETWORK_SESSION)
251 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
252     parameters.defaultSessionParameters.legacyCustomProtocolManager = supplement<LegacyCustomProtocolManager>();
253 #endif
254     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(WTFMove(parameters.defaultSessionParameters)));
255 #endif
256
257     for (auto& supplement : m_supplements.values())
258         supplement->initialize(parameters);
259 }
260
261 void NetworkProcess::initializeConnection(IPC::Connection* connection)
262 {
263     ChildProcess::initializeConnection(connection);
264
265     for (auto& supplement : m_supplements.values())
266         supplement->initializeConnection(connection);
267 }
268
269 void NetworkProcess::createNetworkConnectionToWebProcess()
270 {
271 #if USE(UNIX_DOMAIN_SOCKETS)
272     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
273
274     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
275     m_webProcessConnections.append(WTFMove(connection));
276
277     IPC::Attachment clientSocket(socketPair.client);
278     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
279 #elif OS(DARWIN)
280     // Create the listening port.
281     mach_port_t listeningPort;
282     mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
283
284     // Create a listening connection.
285     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
286     m_webProcessConnections.append(WTFMove(connection));
287
288     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
289     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
290 #else
291     notImplemented();
292 #endif
293 }
294
295 void NetworkProcess::clearCachedCredentials()
296 {
297     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
298 #if USE(NETWORK_SESSION)
299     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
300         networkSession->clearCredentials();
301     else
302         ASSERT_NOT_REACHED();
303 #endif
304 }
305
306 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
307 {
308     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
309 }
310
311 void NetworkProcess::destroySession(PAL::SessionID sessionID)
312 {
313     SessionTracker::destroySession(sessionID);
314 }
315
316 void NetworkProcess::grantSandboxExtensionsToStorageProcessForBlobs(const Vector<String>& filenames, Function<void ()>&& completionHandler)
317 {
318     static uint64_t lastRequestID;
319
320     uint64_t requestID = ++lastRequestID;
321     m_sandboxExtensionForBlobsCompletionHandlers.set(requestID, WTFMove(completionHandler));
322     parentProcessConnection()->send(Messages::NetworkProcessProxy::GrantSandboxExtensionsToStorageProcessForBlobs(requestID, filenames), 0);
323 }
324
325 void NetworkProcess::didGrantSandboxExtensionsToStorageProcessForBlobs(uint64_t requestID)
326 {
327     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlers.take(requestID))
328         handler();
329 }
330
331 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
332 void NetworkProcess::updatePrevalentDomainsToPartitionOrBlockCookies(PAL::SessionID sessionID, const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, bool shouldClearFirst)
333 {
334     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
335         networkStorageSession->setPrevalentDomainsToPartitionOrBlockCookies(domainsToPartition, domainsToBlock, domainsToNeitherPartitionNorBlock, shouldClearFirst);
336 }
337
338 void NetworkProcess::updateStorageAccessForPrevalentDomains(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, bool shouldGrantStorage, uint64_t contextId)
339 {
340     bool isStorageGranted = false;
341     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
342         networkStorageSession->setStorageAccessGranted(resourceDomain, firstPartyDomain, frameID, pageID, shouldGrantStorage);
343         ASSERT(networkStorageSession->isStorageAccessGranted(resourceDomain, firstPartyDomain, frameID, pageID) == shouldGrantStorage);
344         isStorageGranted = shouldGrantStorage;
345     } else
346         ASSERT_NOT_REACHED();
347
348     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
349 }
350
351 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
352 {
353     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
354         networkStorageSession->removePrevalentDomains(domains);
355 }
356 #endif
357
358 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
359 {
360     if (auto* cache = NetworkProcess::singleton().cache()) {
361         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
362         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
363             if (!traversalEntry) {
364                 Vector<WebsiteData::Entry> entries;
365
366                 for (auto& originAndSize : originsAndSizes)
367                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
368
369                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
370                     completionHandler(entries);
371                 });
372
373                 return;
374             }
375
376             auto url = traversalEntry->entry.response().url();
377             auto result = originsAndSizes.add({url.protocol().toString(), url.host(), url.port()}, 0);
378
379             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
380                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
381         });
382
383         return;
384     }
385
386     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
387         completionHandler({ });
388     });
389 }
390
391 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
392 {
393     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
394         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
395             : m_completionHandler(WTFMove(completionHandler))
396         {
397         }
398
399         ~CallbackAggregator()
400         {
401             ASSERT(RunLoop::isMain());
402
403             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
404                 completionHandler(websiteData);
405             });
406         }
407
408         Function<void (WebsiteData)> m_completionHandler;
409         WebsiteData m_websiteData;
410     };
411
412     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
413         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
414     }));
415
416     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
417         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
418             getHostnamesWithCookies(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithCookies);
419     }
420
421     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
422         if (NetworkStorageSession::storageSession(sessionID))
423             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
424     }
425
426     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
427         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
428             callbackAggregator->m_websiteData.entries.appendVector(entries);
429         });
430     }
431
432     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
433         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
434             callbackAggregator->m_websiteData.entries.appendVector(entries);
435         });
436     }
437 }
438
439 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
440 {
441 #if PLATFORM(COCOA)
442     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
443         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
444             clearHSTSCache(*networkStorageSession, modifiedSince);
445     }
446 #endif
447
448     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
449         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
450             deleteAllCookiesModifiedSince(*networkStorageSession, modifiedSince);
451     }
452
453     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
454         if (NetworkStorageSession::storageSession(sessionID))
455             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
456     }
457
458     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
459         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
460     });
461
462     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
463         CacheStorage::Engine::from(sessionID).clearAllCaches(clearTasksHandler);
464
465     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
466         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
467 }
468
469 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
470 {
471     if (auto* cache = NetworkProcess::singleton().cache()) {
472         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
473         for (auto& origin : origins)
474             originsToDelete.add(origin.securityOrigin());
475
476         Vector<NetworkCache::Key> cacheKeysToDelete;
477         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
478             if (traversalEntry) {
479                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
480                     cacheKeysToDelete.append(traversalEntry->entry.key());
481                 return;
482             }
483
484             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
485             return;
486         });
487
488         return;
489     }
490
491     RunLoop::main().dispatch(WTFMove(completionHandler));
492 }
493
494 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, uint64_t callbackID)
495 {
496     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
497         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
498             deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
499     }
500
501     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
502         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
503     });
504
505     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
506         for (auto& originData : originDatas) {
507             auto origin = originData.securityOrigin()->toString();
508             CacheStorage::Engine::from(sessionID).clearCachesForOrigin(origin, clearTasksHandler);
509         }
510     }
511
512     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
513         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
514 }
515
516 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
517 {
518     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
519 }
520
521 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
522 {
523     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
524 }
525
526 void NetworkProcess::cancelDownload(DownloadID downloadID)
527 {
528     downloadManager().cancelDownload(downloadID);
529 }
530     
531 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
532 static uint64_t generateCanAuthenticateIdentifier()
533 {
534     static uint64_t lastLoaderID = 0;
535     return ++lastLoaderID;
536 }
537
538 void NetworkProcess::canAuthenticateAgainstProtectionSpace(NetworkResourceLoader& loader, const WebCore::ProtectionSpace& protectionSpace)
539 {
540     uint64_t loaderID = generateCanAuthenticateIdentifier();
541     m_waitingNetworkResourceLoaders.set(loaderID, loader);
542     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, loader.pageID(), loader.frameID(), protectionSpace), 0);
543 }
544
545 #if ENABLE(SERVER_PRECONNECT)
546 void NetworkProcess::canAuthenticateAgainstProtectionSpace(PreconnectTask& preconnectTask, const WebCore::ProtectionSpace& protectionSpace)
547 {
548     uint64_t loaderID = generateCanAuthenticateIdentifier();
549     m_waitingPreconnectTasks.set(loaderID, preconnectTask.createWeakPtr());
550     parentProcessConnection()->send(Messages::NetworkProcessProxy::CanAuthenticateAgainstProtectionSpace(loaderID, preconnectTask.pageID(), preconnectTask.frameID(), protectionSpace), 0);
551 }
552 #endif
553
554 void NetworkProcess::continueCanAuthenticateAgainstProtectionSpace(uint64_t loaderID, bool canAuthenticate)
555 {
556     if (auto resourceLoader = m_waitingNetworkResourceLoaders.take(loaderID)) {
557         resourceLoader.value()->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
558         return;
559     }
560 #if ENABLE(SERVER_PRECONNECT)
561     if (auto preconnectTask = m_waitingPreconnectTasks.take(loaderID)) {
562         preconnectTask->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
563         return;
564     }
565 #endif
566 }
567
568 #endif
569
570 #if USE(NETWORK_SESSION)
571 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
572 {
573     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
574 }
575
576 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
577 {
578     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
579 }
580
581 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
582 {
583     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
584     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
585
586     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
587
588     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
589     // should override the suggested filename from the download attribute.
590     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
591     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
592
593     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
594 }
595 #endif
596
597 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
598 {
599     if (destination.isEmpty())
600         downloadManager().cancelDownload(downloadID);
601     else
602         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
603 }
604
605 void NetworkProcess::setCacheModel(uint32_t cm)
606 {
607     CacheModel cacheModel = static_cast<CacheModel>(cm);
608
609     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
610         return;
611
612     m_hasSetCacheModel = true;
613     m_cacheModel = cacheModel;
614
615     unsigned urlCacheMemoryCapacity = 0;
616     uint64_t urlCacheDiskCapacity = 0;
617     uint64_t diskFreeSize = 0;
618     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
619         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
620         // count doesn't align exactly to a megabyte boundary.
621         diskFreeSize /= KB * 1000;
622         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
623     }
624
625     if (m_diskCacheSizeOverride >= 0)
626         urlCacheDiskCapacity = m_diskCacheSizeOverride;
627
628     if (m_cache) {
629         m_cache->setCapacity(urlCacheDiskCapacity);
630         return;
631     }
632
633     platformSetURLCacheSize(urlCacheMemoryCapacity, urlCacheDiskCapacity);
634 }
635
636 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
637 {
638     m_canHandleHTTPSServerTrustEvaluation = value;
639 }
640
641 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
642 {
643     StatisticsData data;
644
645     auto& networkProcess = NetworkProcess::singleton();
646     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
647     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
648
649     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
650 }
651
652 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
653 {
654     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
655 }
656
657 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
658 {
659     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
660         return;
661
662     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
663 }
664
665 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
666 {
667     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
668         return;
669
670     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
671 }
672
673 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
674 {
675     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
676         return;
677
678     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
679 }
680
681 void NetworkProcess::terminate()
682 {
683 #if ENABLE(NETWORK_CAPTURE)
684     NetworkCapture::Manager::singleton().terminate();
685 #endif
686
687     platformTerminate();
688     ChildProcess::terminate();
689 }
690
691 // FIXME: We can remove this one by adapting RefCounter.
692 class TaskCounter : public RefCounted<TaskCounter> {
693 public:
694     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
695     ~TaskCounter() { m_callback(); };
696
697 private:
698     Function<void()> m_callback;
699 };
700
701 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
702 {
703     lowMemoryHandler(Critical::Yes);
704
705     RefPtr<TaskCounter> delayedTaskCounter;
706     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
707         delayedTaskCounter = adoptRef(new TaskCounter([this] {
708             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
709             if (parentProcessConnection())
710                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
711         }));
712     }
713
714     for (auto& connection : m_webProcessConnections)
715         connection->cleanupForSuspension([delayedTaskCounter] { });
716 }
717
718 void NetworkProcess::processWillSuspendImminently(bool& handled)
719 {
720     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
721     handled = true;
722 }
723
724 void NetworkProcess::prepareToSuspend()
725 {
726     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
727     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
728 }
729
730 void NetworkProcess::cancelPrepareToSuspend()
731 {
732     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
733     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
734     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
735     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
736     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
737     for (auto& connection : m_webProcessConnections)
738         connection->endSuspension();
739 }
740
741 void NetworkProcess::processDidResume()
742 {
743     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
744     for (auto& connection : m_webProcessConnections)
745         connection->endSuspension();
746 }
747
748 void NetworkProcess::prefetchDNS(const String& hostname)
749 {
750     WebCore::prefetchDNS(hostname);
751 }
752
753 String NetworkProcess::cacheStorageDirectory(PAL::SessionID sessionID) const
754 {
755     if (sessionID.isEphemeral())
756         return { };
757
758     if (sessionID == PAL::SessionID::defaultSessionID())
759         return m_cacheStorageDirectory;
760
761     auto* session = NetworkStorageSession::storageSession(sessionID);
762     if (!session)
763         return { };
764
765     return session->cacheStorageDirectory();
766 }
767
768 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
769 {
770 #if ENABLE(SERVER_PRECONNECT)
771     NetworkLoadParameters parameters;
772     parameters.request = ResourceRequest { url };
773     parameters.sessionID = PAL::SessionID::defaultSessionID();
774     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
775     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
776
777     new PreconnectTask(WTFMove(parameters));
778 #else
779     UNUSED_PARAM(url);
780     UNUSED_PARAM(storedCredentialsPolicy);
781 #endif
782 }
783
784 uint64_t NetworkProcess::cacheStoragePerOriginQuota() const
785 {
786     return m_cacheStoragePerOriginQuota;
787 }
788
789 #if !PLATFORM(COCOA)
790 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
791 {
792 }
793
794 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
795 {
796 }
797
798 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
799 {
800 }
801
802 void NetworkProcess::syncAllCookies()
803 {
804 }
805
806 #endif
807
808 } // namespace WebKit