1/*
2 * Copyright (C) 2012-2019 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 "AuxiliaryProcessMessages.h"
34#include "DataReference.h"
35#include "Download.h"
36#include "DownloadProxyMessages.h"
37#if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
38#include "LegacyCustomProtocolManager.h"
39#endif
40#include "Logging.h"
41#include "NetworkConnectionToWebProcess.h"
42#include "NetworkContentRuleListManagerMessages.h"
43#include "NetworkLoad.h"
44#include "NetworkProcessCreationParameters.h"
45#include "NetworkProcessPlatformStrategies.h"
46#include "NetworkProcessProxyMessages.h"
47#include "NetworkResourceLoadMap.h"
48#include "NetworkResourceLoader.h"
49#include "NetworkSession.h"
50#include "NetworkSessionCreationParameters.h"
51#include "PreconnectTask.h"
52#include "RemoteNetworkingContext.h"
53#include "ShouldGrandfatherStatistics.h"
54#include "StatisticsData.h"
55#include "StorageAccessStatus.h"
56#include "StorageManager.h"
57#include "StorageManagerMessages.h"
58#include "WebCookieManager.h"
59#include "WebPageProxyMessages.h"
60#include "WebProcessPoolMessages.h"
61#include "WebResourceLoadStatisticsStore.h"
62#include "WebSWOriginStore.h"
63#include "WebSWServerConnection.h"
64#include "WebSWServerToContextConnection.h"
65#include "WebsiteDataFetchOption.h"
66#include "WebsiteDataStore.h"
67#include "WebsiteDataStoreParameters.h"
68#include "WebsiteDataType.h"
69#include <WebCore/CookieJar.h>
70#include <WebCore/DNS.h>
71#include <WebCore/DeprecatedGlobalSettings.h>
72#include <WebCore/DiagnosticLoggingClient.h>
73#include <WebCore/LogInitialization.h>
74#include <WebCore/MIMETypeRegistry.h>
75#include <WebCore/NetworkStateNotifier.h>
76#include <WebCore/NetworkStorageSession.h>
77#include <WebCore/ResourceRequest.h>
78#include <WebCore/RuntimeApplicationChecks.h>
79#include <WebCore/RuntimeEnabledFeatures.h>
80#include <WebCore/SchemeRegistry.h>
81#include <WebCore/SecurityOriginData.h>
82#include <WebCore/StorageQuotaManager.h>
83#include <wtf/Algorithms.h>
84#include <wtf/CallbackAggregator.h>
85#include <wtf/OptionSet.h>
86#include <wtf/ProcessPrivilege.h>
87#include <wtf/RunLoop.h>
88#include <wtf/text/AtomString.h>
89
90#if ENABLE(SEC_ITEM_SHIM)
91#include "SecItemShim.h"
92#endif
93
94#include "NetworkCache.h"
95#include "NetworkCacheCoders.h"
96
97#if PLATFORM(COCOA)
98#include "NetworkSessionCocoa.h"
99#endif
100
101#if USE(SOUP)
102#include <WebCore/DNSResolveQueueSoup.h>
103#include <WebCore/SoupNetworkSession.h>
104#endif
105
106#if USE(CURL)
107#include <WebCore/CurlContext.h>
108#endif
109
110#if ENABLE(SERVICE_WORKER)
111#include "WebSWServerToContextConnectionMessages.h"
112#endif
113
114namespace WebKit {
115using namespace WebCore;
116
117static void callExitSoon(IPC::Connection*)
118{
119 // If the connection has been closed and we haven't responded in the main thread for 10 seconds
120 // the process will exit forcibly.
121 auto watchdogDelay = 10_s;
122
123 WorkQueue::create("com.apple.WebKit.NetworkProcess.WatchDogQueue")->dispatchAfter(watchdogDelay, [] {
124 // We use _exit here since the watchdog callback is called from another thread and we don't want
125 // global destructors or atexit handlers to be called from this thread while the main thread is busy
126 // doing its thing.
127 RELEASE_LOG_ERROR(IPC, "Exiting process early due to unacknowledged closed-connection");
128 _exit(EXIT_FAILURE);
129 });
130}
131
132NetworkProcess::NetworkProcess(AuxiliaryProcessInitializationParameters&& parameters)
133 : m_downloadManager(*this)
134#if ENABLE(CONTENT_EXTENSIONS)
135 , m_networkContentRuleListManager(*this)
136#endif
137#if PLATFORM(IOS_FAMILY)
138 , m_webSQLiteDatabaseTracker([this](bool isHoldingLockedFiles) { parentProcessConnection()->send(Messages::NetworkProcessProxy::SetIsHoldingLockedFiles(isHoldingLockedFiles), 0); })
139#endif
140{
141 NetworkProcessPlatformStrategies::initialize();
142
143 addSupplement<AuthenticationManager>();
144 addSupplement<WebCookieManager>();
145#if ENABLE(LEGACY_CUSTOM_PROTOCOL_MANAGER)
146 addSupplement<LegacyCustomProtocolManager>();
147#endif
148#if PLATFORM(COCOA) || USE(SOUP)
149 LegacyCustomProtocolManager::networkProcessCreated(*this);
150#endif
151
152#if USE(SOUP)
153 DNSResolveQueueSoup::setGlobalDefaultNetworkStorageSessionAccessor([this]() -> NetworkStorageSession& {
154 return defaultStorageSession();
155 });
156#endif
157
158 NetworkStateNotifier::singleton().addListener([weakThis = makeWeakPtr(*this)](bool isOnLine) {
159 if (!weakThis)
160 return;
161 for (auto& webProcessConnection : weakThis->m_webProcessConnections)
162 webProcessConnection->setOnLineState(isOnLine);
163 });
164
165 initialize(WTFMove(parameters));
166}
167
168NetworkProcess::~NetworkProcess()
169{
170 for (auto& callbacks : m_cacheStorageParametersCallbacks.values()) {
171 for (auto& callback : callbacks)
172 callback(String { });
173 }
174}
175
176AuthenticationManager& NetworkProcess::authenticationManager()
177{
178 return *supplement<AuthenticationManager>();
179}
180
181DownloadManager& NetworkProcess::downloadManager()
182{
183 return m_downloadManager;
184}
185
186void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess& connection)
187{
188 auto count = m_webProcessConnections.removeAllMatching([&] (const auto& c) {
189 return c.ptr() == &connection;
190 });
191 ASSERT_UNUSED(count, count == 1);
192}
193
194bool NetworkProcess::shouldTerminate()
195{
196 // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
197 return false;
198}
199
200void NetworkProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
201{
202 if (messageReceiverMap().dispatchMessage(connection, decoder))
203 return;
204
205 if (decoder.messageReceiverName() == Messages::AuxiliaryProcess::messageReceiverName()) {
206 AuxiliaryProcess::didReceiveMessage(connection, decoder);
207 return;
208 }
209
210#if ENABLE(CONTENT_EXTENSIONS)
211 if (decoder.messageReceiverName() == Messages::NetworkContentRuleListManager::messageReceiverName()) {
212 m_networkContentRuleListManager.didReceiveMessage(connection, decoder);
213 return;
214 }
215#endif
216
217#if ENABLE(SERVICE_WORKER)
218 if (decoder.messageReceiverName() == Messages::WebSWServerToContextConnection::messageReceiverName()) {
219 ASSERT(parentProcessHasServiceWorkerEntitlement());
220 if (!parentProcessHasServiceWorkerEntitlement())
221 return;
222 if (auto* webSWConnection = connectionToContextProcessFromIPCConnection(connection)) {
223 webSWConnection->didReceiveMessage(connection, decoder);
224 return;
225 }
226 }
227#endif
228 didReceiveNetworkProcessMessage(connection, decoder);
229}
230
231void NetworkProcess::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
232{
233 if (messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder))
234 return;
235
236 didReceiveSyncNetworkProcessMessage(connection, decoder, replyEncoder);
237}
238
239void NetworkProcess::didClose(IPC::Connection&)
240{
241 ASSERT(RunLoop::isMain());
242
243 // Make sure we flush all cookies to disk before exiting.
244 platformSyncAllCookies([this] {
245 stopRunLoop();
246 });
247}
248
249void NetworkProcess::didCreateDownload()
250{
251 disableTermination();
252}
253
254void NetworkProcess::didDestroyDownload()
255{
256 enableTermination();
257}
258
259IPC::Connection* NetworkProcess::downloadProxyConnection()
260{
261 return parentProcessConnection();
262}
263
264AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
265{
266 return authenticationManager();
267}
268
269void NetworkProcess::lowMemoryHandler(Critical critical)
270{
271 if (m_suppressMemoryPressureHandler)
272 return;
273
274 WTF::releaseFastMallocFreeMemory();
275
276 for (auto& networkSession : m_networkSessions.values())
277 networkSession.get().clearPrefetchCache();
278}
279
280void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
281{
282#if HAVE(SEC_KEY_PROXY)
283 WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies });
284#else
285 WTF::setProcessPrivileges({ ProcessPrivilege::CanAccessRawCookies, ProcessPrivilege::CanAccessCredentials });
286#endif
287 WebCore::NetworkStorageSession::permitProcessToUseCookieAPI(true);
288 platformInitializeNetworkProcess(parameters);
289
290 WTF::Thread::setCurrentThreadIsUserInitiated();
291 AtomString::init();
292
293 m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
294 if (!m_suppressMemoryPressureHandler) {
295 auto& memoryPressureHandler = MemoryPressureHandler::singleton();
296 memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
297 lowMemoryHandler(critical);
298 });
299 memoryPressureHandler.install();
300 }
301
302 m_diskCacheIsDisabledForTesting = parameters.shouldUseTestingNetworkSession;
303
304 setCacheModel(parameters.cacheModel);
305
306 setCanHandleHTTPSServerTrustEvaluation(parameters.canHandleHTTPSServerTrustEvaluation);
307
308 if (parameters.shouldUseTestingNetworkSession)
309 switchToNewTestingSession();
310
311 WebCore::RuntimeEnabledFeatures::sharedFeatures().setIsITPDatabaseEnabled(parameters.shouldEnableITPDatabase);
312 WebCore::RuntimeEnabledFeatures::sharedFeatures().setIsITPFirstPartyWebsiteDataRemovalEnabled(parameters.isITPFirstPartyWebsiteDataRemovalEnabled);
313
314 WebCore::RuntimeEnabledFeatures::sharedFeatures().setAdClickAttributionDebugModeEnabled(parameters.enableAdClickAttributionDebugMode);
315
316 SandboxExtension::consumePermanently(parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectoryExtensionHandle);
317
318 auto sessionID = parameters.defaultDataStoreParameters.networkSessionParameters.sessionID;
319 setSession(sessionID, NetworkSession::create(*this, WTFMove(parameters.defaultDataStoreParameters.networkSessionParameters)));
320
321#if ENABLE(INDEXED_DATABASE)
322 addIndexedDatabaseSession(sessionID, parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle);
323#endif
324
325#if ENABLE(SERVICE_WORKER)
326 if (parentProcessHasServiceWorkerEntitlement()) {
327 addServiceWorkerSession(PAL::SessionID::defaultSessionID(), parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
328
329 for (auto& scheme : parameters.urlSchemesServiceWorkersCanHandle)
330 registerURLSchemeServiceWorkersCanHandle(scheme);
331
332 m_shouldDisableServiceWorkerProcessTerminationDelay = parameters.shouldDisableServiceWorkerProcessTerminationDelay;
333 }
334#endif
335 initializeStorageQuota(parameters.defaultDataStoreParameters);
336
337 auto* defaultSession = networkSession(PAL::SessionID::defaultSessionID());
338 for (const auto& cookie : parameters.defaultDataStoreParameters.pendingCookies)
339 defaultSession->networkStorageSession().setCookie(cookie);
340
341 for (auto& supplement : m_supplements.values())
342 supplement->initialize(parameters);
343
344 for (auto& scheme : parameters.urlSchemesRegisteredAsSecure)
345 registerURLSchemeAsSecure(scheme);
346
347 for (auto& scheme : parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy)
348 registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
349
350 for (auto& scheme : parameters.urlSchemesRegisteredAsLocal)
351 registerURLSchemeAsLocal(scheme);
352
353 for (auto& scheme : parameters.urlSchemesRegisteredAsNoAccess)
354 registerURLSchemeAsNoAccess(scheme);
355
356 for (auto& scheme : parameters.urlSchemesRegisteredAsDisplayIsolated)
357 registerURLSchemeAsDisplayIsolated(scheme);
358
359 for (auto& scheme : parameters.urlSchemesRegisteredAsCORSEnabled)
360 registerURLSchemeAsCORSEnabled(scheme);
361
362 for (auto& scheme : parameters.urlSchemesRegisteredAsCanDisplayOnlyIfCanRequest)
363 registerURLSchemeAsCanDisplayOnlyIfCanRequest(scheme);
364
365 m_downloadMonitorSpeedMultiplier = parameters.downloadMonitorSpeedMultiplier;
366
367 RELEASE_LOG(Process, "%p - NetworkProcess::initializeNetworkProcess: Presenting process = %d", this, WebCore::presentingApplicationPID());
368}
369
370void NetworkProcess::initializeConnection(IPC::Connection* connection)
371{
372 AuxiliaryProcess::initializeConnection(connection);
373
374 // We give a chance for didClose() to get called on the main thread but forcefully call _exit() after a delay
375 // in case the main thread is unresponsive or didClose() takes too long.
376 connection->setDidCloseOnConnectionWorkQueueCallback(callExitSoon);
377
378 for (auto& supplement : m_supplements.values())
379 supplement->initializeConnection(connection);
380}
381
382void NetworkProcess::createNetworkConnectionToWebProcess(bool isServiceWorkerProcess, WebCore::RegistrableDomain&& registrableDomain)
383{
384#if USE(UNIX_DOMAIN_SOCKETS)
385 IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
386
387 auto connection = NetworkConnectionToWebProcess::create(*this, socketPair.server);
388 m_webProcessConnections.append(WTFMove(connection));
389
390 IPC::Attachment clientSocket(socketPair.client);
391 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
392#elif OS(DARWIN)
393 // Create the listening port.
394 mach_port_t listeningPort = MACH_PORT_NULL;
395 auto kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
396 if (kr != KERN_SUCCESS) {
397 RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, error %x", kr);
398 CRASH();
399 }
400 if (!MACH_PORT_VALID(listeningPort)) {
401 RELEASE_LOG_ERROR(Process, "NetworkProcess::createNetworkConnectionToWebProcess: Could not allocate mach port, returned port was invalid");
402 CRASH();
403 }
404
405 // Create a listening connection.
406 auto connection = NetworkConnectionToWebProcess::create(*this, IPC::Connection::Identifier(listeningPort));
407 m_webProcessConnections.append(WTFMove(connection));
408
409 IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
410 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
411#elif OS(WINDOWS)
412 IPC::Connection::Identifier serverIdentifier, clientIdentifier;
413 if (!IPC::Connection::createServerAndClientIdentifiers(serverIdentifier, clientIdentifier)) {
414 LOG_ERROR("Failed to create server and client identifiers");
415 CRASH();
416 }
417
418 auto connection = NetworkConnectionToWebProcess::create(*this, serverIdentifier);
419 m_webProcessConnections.append(WTFMove(connection));
420
421 IPC::Attachment clientSocket(clientIdentifier);
422 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
423#else
424 notImplemented();
425#endif
426
427 if (!m_webProcessConnections.isEmpty())
428 m_webProcessConnections.last()->setOnLineState(NetworkStateNotifier::singleton().onLine());
429
430#if ENABLE(SERVICE_WORKER)
431 if (isServiceWorkerProcess && !m_webProcessConnections.isEmpty()) {
432 ASSERT(parentProcessHasServiceWorkerEntitlement());
433 ASSERT(m_waitingForServerToContextProcessConnection);
434 auto contextConnection = WebSWServerToContextConnection::create(*this, registrableDomain, m_webProcessConnections.last()->connection());
435 auto addResult = m_serverToContextConnections.add(WTFMove(registrableDomain), contextConnection.copyRef());
436 ASSERT_UNUSED(addResult, addResult.isNewEntry);
437
438 m_waitingForServerToContextProcessConnection = false;
439
440 for (auto* server : SWServer::allServers())
441 server->serverToContextConnectionCreated(contextConnection);
442 }
443#else
444 UNUSED_PARAM(isServiceWorkerProcess);
445 UNUSED_PARAM(registrableDomain);
446#endif
447}
448
449void NetworkProcess::clearCachedCredentials()
450{
451 defaultStorageSession().credentialStorage().clearCredentials();
452 if (auto* networkSession = this->networkSession(PAL::SessionID::defaultSessionID()))
453 networkSession->clearCredentials();
454 else
455 ASSERT_NOT_REACHED();
456}
457
458void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
459{
460#if ENABLE(INDEXED_DATABASE)
461 addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
462#endif
463
464#if ENABLE(SERVICE_WORKER)
465 if (parentProcessHasServiceWorkerEntitlement())
466 addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
467#endif
468
469 initializeStorageQuota(parameters);
470
471 RemoteNetworkingContext::ensureWebsiteDataStoreSession(*this, WTFMove(parameters));
472}
473
474void NetworkProcess::initializeStorageQuota(const WebsiteDataStoreParameters& parameters)
475{
476 auto& managers = m_storageQuotaManagers.ensure(parameters.networkSessionParameters.sessionID, [] {
477 return StorageQuotaManagers { };
478 }).iterator->value;
479 managers.setDefaultQuotas(parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota);
480}
481
482void NetworkProcess::switchToNewTestingSession()
483{
484#if PLATFORM(COCOA)
485 // Session name should be short enough for shared memory region name to be under the limit, otherwise sandbox rules won't work (see <rdar://problem/13642852>).
486 String sessionName = makeString("WebKit Test-", getCurrentProcessID());
487
488 auto session = adoptCF(WebCore::createPrivateStorageSession(sessionName.createCFString().get()));
489
490 RetainPtr<CFHTTPCookieStorageRef> cookieStorage;
491 if (WebCore::NetworkStorageSession::processMayUseCookieAPI()) {
492 ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
493 if (session)
494 cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, session.get()));
495 }
496
497 m_defaultNetworkStorageSession = std::make_unique<WebCore::NetworkStorageSession>(PAL::SessionID::defaultSessionID(), WTFMove(session), WTFMove(cookieStorage));
498#elif USE(SOUP)
499 m_defaultNetworkStorageSession = std::make_unique<WebCore::NetworkStorageSession>(PAL::SessionID::defaultSessionID(), std::make_unique<WebCore::SoupNetworkSession>());
500#elif USE(CURL)
501 m_defaultNetworkStorageSession = std::make_unique<WebCore::NetworkStorageSession>(PAL::SessionID::defaultSessionID());
502#endif
503}
504
505#if PLATFORM(COCOA)
506void NetworkProcess::ensureSession(const PAL::SessionID& sessionID, const String& identifierBase, RetainPtr<CFHTTPCookieStorageRef>&& cookieStorage)
507#else
508void NetworkProcess::ensureSession(const PAL::SessionID& sessionID, const String& identifierBase)
509#endif
510{
511 ASSERT(sessionID != PAL::SessionID::defaultSessionID());
512
513 auto addResult = m_networkStorageSessions.add(sessionID, nullptr);
514 if (!addResult.isNewEntry)
515 return;
516
517#if PLATFORM(COCOA)
518 RetainPtr<CFURLStorageSessionRef> storageSession;
519 RetainPtr<CFStringRef> cfIdentifier = String(identifierBase + ".PrivateBrowsing").createCFString();
520 if (sessionID.isEphemeral())
521 storageSession = adoptCF(createPrivateStorageSession(cfIdentifier.get()));
522 else
523 storageSession = WebCore::NetworkStorageSession::createCFStorageSessionForIdentifier(cfIdentifier.get());
524
525 if (NetworkStorageSession::processMayUseCookieAPI()) {
526 ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
527 if (!cookieStorage && storageSession)
528 cookieStorage = adoptCF(_CFURLStorageSessionCopyCookieStorage(kCFAllocatorDefault, storageSession.get()));
529 }
530
531 addResult.iterator->value = std::make_unique<NetworkStorageSession>(sessionID, WTFMove(storageSession), WTFMove(cookieStorage));
532#elif USE(SOUP)
533 addResult.iterator->value = std::make_unique<NetworkStorageSession>(sessionID, std::make_unique<SoupNetworkSession>(sessionID));
534#elif USE(CURL)
535 addResult.iterator->value = std::make_unique<NetworkStorageSession>(sessionID);
536#endif
537}
538
539WebCore::NetworkStorageSession* NetworkProcess::storageSession(const PAL::SessionID& sessionID) const
540{
541 if (sessionID == PAL::SessionID::defaultSessionID())
542 return &defaultStorageSession();
543 return m_networkStorageSessions.get(sessionID);
544}
545
546WebCore::NetworkStorageSession& NetworkProcess::defaultStorageSession() const
547{
548 if (!m_defaultNetworkStorageSession)
549 m_defaultNetworkStorageSession = platformCreateDefaultStorageSession();
550 return *m_defaultNetworkStorageSession;
551}
552
553void NetworkProcess::forEachNetworkStorageSession(const Function<void(WebCore::NetworkStorageSession&)>& functor)
554{
555 functor(defaultStorageSession());
556 for (auto& storageSession : m_networkStorageSessions.values())
557 functor(*storageSession);
558}
559
560NetworkSession* NetworkProcess::networkSession(const PAL::SessionID& sessionID) const
561{
562 return m_networkSessions.get(sessionID);
563}
564
565NetworkSession* NetworkProcess::networkSessionByConnection(IPC::Connection& connection) const
566{
567 if (!m_sessionByConnection.contains(connection.uniqueID()))
568 return nullptr;
569
570 return networkSession(m_sessionByConnection.get(connection.uniqueID()));
571}
572
573void NetworkProcess::setSession(const PAL::SessionID& sessionID, Ref<NetworkSession>&& session)
574{
575 m_networkSessions.set(sessionID, WTFMove(session));
576}
577
578void NetworkProcess::destroySession(const PAL::SessionID& sessionID)
579{
580 ASSERT(sessionID != PAL::SessionID::defaultSessionID());
581
582 if (auto session = m_networkSessions.take(sessionID))
583 session->get().invalidateAndCancel();
584 m_networkStorageSessions.remove(sessionID);
585 m_sessionsControlledByAutomation.remove(sessionID);
586 CacheStorage::Engine::destroyEngine(*this, sessionID);
587
588#if ENABLE(SERVICE_WORKER)
589 m_swServers.remove(sessionID);
590 m_swDatabasePaths.remove(sessionID);
591#endif
592
593 m_storageQuotaManagers.remove(sessionID);
594}
595
596#if ENABLE(RESOURCE_LOAD_STATISTICS)
597void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
598{
599 if (auto* networkSession = this->networkSession(sessionID)) {
600 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
601 resourceLoadStatistics->dumpResourceLoadStatistics(WTFMove(completionHandler));
602 else
603 completionHandler({ });
604 } else {
605 ASSERT_NOT_REACHED();
606 completionHandler({ });
607 }
608}
609
610void NetworkProcess::updatePrevalentDomainsToBlockCookiesFor(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
611{
612 if (auto* networkStorageSession = storageSession(sessionID))
613 networkStorageSession->setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
614 completionHandler();
615}
616
617void NetworkProcess::isGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
618{
619 if (auto* networkSession = this->networkSession(sessionID)) {
620 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
621 resourceLoadStatistics->isGrandfathered(domain, WTFMove(completionHandler));
622 else
623 completionHandler(false);
624 } else {
625 ASSERT_NOT_REACHED();
626 completionHandler(false);
627 }
628}
629
630void NetworkProcess::isPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
631{
632 if (auto* networkSession = this->networkSession(sessionID)) {
633 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
634 resourceLoadStatistics->isPrevalentResource(domain, WTFMove(completionHandler));
635 else
636 completionHandler(false);
637 } else {
638 ASSERT_NOT_REACHED();
639 completionHandler(false);
640 }
641}
642
643void NetworkProcess::isVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
644{
645 if (auto* networkSession = this->networkSession(sessionID)) {
646 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
647 resourceLoadStatistics->isVeryPrevalentResource(domain, WTFMove(completionHandler));
648 else
649 completionHandler(false);
650 } else {
651 ASSERT_NOT_REACHED();
652 completionHandler(false);
653 }
654}
655
656void NetworkProcess::setAgeCapForClientSideCookies(PAL::SessionID sessionID, Optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
657{
658 if (auto* networkStorageSession = storageSession(sessionID))
659 networkStorageSession->setAgeCapForClientSideCookies(seconds);
660 completionHandler();
661}
662
663void NetworkProcess::setGrandfathered(PAL::SessionID sessionID, const RegistrableDomain& domain, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
664{
665 if (auto* networkSession = this->networkSession(sessionID)) {
666 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
667 resourceLoadStatistics->setGrandfathered(domain, isGrandfathered, WTFMove(completionHandler));
668 else
669 completionHandler();
670 } else {
671 ASSERT_NOT_REACHED();
672 completionHandler();
673 }
674}
675
676void NetworkProcess::setPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
677{
678 if (auto* networkSession = this->networkSession(sessionID)) {
679 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
680 resourceLoadStatistics->setPrevalentResource(domain, WTFMove(completionHandler));
681 else
682 completionHandler();
683 } else {
684 ASSERT_NOT_REACHED();
685 completionHandler();
686 }
687}
688
689void NetworkProcess::setPrevalentResourceForDebugMode(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
690{
691 if (auto* networkSession = this->networkSession(sessionID)) {
692 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
693 resourceLoadStatistics->setPrevalentResourceForDebugMode(domain, WTFMove(completionHandler));
694 else
695 completionHandler();
696 } else {
697 ASSERT_NOT_REACHED();
698 completionHandler();
699 }
700}
701
702void NetworkProcess::setVeryPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
703{
704 if (auto* networkSession = this->networkSession(sessionID)) {
705 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
706 resourceLoadStatistics->setVeryPrevalentResource(domain, WTFMove(completionHandler));
707 else
708 completionHandler();
709 } else {
710 ASSERT_NOT_REACHED();
711 completionHandler();
712 }
713}
714
715void NetworkProcess::clearPrevalentResource(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
716{
717 if (auto* networkSession = this->networkSession(sessionID)) {
718 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
719 resourceLoadStatistics->clearPrevalentResource(domain, WTFMove(completionHandler));
720 else
721 completionHandler();
722 } else {
723 ASSERT_NOT_REACHED();
724 completionHandler();
725 }
726}
727
728void NetworkProcess::submitTelemetry(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
729{
730 if (auto* networkSession = this->networkSession(sessionID)) {
731 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
732 resourceLoadStatistics->submitTelemetry(WTFMove(completionHandler));
733 else
734 completionHandler();
735 } else {
736 ASSERT_NOT_REACHED();
737 completionHandler();
738 }
739}
740
741void NetworkProcess::scheduleCookieBlockingUpdate(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
742{
743 if (auto* networkSession = this->networkSession(sessionID)) {
744 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
745 resourceLoadStatistics->scheduleCookieBlockingUpdate(WTFMove(completionHandler));
746 else
747 completionHandler();
748 } else {
749 ASSERT_NOT_REACHED();
750 completionHandler();
751 }
752}
753
754void NetworkProcess::scheduleClearInMemoryAndPersistent(PAL::SessionID sessionID, Optional<WallTime> modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
755{
756 if (auto* networkSession = this->networkSession(sessionID)) {
757 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
758 if (modifiedSince)
759 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince.value(), shouldGrandfather, WTFMove(completionHandler));
760 else
761 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(shouldGrandfather, WTFMove(completionHandler));
762 } else
763 completionHandler();
764 } else {
765 ASSERT_NOT_REACHED();
766 completionHandler();
767 }
768}
769
770void NetworkProcess::resetParametersToDefaultValues(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
771{
772 if (auto* networkSession = this->networkSession(sessionID)) {
773 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
774 resourceLoadStatistics->resetParametersToDefaultValues(WTFMove(completionHandler));
775 else
776 completionHandler();
777 } else {
778 ASSERT_NOT_REACHED();
779 completionHandler();
780 }
781}
782
783void NetworkProcess::scheduleStatisticsAndDataRecordsProcessing(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
784{
785 if (auto* networkSession = this->networkSession(sessionID)) {
786 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
787 resourceLoadStatistics->scheduleStatisticsAndDataRecordsProcessing(WTFMove(completionHandler));
788 else
789 completionHandler();
790 } else {
791 ASSERT_NOT_REACHED();
792 completionHandler();
793 }
794}
795
796void NetworkProcess::setNotifyPagesWhenDataRecordsWereScanned(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
797{
798 if (auto* networkSession = this->networkSession(sessionID)) {
799 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
800 resourceLoadStatistics->setNotifyPagesWhenDataRecordsWereScanned(value, WTFMove(completionHandler));
801 else
802 completionHandler();
803 } else {
804 ASSERT_NOT_REACHED();
805 completionHandler();
806 }
807}
808
809void NetworkProcess::setIsRunningResourceLoadStatisticsTest(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
810{
811 if (auto* networkSession = this->networkSession(sessionID)) {
812 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
813 resourceLoadStatistics->setIsRunningTest(value, WTFMove(completionHandler));
814 else
815 completionHandler();
816 } else {
817 ASSERT_NOT_REACHED();
818 completionHandler();
819 }
820}
821
822void NetworkProcess::setNotifyPagesWhenTelemetryWasCaptured(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
823{
824 if (auto* networkSession = this->networkSession(sessionID)) {
825 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
826 resourceLoadStatistics->setNotifyPagesWhenTelemetryWasCaptured(value, WTFMove(completionHandler));
827 else
828 completionHandler();
829 } else {
830 ASSERT_NOT_REACHED();
831 completionHandler();
832 }
833}
834
835void NetworkProcess::setSubframeUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
836{
837 if (auto* networkSession = this->networkSession(sessionID)) {
838 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
839 resourceLoadStatistics->setSubframeUnderTopFrameDomain(subFrameDomain, topFrameDomain, WTFMove(completionHandler));
840 else
841 completionHandler();
842 } else {
843 ASSERT_NOT_REACHED();
844 completionHandler();
845 }
846}
847
848void NetworkProcess::isRegisteredAsRedirectingTo(PAL::SessionID sessionID, const RegistrableDomain& domainRedirectedFrom, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
849{
850 if (auto* networkSession = this->networkSession(sessionID)) {
851 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
852 resourceLoadStatistics->isRegisteredAsRedirectingTo(domainRedirectedFrom, domainRedirectedTo, WTFMove(completionHandler));
853 else
854 completionHandler(false);
855 } else {
856 ASSERT_NOT_REACHED();
857 completionHandler(false);
858 }
859}
860
861void NetworkProcess::isRegisteredAsSubFrameUnder(PAL::SessionID sessionID, const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
862{
863 if (auto* networkSession = this->networkSession(sessionID)) {
864 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
865 resourceLoadStatistics->isRegisteredAsSubFrameUnder(subFrameDomain, topFrameDomain, WTFMove(completionHandler));
866 else
867 completionHandler(false);
868 } else {
869 ASSERT_NOT_REACHED();
870 completionHandler(false);
871 }
872}
873
874void NetworkProcess::setSubresourceUnderTopFrameDomain(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
875{
876 if (auto* networkSession = this->networkSession(sessionID)) {
877 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
878 resourceLoadStatistics->setSubresourceUnderTopFrameDomain(subresourceDomain, topFrameDomain, WTFMove(completionHandler));
879 else
880 completionHandler();
881 } else {
882 ASSERT_NOT_REACHED();
883 completionHandler();
884 }
885}
886
887void NetworkProcess::setSubresourceUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
888{
889 if (auto* networkSession = this->networkSession(sessionID)) {
890 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
891 resourceLoadStatistics->setSubresourceUniqueRedirectTo(subresourceDomain, domainRedirectedTo, WTFMove(completionHandler));
892 else
893 completionHandler();
894 } else {
895 ASSERT_NOT_REACHED();
896 completionHandler();
897 }
898}
899
900void NetworkProcess::setSubresourceUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
901{
902 if (auto* networkSession = this->networkSession(sessionID)) {
903 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
904 resourceLoadStatistics->setSubresourceUniqueRedirectFrom(subresourceDomain, domainRedirectedFrom, WTFMove(completionHandler));
905 else
906 completionHandler();
907 } else {
908 ASSERT_NOT_REACHED();
909 completionHandler();
910 }
911}
912
913void NetworkProcess::isRegisteredAsSubresourceUnder(PAL::SessionID sessionID, const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
914{
915 if (auto* networkSession = this->networkSession(sessionID)) {
916 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
917 resourceLoadStatistics->isRegisteredAsSubresourceUnder(subresourceDomain, topFrameDomain, WTFMove(completionHandler));
918 else
919 completionHandler(false);
920 } else {
921 ASSERT_NOT_REACHED();
922 completionHandler(false);
923 }
924}
925
926void NetworkProcess::setTopFrameUniqueRedirectTo(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
927{
928 if (auto* networkSession = this->networkSession(sessionID)) {
929 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
930 resourceLoadStatistics->setTopFrameUniqueRedirectTo(topFrameDomain, domainRedirectedTo, WTFMove(completionHandler));
931 else
932 completionHandler();
933 } else {
934 ASSERT_NOT_REACHED();
935 completionHandler();
936 }
937}
938
939void NetworkProcess::setTopFrameUniqueRedirectFrom(PAL::SessionID sessionID, const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
940{
941 if (auto* networkSession = this->networkSession(sessionID)) {
942 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
943 resourceLoadStatistics->setTopFrameUniqueRedirectFrom(topFrameDomain, domainRedirectedFrom, WTFMove(completionHandler));
944 else
945 completionHandler();
946 } else {
947 ASSERT_NOT_REACHED();
948 completionHandler();
949 }
950}
951
952
953void NetworkProcess::setLastSeen(PAL::SessionID sessionID, const RegistrableDomain& domain, Seconds seconds, CompletionHandler<void()>&& completionHandler)
954{
955 if (auto* networkSession = this->networkSession(sessionID)) {
956 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
957 resourceLoadStatistics->setLastSeen(domain, seconds, WTFMove(completionHandler));
958 else
959 completionHandler();
960 } else {
961 ASSERT_NOT_REACHED();
962 completionHandler();
963 }
964}
965
966void NetworkProcess::getAllStorageAccessEntries(PAL::SessionID sessionID, CompletionHandler<void(Vector<String> domains)>&& completionHandler)
967{
968 if (auto* networkStorageSession = storageSession(sessionID))
969 completionHandler(networkStorageSession->getAllStorageAccessEntries());
970 else {
971 ASSERT_NOT_REACHED();
972 completionHandler({ });
973 }
974}
975
976void NetworkProcess::logFrameNavigation(PAL::SessionID sessionID, const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, const RegistrableDomain& sourceDomain, bool isRedirect, bool isMainFrame)
977{
978 if (auto* networkSession = this->networkSession(sessionID)) {
979 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
980 resourceLoadStatistics->logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, isMainFrame);
981 } else
982 ASSERT_NOT_REACHED();
983}
984
985void NetworkProcess::logUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
986{
987 if (auto* networkSession = this->networkSession(sessionID)) {
988 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
989 resourceLoadStatistics->logUserInteraction(domain, WTFMove(completionHandler));
990 else
991 completionHandler();
992 } else {
993 ASSERT_NOT_REACHED();
994 completionHandler();
995 }
996}
997
998void NetworkProcess::hadUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
999{
1000 if (auto* networkSession = this->networkSession(sessionID)) {
1001 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1002 resourceLoadStatistics->hasHadUserInteraction(domain, WTFMove(completionHandler));
1003 else
1004 completionHandler(false);
1005 } else {
1006 ASSERT_NOT_REACHED();
1007 completionHandler(false);
1008 }
1009}
1010
1011void NetworkProcess::clearUserInteraction(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
1012{
1013 if (auto* networkSession = this->networkSession(sessionID)) {
1014 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1015 resourceLoadStatistics->clearUserInteraction(domain, WTFMove(completionHandler));
1016 else
1017 completionHandler();
1018 } else {
1019 ASSERT_NOT_REACHED();
1020 completionHandler();
1021 }
1022}
1023
1024void NetworkProcess::hasLocalStorage(PAL::SessionID sessionID, const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
1025{
1026 if (auto* session = networkSession(sessionID)) {
1027 session->storageManager().getLocalStorageOrigins([domain, completionHandler = WTFMove(completionHandler)](auto&& origins) mutable {
1028 completionHandler(WTF::anyOf(origins, [&domain](auto& origin) {
1029 return domain.matches(origin);
1030 }));
1031 });
1032 return;
1033 }
1034 completionHandler(false);
1035}
1036
1037void NetworkProcess::removePrevalentDomains(PAL::SessionID sessionID, const Vector<RegistrableDomain>& domains)
1038{
1039 if (auto* networkStorageSession = storageSession(sessionID))
1040 networkStorageSession->removePrevalentDomains(domains);
1041}
1042
1043void NetworkProcess::setCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1044{
1045 if (auto* networkStorageSession = storageSession(sessionID))
1046 networkStorageSession->setCacheMaxAgeCapForPrevalentResources(Seconds { seconds });
1047 else
1048 ASSERT_NOT_REACHED();
1049 completionHandler();
1050}
1051
1052void NetworkProcess::setGrandfatheringTime(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1053{
1054 if (auto* networkSession = this->networkSession(sessionID)) {
1055 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1056 resourceLoadStatistics->setGrandfatheringTime(seconds, WTFMove(completionHandler));
1057 else
1058 completionHandler();
1059 } else {
1060 ASSERT_NOT_REACHED();
1061 completionHandler();
1062 }
1063}
1064
1065void NetworkProcess::setMaxStatisticsEntries(PAL::SessionID sessionID, uint64_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
1066{
1067 if (auto* networkSession = this->networkSession(sessionID)) {
1068 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1069 resourceLoadStatistics->setMaxStatisticsEntries(maximumEntryCount, WTFMove(completionHandler));
1070 else
1071 completionHandler();
1072 } else {
1073 ASSERT_NOT_REACHED();
1074 completionHandler();
1075 }
1076}
1077
1078void NetworkProcess::setMinimumTimeBetweenDataRecordsRemoval(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1079{
1080 if (auto* networkSession = this->networkSession(sessionID)) {
1081 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1082 resourceLoadStatistics->setMinimumTimeBetweenDataRecordsRemoval(seconds, WTFMove(completionHandler));
1083 else
1084 completionHandler();
1085 } else {
1086 ASSERT_NOT_REACHED();
1087 completionHandler();
1088 }
1089}
1090
1091void NetworkProcess::setPruneEntriesDownTo(PAL::SessionID sessionID, uint64_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
1092{
1093 if (auto* networkSession = this->networkSession(sessionID)) {
1094 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1095 resourceLoadStatistics->setPruneEntriesDownTo(pruneTargetCount, WTFMove(completionHandler));
1096 else
1097 completionHandler();
1098 } else {
1099 ASSERT_NOT_REACHED();
1100 completionHandler();
1101 }
1102}
1103
1104void NetworkProcess::setTimeToLiveUserInteraction(PAL::SessionID sessionID, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1105{
1106 if (auto* networkSession = this->networkSession(sessionID)) {
1107 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1108 resourceLoadStatistics->setTimeToLiveUserInteraction(seconds, WTFMove(completionHandler));
1109 else
1110 completionHandler();
1111 } else {
1112 ASSERT_NOT_REACHED();
1113 completionHandler();
1114 }
1115}
1116
1117void NetworkProcess::setShouldClassifyResourcesBeforeDataRecordsRemoval(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
1118{
1119 if (auto* networkSession = this->networkSession(sessionID)) {
1120 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1121 resourceLoadStatistics->setShouldClassifyResourcesBeforeDataRecordsRemoval(value, WTFMove(completionHandler));
1122 else
1123 completionHandler();
1124 } else {
1125 ASSERT_NOT_REACHED();
1126 completionHandler();
1127 }
1128}
1129
1130void NetworkProcess::setResourceLoadStatisticsEnabled(bool enabled)
1131{
1132 for (auto& networkSession : m_networkSessions.values())
1133 networkSession.get().setResourceLoadStatisticsEnabled(enabled);
1134}
1135
1136void NetworkProcess::setResourceLoadStatisticsDebugMode(PAL::SessionID sessionID, bool debugMode, CompletionHandler<void()>&& completionHandler)
1137{
1138 if (auto* networkSession = this->networkSession(sessionID)) {
1139 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1140 resourceLoadStatistics->setResourceLoadStatisticsDebugMode(debugMode, WTFMove(completionHandler));
1141 else
1142 completionHandler();
1143 } else {
1144 ASSERT_NOT_REACHED();
1145 completionHandler();
1146 }
1147}
1148
1149void NetworkProcess::resetCacheMaxAgeCapForPrevalentResources(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1150{
1151 if (auto* networkStorageSession = storageSession(sessionID))
1152 networkStorageSession->resetCacheMaxAgeCapForPrevalentResources();
1153 else
1154 ASSERT_NOT_REACHED();
1155 completionHandler();
1156}
1157
1158void NetworkProcess::didCommitCrossSiteLoadWithDataTransfer(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, OptionSet<WebCore::CrossSiteNavigationDataTransfer::Flag> navigationDataTransfer, WebCore::PageIdentifier pageID)
1159{
1160 ASSERT(!navigationDataTransfer.isEmpty());
1161
1162 if (auto* networkStorageSession = storageSession(sessionID)) {
1163 if (!networkStorageSession->shouldBlockThirdPartyCookies(fromDomain))
1164 return;
1165
1166 if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration))
1167 networkStorageSession->didCommitCrossSiteLoadWithDataTransferFromPrevalentResource(toDomain, pageID);
1168
1169 if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::ReferrerLinkDecoration))
1170 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCommitCrossSiteLoadWithDataTransferFromPrevalentResource(pageID), 0);
1171 } else
1172 ASSERT_NOT_REACHED();
1173
1174 if (navigationDataTransfer.contains(CrossSiteNavigationDataTransfer::Flag::DestinationLinkDecoration)) {
1175 if (auto* networkSession = this->networkSession(sessionID)) {
1176 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1177 resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, [] { });
1178 } else
1179 ASSERT_NOT_REACHED();
1180 }
1181}
1182
1183void NetworkProcess::setCrossSiteLoadWithLinkDecorationForTesting(PAL::SessionID sessionID, const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
1184{
1185 if (auto* networkSession = this->networkSession(sessionID)) {
1186 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics())
1187 resourceLoadStatistics->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain, WTFMove(completionHandler));
1188 else
1189 completionHandler();
1190 } else {
1191 ASSERT_NOT_REACHED();
1192 completionHandler();
1193 }
1194}
1195
1196void NetworkProcess::resetCrossSiteLoadsWithLinkDecorationForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
1197{
1198 if (auto* networkStorageSession = storageSession(sessionID))
1199 networkStorageSession->resetCrossSiteLoadsWithLinkDecorationForTesting();
1200 else
1201 ASSERT_NOT_REACHED();
1202 completionHandler();
1203}
1204#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1205
1206bool NetworkProcess::sessionIsControlledByAutomation(PAL::SessionID sessionID) const
1207{
1208 return m_sessionsControlledByAutomation.contains(sessionID);
1209}
1210
1211void NetworkProcess::setSessionIsControlledByAutomation(PAL::SessionID sessionID, bool controlled)
1212{
1213 if (controlled)
1214 m_sessionsControlledByAutomation.add(sessionID);
1215 else
1216 m_sessionsControlledByAutomation.remove(sessionID);
1217}
1218
1219static void fetchDiskCacheEntries(NetworkCache::Cache* cache, PAL::SessionID sessionID, OptionSet<WebsiteDataFetchOption> fetchOptions, CompletionHandler<void(Vector<WebsiteData::Entry>)>&& completionHandler)
1220{
1221 if (!cache) {
1222 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
1223 completionHandler({ });
1224 });
1225 return;
1226 }
1227
1228 HashMap<SecurityOriginData, uint64_t> originsAndSizes;
1229 cache->traverse([fetchOptions, completionHandler = WTFMove(completionHandler), originsAndSizes = WTFMove(originsAndSizes)](auto* traversalEntry) mutable {
1230 if (!traversalEntry) {
1231 Vector<WebsiteData::Entry> entries;
1232
1233 for (auto& originAndSize : originsAndSizes)
1234 entries.append(WebsiteData::Entry { originAndSize.key, WebsiteDataType::DiskCache, originAndSize.value });
1235
1236 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), entries = WTFMove(entries)] () mutable {
1237 completionHandler(entries);
1238 });
1239
1240 return;
1241 }
1242
1243 auto url = traversalEntry->entry.response().url();
1244 auto result = originsAndSizes.add({url.protocol().toString(), url.host().toString(), url.port()}, 0);
1245
1246 if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes))
1247 result.iterator->value += traversalEntry->entry.sourceStorageRecord().header.size() + traversalEntry->recordInfo.bodySize;
1248 });
1249}
1250
1251void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, uint64_t callbackID)
1252{
1253 struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1254 explicit CallbackAggregator(Function<void (WebsiteData)>&& completionHandler)
1255 : m_completionHandler(WTFMove(completionHandler))
1256 {
1257 }
1258
1259 ~CallbackAggregator()
1260 {
1261 RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1262 completionHandler(websiteData);
1263 });
1264 }
1265
1266 CompletionHandler<void(WebsiteData)> m_completionHandler;
1267 WebsiteData m_websiteData;
1268 };
1269
1270 auto callbackAggregator = adoptRef(*new CallbackAggregator([this, callbackID] (WebsiteData websiteData) {
1271 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidFetchWebsiteData(callbackID, websiteData), 0);
1272 }));
1273
1274 if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1275 if (auto* networkStorageSession = storageSession(sessionID))
1276 networkStorageSession->getHostnamesWithCookies(callbackAggregator->m_websiteData.hostNamesWithCookies);
1277 }
1278
1279 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1280 if (storageSession(sessionID)) {
1281 auto securityOrigins = storageSession(sessionID)->credentialStorage().originsWithCredentials();
1282 for (auto& securityOrigin : securityOrigins)
1283 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1284 }
1285 }
1286
1287 if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1288 CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1289 callbackAggregator->m_websiteData.entries.appendVector(entries);
1290 });
1291 }
1292
1293 auto* session = networkSession(sessionID);
1294 if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session) {
1295 session->storageManager().getSessionStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1296 while (!origins.isEmpty())
1297 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 });
1298 });
1299 }
1300
1301 if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session) {
1302 session->storageManager().getLocalStorageOrigins([callbackAggregator = callbackAggregator.copyRef()](auto&& origins) {
1303 while (!origins.isEmpty())
1304 callbackAggregator->m_websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 });
1305 });
1306 }
1307
1308#if PLATFORM(COCOA)
1309 if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1310 if (auto* networkStorageSession = storageSession(sessionID))
1311 getHostNamesWithHSTSCache(*networkStorageSession, callbackAggregator->m_websiteData.hostNamesWithHSTSCache);
1312 }
1313#endif
1314
1315#if ENABLE(INDEXED_DATABASE)
1316 auto path = m_idbDatabasePaths.get(sessionID);
1317 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1318 // FIXME: Pick the right database store based on the session ID.
1319 postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
1320 RunLoop::main().dispatch([callbackAggregator = WTFMove(callbackAggregator), securityOrigins = indexedDatabaseOrigins(path)] {
1321 for (const auto& securityOrigin : securityOrigins)
1322 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1323 });
1324 }));
1325 }
1326#endif
1327
1328#if ENABLE(SERVICE_WORKER)
1329 path = m_swDatabasePaths.get(sessionID);
1330 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1331 swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1332 for (auto& origin : securityOrigins)
1333 callbackAggregator->m_websiteData.entries.append({ origin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1334 });
1335 }
1336#endif
1337
1338 if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1339 fetchDiskCacheEntries(cache(), sessionID, fetchOptions, [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
1340 callbackAggregator->m_websiteData.entries.appendVector(entries);
1341 });
1342 }
1343}
1344
1345void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, uint64_t callbackID)
1346{
1347#if PLATFORM(COCOA)
1348 if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1349 if (auto* networkStorageSession = storageSession(sessionID))
1350 clearHSTSCache(*networkStorageSession, modifiedSince);
1351 }
1352#endif
1353
1354 if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1355 if (auto* networkStorageSession = storageSession(sessionID))
1356 networkStorageSession->deleteAllCookiesModifiedSince(modifiedSince);
1357 }
1358
1359 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1360 if (auto* session = storageSession(sessionID))
1361 session->credentialStorage().clearCredentials();
1362 }
1363
1364 auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1365 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
1366 });
1367
1368 if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
1369 CacheStorage::Engine::clearAllCaches(*this, sessionID, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1370
1371 auto* session = networkSession(sessionID);
1372 if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
1373 session->storageManager().deleteSessionStorageOrigins([clearTasksHandler = clearTasksHandler.copyRef()] { });
1374
1375 if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
1376 session->storageManager().deleteLocalStorageOriginsModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1377
1378#if ENABLE(INDEXED_DATABASE)
1379 if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1380 idbServer(sessionID).closeAndDeleteDatabasesModifiedSince(modifiedSince, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1381#endif
1382
1383#if ENABLE(SERVICE_WORKER)
1384 if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral())
1385 swServerForSession(sessionID).clearAll([clearTasksHandler = clearTasksHandler.copyRef()] { });
1386#endif
1387
1388#if ENABLE(RESOURCE_LOAD_STATISTICS)
1389 if (websiteDataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
1390 if (auto* networkSession = this->networkSession(sessionID)) {
1391 if (auto* resourceLoadStatistics = networkSession->resourceLoadStatistics()) {
1392 auto deletedTypesRaw = websiteDataTypes.toRaw();
1393 auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
1394
1395 // If we are deleting all of the data types that the resource load statistics store monitors
1396 // we do not need to re-grandfather old data.
1397 auto shouldGrandfather = ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw) ? ShouldGrandfatherStatistics::No : ShouldGrandfatherStatistics::Yes;
1398
1399 resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, shouldGrandfather, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1400 }
1401 }
1402 }
1403#endif
1404
1405 if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
1406 clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
1407
1408 if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) || websiteDataTypes.contains(WebsiteDataType::DOMCache))
1409 clearStorageQuota(sessionID);
1410
1411 if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1412 if (auto* networkSession = this->networkSession(sessionID))
1413 networkSession->clearAdClickAttribution();
1414 }
1415}
1416
1417static void clearDiskCacheEntries(NetworkCache::Cache* cache, const Vector<SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
1418{
1419 if (!cache) {
1420 RunLoop::main().dispatch(WTFMove(completionHandler));
1421 return;
1422 }
1423
1424 HashSet<RefPtr<SecurityOrigin>> originsToDelete;
1425 for (auto& origin : origins)
1426 originsToDelete.add(origin.securityOrigin());
1427
1428 Vector<NetworkCache::Key> cacheKeysToDelete;
1429 cache->traverse([cache, completionHandler = WTFMove(completionHandler), originsToDelete = WTFMove(originsToDelete), cacheKeysToDelete = WTFMove(cacheKeysToDelete)](auto* traversalEntry) mutable {
1430 if (traversalEntry) {
1431 if (originsToDelete.contains(SecurityOrigin::create(traversalEntry->entry.response().url())))
1432 cacheKeysToDelete.append(traversalEntry->entry.key());
1433 return;
1434 }
1435
1436 cache->remove(cacheKeysToDelete, WTFMove(completionHandler));
1437 return;
1438 });
1439}
1440
1441void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, const Vector<String>& HSTSCacheHostNames, uint64_t callbackID)
1442{
1443 if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1444 if (auto* networkStorageSession = storageSession(sessionID))
1445 networkStorageSession->deleteCookiesForHostnames(cookieHostNames);
1446 }
1447
1448#if PLATFORM(COCOA)
1449 if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1450 if (auto* networkStorageSession = storageSession(sessionID))
1451 deleteHSTSCacheForHostNames(*networkStorageSession, HSTSCacheHostNames);
1452 }
1453#endif
1454
1455 if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
1456 if (auto* networkSession = this->networkSession(sessionID)) {
1457 for (auto& originData : originDatas)
1458 networkSession->clearAdClickAttributionForRegistrableDomain(RegistrableDomain::uncheckedCreateFromHost(originData.host));
1459 }
1460 }
1461
1462 auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
1463 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
1464 });
1465
1466 if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1467 for (auto& originData : originDatas)
1468 CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { originData }, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1469 }
1470
1471 auto* session = networkSession(sessionID);
1472 if (websiteDataTypes.contains(WebsiteDataType::SessionStorage) && session)
1473 session->storageManager().deleteSessionStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1474
1475 if (websiteDataTypes.contains(WebsiteDataType::LocalStorage) && session)
1476 session->storageManager().deleteLocalStorageEntriesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1477
1478#if ENABLE(INDEXED_DATABASE)
1479 if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !sessionID.isEphemeral())
1480 idbServer(sessionID).closeAndDeleteDatabasesForOrigins(originDatas, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1481#endif
1482
1483#if ENABLE(SERVICE_WORKER)
1484 if (websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !sessionID.isEphemeral()) {
1485 auto& server = swServerForSession(sessionID);
1486 for (auto& originData : originDatas)
1487 server.clear(originData, [clearTasksHandler = clearTasksHandler.copyRef()] { });
1488 }
1489#endif
1490
1491 if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
1492 clearDiskCacheEntries(cache(), originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
1493
1494 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1495 if (auto* session = storageSession(sessionID)) {
1496 for (auto& originData : originDatas)
1497 session->credentialStorage().removeCredentialsWithOrigin(originData);
1498 }
1499 }
1500
1501 // FIXME: Implement storage quota clearing for these origins.
1502}
1503
1504void NetworkProcess::clearStorageQuota(PAL::SessionID sessionID)
1505{
1506 auto iterator = m_storageQuotaManagers.find(sessionID);
1507 if (iterator == m_storageQuotaManagers.end())
1508 return;
1509
1510 auto& managers = iterator->value;
1511 for (auto& manager : managers.managersPerOrigin())
1512 manager.value->resetQuota(managers.defaultQuota(manager.key));
1513}
1514
1515#if ENABLE(RESOURCE_LOAD_STATISTICS)
1516static Vector<String> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const HashSet<String>& foundValues)
1517{
1518 Vector<String> result;
1519 for (const auto& value : foundValues) {
1520 if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value)))
1521 result.append(value);
1522 }
1523
1524 return result;
1525}
1526
1527static Vector<WebsiteData::Entry> filterForRegistrableDomains(const Vector<RegistrableDomain>& registrableDomains, const Vector<WebsiteData::Entry>& foundValues)
1528{
1529 Vector<WebsiteData::Entry> result;
1530 for (const auto& value : foundValues) {
1531 if (registrableDomains.contains(RegistrableDomain::uncheckedCreateFromHost(value.origin.host)))
1532 result.append(value);
1533 }
1534
1535 return result;
1536}
1537
1538static Vector<WebCore::SecurityOriginData> filterForRegistrableDomains(const HashSet<WebCore::SecurityOriginData>& origins, const Vector<RegistrableDomain>& domainsToDelete, HashSet<RegistrableDomain>& domainsDeleted)
1539{
1540 Vector<SecurityOriginData> originsDeleted;
1541 for (const auto& origin : origins) {
1542 auto domain = RegistrableDomain::uncheckedCreateFromHost(origin.host);
1543 if (!domainsToDelete.contains(domain))
1544 continue;
1545 originsDeleted.append(origin);
1546 domainsDeleted.add(domain);
1547 }
1548
1549 return originsDeleted;
1550}
1551
1552void NetworkProcess::deleteWebsiteDataForRegistrableDomains(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domains, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1553{
1554 OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1555
1556 struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1557 explicit CallbackAggregator(CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1558 : m_completionHandler(WTFMove(completionHandler))
1559 {
1560 }
1561
1562 ~CallbackAggregator()
1563 {
1564 RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), domains = WTFMove(m_domains)] () mutable {
1565 completionHandler(domains);
1566 });
1567 }
1568
1569 CompletionHandler<void(const HashSet<RegistrableDomain>&)> m_completionHandler;
1570 HashSet<RegistrableDomain> m_domains;
1571 };
1572
1573 auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (const HashSet<RegistrableDomain>& domainsWithData) mutable {
1574 if (shouldNotifyPage)
1575 parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataDeletionForRegistrableDomainsFinished(), 0);
1576
1577 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1578 completionHandler(domainsWithData);
1579 });
1580 }));
1581
1582 HashSet<String> hostNamesWithCookies;
1583 HashSet<String> hostNamesWithHSTSCache;
1584
1585 Vector<RegistrableDomain> domainsToDeleteCookiesFor;
1586 Vector<RegistrableDomain> domainsToDeleteAllButHttpOnlyCookiesFor;
1587 Vector<RegistrableDomain> domainsToDeleteAllButCookiesFor;
1588 Vector<String> hostnamesWithCookiesToDelete;
1589 if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1590 for (auto& domain : domains.keys()) {
1591 domainsToDeleteAllButCookiesFor.append(domain);
1592 switch (domains.get(domain)) {
1593 case WebsiteDataToRemove::All:
1594 domainsToDeleteCookiesFor.append(domain);
1595 break;
1596 case WebsiteDataToRemove::AllButHttpOnlyCookies:
1597 domainsToDeleteAllButHttpOnlyCookiesFor.append(domain);
1598 break;
1599 case WebsiteDataToRemove::AllButCookies:
1600 // Already added.
1601 break;
1602 }
1603 }
1604 if (auto* networkStorageSession = storageSession(sessionID)) {
1605 networkStorageSession->getHostnamesWithCookies(hostNamesWithCookies);
1606
1607 hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteCookiesFor, hostNamesWithCookies);
1608 networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::Yes);
1609
1610 for (const auto& host : hostnamesWithCookiesToDelete)
1611 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1612
1613 hostnamesWithCookiesToDelete = filterForRegistrableDomains(domainsToDeleteAllButHttpOnlyCookiesFor, hostNamesWithCookies);
1614 networkStorageSession->deleteCookiesForHostnames(hostnamesWithCookiesToDelete, WebCore::IncludeHttpOnlyCookies::No);
1615
1616 for (const auto& host : hostnamesWithCookiesToDelete)
1617 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1618 }
1619 } else {
1620 for (auto& domain : domains.keys())
1621 domainsToDeleteAllButCookiesFor.append(domain);
1622 }
1623
1624 Vector<String> hostnamesWithHSTSToDelete;
1625#if PLATFORM(COCOA)
1626 if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1627 if (auto* networkStorageSession = storageSession(sessionID)) {
1628 getHostNamesWithHSTSCache(*networkStorageSession, hostNamesWithHSTSCache);
1629 hostnamesWithHSTSToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, hostNamesWithHSTSCache);
1630
1631 for (const auto& host : hostnamesWithHSTSToDelete)
1632 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(host));
1633
1634 deleteHSTSCacheForHostNames(*networkStorageSession, hostnamesWithHSTSToDelete);
1635 }
1636 }
1637#endif
1638
1639 /*
1640 // FIXME: No API to delete credentials by origin
1641 HashSet<String> originsWithCredentials;
1642 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1643 if (storageSession(sessionID))
1644 originsWithCredentials = storageSession(sessionID)->credentialStorage().originsWithCredentials();
1645 }
1646 */
1647
1648 if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1649 CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [this, domainsToDeleteAllButCookiesFor, sessionID, callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1650
1651 auto entriesToDelete = filterForRegistrableDomains(domainsToDeleteAllButCookiesFor, entries);
1652
1653 for (const auto& entry : entriesToDelete)
1654 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1655
1656 for (auto& entry : entriesToDelete)
1657 CacheStorage::Engine::clearCachesForOrigin(*this, sessionID, SecurityOriginData { entry.origin }, [callbackAggregator = callbackAggregator.copyRef()] { });
1658 });
1659 }
1660
1661 auto* session = networkSession(sessionID);
1662 if (session) {
1663 auto& storageManager = session->storageManager();
1664 if (websiteDataTypes.contains(WebsiteDataType::SessionStorage)) {
1665 storageManager.getSessionStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1666 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1667 storageManager->deleteSessionStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1668 });
1669 }
1670
1671 if (websiteDataTypes.contains(WebsiteDataType::LocalStorage)) {
1672 storageManager.getLocalStorageOrigins([storageManager = makeRefPtr(storageManager), callbackAggregator = callbackAggregator.copyRef(), domainsToDeleteAllButCookiesFor](auto&& origins) {
1673 auto originsToDelete = filterForRegistrableDomains(origins, domainsToDeleteAllButCookiesFor, callbackAggregator->m_domains);
1674 storageManager->deleteLocalStorageEntriesForOrigins(originsToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1675 });
1676 }
1677 }
1678
1679#if ENABLE(INDEXED_DATABASE)
1680 auto path = m_idbDatabasePaths.get(sessionID);
1681 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1682 // FIXME: Pick the right database store based on the session ID.
1683 postStorageTask(CrossThreadTask([this, sessionID, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path), domainsToDeleteAllButCookiesFor]() mutable {
1684 RunLoop::main().dispatch([this, sessionID, domainsToDeleteAllButCookiesFor = crossThreadCopy(domainsToDeleteAllButCookiesFor), callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1685 Vector<SecurityOriginData> entriesToDelete;
1686 for (const auto& securityOrigin : securityOrigins) {
1687 auto domain = RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host);
1688 if (!domainsToDeleteAllButCookiesFor.contains(domain))
1689 continue;
1690
1691 entriesToDelete.append(securityOrigin);
1692 callbackAggregator->m_domains.add(domain);
1693 }
1694
1695 idbServer(sessionID).closeAndDeleteDatabasesForOrigins(entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1696 });
1697 }));
1698 }
1699#endif
1700
1701#if ENABLE(SERVICE_WORKER)
1702 path = m_swDatabasePaths.get(sessionID);
1703 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1704 swServerForSession(sessionID).getOriginsWithRegistrations([this, sessionID, domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1705 for (auto& securityOrigin : securityOrigins) {
1706 if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host)))
1707 continue;
1708 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(securityOrigin.host));
1709 swServerForSession(sessionID).clear(securityOrigin, [callbackAggregator = callbackAggregator.copyRef()] { });
1710 }
1711 });
1712 }
1713#endif
1714
1715 if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1716 fetchDiskCacheEntries(cache(), sessionID, fetchOptions, [this, domainsToDeleteAllButCookiesFor, callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1717
1718 Vector<SecurityOriginData> entriesToDelete;
1719 for (auto& entry : entries) {
1720 if (!domainsToDeleteAllButCookiesFor.contains(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host)))
1721 continue;
1722 entriesToDelete.append(entry.origin);
1723 callbackAggregator->m_domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1724 }
1725 clearDiskCacheEntries(cache(), entriesToDelete, [callbackAggregator = callbackAggregator.copyRef()] { });
1726 });
1727 }
1728
1729 auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
1730 if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllButCookiesFor.isEmpty()) {
1731 CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator = callbackAggregator.copyRef()] (const HashSet<RegistrableDomain>& domains) {
1732 for (auto& domain : domains)
1733 callbackAggregator->m_domains.add(domain);
1734 };
1735 parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::DeleteWebsiteDataInUIProcessForRegistrableDomains(sessionID, dataTypesForUIProcess, fetchOptions, domainsToDeleteAllButCookiesFor), WTFMove(completionHandler));
1736 }
1737}
1738
1739void NetworkProcess::deleteCookiesForTesting(PAL::SessionID sessionID, RegistrableDomain domain, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1740{
1741 OptionSet<WebsiteDataType> cookieType = WebsiteDataType::Cookies;
1742 HashMap<RegistrableDomain, WebsiteDataToRemove> toDeleteFor;
1743 toDeleteFor.add(domain, includeHttpOnlyCookies ? WebsiteDataToRemove::All : WebsiteDataToRemove::AllButHttpOnlyCookies);
1744 deleteWebsiteDataForRegistrableDomains(sessionID, cookieType, WTFMove(toDeleteFor), true, [completionHandler = WTFMove(completionHandler)] (const HashSet<RegistrableDomain>& domainsDeletedFor) mutable {
1745 UNUSED_PARAM(domainsDeletedFor);
1746 completionHandler();
1747 });
1748}
1749
1750void NetworkProcess::registrableDomainsWithWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1751{
1752 OptionSet<WebsiteDataFetchOption> fetchOptions = WebsiteDataFetchOption::DoNotCreateProcesses;
1753
1754 struct CallbackAggregator final : public ThreadSafeRefCounted<CallbackAggregator> {
1755 explicit CallbackAggregator(CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1756 : m_completionHandler(WTFMove(completionHandler))
1757 {
1758 }
1759
1760 ~CallbackAggregator()
1761 {
1762 RunLoop::main().dispatch([completionHandler = WTFMove(m_completionHandler), websiteData = WTFMove(m_websiteData)] () mutable {
1763 HashSet<RegistrableDomain> domains;
1764 for (const auto& hostnameWithCookies : websiteData.hostNamesWithCookies)
1765 domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithCookies));
1766
1767 for (const auto& hostnameWithHSTS : websiteData.hostNamesWithHSTSCache)
1768 domains.add(RegistrableDomain::uncheckedCreateFromHost(hostnameWithHSTS));
1769
1770 for (const auto& entry : websiteData.entries)
1771 domains.add(RegistrableDomain::uncheckedCreateFromHost(entry.origin.host));
1772
1773 completionHandler(WTFMove(domains));
1774 });
1775 }
1776
1777 CompletionHandler<void(HashSet<RegistrableDomain>&&)> m_completionHandler;
1778 WebsiteData m_websiteData;
1779 };
1780
1781 auto callbackAggregator = adoptRef(*new CallbackAggregator([this, completionHandler = WTFMove(completionHandler), shouldNotifyPage] (HashSet<RegistrableDomain>&& domainsWithData) mutable {
1782 if (shouldNotifyPage)
1783 parentProcessConnection()->send(Messages::NetworkProcessProxy::NotifyWebsiteDataScanForRegistrableDomainsFinished(), 0);
1784
1785 RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), domainsWithData = crossThreadCopy(domainsWithData)] () mutable {
1786 completionHandler(WTFMove(domainsWithData));
1787 });
1788 }));
1789
1790 auto& websiteDataStore = callbackAggregator->m_websiteData;
1791
1792 Vector<String> hostnamesWithCookiesToDelete;
1793 if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
1794 if (auto* networkStorageSession = storageSession(sessionID))
1795 networkStorageSession->getHostnamesWithCookies(websiteDataStore.hostNamesWithCookies);
1796 }
1797
1798 Vector<String> hostnamesWithHSTSToDelete;
1799#if PLATFORM(COCOA)
1800 if (websiteDataTypes.contains(WebsiteDataType::HSTSCache)) {
1801 if (auto* networkStorageSession = storageSession(sessionID))
1802 getHostNamesWithHSTSCache(*networkStorageSession, websiteDataStore.hostNamesWithHSTSCache);
1803 }
1804#endif
1805
1806 if (websiteDataTypes.contains(WebsiteDataType::Credentials)) {
1807 if (auto* networkStorageSession = storageSession(sessionID)) {
1808 auto securityOrigins = networkStorageSession->credentialStorage().originsWithCredentials();
1809 for (auto& securityOrigin : securityOrigins)
1810 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::Credentials, 0 });
1811 }
1812 }
1813
1814 if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
1815 CacheStorage::Engine::fetchEntries(*this, sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1816 callbackAggregator->m_websiteData.entries.appendVector(entries);
1817 });
1818 }
1819
1820#if ENABLE(INDEXED_DATABASE)
1821 auto path = m_idbDatabasePaths.get(sessionID);
1822 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases)) {
1823 // FIXME: Pick the right database store based on the session ID.
1824 postStorageTask(CrossThreadTask([this, callbackAggregator = callbackAggregator.copyRef(), path = WTFMove(path)]() mutable {
1825 RunLoop::main().dispatch([callbackAggregator = callbackAggregator.copyRef(), securityOrigins = indexedDatabaseOrigins(path)] {
1826 for (const auto& securityOrigin : securityOrigins)
1827 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::IndexedDBDatabases, 0 });
1828 });
1829 }));
1830 }
1831#endif
1832
1833#if ENABLE(SERVICE_WORKER)
1834 path = m_swDatabasePaths.get(sessionID);
1835 if (!path.isEmpty() && websiteDataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations)) {
1836 swServerForSession(sessionID).getOriginsWithRegistrations([callbackAggregator = callbackAggregator.copyRef()](const HashSet<SecurityOriginData>& securityOrigins) mutable {
1837 for (auto& securityOrigin : securityOrigins)
1838 callbackAggregator->m_websiteData.entries.append({ securityOrigin, WebsiteDataType::ServiceWorkerRegistrations, 0 });
1839 });
1840 }
1841#endif
1842
1843 if (websiteDataTypes.contains(WebsiteDataType::DiskCache)) {
1844 fetchDiskCacheEntries(cache(), sessionID, fetchOptions, [callbackAggregator = callbackAggregator.copyRef()](auto entries) mutable {
1845 callbackAggregator->m_websiteData.entries.appendVector(entries);
1846 });
1847 }
1848}
1849#endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1850
1851CacheStorage::Engine* NetworkProcess::findCacheEngine(const PAL::SessionID& sessionID)
1852{
1853 return m_cacheEngines.get(sessionID);
1854}
1855
1856CacheStorage::Engine& NetworkProcess::ensureCacheEngine(const PAL::SessionID& sessionID, Function<Ref<CacheStorage::Engine>()>&& functor)
1857{
1858 return m_cacheEngines.ensure(sessionID, WTFMove(functor)).iterator->value;
1859}
1860
1861void NetworkProcess::removeCacheEngine(const PAL::SessionID& sessionID)
1862{
1863 m_cacheEngines.remove(sessionID);
1864}
1865
1866void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
1867{
1868 downloadManager().startDownload(sessionID, downloadID, request, suggestedFilename);
1869}
1870
1871void NetworkProcess::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, WebKit::SandboxExtension::Handle&& sandboxExtensionHandle)
1872{
1873 downloadManager().resumeDownload(sessionID, downloadID, resumeData, path, WTFMove(sandboxExtensionHandle));
1874}
1875
1876void NetworkProcess::cancelDownload(DownloadID downloadID)
1877{
1878 downloadManager().cancelDownload(downloadID);
1879}
1880
1881#if PLATFORM(COCOA)
1882void NetworkProcess::publishDownloadProgress(DownloadID downloadID, const URL& url, SandboxExtension::Handle&& sandboxExtensionHandle)
1883{
1884 downloadManager().publishDownloadProgress(downloadID, url, WTFMove(sandboxExtensionHandle));
1885}
1886#endif
1887
1888void NetworkProcess::continueWillSendRequest(DownloadID downloadID, WebCore::ResourceRequest&& request)
1889{
1890 downloadManager().continueWillSendRequest(downloadID, WTFMove(request));
1891}
1892
1893void NetworkProcess::pendingDownloadCanceled(DownloadID downloadID)
1894{
1895 downloadProxyConnection()->send(Messages::DownloadProxy::DidCancel({ }), downloadID.downloadID());
1896}
1897
1898void NetworkProcess::findPendingDownloadLocation(NetworkDataTask& networkDataTask, ResponseCompletionHandler&& completionHandler, const ResourceResponse& response)
1899{
1900 uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
1901 downloadProxyConnection()->send(Messages::DownloadProxy::DidReceiveResponse(response), destinationID);
1902
1903 downloadManager().willDecidePendingDownloadDestination(networkDataTask, WTFMove(completionHandler));
1904
1905 // As per https://html.spec.whatwg.org/#as-a-download (step 2), the filename from the Content-Disposition header
1906 // should override the suggested filename from the download attribute.
1907 String suggestedFilename = response.isAttachmentWithFilename() ? response.suggestedFilename() : networkDataTask.suggestedFilename();
1908 suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType());
1909
1910 downloadProxyConnection()->send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
1911}
1912
1913void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, SandboxExtension::Handle&& sandboxExtensionHandle, bool allowOverwrite)
1914{
1915 if (destination.isEmpty())
1916 downloadManager().cancelDownload(downloadID);
1917 else
1918 downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, WTFMove(sandboxExtensionHandle), allowOverwrite);
1919}
1920
1921void NetworkProcess::setCacheModel(CacheModel cacheModel)
1922{
1923 if (m_hasSetCacheModel && (cacheModel == m_cacheModel))
1924 return;
1925
1926 m_hasSetCacheModel = true;
1927 m_cacheModel = cacheModel;
1928
1929 unsigned urlCacheMemoryCapacity = 0;
1930 uint64_t urlCacheDiskCapacity = 0;
1931 uint64_t diskFreeSize = 0;
1932 if (FileSystem::getVolumeFreeSpace(m_diskCacheDirectory, diskFreeSize)) {
1933 // As a fudge factor, use 1000 instead of 1024, in case the reported byte
1934 // count doesn't align exactly to a megabyte boundary.
1935 diskFreeSize /= KB * 1000;
1936 calculateURLCacheSizes(cacheModel, diskFreeSize, urlCacheMemoryCapacity, urlCacheDiskCapacity);
1937 }
1938
1939 if (m_cache)
1940 m_cache->setCapacity(urlCacheDiskCapacity);
1941}
1942
1943void NetworkProcess::setCanHandleHTTPSServerTrustEvaluation(bool value)
1944{
1945 m_canHandleHTTPSServerTrustEvaluation = value;
1946}
1947
1948void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
1949{
1950 StatisticsData data;
1951
1952 data.statisticsNumbers.set("DownloadsActiveCount", downloadManager().activeDownloadCount());
1953 data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", authenticationManager().outstandingAuthenticationChallengeCount());
1954
1955 parentProcessConnection()->send(Messages::WebProcessPool::DidGetStatistics(data, callbackID), 0);
1956}
1957
1958void NetworkProcess::setAllowsAnySSLCertificateForWebSocket(bool allows, CompletionHandler<void()>&& completionHandler)
1959{
1960 DeprecatedGlobalSettings::setAllowsAnySSLCertificate(allows);
1961 completionHandler();
1962}
1963
1964void NetworkProcess::logDiagnosticMessage(PageIdentifier webPageID, const String& message, const String& description, ShouldSample shouldSample)
1965{
1966 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
1967 return;
1968
1969 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessage(webPageID, message, description, ShouldSample::No), 0);
1970}
1971
1972void NetworkProcess::logDiagnosticMessageWithResult(PageIdentifier webPageID, const String& message, const String& description, DiagnosticLoggingResultType result, ShouldSample shouldSample)
1973{
1974 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
1975 return;
1976
1977 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithResult(webPageID, message, description, result, ShouldSample::No), 0);
1978}
1979
1980void NetworkProcess::logDiagnosticMessageWithValue(PageIdentifier webPageID, const String& message, const String& description, double value, unsigned significantFigures, ShouldSample shouldSample)
1981{
1982 if (!DiagnosticLoggingClient::shouldLogAfterSampling(shouldSample))
1983 return;
1984
1985 parentProcessConnection()->send(Messages::NetworkProcessProxy::LogDiagnosticMessageWithValue(webPageID, message, description, value, significantFigures, ShouldSample::No), 0);
1986}
1987
1988void NetworkProcess::terminate()
1989{
1990 platformTerminate();
1991 AuxiliaryProcess::terminate();
1992}
1993
1994void NetworkProcess::processDidTransitionToForeground()
1995{
1996 platformProcessDidTransitionToForeground();
1997}
1998
1999void NetworkProcess::processDidTransitionToBackground()
2000{
2001 platformProcessDidTransitionToBackground();
2002}
2003
2004// FIXME: We can remove this one by adapting RefCounter.
2005class TaskCounter : public RefCounted<TaskCounter> {
2006public:
2007 explicit TaskCounter(Function<void()>&& callback) : m_callback(WTFMove(callback)) { }
2008 ~TaskCounter() { m_callback(); };
2009
2010private:
2011 Function<void()> m_callback;
2012};
2013
2014void NetworkProcess::actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend shouldAcknowledgeWhenReadyToSuspend)
2015{
2016#if PLATFORM(IOS_FAMILY)
2017 m_webSQLiteDatabaseTracker.setIsSuspended(true);
2018#endif
2019
2020 lowMemoryHandler(Critical::Yes);
2021
2022 RefPtr<TaskCounter> delayedTaskCounter;
2023 if (shouldAcknowledgeWhenReadyToSuspend == ShouldAcknowledgeWhenReadyToSuspend::Yes) {
2024 delayedTaskCounter = adoptRef(new TaskCounter([this] {
2025 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::notifyProcessReadyToSuspend() Sending ProcessReadyToSuspend IPC message", this);
2026 if (parentProcessConnection())
2027 parentProcessConnection()->send(Messages::NetworkProcessProxy::ProcessReadyToSuspend(), 0);
2028 }));
2029 }
2030
2031 platformPrepareToSuspend([delayedTaskCounter] { });
2032 platformSyncAllCookies([delayedTaskCounter] { });
2033
2034 for (auto& connection : m_webProcessConnections)
2035 connection->cleanupForSuspension([delayedTaskCounter] { });
2036
2037#if ENABLE(SERVICE_WORKER)
2038 for (auto& server : m_swServers.values())
2039 server->startSuspension([delayedTaskCounter] { });
2040#endif
2041
2042 for (auto& session : m_networkSessions)
2043 session.value->storageManager().suspend([delayedTaskCounter] { });
2044}
2045
2046void NetworkProcess::processWillSuspendImminently()
2047{
2048 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() BEGIN", this);
2049#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2050 for (auto& server : m_idbServers.values())
2051 server->tryStop(IDBServer::ShouldForceStop::Yes);
2052#endif
2053 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No);
2054 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processWillSuspendImminently() END", this);
2055}
2056
2057void NetworkProcess::prepareToSuspend()
2058{
2059 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this);
2060
2061#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2062 for (auto& server : m_idbServers.values())
2063 server->tryStop(IDBServer::ShouldForceStop::No);
2064#endif
2065 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes);
2066}
2067
2068void NetworkProcess::cancelPrepareToSuspend()
2069{
2070 // Although it is tempting to send a NetworkProcessProxy::DidCancelProcessSuspension message from here
2071 // we do not because prepareToSuspend() already replied with a NetworkProcessProxy::ProcessReadyToSuspend
2072 // message. And NetworkProcessProxy expects to receive either a NetworkProcessProxy::ProcessReadyToSuspend-
2073 // or NetworkProcessProxy::DidCancelProcessSuspension- message, but not both.
2074 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::cancelPrepareToSuspend()", this);
2075 resume();
2076}
2077
2078void NetworkProcess::applicationDidEnterBackground()
2079{
2080 m_downloadManager.applicationDidEnterBackground();
2081}
2082
2083void NetworkProcess::applicationWillEnterForeground()
2084{
2085 m_downloadManager.applicationWillEnterForeground();
2086}
2087
2088void NetworkProcess::processDidResume()
2089{
2090 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::processDidResume()", this);
2091 resume();
2092}
2093
2094void NetworkProcess::resume()
2095{
2096#if PLATFORM(IOS_FAMILY)
2097 m_webSQLiteDatabaseTracker.setIsSuspended(false);
2098#endif
2099
2100 platformProcessDidResume();
2101 for (auto& connection : m_webProcessConnections)
2102 connection->endSuspension();
2103
2104#if ENABLE(SERVICE_WORKER)
2105 for (auto& server : m_swServers.values())
2106 server->endSuspension();
2107#endif
2108#if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE)
2109 for (auto& server : m_idbServers.values())
2110 server->resume();
2111#endif
2112
2113 for (auto& session : m_networkSessions)
2114 session.value->storageManager().resume();
2115}
2116
2117void NetworkProcess::prefetchDNS(const String& hostname)
2118{
2119 WebCore::prefetchDNS(hostname);
2120}
2121
2122void NetworkProcess::cacheStorageRootPath(PAL::SessionID sessionID, CacheStorageRootPathCallback&& callback)
2123{
2124 m_cacheStorageParametersCallbacks.ensure(sessionID, [&] {
2125 parentProcessConnection()->send(Messages::NetworkProcessProxy::RetrieveCacheStorageParameters { sessionID }, 0);
2126 return Vector<CacheStorageRootPathCallback> { };
2127 }).iterator->value.append(WTFMove(callback));
2128}
2129
2130void NetworkProcess::setCacheStorageParameters(PAL::SessionID sessionID, String&& cacheStorageDirectory, SandboxExtension::Handle&& handle)
2131{
2132 auto iterator = m_cacheStorageParametersCallbacks.find(sessionID);
2133 if (iterator == m_cacheStorageParametersCallbacks.end())
2134 return;
2135
2136 SandboxExtension::consumePermanently(handle);
2137 auto callbacks = WTFMove(iterator->value);
2138 m_cacheStorageParametersCallbacks.remove(iterator);
2139 for (auto& callback : callbacks)
2140 callback(String { cacheStorageDirectory });
2141}
2142
2143void NetworkProcess::preconnectTo(const URL& url, WebCore::StoredCredentialsPolicy storedCredentialsPolicy)
2144{
2145#if ENABLE(SERVER_PRECONNECT)
2146 NetworkLoadParameters parameters;
2147 parameters.request = ResourceRequest { url };
2148 parameters.sessionID = PAL::SessionID::defaultSessionID();
2149 parameters.storedCredentialsPolicy = storedCredentialsPolicy;
2150 parameters.shouldPreconnectOnly = PreconnectOnly::Yes;
2151
2152 new PreconnectTask(*this, WTFMove(parameters));
2153#else
2154 UNUSED_PARAM(url);
2155 UNUSED_PARAM(storedCredentialsPolicy);
2156#endif
2157}
2158
2159void NetworkProcess::registerURLSchemeAsSecure(const String& scheme) const
2160{
2161 SchemeRegistry::registerURLSchemeAsSecure(scheme);
2162}
2163
2164void NetworkProcess::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme) const
2165{
2166 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2167}
2168
2169void NetworkProcess::registerURLSchemeAsLocal(const String& scheme) const
2170{
2171 SchemeRegistry::registerURLSchemeAsLocal(scheme);
2172}
2173
2174void NetworkProcess::registerURLSchemeAsNoAccess(const String& scheme) const
2175{
2176 SchemeRegistry::registerURLSchemeAsNoAccess(scheme);
2177}
2178
2179void NetworkProcess::registerURLSchemeAsDisplayIsolated(const String& scheme) const
2180{
2181 SchemeRegistry::registerURLSchemeAsDisplayIsolated(scheme);
2182}
2183
2184void NetworkProcess::registerURLSchemeAsCORSEnabled(const String& scheme) const
2185{
2186 SchemeRegistry::registerURLSchemeAsCORSEnabled(scheme);
2187}
2188
2189void NetworkProcess::registerURLSchemeAsCanDisplayOnlyIfCanRequest(const String& scheme) const
2190{
2191 SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(scheme);
2192}
2193
2194void NetworkProcess::didSyncAllCookies()
2195{
2196 parentProcessConnection()->send(Messages::NetworkProcessProxy::DidSyncAllCookies(), 0);
2197}
2198
2199#if ENABLE(INDEXED_DATABASE)
2200Ref<IDBServer::IDBServer> NetworkProcess::createIDBServer(PAL::SessionID sessionID)
2201{
2202 String path;
2203 if (!sessionID.isEphemeral()) {
2204 ASSERT(m_idbDatabasePaths.contains(sessionID));
2205 path = m_idbDatabasePaths.get(sessionID);
2206 }
2207
2208 auto server = IDBServer::IDBServer::create(sessionID, path, *this, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* {
2209 if (!weakThis)
2210 return nullptr;
2211 return &this->storageQuotaManager(sessionID, origin);
2212 });
2213 server->setPerOriginQuota(m_idbPerOriginQuota);
2214 return server;
2215}
2216
2217IDBServer::IDBServer& NetworkProcess::idbServer(PAL::SessionID sessionID)
2218{
2219 return *m_idbServers.ensure(sessionID, [this, sessionID] {
2220 return this->createIDBServer(sessionID);
2221 }).iterator->value;
2222}
2223
2224void NetworkProcess::ensurePathExists(const String& path)
2225{
2226 ASSERT(!RunLoop::isMain());
2227
2228 if (!FileSystem::makeAllDirectories(path))
2229 LOG_ERROR("Failed to make all directories for path '%s'", path.utf8().data());
2230}
2231
2232void NetworkProcess::postStorageTask(CrossThreadTask&& task)
2233{
2234 ASSERT(RunLoop::isMain());
2235
2236 LockHolder locker(m_storageTaskMutex);
2237
2238 m_storageTasks.append(WTFMove(task));
2239
2240 m_storageTaskQueue->dispatch([this] {
2241 performNextStorageTask();
2242 });
2243}
2244
2245void NetworkProcess::performNextStorageTask()
2246{
2247 ASSERT(!RunLoop::isMain());
2248
2249 CrossThreadTask task;
2250 {
2251 LockHolder locker(m_storageTaskMutex);
2252 ASSERT(!m_storageTasks.isEmpty());
2253 task = m_storageTasks.takeFirst();
2254 }
2255
2256 task.performTask();
2257}
2258
2259void NetworkProcess::accessToTemporaryFileComplete(const String& path)
2260{
2261 // We've either hard linked the temporary blob file to the database directory, copied it there,
2262 // or the transaction is being aborted.
2263 // In any of those cases, we can delete the temporary blob file now.
2264 FileSystem::deleteFile(path);
2265}
2266
2267void NetworkProcess::collectIndexedDatabaseOriginsForVersion(const String& path, HashSet<WebCore::SecurityOriginData>& securityOrigins)
2268{
2269 if (path.isEmpty())
2270 return;
2271
2272 for (auto& topOriginPath : FileSystem::listDirectory(path, "*")) {
2273 auto databaseIdentifier = FileSystem::pathGetFileName(topOriginPath);
2274 if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier)) {
2275 securityOrigins.add(WTFMove(*securityOrigin));
2276
2277 for (auto& originPath : FileSystem::listDirectory(topOriginPath, "*")) {
2278 databaseIdentifier = FileSystem::pathGetFileName(originPath);
2279 if (auto securityOrigin = SecurityOriginData::fromDatabaseIdentifier(databaseIdentifier))
2280 securityOrigins.add(WTFMove(*securityOrigin));
2281 }
2282 }
2283 }
2284}
2285
2286HashSet<WebCore::SecurityOriginData> NetworkProcess::indexedDatabaseOrigins(const String& path)
2287{
2288 if (path.isEmpty())
2289 return { };
2290
2291 HashSet<WebCore::SecurityOriginData> securityOrigins;
2292 collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v0"), securityOrigins);
2293 collectIndexedDatabaseOriginsForVersion(FileSystem::pathByAppendingComponent(path, "v1"), securityOrigins);
2294
2295 return securityOrigins;
2296}
2297
2298void NetworkProcess::addIndexedDatabaseSession(PAL::SessionID sessionID, String& indexedDatabaseDirectory, SandboxExtension::Handle& handle)
2299{
2300 // *********
2301 // IMPORTANT: Do not change the directory structure for indexed databases on disk without first consulting a reviewer from Apple (<rdar://problem/17454712>)
2302 // *********
2303 auto addResult = m_idbDatabasePaths.add(sessionID, indexedDatabaseDirectory);
2304 if (addResult.isNewEntry) {
2305 SandboxExtension::consumePermanently(handle);
2306 if (!indexedDatabaseDirectory.isEmpty())
2307 postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
2308 }
2309}
2310
2311void NetworkProcess::setIDBPerOriginQuota(uint64_t quota)
2312{
2313 m_idbPerOriginQuota = quota;
2314
2315 for (auto& server : m_idbServers.values())
2316 server->setPerOriginQuota(quota);
2317}
2318#endif // ENABLE(INDEXED_DATABASE)
2319
2320void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
2321{
2322 auto& manager = storageQuotaManager(sessionID, origin);
2323 manager.resetQuota(m_storageQuotaManagers.find(sessionID)->value.defaultQuota(origin));
2324 manager.updateQuotaBasedOnSpaceUsage();
2325}
2326
2327#if ENABLE(SANDBOX_EXTENSIONS)
2328void NetworkProcess::getSandboxExtensionsForBlobFiles(const Vector<String>& filenames, CompletionHandler<void(SandboxExtension::HandleArray&&)>&& completionHandler)
2329{
2330 parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::GetSandboxExtensionsForBlobFiles(filenames), WTFMove(completionHandler));
2331}
2332#endif // ENABLE(SANDBOX_EXTENSIONS)
2333
2334#if ENABLE(SERVICE_WORKER)
2335WebSWServerToContextConnection* NetworkProcess::connectionToContextProcessFromIPCConnection(IPC::Connection& connection)
2336{
2337 for (auto& serverToContextConnection : m_serverToContextConnections.values()) {
2338 if (serverToContextConnection->ipcConnection() == &connection)
2339 return serverToContextConnection.get();
2340 }
2341 return nullptr;
2342}
2343
2344void NetworkProcess::connectionToContextProcessWasClosed(Ref<WebSWServerToContextConnection>&& serverToContextConnection)
2345{
2346 auto& registrableDomain = serverToContextConnection->registrableDomain();
2347
2348 serverToContextConnection->connectionClosed();
2349 m_serverToContextConnections.remove(registrableDomain);
2350
2351 for (auto& swServer : m_swServers.values())
2352 swServer->markAllWorkersForRegistrableDomainAsTerminated(registrableDomain);
2353
2354 if (needsServerToContextConnectionForRegistrableDomain(registrableDomain)) {
2355 RELEASE_LOG(ServiceWorker, "Connection to service worker process was closed but is still needed, relaunching it");
2356 createServerToContextConnection(registrableDomain, WTF::nullopt);
2357 }
2358}
2359
2360bool NetworkProcess::needsServerToContextConnectionForRegistrableDomain(const RegistrableDomain& registrableDomain) const
2361{
2362 return WTF::anyOf(m_swServers.values(), [&](auto& swServer) {
2363 return swServer->needsServerToContextConnectionForRegistrableDomain(registrableDomain);
2364 });
2365}
2366
2367SWServer& NetworkProcess::swServerForSession(PAL::SessionID sessionID)
2368{
2369 ASSERT(sessionID.isValid());
2370
2371 auto result = m_swServers.ensure(sessionID, [&] {
2372 auto path = m_swDatabasePaths.get(sessionID);
2373 // There should already be a registered path for this PAL::SessionID.
2374 // If there's not, then where did this PAL::SessionID come from?
2375 ASSERT(sessionID.isEphemeral() || !path.isEmpty());
2376
2377 auto value = std::make_unique<SWServer>(makeUniqueRef<WebSWOriginStore>(), WTFMove(path), sessionID);
2378 if (m_shouldDisableServiceWorkerProcessTerminationDelay)
2379 value->disableServiceWorkerProcessTerminationDelay();
2380 return value;
2381 });
2382
2383 return *result.iterator->value;
2384}
2385
2386WebSWOriginStore& NetworkProcess::swOriginStoreForSession(PAL::SessionID sessionID)
2387{
2388 return static_cast<WebSWOriginStore&>(swServerForSession(sessionID).originStore());
2389}
2390
2391WebSWOriginStore* NetworkProcess::existingSWOriginStoreForSession(PAL::SessionID sessionID) const
2392{
2393 auto* swServer = m_swServers.get(sessionID);
2394 if (!swServer)
2395 return nullptr;
2396 return &static_cast<WebSWOriginStore&>(swServer->originStore());
2397}
2398
2399WebSWServerToContextConnection* NetworkProcess::serverToContextConnectionForRegistrableDomain(const RegistrableDomain& registrableDomain)
2400{
2401 return m_serverToContextConnections.get(registrableDomain);
2402}
2403
2404void NetworkProcess::createServerToContextConnection(const RegistrableDomain& registrableDomain, Optional<PAL::SessionID> sessionID)
2405{
2406 if (m_waitingForServerToContextProcessConnection)
2407 return;
2408
2409 m_waitingForServerToContextProcessConnection = true;
2410 if (sessionID)
2411 parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcessForExplicitSession(registrableDomain, *sessionID), 0);
2412 else
2413 parentProcessConnection()->send(Messages::NetworkProcessProxy::EstablishWorkerContextConnectionToNetworkProcess(registrableDomain), 0);
2414}
2415
2416void NetworkProcess::postMessageToServiceWorkerClient(const ServiceWorkerClientIdentifier& destinationIdentifier, MessageWithMessagePorts&& message, ServiceWorkerIdentifier sourceIdentifier, const String& sourceOrigin)
2417{
2418 if (auto* connection = m_swServerConnections.get(destinationIdentifier.serverConnectionIdentifier))
2419 connection->postMessageToServiceWorkerClient(destinationIdentifier.contextIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
2420}
2421
2422void NetworkProcess::postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destination, WebCore::MessageWithMessagePorts&& message, const WebCore::ServiceWorkerOrClientIdentifier& source, SWServerConnectionIdentifier connectionIdentifier)
2423{
2424 if (auto* connection = m_swServerConnections.get(connectionIdentifier))
2425 connection->postMessageToServiceWorker(destination, WTFMove(message), source);
2426}
2427
2428void NetworkProcess::registerSWServerConnection(WebSWServerConnection& connection)
2429{
2430 ASSERT(parentProcessHasServiceWorkerEntitlement());
2431 ASSERT(!m_swServerConnections.contains(connection.identifier()));
2432 m_swServerConnections.add(connection.identifier(), &connection);
2433 swOriginStoreForSession(connection.sessionID()).registerSWServerConnection(connection);
2434}
2435
2436void NetworkProcess::unregisterSWServerConnection(WebSWServerConnection& connection)
2437{
2438 ASSERT(m_swServerConnections.get(connection.identifier()) == &connection);
2439 m_swServerConnections.remove(connection.identifier());
2440 if (auto* store = existingSWOriginStoreForSession(connection.sessionID()))
2441 store->unregisterSWServerConnection(connection);
2442}
2443
2444void NetworkProcess::swContextConnectionMayNoLongerBeNeeded(WebSWServerToContextConnection& serverToContextConnection)
2445{
2446 auto& registrableDomain = serverToContextConnection.registrableDomain();
2447 if (needsServerToContextConnectionForRegistrableDomain(registrableDomain))
2448 return;
2449
2450 RELEASE_LOG(ServiceWorker, "Service worker process is no longer needed, terminating it");
2451 serverToContextConnection.terminate();
2452
2453 for (auto& swServer : m_swServers.values())
2454 swServer->markAllWorkersForRegistrableDomainAsTerminated(registrableDomain);
2455
2456 serverToContextConnection.connectionClosed();
2457 m_serverToContextConnections.remove(registrableDomain);
2458}
2459
2460void NetworkProcess::disableServiceWorkerProcessTerminationDelay()
2461{
2462 if (m_shouldDisableServiceWorkerProcessTerminationDelay)
2463 return;
2464
2465 m_shouldDisableServiceWorkerProcessTerminationDelay = true;
2466 for (auto& swServer : m_swServers.values())
2467 swServer->disableServiceWorkerProcessTerminationDelay();
2468}
2469
2470void NetworkProcess::addServiceWorkerSession(PAL::SessionID sessionID, String& serviceWorkerRegistrationDirectory, const SandboxExtension::Handle& handle)
2471{
2472 auto addResult = m_swDatabasePaths.add(sessionID, serviceWorkerRegistrationDirectory);
2473 if (addResult.isNewEntry) {
2474 SandboxExtension::consumePermanently(handle);
2475 if (!serviceWorkerRegistrationDirectory.isEmpty())
2476 postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, serviceWorkerRegistrationDirectory));
2477 }
2478}
2479#endif // ENABLE(SERVICE_WORKER)
2480
2481void NetworkProcess::requestStorageSpace(PAL::SessionID sessionID, const ClientOrigin& origin, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(Optional<uint64_t>)>&& callback)
2482{
2483 parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageSpace { sessionID, origin, quota, currentSize, spaceRequired }, WTFMove(callback), 0);
2484}
2485
2486class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
2487public:
2488 explicit QuotaUserInitializer(StorageQuotaManager& manager)
2489 : m_manager(makeWeakPtr(manager))
2490 {
2491 manager.addUser(*this);
2492 }
2493
2494 ~QuotaUserInitializer()
2495 {
2496 if (m_manager)
2497 m_manager->removeUser(*this);
2498 if (m_callback)
2499 m_callback();
2500 }
2501
2502private:
2503 // StorageQuotaUser API.
2504 uint64_t spaceUsed() const final
2505 {
2506 ASSERT_NOT_REACHED();
2507 return 0;
2508 }
2509
2510 void whenInitialized(CompletionHandler<void()>&& callback) final
2511 {
2512 m_callback = WTFMove(callback);
2513 }
2514
2515 WeakPtr<StorageQuotaManager> m_manager;
2516 CompletionHandler<void()> m_callback;
2517};
2518
2519void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
2520{
2521 RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = std::make_unique<QuotaUserInitializer>(manager)]() mutable {
2522 if (!weakThis)
2523 return;
2524 this->idbServer(sessionID).initializeQuotaUser(origin);
2525 CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
2526 });
2527}
2528
2529StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
2530{
2531 auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
2532 return StorageQuotaManagers { };
2533 }).iterator->value;
2534 return *storageQuotaManagers.managersPerOrigin().ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
2535 auto manager = std::make_unique<StorageQuotaManager>(storageQuotaManagers.defaultQuota(origin), [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
2536 this->requestStorageSpace(sessionID, origin, quota, currentSpace, spaceIncrease, WTFMove(callback));
2537 });
2538 initializeQuotaUsers(*manager, sessionID, origin);
2539 return manager;
2540 }).iterator->value;
2541}
2542
2543#if !PLATFORM(COCOA)
2544void NetworkProcess::originsWithPersistentCredentials(CompletionHandler<void(Vector<WebCore::SecurityOriginData>)>&& completionHandler)
2545{
2546 completionHandler(Vector<WebCore::SecurityOriginData>());
2547}
2548
2549void NetworkProcess::removeCredentialsWithOrigins(const Vector<WebCore::SecurityOriginData>&, CompletionHandler<void()>&& completionHandler)
2550{
2551 completionHandler();
2552}
2553
2554void NetworkProcess::initializeProcess(const AuxiliaryProcessInitializationParameters&)
2555{
2556}
2557
2558void NetworkProcess::initializeProcessName(const AuxiliaryProcessInitializationParameters&)
2559{
2560}
2561
2562void NetworkProcess::initializeSandbox(const AuxiliaryProcessInitializationParameters&, SandboxInitializationParameters&)
2563{
2564}
2565
2566void NetworkProcess::syncAllCookies()
2567{
2568}
2569
2570void NetworkProcess::platformSyncAllCookies(CompletionHandler<void()>&& completionHandler)
2571{
2572 completionHandler();
2573}
2574
2575#endif
2576
2577void NetworkProcess::storeAdClickAttribution(PAL::SessionID sessionID, WebCore::AdClickAttribution&& adClickAttribution)
2578{
2579 if (auto* session = networkSession(sessionID))
2580 session->storeAdClickAttribution(WTFMove(adClickAttribution));
2581}
2582
2583void NetworkProcess::dumpAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
2584{
2585 if (auto* session = networkSession(sessionID))
2586 return session->dumpAdClickAttribution(WTFMove(completionHandler));
2587
2588 completionHandler({ });
2589}
2590
2591void NetworkProcess::clearAdClickAttribution(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2592{
2593 if (auto* session = networkSession(sessionID))
2594 session->clearAdClickAttribution();
2595
2596 completionHandler();
2597}
2598
2599void NetworkProcess::setAdClickAttributionOverrideTimerForTesting(PAL::SessionID sessionID, bool value, CompletionHandler<void()>&& completionHandler)
2600{
2601 if (auto* session = networkSession(sessionID))
2602 session->setAdClickAttributionOverrideTimerForTesting(value);
2603
2604 completionHandler();
2605}
2606
2607void NetworkProcess::setAdClickAttributionConversionURLForTesting(PAL::SessionID sessionID, URL&& url, CompletionHandler<void()>&& completionHandler)
2608{
2609 if (auto* session = networkSession(sessionID))
2610 session->setAdClickAttributionConversionURLForTesting(WTFMove(url));
2611
2612 completionHandler();
2613}
2614
2615void NetworkProcess::markAdClickAttributionsAsExpiredForTesting(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
2616{
2617 if (auto* session = networkSession(sessionID))
2618 session->markAdClickAttributionsAsExpiredForTesting();
2619
2620 completionHandler();
2621}
2622
2623void NetworkProcess::addKeptAliveLoad(Ref<NetworkResourceLoader>&& loader)
2624{
2625 if (auto session = m_networkSessions.get(loader->sessionID()))
2626 session->addKeptAliveLoad(WTFMove(loader));
2627}
2628
2629void NetworkProcess::removeKeptAliveLoad(NetworkResourceLoader& loader)
2630{
2631 if (auto session = m_networkSessions.get(loader.sessionID()))
2632 session->removeKeptAliveLoad(loader);
2633}
2634
2635void NetworkProcess::webPageWasAdded(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID, PageIdentifier oldPageID)
2636{
2637 if (!pageID || !oldPageID) {
2638 LOG_ERROR("Cannot add page with invalid id");
2639 return;
2640 }
2641
2642 auto* session = networkSession(sessionID);
2643 if (!session) {
2644 LOG_ERROR("Cannot add page to an unknown session");
2645 return;
2646 }
2647 auto& storageManager = session->storageManager();
2648
2649 auto connectionID = connection.uniqueID();
2650 m_sessionByConnection.ensure(connectionID, [&]() {
2651 return sessionID;
2652 });
2653
2654 storageManager.createSessionStorageNamespace(pageID.toUInt64(), std::numeric_limits<unsigned>::max());
2655 storageManager.addAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
2656 if (pageID != oldPageID)
2657 storageManager.cloneSessionStorageNamespace(oldPageID.toUInt64(), pageID.toUInt64());
2658}
2659
2660void NetworkProcess::webPageWasRemoved(IPC::Connection& connection, PAL::SessionID sessionID, PageIdentifier pageID)
2661{
2662 if (!pageID) {
2663 LOG_ERROR("Cannot remove page with invalid id");
2664 return;
2665 }
2666
2667 auto* session = networkSession(sessionID);
2668 // Session can be destroyed before page gets removed.
2669 if (!session)
2670 return;
2671
2672 auto& storageManager = session->storageManager();
2673 storageManager.removeAllowedSessionStorageNamespaceConnection(pageID.toUInt64(), connection);
2674 storageManager.destroySessionStorageNamespace(pageID.toUInt64());
2675}
2676
2677void NetworkProcess::webProcessWasDisconnected(IPC::Connection& connection)
2678{
2679 auto connectionID = connection.uniqueID();
2680 if (!m_sessionByConnection.contains(connectionID))
2681 return;
2682
2683 auto sessionID = m_sessionByConnection.take(connectionID);
2684 if (!m_networkSessions.contains(sessionID))
2685 return;
2686
2687 networkSession(sessionID)->storageManager().processDidCloseConnection(connection);
2688}
2689
2690void NetworkProcess::webProcessSessionChanged(IPC::Connection& connection, PAL::SessionID newSessionID, const Vector<PageIdentifier>& pageIDs)
2691{
2692 auto connectionID = connection.uniqueID();
2693 ASSERT(m_sessionByConnection.contains(connectionID));
2694 if (m_sessionByConnection.get(connectionID) == newSessionID)
2695 return;
2696
2697 webProcessWasDisconnected(connection);
2698 for (auto& pageID : pageIDs)
2699 webPageWasAdded(connection, newSessionID, pageID, pageID);
2700}
2701
2702void NetworkProcess::getLocalStorageOriginDetails(PAL::SessionID sessionID, CompletionHandler<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2703{
2704 auto* session = networkSession(sessionID);
2705 if (!session) {
2706 LOG_ERROR("Cannot get local storage information for an unknown session");
2707 return;
2708 }
2709
2710 auto& storageManager = session->storageManager();
2711 storageManager.getLocalStorageOriginDetails([completionHandler = WTFMove(completionHandler)](auto&& details) mutable {
2712 completionHandler(WTFMove(details));
2713 });
2714}
2715
2716} // namespace WebKit
2717