Move IndexedDB to Network Process
[WebKit-https.git] / Source / WebKit / NetworkProcess / NetworkProcess.cpp
1 /*
2  * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2018 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "NetworkProcess.h"
29
30 #include "ArgumentCoders.h"
31 #include "Attachment.h"
32 #include "AuthenticationManager.h"
33 #include "ChildProcessMessages.h"
34 #include "DataReference.h"
35 #include "DownloadProxyMessages.h"
36 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
37 #include "LegacyCustomProtocolManager.h"
38 #endif
39 #include "Logging.h"
40 #include "NetworkBlobRegistry.h"
41 #include "NetworkConnectionToWebProcess.h"
42 #include "NetworkContentRuleListManagerMessages.h"
43 #include "NetworkProcessCreationParameters.h"
44 #include "NetworkProcessPlatformStrategies.h"
45 #include "NetworkProcessProxyMessages.h"
46 #include "NetworkProximityManager.h"
47 #include "NetworkResourceLoader.h"
48 #include "NetworkSession.h"
49 #include "NetworkSessionCreationParameters.h"
50 #include "PreconnectTask.h"
51 #include "RemoteNetworkingContext.h"
52 #include "SessionTracker.h"
53 #include "StatisticsData.h"
54 #include "WebCookieManager.h"
55 #include "WebCoreArgumentCoders.h"
56 #include "WebPageProxyMessages.h"
57 #include "WebProcessPoolMessages.h"
58 #include "WebsiteData.h"
59 #include "WebsiteDataFetchOption.h"
60 #include "WebsiteDataStore.h"
61 #include "WebsiteDataStoreParameters.h"
62 #include "WebsiteDataType.h"
63 #include <WebCore/DNS.h>
64 #include <WebCore/DeprecatedGlobalSettings.h>
65 #include <WebCore/DiagnosticLoggingClient.h>
66 #include <WebCore/LogInitialization.h>
67 #include <WebCore/MIMETypeRegistry.h>
68 #include <WebCore/NetworkStateNotifier.h>
69 #include <WebCore/NetworkStorageSession.h>
70 #include <WebCore/ResourceRequest.h>
71 #include <WebCore/RuntimeApplicationChecks.h>
72 #include <WebCore/SchemeRegistry.h>
73 #include <WebCore/SecurityOriginData.h>
74 #include <WebCore/SecurityOriginHash.h>
75 #include <WebCore/Settings.h>
76 #include <WebCore/URLParser.h>
77 #include <pal/SessionID.h>
78 #include <wtf/CallbackAggregator.h>
79 #include <wtf/OptionSet.h>
80 #include <wtf/ProcessPrivilege.h>
81 #include <wtf/RunLoop.h>
82 #include <wtf/text/AtomicString.h>
83 #include <wtf/text/CString.h>
84
85 #if ENABLE(SEC_ITEM_SHIM)
86 #include "SecItemShim.h"
87 #endif
88
89 #include "NetworkCache.h"
90 #include "NetworkCacheCoders.h"
91
92 #if ENABLE(NETWORK_CAPTURE)
93 #include "NetworkCaptureManager.h"
94 #endif
95
96 #if PLATFORM(COCOA)
97 #include "NetworkSessionCocoa.h"
98 #endif
99
100 namespace WebKit {
101 using namespace WebCore;
102
103 NetworkProcess& NetworkProcess::singleton()
104 {
105     static NeverDestroyed<NetworkProcess> networkProcess;
106     return networkProcess;
107 }
108
109 NetworkProcess::NetworkProcess()
110     : m_hasSetCacheModel(false)
111     , m_cacheModel(CacheModelDocumentViewer)
112     , m_diskCacheIsDisabledForTesting(false)
113     , m_canHandleHTTPSServerTrustEvaluation(true)
114 #if PLATFORM(COCOA)
115     , m_clearCacheDispatchGroup(0)
116 #endif
117     , m_storageTaskQueue(WorkQueue::create("com.apple.WebKit.StorageTask"))
118 {
119     NetworkProcessPlatformStrategies::initialize();
120
121     addSupplement<AuthenticationManager>();
122     addSupplement<WebCookieManager>();
123 #if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
124     addSupplement<LegacyCustomProtocolManager>();
125 #endif
126 #if ENABLE(PROXIMITY_NETWORKING)
127     addSupplement<NetworkProximityManager>();
128 #endif
129
130     NetworkStateNotifier::singleton().addListener([this](bool isOnLine) {
131         auto webProcessConnections = m_webProcessConnections;
132         for (auto& webProcessConnection : webProcessConnections)
133             webProcessConnection->setOnLineState(isOnLine);
134     });
135 }
136
137 NetworkProcess::~NetworkProcess()
138 {
139     for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
140         for (auto& callback : callbacks)
141             callback(String { }, 0);
142     }
143 }
144
145 AuthenticationManager& NetworkProcess::authenticationManager()
146 {
147     return *supplement<AuthenticationManager>();
148 }
149
150 DownloadManager& NetworkProcess::downloadManager()
151 {
152     static NeverDestroyed<DownloadManager> downloadManager(*this);
153     return downloadManager;
154 }
155
156 #if ENABLE(PROXIMITY_NETWORKING)
157 NetworkProximityManager& NetworkProcess::proximityManager()
158 {
159     return *supplement<NetworkProximityManager>();
160 }
161 #endif
162
163 void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
164 {
165     size_t vectorIndex = m_webProcessConnections.find(connection);
166     ASSERT(vectorIndex != notFound);
167
168     m_webProcessConnections.remove(vectorIndex);
169 }
170
171 bool NetworkProcess::shouldTerminate()
172 {
173     // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
174     return false;
175 }
176
177 void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
178 {
179     if (messageReceiverMap().dispatchMessage(connection, decoder))
180         return;
181
182     if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
183         ChildProcess::didReceiveMessage(connection, decoder);
184         return;
185     }
186
187 #if ENABLE(CONTENT_EXTENSIONS)
188     if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
189         m_NetworkContentRuleListManager.didReceiveMessage(connection, decoder);
190         return;
191     }
192 #endif
193
194     didReceiveNetworkProcessMessage(connection, decoder);
195 }
196
197 void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
198 {
199     if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
200         return;
201
202     didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
203 }
204
205 void NetworkProcess::didClose(IPC::Connection&)
206 {
207     ASSERT(RunLoop::isMain());
208
209     // Make sure we flush all cookies to disk before exiting.
210     platformSyncAllCookies([this] {
211         stopRunLoop();
212     });
213 }
214
215 void NetworkProcess::didCreateDownload()
216 {
217     disableTermination();
218 }
219
220 void NetworkProcess::didDestroyDownload()
221 {
222     enableTermination();
223 }
224
225 IPC::Connection* NetworkProcess::downloadProxyConnection()
226 {
227     return parentProcessConnection();
228 }
229
230 AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
231 {
232     return authenticationManager();
233 }
234
235 void NetworkProcess::lowMemoryHandler(Critical critical)
236 {
237     if (m_suppressMemoryPressureHandler)
238         return;
239
240     WTF::releaseFastMallocFreeMemory();
241 }
242
243 void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
244 {
245 #if HAVE(SEC_KEY_PROXY)
246     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
247 #else
248     WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
249 #endif
250     WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
251     WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
252     platformInitializeNetworkProcess(parameters);
253
254     WTF::Thread::setCurrentThreadIsUserInitiated();
255     AtomicString::init();
256
257     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
258     m_loadThrottleLatency = parameters.loadThrottleLatency;
259     if (!m_suppressMemoryPressureHandler) {
260         auto& memoryPressureHandler = MemoryPressureHandler::singleton();
261         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
262             lowMemoryHandler(critical);
263         });
264         memoryPressureHandler.install();
265     }
266
267 #if ENABLE(NETWORK_CAPTURE)
268     NetworkCapture::Manager::singleton().initialize(
269         parameters.recordReplayMode,
270         parameters.recordReplayCacheLocation);
271 #endif
272
273     m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
274
275     m_diskCacheSizeOverride = parameters.diskCacheSizeOverride;
276     setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
277
278     setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
279
280     // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
281     if (parameters.privateBrowsingEnabled)
282         RemoteNetworkingContext::ensureWebsiteDataStoreSession(WebsiteDataStoreParameters::legacyPrivateSessionParameters());
283
284     if (parameters.shouldUseTestingNetworkSession)
285         NetworkStorageSession::switchToNewTestingSession();
286
287 #if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
288     m_logCookieInformation = parameters.logCookieInformation;
289 #endif
290
291     SessionTracker::setSession(PAL::SessionID::defaultSessionID(), NetworkSession::create(NetworkSessionCreationParameters()));
292
293 #if ENABLE(INDEXED_DATABASE)
294     addIndexedDatabaseSession(PAL::SessionID::defaultSessionID(), parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
295 #endif
296
297     auto* defaultSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID());
298     for (const auto& cookie : parameters.defaultSessionPendingCookies)
299         defaultSession->networkStorageSession().setCookie(cookie);
300
301     for (auto& supplement : m_supplements.values())
302         supplement->initialize(parameters);
303
304     for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
305         registerURLSchemeAsSecure(scheme);
306
307     for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
308         registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
309
310     for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
311         registerURLSchemeAsLocal(scheme);
312
313     for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
314         registerURLSchemeAsNoAccess(scheme);
315
316     for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
317         registerURLSchemeAsDisplayIsolated(scheme);
318
319     for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
320         registerURLSchemeAsCORSEnabled(scheme);
321
322     for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
323         registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
324
325     RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
326 }
327
328 void NetworkProcess::initializeConnection(IPC::Connection* connection)
329 {
330     ChildProcess::initializeConnection(connection);
331
332     for (auto& supplement : m_supplements.values())
333         supplement->initializeConnection(connection);
334 }
335
336 void NetworkProcess::createNetworkConnectionToWebProcess()
337 {
338 #if USE(UNIX_DOMAIN_SOCKETS)
339     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
340
341     auto connection = NetworkConnectionToWebProcess::create(socketPair.server);
342     m_webProcessConnections.append(WTFMove(connection));
343
344     IPC::Attachment clientSocket(socketPair.client);
345     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
346 #elif OS(DARWIN)
347     // Create the listening port.
348     mach_port_t listeningPort = MACH_PORT_NULL;
349     auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
350     if (kr != KERN_SUCCESS) {
351         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
352         CRASH();
353     }
354     if (!MACH_PORT_VALID(listeningPort)) {
355         RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
356         CRASH();
357     }
358
359     // Create a listening connection.
360     auto connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
361     m_webProcessConnections.append(WTFMove(connection));
362
363     IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
364     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
365 #elif OS(WINDOWS)
366     IPC::Connection::Identifier serverIdentifier, clientIdentifier;
367     if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
368         LOG_ERROR("Failed to create server and client identifiers");
369         CRASH();
370     }
371
372     auto connection = NetworkConnectionToWebProcess::create(serverIdentifier);
373     m_webProcessConnections.append(WTFMove(connection));
374
375     IPC::Attachment clientSocket(clientIdentifier);
376     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
377 #else
378     notImplemented();
379 #endif
380
381     if (!m_webProcessConnections.isEmpty())
382         m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
383 }
384
385 void NetworkProcess::clearCachedCredentials()
386 {
387     NetworkStorageSession::defaultStorageSession().credentialStorage().clearCredentials();
388     if (auto* networkSession = SessionTracker::networkSession(PAL::SessionID::defaultSessionID()))
389         networkSession->clearCredentials();
390     else
391         ASSERT_NOT_REACHED();
392 }
393
394 void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
395 {
396 #if ENABLE(INDEXED_DATABASE)
397     addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
398 #endif
399
400     RemoteNetworkingContext::ensureWebsiteDataStoreSession(WTFMove(parameters));
401 }
402
403 void NetworkProcess::destroySession(PAL::SessionID sessionID)
404 {
405     SessionTracker::destroySession(sessionID);
406     m_sessionsControlledByAutomation.remove(sessionID);
407     CacheStorage::Engine::destroyEngine(sessionID);
408 }
409
410 void NetworkProcess::writeBlobToFilePath(const WebCore::URL& url, const String& path, SandboxExtension::Handle&& handleForWriting, uint64_t requestID)
411 {
412     auto extension = SandboxExtension::create(WTFMove(handleForWriting));
413     if (!extension) {
414         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(false, requestID), 0);
415         return;
416     }
417
418     extension->consume();
419     NetworkBlobRegistry::singleton().writeBlobToFilePath(url, path, [this, extension = WTFMove(extension), requestID] (bool success) {
420         extension->revoke();
421         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidWriteBlobToFilePath(success, requestID), 0);
422     });
423 }
424
425 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
426 void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<String>& domainsToBlock, bool shouldClearFirst, uint64_t contextId)
427 {
428     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
429         networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock, shouldClearFirst);
430     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidUpdateBlockCookies(contextId), 0);
431 }
432
433 void NetworkProcess::hasStorageAccessForFrame(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, uint64_t contextId)
434 {
435     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
436         parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID), contextId), 0);
437     else
438         ASSERT_NOT_REACHED();
439 }
440
441 void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, uint64_t contextId)
442 {
443     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
444         parentProcessConnection()->send(Messages::NetworkProcessProxy::AllStorageAccessEntriesResult(networkStorageSession->getAllStorageAccessEntries(), contextId), 0);
445     else
446         ASSERT_NOT_REACHED();
447 }
448
449 void NetworkProcess::grantStorageAccess(PAL::SessionID sessionID, const String& resourceDomain, const String& firstPartyDomain, std::optional<uint64_t> frameID, uint64_t pageID, uint64_t contextId)
450 {
451     bool isStorageGranted = false;
452     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID)) {
453         networkStorageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
454         ASSERT(networkStorageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
455         isStorageGranted = true;
456     } else
457         ASSERT_NOT_REACHED();
458
459     parentProcessConnection()->send(Messages::NetworkProcessProxy::StorageAccessRequestResult(isStorageGranted, contextId), 0);
460 }
461
462 void NetworkProcess::removeAllStorageAccess(PAL::SessionID sessionID, uint64_t contextId)
463 {
464     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
465         networkStorageSession->removeAllStorageAccess();
466     else
467         ASSERT_NOT_REACHED();
468     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidRemoveAllStorageAccess(contextId), 0);
469 }
470
471 void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<String>& domains)
472 {
473     if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
474         networkStorageSession->removePrevalentDomains(domains);
475 }
476 #endif
477
478 bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
479 {
480     return m_sessionsControlledByAutomation.contains(sessionID);
481 }
482
483 void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
484 {
485     if (controlled)
486         m_sessionsControlledByAutomation.add(sessionID);
487     else
488         m_sessionsControlledByAutomation.remove(sessionID);
489 }
490
491 static void fetchDiskCacheEntries(PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void (Vector<WebsiteData::Entry>)>&& completionHandler)
492 {
493     if (auto* cache = NetworkProcess::singleton().cache()) {
494         HashMap<SecurityOriginData, uint64_t> originsAndSizes;
495         cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
496             if (!traversalEntry) {
497                 Vector<WebsiteData::Entry> entries;
498
499                 for (auto& originAndSize : originsAndSizes)
500                     entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
501
502                 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] {
503                     completionHandler(entries);
504                 });
505
506                 return;
507             }
508
509             auto url = traversalEntry->entry.response().url();
510             auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
511
512             if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
513                 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
514         });
515
516         return;
517     }
518
519     RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] {
520         completionHandler({ });
521     });
522 }
523
524 void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
525 {
526     struct CallbackAggregator final : public RefCounted<CallbackAggregator> {
527         explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
528             : m_completionHandler(WTFMove(completionHandler))
529         {
530         }
531
532         ~CallbackAggregator()
533         {
534             ASSERT(RunLoop::isMain());
535
536             RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] {
537                 completionHandler(websiteData);
538             });
539         }
540
541         Function<void (WebsiteData)> m_completionHandler;
542         WebsiteData m_websiteData;
543     };
544
545     auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
546         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
547     }));
548
549     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
550         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
551             networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
552     }
553
554     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
555         if (NetworkStorageSession::storageSession(sessionID))
556             callbackAggregator->m_websiteData.originsWithCredentials = NetworkStorageSession::storageSession(sessionID)->credentialStorage().originsWithCredentials();
557     }
558
559     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
560         CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
561             callbackAggregator->m_websiteData.entries.appendVector(entries);
562         });
563     }
564
565 #if PLATFORM(COCOA)
566     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
567         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
568             getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
569     }
570 #endif
571
572 #if ENABLE(INDEXED_DATABASE)
573     auto path = m_idbDatabasePaths.get(sessionID);
574     if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
575         // FIXME: Pick the right database store based on the session ID.
576         postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
577             RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
578                 for (const auto& securityOrigin : securityOrigins)
579                     callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
580             });
581         }));
582     }
583 #endif
584
585     if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
586         fetchDiskCacheEntries(sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
587             callbackAggregator->m_websiteData.entries.appendVector(entries);
588         });
589     }
590 }
591
592 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
593 {
594 #if PLATFORM(COCOA)
595     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
596         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
597             clearHSTSCache(*networkStorageSession, modifiedSince);
598     }
599 #endif
600
601     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
602         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
603             networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
604     }
605
606     if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
607         if (NetworkStorageSession::storageSession(sessionID))
608             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
609     }
610
611     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
612         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
613     });
614
615     if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
616         CacheStorage::Engine::clearAllCaches(sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
617
618 #if ENABLE(INDEXED_DATABASE)
619     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases))
620         idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
621 #endif
622
623     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
624         clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
625 }
626
627 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
628 {
629     if (auto* cache = NetworkProcess::singleton().cache()) {
630         HashSet<RefPtr<SecurityOrigin>> originsToDelete;
631         for (auto& origin : origins)
632             originsToDelete.add(origin.securityOrigin());
633
634         Vector<NetworkCache::Key> cacheKeysToDelete;
635         cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
636             if (traversalEntry) {
637                 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
638                     cacheKeysToDelete.append(traversalEntry->entry.key());
639                 return;
640             }
641
642             cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
643             return;
644         });
645
646         return;
647     }
648
649     RunLoop::main().dispatch(WTFMove(completionHandler));
650 }
651
652 void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
653 {
654     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
655         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
656             networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
657     }
658
659 #if PLATFORM(COCOA)
660     if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
661         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
662             deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
663     }
664 #endif
665
666     auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
667         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
668     });
669
670     if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
671         for (auto& originData : originDatas)
672             CacheStorage::Engine::clearCachesForOrigin(sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
673     }
674
675 #if ENABLE(INDEXED_DATABASE)
676     if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases))
677         idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
678 #endif
679
680     if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
681         clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
682 }
683
684 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
685 {
686     downloadManager().startDownload(nullptr, sessionID, downloadID, request, suggestedFilename);
687 }
688
689 void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
690 {
691     downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
692 }
693
694 void NetworkProcess::cancelDownload(DownloadID downloadID)
695 {
696     downloadManager().cancelDownload(downloadID);
697 }
698
699 void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
700 {
701     downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
702 }
703
704 void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
705 {
706     downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
707 }
708
709 void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
710 {
711     uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
712     downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
713
714     downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
715
716     // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
717     // should override the suggested filename from the download attribute.
718     String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
719     suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
720
721     downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
722 }
723
724 void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
725 {
726     if (destination.isEmpty())
727         downloadManager().cancelDownload(downloadID);
728     else
729         downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
730 }
731
732 void NetworkProcess::setCacheModel(uint32_t cm)
733 {
734     CacheModel cacheModel = static_cast<CacheModel>(cm);
735
736     if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
737         return;
738
739     m_hasSetCacheModel = true;
740     m_cacheModel = cacheModel;
741
742     unsigned urlCacheMemoryCapacity = 0;
743     uint64_t urlCacheDiskCapacity = 0;
744     uint64_t diskFreeSize = 0;
745     if (WebCore::FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
746         // As a fudge factor, use 1000 instead of 1024, in case the reported byte
747         // count doesn't align exactly to a megabyte boundary.
748         diskFreeSize /= KB * 1000;
749         calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
750     }
751
752     if (m_diskCacheSizeOverride >= 0)
753         urlCacheDiskCapacity = m_diskCacheSizeOverride;
754
755     if (m_cache)
756         m_cache->setCapacity(urlCacheDiskCapacity);
757 }
758
759 void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
760 {
761     m_canHandleHTTPSServerTrustEvaluation = value;
762 }
763
764 void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
765 {
766     StatisticsData data;
767
768     auto& networkProcess = NetworkProcess::singleton();
769     data.statisticsNumbers.set("DownloadsActiveCount", networkProcess.downloadManager().activeDownloadCount());
770     data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", networkProcess.authenticationManager().outstandingAuthenticationChallengeCount());
771
772     parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
773 }
774
775 void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows)
776 {
777     DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
778 }
779
780 void NetworkProcess::logDiagnosticMessage(uint64_t webPageID, const String& message, const String& description, ShouldSample shouldSample)
781 {
782     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
783         return;
784
785     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
786 }
787
788 void NetworkProcess::logDiagnosticMessageWithResult(uint64_t webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
789 {
790     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
791         return;
792
793     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
794 }
795
796 void NetworkProcess::logDiagnosticMessageWithValue(uint64_t webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
797 {
798     if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
799         return;
800
801     parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
802 }
803
804 void NetworkProcess::terminate()
805 {
806 #if ENABLE(NETWORK_CAPTURE)
807     NetworkCapture::Manager::singleton().terminate();
808 #endif
809
810     platformTerminate();
811     ChildProcess::terminate();
812 }
813
814 void NetworkProcess::processDidTransitionToForeground()
815 {
816     platformProcessDidTransitionToForeground();
817 }
818
819 void NetworkProcess::processDidTransitionToBackground()
820 {
821     platformProcessDidTransitionToBackground();
822 }
823
824 // FIXME: We can remove this one by adapting RefCounter.
825 class TaskCounter : public RefCounted<TaskCounter> {
826 public:
827     explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
828     ~TaskCounter() { m_callback(); };
829
830 private:
831     Function<void()> m_callback;
832 };
833
834 void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
835 {
836     lowMemoryHandler(Critical::Yes);
837
838     RefPtr<TaskCounter> delayedTaskCounter;
839     if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
840         delayedTaskCounter = adoptRef(new TaskCounter([this] {
841             RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
842             if (parentProcessConnection())
843                 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
844         }));
845     }
846
847     platformPrepareToSuspend([delayedTaskCounter] { });
848     platformSyncAllCookies([delayedTaskCounter] { });
849
850     for (auto& connection : m_webProcessConnections)
851         connection->cleanupForSuspension([delayedTaskCounter] { });
852 }
853
854 void NetworkProcess::processWillSuspendImminently(bool& handled)
855 {
856     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
857     handled = true;
858 }
859
860 void NetworkProcess::prepareToSuspend()
861 {
862     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
863     actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
864 }
865
866 void NetworkProcess::cancelPrepareToSuspend()
867 {
868     // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
869     // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
870     // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
871     // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
872     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
873     platformProcessDidResume();
874     for (auto& connection : m_webProcessConnections)
875         connection->endSuspension();
876 }
877
878 void NetworkProcess::processDidResume()
879 {
880     RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
881     platformProcessDidResume();
882     for (auto& connection : m_webProcessConnections)
883         connection->endSuspension();
884 }
885
886 void NetworkProcess::prefetchDNS(const String& hostname)
887 {
888     WebCore::prefetchDNS(hostname);
889 }
890
891 void NetworkProcess::cacheStorageParameters(PAL::SessionID sessionID, CacheStorageParametersCallback&& callback)
892 {
893     m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
894         parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
895         return Vector<CacheStorageParametersCallback> { };
896     }).iterator->value.append(WTFMove(callback));
897 }
898
899 void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, uint64_t quota, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
900 {
901     auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
902     if (iterator == m_cacheStorageParametersCallbacks.end())
903         return;
904
905     SandboxExtension::consumePermanently(handle);
906     auto callbacks = WTFMove(iterator->value);
907     m_cacheStorageParametersCallbacks.remove(iterator);
908     for (auto& callback : callbacks)
909         callback(String { cacheStorageDirectory }, quota);
910 }
911
912 void NetworkProcess::preconnectTo(const WebCore::URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
913 {
914 #if ENABLE(SERVER_PRECONNECT)
915     NetworkLoadParameters parameters;
916     parameters.request = ResourceRequest { url };
917     parameters.sessionID = PAL::SessionID::defaultSessionID();
918     parameters.storedCredentialsPolicy = storedCredentialsPolicy;
919     parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
920
921     new PreconnectTask(WTFMove(parameters));
922 #else
923     UNUSED_PARAM(url);
924     UNUSED_PARAM(storedCredentialsPolicy);
925 #endif
926 }
927
928 void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
929 {
930     SchemeRegistry::registerURLSchemeAsSecure(scheme);
931 }
932
933 void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
934 {
935     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
936 }
937
938 void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
939 {
940     SchemeRegistry::registerURLSchemeAsLocal(scheme);
941 }
942
943 void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
944 {
945     SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
946 }
947
948 void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
949 {
950     SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
951 }
952
953 void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
954 {
955     SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
956 }
957
958 void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
959 {
960     SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
961 }
962
963 void NetworkProcess::didSyncAllCookies()
964 {
965     parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
966 }
967
968 #if ENABLE(INDEXED_DATABASE)
969 IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
970 {
971     auto addResult = m_idbServers.add(sessionID, nullptr);
972     if (!addResult.isNewEntry) {
973         ASSERT(addResult.iterator->value);
974         return *addResult.iterator->value;
975     }
976     
977     auto path = m_idbDatabasePaths.get(sessionID);
978     // There should already be a registered path for this PAL::SessionID.
979     // If there's not, then where did this PAL::SessionID come from?
980     ASSERT(!path.isEmpty());
981     
982     addResult.iterator->value = IDBServer::IDBServer::create(path, NetworkProcess::singleton());
983     return *addResult.iterator->value;
984 }
985
986 void NetworkProcess::ensurePathExists(const String& path)
987 {
988     ASSERT(!RunLoop::isMain());
989     
990     if (!FileSystem::makeAllDirectories(path))
991         LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
992 }
993
994 void NetworkProcess::postStorageTask(CrossThreadTask&& task)
995 {
996     ASSERT(RunLoop::isMain());
997     
998     LockHolder locker(m_storageTaskMutex);
999     
1000     m_storageTasks.append(WTFMove(task));
1001     
1002     m_storageTaskQueue->dispatch([this] {
1003         performNextStorageTask();
1004     });
1005 }
1006
1007 void NetworkProcess::performNextStorageTask()
1008 {
1009     ASSERT(!RunLoop::isMain());
1010     
1011     CrossThreadTask task;
1012     {
1013         LockHolder locker(m_storageTaskMutex);
1014         ASSERT(!m_storageTasks.isEmpty());
1015         task = m_storageTasks.takeFirst();
1016     }
1017     
1018     task.performTask();
1019 }
1020
1021 void NetworkProcess::prepareForAccessToTemporaryFile(const String& path)
1022 {
1023     if (auto extension = m_blobTemporaryFileSandboxExtensions.get(path))
1024         extension->consume();
1025 }
1026
1027 void NetworkProcess::accessToTemporaryFileComplete(const String& path)
1028 {
1029     // We've either hard linked the temporary blob file to the database directory, copied it there,
1030     // or the transaction is being aborted.
1031     // In any of those cases, we can delete the temporary blob file now.
1032     FileSystem::deleteFile(path);
1033     
1034     if (auto extension = m_blobTemporaryFileSandboxExtensions.take(path))
1035         extension->revoke();
1036 }
1037
1038 HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
1039 {
1040     if (path.isEmpty())
1041         return { };
1042     
1043     HashSet<WebCore::SecurityOriginData> securityOrigins;
1044     for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
1045         auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
1046         if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1047             securityOrigins.add(WTFMove(*securityOrigin));
1048         
1049         for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
1050             databaseIdentifier = FileSystem::pathGetFileName(originPath);
1051             if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
1052                 securityOrigins.add(WTFMove(*securityOrigin));
1053         }
1054     }
1055
1056     return securityOrigins;
1057 }
1058
1059 void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
1060 {
1061     // *********
1062     // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
1063     // *********
1064     auto addResult = m_idbDatabasePaths.ensure(sessionID, [path = indexedDatabaseDirectory] {
1065         return path;
1066     });
1067     if (addResult.isNewEntry) {
1068         SandboxExtension::consumePermanently(handle);
1069         if (!indexedDatabaseDirectory.isEmpty())
1070             postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
1071     }
1072 }
1073
1074 #endif // ENABLE(INDEXED_DATABASE)
1075
1076 #if ENABLE(SANDBOX_EXTENSIONS)
1077 void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, WTF::Function<void(SandboxExtension::HandleArray&&)>&& completionHandler)
1078 {
1079
1080     static uint64_t lastRequestID;
1081     
1082     uint64_t requestID = ++lastRequestID;
1083     m_sandboxExtensionForBlobsCompletionHandlersStorageForNetworkProcess.set(requestID, WTFMove(completionHandler));
1084     parentProcessConnection()->send(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(requestID, filenames), 0);
1085 }
1086
1087 void NetworkProcess::didGetSandboxExtensionsForBlobFiles(uint64_t requestID, SandboxExtension::HandleArray&& handles)
1088 {
1089     if (auto handler = m_sandboxExtensionForBlobsCompletionHandlersStorageForNetworkProcess.take(requestID))
1090         handler(WTFMove(handles));
1091 }
1092     
1093 void NetworkProcess::updateTemporaryFileSandboxExtensions(const Vector<String>& paths, SandboxExtension::HandleArray& handles)
1094 {
1095     for (size_t i = 0; i < handles.size(); ++i) {
1096         auto result = m_blobTemporaryFileSandboxExtensions.add(paths[i], SandboxExtension::create(WTFMove(handles[i])));
1097         ASSERT_UNUSED(result, result.isNewEntry);
1098     }
1099 }
1100 #endif // ENABLE(SANDBOX_EXTENSIONS)
1101
1102 #if !PLATFORM(COCOA)
1103 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
1104 {
1105 }
1106
1107 void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
1108 {
1109 }
1110
1111 void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
1112 {
1113 }
1114
1115 void NetworkProcess::syncAllCookies()
1116 {
1117 }
1118
1119 void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
1120 {
1121     completionHandler();
1122 }
1123
1124 #endif
1125
1126 } // namespace WebKit