ce9bd7f8b84119d90a838b5afee04b8bf79e2dd2
[WebKit-https.git] / Source / WebKit / UIProcess / WebsiteData / WebsiteDataStore.cpp
1 /*
2  * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebsiteDataStore.h"
28
29 #include "APIHTTPCookieStore.h"
30 #include "APIProcessPoolConfiguration.h"
31 #include "APIWebsiteDataRecord.h"
32 #include "AuthenticatorManager.h"
33 #include "DeviceIdHashSaltStorage.h"
34 #include "GPUProcessProxy.h"
35 #include "MockAuthenticatorManager.h"
36 #include "NetworkProcessMessages.h"
37 #include "ShouldGrandfatherStatistics.h"
38 #include "StorageAccessStatus.h"
39 #include "WebBackForwardCache.h"
40 #include "WebKit2Initialize.h"
41 #include "WebPageProxy.h"
42 #include "WebProcessCache.h"
43 #include "WebProcessMessages.h"
44 #include "WebProcessPool.h"
45 #include "WebResourceLoadStatisticsStore.h"
46 #include "WebsiteData.h"
47 #include "WebsiteDataStoreClient.h"
48 #include "WebsiteDataStoreParameters.h"
49 #include <WebCore/ApplicationCacheStorage.h>
50 #include <WebCore/CredentialStorage.h>
51 #include <WebCore/DatabaseTracker.h>
52 #include <WebCore/HTMLMediaElement.h>
53 #include <WebCore/NetworkStorageSession.h>
54 #include <WebCore/OriginLock.h>
55 #include <WebCore/RegistrableDomain.h>
56 #include <WebCore/SecurityOrigin.h>
57 #include <WebCore/SecurityOriginData.h>
58 #include <WebCore/StorageQuotaManager.h>
59 #include <wtf/CallbackAggregator.h>
60 #include <wtf/CompletionHandler.h>
61 #include <wtf/CrossThreadCopier.h>
62 #include <wtf/FileSystem.h>
63 #include <wtf/ProcessPrivilege.h>
64 #include <wtf/RunLoop.h>
65
66 #if ENABLE(NETSCAPE_PLUGIN_API)
67 #include "PluginProcessManager.h"
68 #endif
69
70 #if HAVE(SEC_KEY_PROXY)
71 #include "SecKeyProxyStore.h"
72 #endif
73
74 #if HAVE(APP_SSO)
75 #include "SOAuthorizationCoordinator.h"
76 #endif
77
78 namespace WebKit {
79
80 static bool allowsWebsiteDataRecordsForAllOrigins;
81 void WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins()
82 {
83     allowsWebsiteDataRecordsForAllOrigins = true;
84 }
85
86 static HashMap<PAL::SessionID, WebsiteDataStore*>& nonDefaultDataStores()
87 {
88     RELEASE_ASSERT(isUIThread());
89     static NeverDestroyed<HashMap<PAL::SessionID, WebsiteDataStore*>> map;
90     return map;
91 }
92
93 Ref<WebsiteDataStore> WebsiteDataStore::createNonPersistent()
94 {
95     return adoptRef(*new WebsiteDataStore(WebsiteDataStoreConfiguration::create(IsPersistent::No), PAL::SessionID::generateEphemeralSessionID()));
96 }
97
98 Ref<WebsiteDataStore> WebsiteDataStore::create(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
99 {
100     return adoptRef(*new WebsiteDataStore(WTFMove(configuration), sessionID));
101 }
102
103 WebsiteDataStore::WebsiteDataStore(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
104     : m_sessionID(sessionID)
105     , m_resolvedConfiguration(WTFMove(configuration))
106     , m_configuration(m_resolvedConfiguration->copy())
107     , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String()))
108     , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore"))
109 #if ENABLE(WEB_AUTHN)
110     , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>())
111 #endif
112     , m_client(makeUniqueRef<WebsiteDataStoreClient>())
113 #if HAVE(APP_SSO)
114     , m_soAuthorizationCoordinator(makeUniqueRef<SOAuthorizationCoordinator>())
115 #endif
116 {
117     WTF::setProcessPrivileges(allPrivileges());
118     maybeRegisterWithSessionIDMap();
119     platformInitialize();
120
121     ASSERT(RunLoop::isMain());
122 }
123
124 WebsiteDataStore::~WebsiteDataStore()
125 {
126     ASSERT(RunLoop::isMain());
127     RELEASE_ASSERT(m_sessionID.isValid());
128
129     platformDestroy();
130
131     if (m_sessionID != PAL::SessionID::defaultSessionID()) {
132         ASSERT(nonDefaultDataStores().get(m_sessionID) == this);
133         nonDefaultDataStores().remove(m_sessionID);
134         for (auto& processPool : WebProcessPool::allProcessPools()) {
135             if (auto* networkProcess = processPool->networkProcess())
136                 networkProcess->removeSession(m_sessionID);
137         }
138     }
139 #if ENABLE(GPU_PROCESS)
140         if (auto* gpuProcessProxy = GPUProcessProxy::singletonIfCreated())
141             gpuProcessProxy->removeSession(m_sessionID);
142 #endif
143 }
144
145 static RefPtr<WebsiteDataStore>& globalDefaultDataStore()
146 {
147     static NeverDestroyed<RefPtr<WebsiteDataStore>> globalDefaultDataStore;
148     return globalDefaultDataStore.get();
149 }
150
151 Ref<WebsiteDataStore> WebsiteDataStore::defaultDataStore()
152 {
153     InitializeWebKit2();
154
155     auto& store = globalDefaultDataStore();
156     if (!store)
157         store = adoptRef(new WebsiteDataStore(WebsiteDataStoreConfiguration::create(IsPersistent::Yes), PAL::SessionID::defaultSessionID()));
158
159     return *store;
160 }
161
162 void WebsiteDataStore::deleteDefaultDataStoreForTesting()
163 {
164     globalDefaultDataStore() = nullptr;
165 }
166
167 bool WebsiteDataStore::defaultDataStoreExists()
168 {
169     return !!globalDefaultDataStore();
170 }
171
172 void WebsiteDataStore::maybeRegisterWithSessionIDMap()
173 {
174     if (m_sessionID != PAL::SessionID::defaultSessionID()) {
175         auto result = nonDefaultDataStores().add(m_sessionID, this);
176         ASSERT_UNUSED(result, result.isNewEntry);
177     }
178 }
179
180 WebsiteDataStore* WebsiteDataStore::existingNonDefaultDataStoreForSessionID(PAL::SessionID sessionID)
181 {
182     return sessionID != PAL::SessionID::defaultSessionID() ? nonDefaultDataStores().get(sessionID) : nullptr;
183 }
184
185 void WebsiteDataStore::registerProcess(WebProcessProxy& process)
186 {
187     ASSERT(process.pageCount() || process.provisionalPageCount());
188     m_processes.add(process);
189 }
190
191 void WebsiteDataStore::unregisterProcess(WebProcessProxy& process)
192 {
193     ASSERT(!process.pageCount());
194     ASSERT(!process.provisionalPageCount());
195     m_processes.remove(process);
196 }
197
198 WebProcessPool* WebsiteDataStore::processPoolForCookieStorageOperations()
199 {
200     auto pools = processPools(1);
201     return pools.isEmpty() ? nullptr : pools.begin()->get();
202 }
203
204 void WebsiteDataStore::resolveDirectoriesIfNecessary()
205 {
206     if (m_hasResolvedDirectories)
207         return;
208     m_hasResolvedDirectories = true;
209
210     // Resolve directory paths.
211     if (!m_configuration->applicationCacheDirectory().isEmpty())
212         m_resolvedConfiguration->setApplicationCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory()));
213     if (!m_configuration->mediaCacheDirectory().isEmpty())
214         m_resolvedConfiguration->setMediaCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory()));
215     if (!m_configuration->mediaKeysStorageDirectory().isEmpty())
216         m_resolvedConfiguration->setMediaKeysStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory()));
217     if (!m_configuration->webSQLDatabaseDirectory().isEmpty())
218         m_resolvedConfiguration->setWebSQLDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory()));
219     if (!m_configuration->indexedDBDatabaseDirectory().isEmpty())
220         m_resolvedConfiguration->setIndexedDBDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory()));
221     if (!m_configuration->alternativeServicesDirectory().isEmpty() && WebsiteDataStore::http3Enabled())
222         m_resolvedConfiguration->setAlternativeServicesDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->alternativeServicesDirectory()));
223     if (!m_configuration->deviceIdHashSaltsStorageDirectory().isEmpty())
224         m_resolvedConfiguration->setDeviceIdHashSaltsStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->deviceIdHashSaltsStorageDirectory()));
225     if (!m_configuration->networkCacheDirectory().isEmpty())
226         m_resolvedConfiguration->setNetworkCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->networkCacheDirectory()));
227     if (!m_configuration->resourceLoadStatisticsDirectory().isEmpty())
228         m_resolvedConfiguration->setResourceLoadStatisticsDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->resourceLoadStatisticsDirectory()));
229     if (!m_configuration->serviceWorkerRegistrationDirectory().isEmpty() && m_resolvedConfiguration->serviceWorkerRegistrationDirectory().isEmpty())
230         m_resolvedConfiguration->setServiceWorkerRegistrationDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->serviceWorkerRegistrationDirectory()));
231     if (!m_configuration->javaScriptConfigurationDirectory().isEmpty())
232         m_resolvedConfiguration->setJavaScriptConfigurationDirectory(resolvePathForSandboxExtension(m_configuration->javaScriptConfigurationDirectory()));
233     if (!m_configuration->cacheStorageDirectory().isEmpty() && m_resolvedConfiguration->cacheStorageDirectory().isEmpty())
234         m_resolvedConfiguration->setCacheStorageDirectory(resolvePathForSandboxExtension(m_configuration->cacheStorageDirectory()));
235
236     // Resolve directories for file paths.
237     if (!m_configuration->cookieStorageFile().isEmpty()) {
238         m_resolvedConfiguration->setCookieStorageFile(resolveAndCreateReadWriteDirectoryForSandboxExtension(FileSystem::directoryName(m_configuration->cookieStorageFile())));
239         m_resolvedConfiguration->setCookieStorageFile(FileSystem::pathByAppendingComponent(m_resolvedConfiguration->cookieStorageFile(), FileSystem::pathGetFileName(m_configuration->cookieStorageFile())));
240     }
241 }
242
243 enum class ProcessAccessType {
244     None,
245     OnlyIfLaunched,
246     Launch,
247 };
248
249 static ProcessAccessType computeNetworkProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
250 {
251     for (auto dataType : dataTypes) {
252         if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network) {
253             if (isNonPersistentStore)
254                 return ProcessAccessType::OnlyIfLaunched;
255             return ProcessAccessType::Launch;
256         }
257     }
258     return ProcessAccessType::None;
259 }
260
261 static ProcessAccessType computeWebProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
262 {
263     UNUSED_PARAM(isNonPersistentStore);
264
265     ProcessAccessType processAccessType = ProcessAccessType::None;
266
267     if (dataTypes.contains(WebsiteDataType::MemoryCache))
268         return ProcessAccessType::OnlyIfLaunched;
269
270     return processAccessType;
271 }
272
273 void WebsiteDataStore::fetchData(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void(Vector<WebsiteDataRecord>)>&& completionHandler)
274 {
275     fetchDataAndApply(dataTypes, fetchOptions, nullptr, WTFMove(completionHandler));
276 }
277
278 void WebsiteDataStore::fetchDataAndApply(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply)
279 {
280     struct CallbackAggregator final : ThreadSafeRefCounted<CallbackAggregator> {
281         CallbackAggregator(OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply, WebsiteDataStore& dataStore)
282             : fetchOptions(fetchOptions)
283             , queue(WTFMove(queue))
284             , apply(WTFMove(apply))
285             , protectedDataStore(dataStore)
286         {
287             ASSERT(RunLoop::isMain());
288         }
289
290         ~CallbackAggregator()
291         {
292             ASSERT(!pendingCallbacks);
293
294             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
295             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
296         }
297
298         void addPendingCallback()
299         {
300             pendingCallbacks++;
301         }
302
303         void removePendingCallback(WebsiteData websiteData)
304         {
305             ASSERT(pendingCallbacks);
306             --pendingCallbacks;
307
308             for (auto& entry : websiteData.entries) {
309                 auto displayName = WebsiteDataRecord::displayNameForOrigin(entry.origin);
310                 if (!displayName) {
311                     if (!allowsWebsiteDataRecordsForAllOrigins)
312                         continue;
313
314                     displayName = makeString(entry.origin.protocol, " ", entry.origin.host);
315                 }
316
317                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
318                 if (!record.displayName)
319                     record.displayName = WTFMove(displayName);
320
321                 record.add(entry.type, entry.origin);
322
323                 if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes)) {
324                     if (!record.size)
325                         record.size = WebsiteDataRecord::Size { 0, { } };
326
327                     record.size->totalSize += entry.size;
328                     record.size->typeSizes.add(static_cast<unsigned>(entry.type), 0).iterator->value += entry.size;
329                 }
330             }
331
332             for (auto& hostName : websiteData.hostNamesWithCookies) {
333                 auto displayName = WebsiteDataRecord::displayNameForCookieHostName(hostName);
334                 if (!displayName)
335                     continue;
336
337                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
338                 if (!record.displayName)
339                     record.displayName = WTFMove(displayName);
340
341                 record.addCookieHostName(hostName);
342             }
343
344 #if ENABLE(NETSCAPE_PLUGIN_API)
345             for (auto& hostName : websiteData.hostNamesWithPluginData) {
346                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
347                 if (!displayName)
348                     continue;
349
350                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
351                 if (!record.displayName)
352                     record.displayName = WTFMove(displayName);
353
354                 record.addPluginDataHostName(hostName);
355             }
356 #endif
357
358             for (auto& hostName : websiteData.hostNamesWithHSTSCache) {
359                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
360                 if (!displayName)
361                     continue;
362                 
363                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
364                 if (!record.displayName)
365                     record.displayName = WTFMove(displayName);
366
367                 record.addHSTSCacheHostname(hostName);
368             }
369
370 #if ENABLE(RESOURCE_LOAD_STATISTICS)
371             for (const auto& domain : websiteData.registrableDomainsWithResourceLoadStatistics) {
372                 auto displayName = WebsiteDataRecord::displayNameForHostName(domain.string());
373                 if (!displayName)
374                     continue;
375
376                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
377                 if (!record.displayName)
378                     record.displayName = WTFMove(displayName);
379
380                 record.addResourceLoadStatisticsRegistrableDomain(domain);
381             }
382 #endif
383
384             callIfNeeded();
385         }
386
387         void callIfNeeded()
388         {
389             if (pendingCallbacks)
390                 return;
391
392             Vector<WebsiteDataRecord> records;
393             records.reserveInitialCapacity(m_websiteDataRecords.size());
394             for (auto& record : m_websiteDataRecords.values())
395                 records.uncheckedAppend(WTFMove(record));
396
397             auto processRecords = [apply = WTFMove(apply), records = WTFMove(records)] () mutable {
398                 apply(WTFMove(records));
399             };
400
401             if (queue)
402                 queue->dispatch(WTFMove(processRecords));
403             else
404                 RunLoop::main().dispatch(WTFMove(processRecords));
405         }
406
407         const OptionSet<WebsiteDataFetchOption> fetchOptions;
408
409         unsigned pendingCallbacks = 0;
410         RefPtr<WorkQueue> queue;
411         Function<void(Vector<WebsiteDataRecord>)> apply;
412
413         HashMap<String, WebsiteDataRecord> m_websiteDataRecords;
414         Ref<WebsiteDataStore> protectedDataStore;
415     };
416
417     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(fetchOptions, WTFMove(queue), WTFMove(apply), *this));
418
419 #if ENABLE(VIDEO)
420     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
421         callbackAggregator->addPendingCallback();
422         m_queue->dispatch([mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
423             // FIXME: Make HTMLMediaElement::originsInMediaCache return a collection of SecurityOriginDatas.
424             HashSet<RefPtr<WebCore::SecurityOrigin>> origins = WebCore::HTMLMediaElement::originsInMediaCache(mediaCacheDirectory);
425             WebsiteData websiteData;
426             
427             for (auto& origin : origins) {
428                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::DiskCache, 0 };
429                 websiteData.entries.append(WTFMove(entry));
430             }
431             
432             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
433                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
434             });
435         });
436     }
437 #endif
438
439     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
440     if (networkProcessAccessType != ProcessAccessType::None) {
441         auto pools = networkProcessAccessType == ProcessAccessType::Launch ? ensureProcessPools() : processPools();
442         for (auto& processPool : pools) {
443             switch (networkProcessAccessType) {
444             case ProcessAccessType::OnlyIfLaunched:
445                 if (!processPool->networkProcess())
446                     continue;
447                 break;
448
449             case ProcessAccessType::Launch:
450                 processPool->ensureNetworkProcess(this);
451                 break;
452
453             case ProcessAccessType::None:
454                 ASSERT_NOT_REACHED();
455             }
456
457             callbackAggregator->addPendingCallback();
458             processPool->networkProcess()->fetchWebsiteData(m_sessionID, dataTypes, fetchOptions, [callbackAggregator, processPool](WebsiteData websiteData) {
459                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
460             });
461         }
462     }
463
464     auto webProcessAccessType = computeWebProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
465     if (webProcessAccessType != ProcessAccessType::None) {
466         for (auto& process : processes()) {
467             switch (webProcessAccessType) {
468             case ProcessAccessType::OnlyIfLaunched:
469                 if (process.state() != WebProcessProxy::State::Running)
470                     continue;
471                 break;
472
473             case ProcessAccessType::Launch:
474                 // FIXME: Handle this.
475                 ASSERT_NOT_REACHED();
476                 break;
477
478             case ProcessAccessType::None:
479                 ASSERT_NOT_REACHED();
480             }
481
482             callbackAggregator->addPendingCallback();
483             process.fetchWebsiteData(m_sessionID, dataTypes, [callbackAggregator](WebsiteData websiteData) {
484                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
485             });
486         }
487     }
488
489     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt)) {
490         callbackAggregator->addPendingCallback();
491
492         m_deviceIdHashSaltStorage->getDeviceIdHashSaltOrigins([callbackAggregator](auto&& origins) {
493             WebsiteData websiteData;
494
495             while (!origins.isEmpty())
496                 websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::DeviceIdHashSalt, 0 });
497
498             callbackAggregator->removePendingCallback(WTFMove(websiteData));
499         });
500     }
501
502     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
503         callbackAggregator->addPendingCallback();
504
505         m_queue->dispatch([fetchOptions, applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
506             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
507
508             WebsiteData websiteData;
509
510             // FIXME: getOriginsWithCache should return a collection of SecurityOriginDatas.
511             auto origins = storage->originsWithCache();
512
513             for (auto& origin : origins) {
514                 uint64_t size = fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes) ? storage->diskUsageForOrigin(origin) : 0;
515                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::OfflineWebApplicationCache, size };
516
517                 websiteData.entries.append(WTFMove(entry));
518             }
519
520             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
521                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
522             });
523         });
524     }
525
526     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
527         callbackAggregator->addPendingCallback();
528
529         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator] {
530             auto origins = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->origins();
531             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
532                 WebsiteData websiteData;
533                 for (auto& origin : origins)
534                     websiteData.entries.append(WebsiteData::Entry { WTFMove(origin), WebsiteDataType::WebSQLDatabases, 0 });
535                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
536             });
537         });
538     }
539
540     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
541         callbackAggregator->addPendingCallback();
542
543         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator] {
544             auto origins = mediaKeyOrigins(mediaKeysStorageDirectory);
545
546             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
547                 WebsiteData websiteData;
548                 for (auto& origin : origins)
549                     websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataType::MediaKeys, 0 });
550
551                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
552             });
553         });
554     }
555
556 #if ENABLE(NETSCAPE_PLUGIN_API)
557     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
558         class State {
559         public:
560             static void fetchData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
561             {
562                 new State(WTFMove(callbackAggregator), WTFMove(plugins));
563             }
564
565         private:
566             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
567                 : m_callbackAggregator(WTFMove(callbackAggregator))
568                 , m_plugins(WTFMove(plugins))
569             {
570                 m_callbackAggregator->addPendingCallback();
571
572                 fetchWebsiteDataForNextPlugin();
573             }
574
575             ~State()
576             {
577                 ASSERT(m_plugins.isEmpty());
578             }
579
580             void fetchWebsiteDataForNextPlugin()
581             {
582                 if (m_plugins.isEmpty()) {
583                     WebsiteData websiteData;
584                     websiteData.hostNamesWithPluginData = WTFMove(m_hostNames);
585
586                     m_callbackAggregator->removePendingCallback(WTFMove(websiteData));
587
588                     delete this;
589                     return;
590                 }
591
592                 auto plugin = m_plugins.takeLast();
593                 PluginProcessManager::singleton().fetchWebsiteData(plugin, m_callbackAggregator->fetchOptions, [this](Vector<String> hostNames) {
594                     for (auto& hostName : hostNames)
595                         m_hostNames.add(WTFMove(hostName));
596                     fetchWebsiteDataForNextPlugin();
597                 });
598             }
599
600             Ref<CallbackAggregator> m_callbackAggregator;
601             Vector<PluginModuleInfo> m_plugins;
602             HashSet<String> m_hostNames;
603         };
604
605         State::fetchData(*callbackAggregator, plugins());
606     }
607 #endif
608
609     callbackAggregator->callIfNeeded();
610 }
611
612 #if ENABLE(RESOURCE_LOAD_STATISTICS)
613 void WebsiteDataStore::fetchDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
614 {
615     fetchDataAndApply(dataTypes, fetchOptions, m_queue.copyRef(), [domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)] (auto&& existingDataRecords) mutable {
616         ASSERT(!RunLoop::isMain());
617         
618         Vector<WebsiteDataRecord> matchingDataRecords;
619         HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords;
620         for (auto&& dataRecord : existingDataRecords) {
621             for (auto& domain : domains) {
622                 if (dataRecord.matches(domain)) {
623                     matchingDataRecords.append(WTFMove(dataRecord));
624                     domainsWithMatchingDataRecords.add(domain.isolatedCopy());
625                     break;
626                 }
627             }
628         }
629         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), matchingDataRecords = WTFMove(matchingDataRecords), domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords)] () mutable {
630             completionHandler(WTFMove(matchingDataRecords), WTFMove(domainsWithMatchingDataRecords));
631         });
632     });
633 }
634 #endif
635
636 static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
637 {
638     ProcessAccessType processAccessType = ProcessAccessType::None;
639
640     for (auto dataType : dataTypes) {
641         if (dataType == WebsiteDataType::Cookies) {
642             if (isNonPersistentStore)
643                 processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
644             else
645                 processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
646         } else if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network)
647             return ProcessAccessType::Launch;
648     }
649     
650     return processAccessType;
651 }
652
653 static ProcessAccessType computeWebProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
654 {
655     UNUSED_PARAM(isNonPersistentStore);
656
657     ProcessAccessType processAccessType = ProcessAccessType::None;
658
659     if (dataTypes.contains(WebsiteDataType::MemoryCache))
660         processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
661
662     return processAccessType;
663 }
664
665 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, Function<void()>&& completionHandler)
666 {
667     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
668         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
669             : completionHandler(WTFMove(completionHandler))
670             , protectedDataStore(dataStore)
671         {
672             ASSERT(RunLoop::isMain());
673         }
674
675         ~CallbackAggregator()
676         {
677             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
678             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
679         }
680
681         void addPendingCallback()
682         {
683             pendingCallbacks++;
684         }
685
686         void removePendingCallback()
687         {
688             ASSERT(pendingCallbacks);
689             --pendingCallbacks;
690
691             callIfNeeded();
692         }
693
694         void callIfNeeded()
695         {
696             if (!pendingCallbacks)
697                 RunLoop::main().dispatch(WTFMove(completionHandler));
698         }
699
700         unsigned pendingCallbacks = 0;
701         Function<void()> completionHandler;
702         Ref<WebsiteDataStore> protectedDataStore;
703     };
704
705     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
706
707 #if ENABLE(VIDEO)
708     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
709         callbackAggregator->addPendingCallback();
710         m_queue->dispatch([modifiedSince, mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
711             WebCore::HTMLMediaElement::clearMediaCache(mediaCacheDirectory, modifiedSince);
712             
713             WTF::RunLoop::main().dispatch([callbackAggregator] {
714                 callbackAggregator->removePendingCallback();
715             });
716         });
717     }
718 #endif
719
720 #if ENABLE(RESOURCE_LOAD_STATISTICS)
721     bool didNotifyNetworkProcessToDeleteWebsiteData = false;
722 #endif
723     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
724     if (networkProcessAccessType != ProcessAccessType::None) {
725         auto pools = networkProcessAccessType == ProcessAccessType::Launch ? ensureProcessPools() : processPools();
726         for (auto& processPool : pools) {
727             switch (networkProcessAccessType) {
728             case ProcessAccessType::OnlyIfLaunched:
729                 if (!processPool->networkProcess())
730                     continue;
731                 break;
732
733             case ProcessAccessType::Launch:
734                 processPool->ensureNetworkProcess(this);
735                 break;
736
737             case ProcessAccessType::None:
738                 ASSERT_NOT_REACHED();
739             }
740
741             callbackAggregator->addPendingCallback();
742             processPool->networkProcess()->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator, processPool] {
743                 callbackAggregator->removePendingCallback();
744             });
745 #if ENABLE(RESOURCE_LOAD_STATISTICS)
746             didNotifyNetworkProcessToDeleteWebsiteData = true;
747 #endif
748         }
749     }
750
751     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
752     if (webProcessAccessType != ProcessAccessType::None) {
753         for (auto& processPool : processPools()) {
754             // Clear back/forward cache first as processes removed from the back/forward cache will likely
755             // be added to the WebProcess cache.
756             processPool->backForwardCache().removeEntriesForSession(sessionID());
757             processPool->webProcessCache().clearAllProcessesForSession(sessionID());
758         }
759
760         for (auto& process : processes()) {
761             switch (webProcessAccessType) {
762             case ProcessAccessType::OnlyIfLaunched:
763                 if (process.state() != WebProcessProxy::State::Running)
764                     continue;
765                 break;
766
767             case ProcessAccessType::Launch:
768                 // FIXME: Handle this.
769                 ASSERT_NOT_REACHED();
770                 break;
771
772             case ProcessAccessType::None:
773                 ASSERT_NOT_REACHED();
774             }
775
776             callbackAggregator->addPendingCallback();
777             process.deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator] {
778                 callbackAggregator->removePendingCallback();
779             });
780         }
781     }
782
783     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
784         callbackAggregator->addPendingCallback();
785
786         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltOriginsModifiedSince(modifiedSince, [callbackAggregator] {
787             callbackAggregator->removePendingCallback();
788         });
789     }
790
791     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
792         callbackAggregator->addPendingCallback();
793
794         m_queue->dispatch([applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
795             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
796
797             storage->deleteAllCaches();
798
799             WTF::RunLoop::main().dispatch([callbackAggregator] {
800                 callbackAggregator->removePendingCallback();
801             });
802         });
803     }
804
805     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
806         callbackAggregator->addPendingCallback();
807
808         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
809             WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->deleteDatabasesModifiedSince(modifiedSince);
810
811             RunLoop::main().dispatch([callbackAggregator] {
812                 callbackAggregator->removePendingCallback();
813             });
814         });
815     }
816
817     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
818         callbackAggregator->addPendingCallback();
819
820         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
821             removeMediaKeys(mediaKeysStorageDirectory, modifiedSince);
822
823             RunLoop::main().dispatch([callbackAggregator] {
824                 callbackAggregator->removePendingCallback();
825             });
826         });
827     }
828
829     if (dataTypes.contains(WebsiteDataType::SearchFieldRecentSearches) && isPersistent()) {
830         callbackAggregator->addPendingCallback();
831
832         m_queue->dispatch([modifiedSince, callbackAggregator] {
833             platformRemoveRecentSearches(modifiedSince);
834
835             RunLoop::main().dispatch([callbackAggregator] {
836                 callbackAggregator->removePendingCallback();
837             });
838         });
839     }
840
841 #if ENABLE(NETSCAPE_PLUGIN_API)
842     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
843         class State {
844         public:
845             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
846             {
847                 new State(WTFMove(callbackAggregator), WTFMove(plugins), modifiedSince);
848             }
849
850         private:
851             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
852                 : m_callbackAggregator(WTFMove(callbackAggregator))
853                 , m_plugins(WTFMove(plugins))
854                 , m_modifiedSince(modifiedSince)
855             {
856                 m_callbackAggregator->addPendingCallback();
857
858                 deleteWebsiteDataForNextPlugin();
859             }
860
861             ~State()
862             {
863                 ASSERT(m_plugins.isEmpty());
864             }
865
866             void deleteWebsiteDataForNextPlugin()
867             {
868                 if (m_plugins.isEmpty()) {
869                     m_callbackAggregator->removePendingCallback();
870
871                     delete this;
872                     return;
873                 }
874
875                 auto plugin = m_plugins.takeLast();
876                 PluginProcessManager::singleton().deleteWebsiteData(plugin, m_modifiedSince, [this] {
877                     deleteWebsiteDataForNextPlugin();
878                 });
879             }
880
881             Ref<CallbackAggregator> m_callbackAggregator;
882             Vector<PluginModuleInfo> m_plugins;
883             WallTime m_modifiedSince;
884         };
885
886         State::deleteData(*callbackAggregator, plugins(), modifiedSince);
887     }
888 #endif
889
890 #if ENABLE(RESOURCE_LOAD_STATISTICS)
891     if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
892         if (!didNotifyNetworkProcessToDeleteWebsiteData) {
893             for (auto& processPool : processPools()) {
894                 if (auto* process = processPool->networkProcess()) {
895                     callbackAggregator->addPendingCallback();
896                     process->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator] {
897                         callbackAggregator->removePendingCallback();
898                     });
899                 }
900             }
901         }
902
903         callbackAggregator->addPendingCallback();
904         clearResourceLoadStatisticsInWebProcesses([callbackAggregator] {
905             callbackAggregator->removePendingCallback();
906         });
907     }
908 #endif
909
910     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
911     callbackAggregator->callIfNeeded();
912 }
913
914 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, const Vector<WebsiteDataRecord>& dataRecords, Function<void()>&& completionHandler)
915 {
916     Vector<WebCore::SecurityOriginData> origins;
917
918     for (const auto& dataRecord : dataRecords) {
919         for (auto& origin : dataRecord.origins)
920             origins.append(origin);
921     }
922
923     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
924         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
925             : completionHandler(WTFMove(completionHandler))
926             , protectedDataStore(dataStore)
927         {
928             ASSERT(RunLoop::isMain());
929         }
930
931         ~CallbackAggregator()
932         {
933             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
934             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
935         }
936
937         void addPendingCallback()
938         {
939             pendingCallbacks++;
940         }
941
942         void removePendingCallback()
943         {
944             ASSERT(pendingCallbacks);
945             --pendingCallbacks;
946
947             callIfNeeded();
948         }
949
950         void callIfNeeded()
951         {
952             if (!pendingCallbacks)
953                 RunLoop::main().dispatch(WTFMove(completionHandler));
954         }
955
956         unsigned pendingCallbacks = 0;
957         Function<void()> completionHandler;
958         Ref<WebsiteDataStore> protectedDataStore;
959     };
960
961     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
962     
963     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
964         HashSet<WebCore::SecurityOriginData> origins;
965         for (const auto& dataRecord : dataRecords) {
966             for (const auto& origin : dataRecord.origins)
967                 origins.add(origin);
968         }
969         
970 #if ENABLE(VIDEO)
971         callbackAggregator->addPendingCallback();
972         m_queue->dispatch([origins = WTFMove(origins), mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
973
974             // FIXME: Move SecurityOrigin::toRawString to SecurityOriginData and
975             // make HTMLMediaElement::clearMediaCacheForOrigins take SecurityOriginData.
976             HashSet<RefPtr<WebCore::SecurityOrigin>> securityOrigins;
977             for (auto& origin : origins)
978                 securityOrigins.add(origin.securityOrigin());
979             WebCore::HTMLMediaElement::clearMediaCacheForOrigins(mediaCacheDirectory, securityOrigins);
980             
981             WTF::RunLoop::main().dispatch([callbackAggregator] {
982                 callbackAggregator->removePendingCallback();
983             });
984         });
985 #endif
986     }
987     
988     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
989     if (networkProcessAccessType != ProcessAccessType::None) {
990         auto pools = networkProcessAccessType == ProcessAccessType::Launch ? ensureProcessPools() : processPools();
991         for (auto& processPool : pools) {
992             switch (networkProcessAccessType) {
993             case ProcessAccessType::OnlyIfLaunched:
994                 if (!processPool->networkProcess())
995                     continue;
996                 break;
997
998             case ProcessAccessType::Launch:
999                 processPool->ensureNetworkProcess(this);
1000                 break;
1001
1002             case ProcessAccessType::None:
1003                 ASSERT_NOT_REACHED();
1004             }
1005
1006             Vector<String> cookieHostNames;
1007             Vector<String> HSTSCacheHostNames;
1008             Vector<WebCore::RegistrableDomain> registrableDomains;
1009             for (const auto& dataRecord : dataRecords) {
1010                 for (auto& hostName : dataRecord.cookieHostNames)
1011                     cookieHostNames.append(hostName);
1012                 for (auto& hostName : dataRecord.HSTSCacheHostNames)
1013                     HSTSCacheHostNames.append(hostName);
1014 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1015                 for (auto& registrableDomain : dataRecord.resourceLoadStatisticsRegistrableDomains)
1016                     registrableDomains.append(registrableDomain);
1017 #endif
1018             }
1019
1020             callbackAggregator->addPendingCallback();
1021             processPool->networkProcess()->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, registrableDomains, [callbackAggregator, processPool] {
1022                 callbackAggregator->removePendingCallback();
1023             });
1024         }
1025     }
1026
1027     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
1028     if (webProcessAccessType != ProcessAccessType::None) {
1029         for (auto& process : processes()) {
1030             switch (webProcessAccessType) {
1031             case ProcessAccessType::OnlyIfLaunched:
1032                 if (process.state() != WebProcessProxy::State::Running)
1033                     continue;
1034                 break;
1035
1036             case ProcessAccessType::Launch:
1037                 // FIXME: Handle this.
1038                 ASSERT_NOT_REACHED();
1039                 break;
1040
1041             case ProcessAccessType::None:
1042                 ASSERT_NOT_REACHED();
1043             }
1044
1045             callbackAggregator->addPendingCallback();
1046
1047             process.deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, [callbackAggregator] {
1048                 callbackAggregator->removePendingCallback();
1049             });
1050         }
1051     }
1052
1053     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
1054         callbackAggregator->addPendingCallback();
1055
1056         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltForOrigins(origins, [callbackAggregator] {
1057             callbackAggregator->removePendingCallback();
1058         });
1059     }
1060
1061     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
1062         HashSet<WebCore::SecurityOriginData> origins;
1063         for (const auto& dataRecord : dataRecords) {
1064             for (const auto& origin : dataRecord.origins)
1065                 origins.add(origin);
1066         }
1067
1068         callbackAggregator->addPendingCallback();
1069         m_queue->dispatch([origins = WTFMove(origins), applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
1070             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
1071
1072             for (const auto& origin : origins)
1073                 storage->deleteCacheForOrigin(origin.securityOrigin());
1074
1075             WTF::RunLoop::main().dispatch([callbackAggregator] {
1076                 callbackAggregator->removePendingCallback();
1077             });
1078         });
1079     }
1080
1081     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
1082         HashSet<WebCore::SecurityOriginData> origins;
1083         for (const auto& dataRecord : dataRecords) {
1084             for (const auto& origin : dataRecord.origins)
1085                 origins.add(origin);
1086         }
1087
1088         callbackAggregator->addPendingCallback();
1089         m_queue->dispatch([origins = WTFMove(origins), callbackAggregator, webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy()] {
1090             auto databaseTracker = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory);
1091             for (auto& origin : origins)
1092                 databaseTracker->deleteOrigin(origin);
1093             RunLoop::main().dispatch([callbackAggregator] {
1094                 callbackAggregator->removePendingCallback();
1095             });
1096         });
1097     }
1098
1099     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
1100         HashSet<WebCore::SecurityOriginData> origins;
1101         for (const auto& dataRecord : dataRecords) {
1102             for (const auto& origin : dataRecord.origins)
1103                 origins.add(origin);
1104         }
1105
1106         callbackAggregator->addPendingCallback();
1107         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, origins = WTFMove(origins)] {
1108
1109             removeMediaKeys(mediaKeysStorageDirectory, origins);
1110
1111             RunLoop::main().dispatch([callbackAggregator] {
1112                 callbackAggregator->removePendingCallback();
1113             });
1114         });
1115     }
1116
1117 #if ENABLE(NETSCAPE_PLUGIN_API)
1118     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
1119         Vector<String> hostNames;
1120         for (const auto& dataRecord : dataRecords) {
1121             for (const auto& hostName : dataRecord.pluginDataHostNames)
1122                 hostNames.append(hostName);
1123         }
1124
1125
1126         class State {
1127         public:
1128             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1129             {
1130                 new State(WTFMove(callbackAggregator), WTFMove(plugins), WTFMove(hostNames));
1131             }
1132
1133         private:
1134             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1135                 : m_callbackAggregator(WTFMove(callbackAggregator))
1136                 , m_plugins(WTFMove(plugins))
1137                 , m_hostNames(WTFMove(hostNames))
1138             {
1139                 m_callbackAggregator->addPendingCallback();
1140
1141                 deleteWebsiteDataForNextPlugin();
1142             }
1143
1144             ~State()
1145             {
1146                 ASSERT(m_plugins.isEmpty());
1147             }
1148
1149             void deleteWebsiteDataForNextPlugin()
1150             {
1151                 if (m_plugins.isEmpty()) {
1152                     m_callbackAggregator->removePendingCallback();
1153
1154                     delete this;
1155                     return;
1156                 }
1157
1158                 auto plugin = m_plugins.takeLast();
1159                 PluginProcessManager::singleton().deleteWebsiteDataForHostNames(plugin, m_hostNames, [this] {
1160                     deleteWebsiteDataForNextPlugin();
1161                 });
1162             }
1163
1164             Ref<CallbackAggregator> m_callbackAggregator;
1165             Vector<PluginModuleInfo> m_plugins;
1166             Vector<String> m_hostNames;
1167         };
1168
1169         if (!hostNames.isEmpty())
1170             State::deleteData(*callbackAggregator, plugins(), WTFMove(hostNames));
1171     }
1172 #endif
1173
1174     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
1175     callbackAggregator->callIfNeeded();
1176 }
1177
1178 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1179 void WebsiteDataStore::setMaxStatisticsEntries(size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
1180 {
1181     ASSERT(RunLoop::isMain());
1182
1183     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1184
1185     for (auto& processPool : processPools())
1186         processPool->ensureNetworkProcess().setMaxStatisticsEntries(m_sessionID, maximumEntryCount, [processPool, callbackAggregator] { });
1187 }
1188
1189 void WebsiteDataStore::setPruneEntriesDownTo(size_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
1190 {
1191     ASSERT(RunLoop::isMain());
1192     
1193     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1194
1195     for (auto& processPool : processPools())
1196         processPool->ensureNetworkProcess().setPruneEntriesDownTo(m_sessionID, pruneTargetCount, [processPool, callbackAggregator] { });
1197 }
1198
1199 void WebsiteDataStore::setGrandfatheringTime(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1200 {
1201     ASSERT(RunLoop::isMain());
1202
1203     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1204
1205     for (auto& processPool : processPools())
1206         processPool->ensureNetworkProcess().setGrandfatheringTime(m_sessionID, seconds, [processPool, callbackAggregator] { });
1207 }
1208
1209 void WebsiteDataStore::setMinimumTimeBetweenDataRecordsRemoval(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1210 {
1211     ASSERT(RunLoop::isMain());
1212
1213     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1214
1215     for (auto& processPool : processPools())
1216         processPool->ensureNetworkProcess().setMinimumTimeBetweenDataRecordsRemoval(m_sessionID, seconds, [processPool, callbackAggregator] { });
1217 }
1218     
1219 void WebsiteDataStore::dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&& completionHandler)
1220 {
1221     ASSERT(RunLoop::isMain());
1222
1223     for (auto& processPool : processPools()) {
1224         if (auto* process = processPool->networkProcess()) {
1225             process->dumpResourceLoadStatistics(m_sessionID, WTFMove(completionHandler));
1226             break;
1227         }
1228     }
1229 }
1230
1231 void WebsiteDataStore::isPrevalentResource(const URL& url, CompletionHandler<void(bool isPrevalent)>&& completionHandler)
1232 {
1233     ASSERT(RunLoop::isMain());
1234     
1235     if (url.protocolIsAbout() || url.isEmpty()) {
1236         completionHandler(false);
1237         return;
1238     }
1239
1240     for (auto& processPool : processPools()) {
1241         if (auto* process = processPool->networkProcess()) {
1242             process->isPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1243             break;
1244         }
1245     }
1246 }
1247
1248 void WebsiteDataStore::isGrandfathered(const URL& url, CompletionHandler<void(bool isPrevalent)>&& completionHandler)
1249 {
1250     ASSERT(RunLoop::isMain());
1251     
1252     if (url.protocolIsAbout() || url.isEmpty()) {
1253         completionHandler(false);
1254         return;
1255     }
1256
1257     for (auto& processPool : processPools()) {
1258         if (auto* process = processPool->networkProcess()) {
1259             process->isGrandfathered(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1260             break;
1261         }
1262     }
1263 }
1264
1265 void WebsiteDataStore::setPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1266 {
1267     ASSERT(RunLoop::isMain());
1268     
1269     if (url.protocolIsAbout() || url.isEmpty()) {
1270         completionHandler();
1271         return;
1272     }
1273     
1274     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1275
1276     for (auto& processPool : ensureProcessPools())
1277         processPool->ensureNetworkProcess().setPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator] { });
1278 }
1279
1280 void WebsiteDataStore::setPrevalentResourceForDebugMode(const URL& url, CompletionHandler<void()>&& completionHandler)
1281 {
1282     ASSERT(RunLoop::isMain());
1283     
1284     if (url.protocolIsAbout() || url.isEmpty()) {
1285         completionHandler();
1286         return;
1287     }
1288     
1289     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1290     
1291     for (auto& processPool : processPools()) {
1292         if (auto* process = processPool->networkProcess())
1293             process->setPrevalentResourceForDebugMode(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator] { });
1294     }
1295 }
1296
1297 void WebsiteDataStore::isVeryPrevalentResource(const URL& url, CompletionHandler<void(bool isVeryPrevalent)>&& completionHandler)
1298 {
1299     ASSERT(RunLoop::isMain());
1300     
1301     if (url.protocolIsAbout() || url.isEmpty()) {
1302         completionHandler(false);
1303         return;
1304     }
1305     
1306     for (auto& processPool : processPools()) {
1307         if (auto* process = processPool->networkProcess()) {
1308             process->isVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1309             break;
1310         }
1311     }
1312 }
1313
1314 void WebsiteDataStore::setVeryPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1315 {
1316     ASSERT(RunLoop::isMain());
1317     
1318     if (url.protocolIsAbout() || url.isEmpty()) {
1319         completionHandler();
1320         return;
1321     }
1322     
1323     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1324     
1325     for (auto& processPool : processPools()) {
1326         if (auto* networkProcess = processPool->networkProcess())
1327             networkProcess->setVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator] { });
1328     }
1329 }
1330
1331 void WebsiteDataStore::setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value, CompletionHandler<void()>&& completionHandler)
1332 {
1333     ASSERT(RunLoop::isMain());
1334     
1335     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1336
1337     for (auto& processPool : processPools())
1338         processPool->ensureNetworkProcess().setShouldClassifyResourcesBeforeDataRecordsRemoval(m_sessionID, value, [processPool, callbackAggregator] { });
1339 }
1340
1341 void WebsiteDataStore::setSubframeUnderTopFrameDomain(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1342 {
1343     ASSERT(RunLoop::isMain());
1344     
1345     if (subFrameURL.protocolIsAbout() || subFrameURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1346         completionHandler();
1347         return;
1348     }
1349
1350     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1351     
1352     for (auto& processPool : processPools()) {
1353         if (auto* process = processPool->networkProcess())
1354             process->setSubframeUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator] { });
1355     }
1356 }
1357
1358 void WebsiteDataStore::isRegisteredAsSubFrameUnder(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1359 {
1360     ASSERT(RunLoop::isMain());
1361
1362     for (auto& processPool : processPools()) {
1363         if (auto* process = processPool->networkProcess()) {
1364             process->isRegisteredAsSubFrameUnder(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1365             break;
1366         }
1367     }
1368 }
1369
1370 void WebsiteDataStore::setSubresourceUnderTopFrameDomain(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1371 {
1372     ASSERT(RunLoop::isMain());
1373     
1374     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1375         completionHandler();
1376         return;
1377     }
1378
1379     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1380     
1381     for (auto& processPool : processPools()) {
1382         if (auto* process = processPool->networkProcess())
1383             process->setSubresourceUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator] { });
1384     }
1385 }
1386
1387 void WebsiteDataStore::isRegisteredAsSubresourceUnder(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1388 {
1389     ASSERT(RunLoop::isMain());
1390     
1391     for (auto& processPool : processPools()) {
1392         if (auto* process = processPool->networkProcess()) {
1393             process->isRegisteredAsSubresourceUnder(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1394             return;
1395         }
1396     }
1397     completionHandler(false);
1398 }
1399
1400 void WebsiteDataStore::setSubresourceUniqueRedirectTo(const URL& subresourceURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1401 {
1402     ASSERT(RunLoop::isMain());
1403     
1404     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1405         completionHandler();
1406         return;
1407     }
1408
1409     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1410     
1411     for (auto& processPool : processPools()) {
1412         if (auto* process = processPool->networkProcess())
1413             process->setSubresourceUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator] { });
1414     }
1415 }
1416
1417 void WebsiteDataStore::setSubresourceUniqueRedirectFrom(const URL& subresourceURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1418 {
1419     ASSERT(RunLoop::isMain());
1420     
1421     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1422         completionHandler();
1423         return;
1424     }
1425
1426     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1427     
1428     for (auto& processPool : processPools()) {
1429         if (auto* process = processPool->networkProcess())
1430             process->setSubresourceUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator] { });
1431     }
1432 }
1433
1434 void WebsiteDataStore::setTopFrameUniqueRedirectTo(const URL& topFrameURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1435 {
1436     ASSERT(RunLoop::isMain());
1437     
1438     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1439         completionHandler();
1440         return;
1441     }
1442
1443     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1444     
1445     for (auto& processPool : processPools()) {
1446         if (auto* process = processPool->networkProcess())
1447             process->setTopFrameUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator] { });
1448     }
1449 }
1450
1451 void WebsiteDataStore::setTopFrameUniqueRedirectFrom(const URL& topFrameURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1452 {
1453     ASSERT(RunLoop::isMain());
1454     
1455     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1456         completionHandler();
1457         return;
1458     }
1459
1460     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1461     
1462     for (auto& processPool : processPools()) {
1463         if (auto* process = processPool->networkProcess())
1464             process->setTopFrameUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator] { });
1465     }
1466 }
1467
1468 void WebsiteDataStore::isRegisteredAsRedirectingTo(const URL& urlRedirectedFrom, const URL& urlRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
1469 {
1470     ASSERT(RunLoop::isMain());
1471     
1472     for (auto& processPool : processPools()) {
1473         if (auto* process = processPool->networkProcess()) {
1474             process->isRegisteredAsRedirectingTo(m_sessionID, WebCore::RegistrableDomain { urlRedirectedFrom }, WebCore::RegistrableDomain { urlRedirectedTo }, WTFMove(completionHandler));
1475             return;
1476         }
1477     }
1478     completionHandler(false);
1479 }
1480
1481 void WebsiteDataStore::clearPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1482 {
1483     ASSERT(RunLoop::isMain());
1484         
1485     if (url.protocolIsAbout() || url.isEmpty()) {
1486         completionHandler();
1487         return;
1488     }
1489
1490     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1491
1492     for (auto& processPool : processPools()) {
1493         if (auto* process = processPool->networkProcess())
1494             process->clearPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator] { });
1495     }
1496 }
1497
1498 void WebsiteDataStore::resetParametersToDefaultValues(CompletionHandler<void()>&& completionHandler)
1499 {
1500     ASSERT(RunLoop::isMain());
1501
1502     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1503     
1504     for (auto& processPool : processPools()) {
1505         if (auto* process = processPool->networkProcess())
1506             process->resetParametersToDefaultValues(m_sessionID, [processPool, callbackAggregator] { });
1507     }
1508 }
1509
1510 void WebsiteDataStore::submitTelemetry()
1511 {
1512     ASSERT(RunLoop::isMain());
1513     
1514     for (auto& processPool : processPools()) {
1515         if (auto* process = processPool->networkProcess())
1516             process->submitTelemetry(m_sessionID, [] { });
1517     }
1518 }
1519
1520 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1521 {
1522     ASSERT(RunLoop::isMain());
1523     
1524     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1525
1526     for (auto& processPool : processPools()) {
1527         if (auto* process = processPool->networkProcess())
1528             process->scheduleClearInMemoryAndPersistent(m_sessionID, modifiedSince, shouldGrandfather, [processPool, callbackAggregator] { });
1529     }
1530 }
1531
1532 void WebsiteDataStore::getResourceLoadStatisticsDataSummary(CompletionHandler<void(Vector<WebResourceLoadStatisticsStore::ThirdPartyData>&&)>&& completionHandler)
1533 {
1534     ASSERT(RunLoop::isMain());
1535
1536     struct CallbackAggregator : RefCounted<CallbackAggregator> {
1537         CallbackAggregator(CompletionHandler<void(Vector<WebResourceLoadStatisticsStore::ThirdPartyData>&&)>&& completionHandler)
1538             : m_completionHandler(WTFMove(completionHandler))
1539         {
1540             ASSERT(RunLoop::isMain());
1541         };
1542
1543         ~CallbackAggregator()
1544         {
1545             ASSERT(RunLoop::isMain());
1546
1547             m_completionHandler(WTFMove(m_results));
1548         }
1549
1550         void addResult(Vector<WebResourceLoadStatisticsStore::ThirdPartyData>&& results)
1551         {
1552             m_results.appendVector(WTFMove(results));
1553         }
1554
1555         CompletionHandler<void(Vector<WebResourceLoadStatisticsStore::ThirdPartyData>&&)> m_completionHandler;
1556         Vector<WebResourceLoadStatisticsStore::ThirdPartyData> m_results;
1557     };
1558
1559     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(WTFMove(completionHandler)));
1560
1561     for (auto& processPool : ensureProcessPools()) {
1562         processPool->ensureNetworkProcess(this).getResourceLoadStatisticsDataSummary(m_sessionID, [callbackAggregator, processPool](Vector<WebResourceLoadStatisticsStore::ThirdPartyData>&& data) {
1563             callbackAggregator->addResult(WTFMove(data));
1564         });
1565     }
1566 }
1567
1568 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1569 {
1570     ASSERT(RunLoop::isMain());
1571     
1572     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1573
1574     for (auto& processPool : processPools()) {
1575         if (auto* process = processPool->networkProcess())
1576             process->scheduleClearInMemoryAndPersistent(m_sessionID, { }, shouldGrandfather, [processPool, callbackAggregator] { });
1577     }
1578 }
1579
1580 void WebsiteDataStore::scheduleCookieBlockingUpdate(CompletionHandler<void()>&& completionHandler)
1581 {
1582     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1583
1584     for (auto& processPool : processPools()) {
1585         if (auto* process = processPool->networkProcess())
1586             process->scheduleCookieBlockingUpdate(m_sessionID, [processPool, callbackAggregator] { });
1587     }
1588 }
1589
1590 void WebsiteDataStore::scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&& completionHandler)
1591 {
1592     ASSERT(RunLoop::isMain());
1593     
1594     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1595     
1596     for (auto& processPool : processPools()) {
1597         if (auto* process = processPool->networkProcess())
1598             process->scheduleStatisticsAndDataRecordsProcessing(m_sessionID, [processPool, callbackAggregator] { });
1599     }
1600 }
1601
1602 void WebsiteDataStore::statisticsDatabaseHasAllTables(CompletionHandler<void(bool)>&& completionHandler)
1603 {
1604     ASSERT(RunLoop::isMain());
1605
1606     for (auto& processPool : processPools()) {
1607         if (auto* process = processPool->networkProcess()) {
1608             process->statisticsDatabaseHasAllTables(m_sessionID, WTFMove(completionHandler));
1609             return;
1610         }
1611     }
1612
1613     completionHandler(false);
1614 }
1615
1616 void WebsiteDataStore::setLastSeen(const URL& url, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1617 {
1618     if (url.protocolIsAbout() || url.isEmpty()) {
1619         completionHandler();
1620         return;
1621     }
1622
1623     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1624
1625     for (auto& processPool : processPools()) {
1626         if (auto* process = processPool->networkProcess())
1627             process->setLastSeen(m_sessionID, WebCore::RegistrableDomain { url }, seconds, [processPool, callbackAggregator] { });
1628     }
1629 }
1630
1631 void WebsiteDataStore::domainIDExistsInDatabase(int domainID, CompletionHandler<void(bool)>&& completionHandler)
1632 {
1633     ASSERT(RunLoop::isMain());
1634
1635     for (auto& processPool : processPools()) {
1636         if (auto* process = processPool->networkProcess()) {
1637             process->domainIDExistsInDatabase(m_sessionID, domainID, WTFMove(completionHandler));
1638             break;
1639         }
1640     }
1641 }
1642
1643 void WebsiteDataStore::mergeStatisticForTesting(const URL& url, const URL& topFrameUrl1, const URL& topFrameUrl2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
1644 {
1645     if (url.protocolIsAbout() || url.isEmpty()) {
1646         completionHandler();
1647         return;
1648     }
1649
1650     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1651
1652     for (auto& processPool : processPools()) {
1653         if (auto* process = processPool->networkProcess())
1654             process->mergeStatisticForTesting(m_sessionID, WebCore::RegistrableDomain { url }, WebCore::RegistrableDomain { topFrameUrl1 }, WebCore::RegistrableDomain { topFrameUrl2 }, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, [processPool, callbackAggregator] { });
1655     }
1656 }
1657
1658 void WebsiteDataStore::insertExpiredStatisticForTesting(const URL& url, bool hadUserInteraction, bool isScheduledForAllButCookieDataRemoval, bool isPrevalent, CompletionHandler<void()>&& completionHandler)
1659 {
1660     if (url.protocolIsAbout() || url.isEmpty()) {
1661         completionHandler();
1662         return;
1663     }
1664
1665     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1666
1667     for (auto& processPool : processPools()) {
1668         if (auto* process = processPool->networkProcess())
1669             process->insertExpiredStatisticForTesting(m_sessionID, WebCore::RegistrableDomain { url }, hadUserInteraction, isScheduledForAllButCookieDataRemoval, isPrevalent, [processPool, callbackAggregator] { });
1670     }
1671 }
1672
1673 void WebsiteDataStore::setNotifyPagesWhenDataRecordsWereScanned(bool value, CompletionHandler<void()>&& completionHandler)
1674 {
1675     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1676
1677     for (auto& processPool : processPools())
1678         processPool->ensureNetworkProcess().setNotifyPagesWhenDataRecordsWereScanned(m_sessionID, value, [processPool, callbackAggregator] { });
1679 }
1680
1681 void WebsiteDataStore::setIsRunningResourceLoadStatisticsTest(bool value, CompletionHandler<void()>&& completionHandler)
1682 {
1683     useExplicitITPState();
1684     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1685     
1686     for (auto& processPool : processPools())
1687         processPool->ensureNetworkProcess().setIsRunningResourceLoadStatisticsTest(m_sessionID, value, [processPool, callbackAggregator] { });
1688 }
1689
1690 void WebsiteDataStore::setNotifyPagesWhenTelemetryWasCaptured(bool value, CompletionHandler<void()>&& completionHandler)
1691 {
1692     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1693     
1694     for (auto& processPool : processPools())
1695         processPool->ensureNetworkProcess().setNotifyPagesWhenTelemetryWasCaptured(m_sessionID, value, [processPool, callbackAggregator] { });
1696 }
1697
1698 void WebsiteDataStore::getAllStorageAccessEntries(WebPageProxyIdentifier pageID, CompletionHandler<void(Vector<String>&& domains)>&& completionHandler)
1699 {
1700     auto* webPage = WebProcessProxy::webPage(pageID);
1701     if (!webPage) {
1702         completionHandler({ });
1703         return;
1704     }
1705
1706     webPage->process().processPool().ensureNetworkProcess().getAllStorageAccessEntries(m_sessionID, WTFMove(completionHandler));
1707 }
1708
1709
1710 void WebsiteDataStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1711 {
1712     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1713     
1714     for (auto& processPool : processPools())
1715         processPool->ensureNetworkProcess().setTimeToLiveUserInteraction(m_sessionID, seconds, [callbackAggregator] { });
1716 }
1717
1718 void WebsiteDataStore::logUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1719 {
1720     ASSERT(RunLoop::isMain());
1721     
1722     if (url.protocolIsAbout() || url.isEmpty()) {
1723         completionHandler();
1724         return;
1725     }
1726     
1727     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1728
1729     for (auto& processPool : processPools()) {
1730         if (auto* process = processPool->networkProcess())
1731             process->logUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator] { });
1732     }
1733 }
1734
1735 void WebsiteDataStore::hasHadUserInteraction(const URL& url, CompletionHandler<void(bool)>&& completionHandler)
1736 {
1737     ASSERT(RunLoop::isMain());
1738     
1739     if (url.protocolIsAbout() || url.isEmpty()) {
1740         completionHandler(false);
1741         return;
1742     }
1743     
1744     for (auto& processPool : processPools()) {
1745         if (auto* process = processPool->networkProcess()) {
1746             process->hasHadUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1747             return;
1748         }
1749     }
1750     completionHandler(false);
1751 }
1752
1753 void WebsiteDataStore::isRelationshipOnlyInDatabaseOnce(const URL& subUrl, const URL& topUrl, CompletionHandler<void(bool)>&& completionHandler)
1754 {
1755     ASSERT(RunLoop::isMain());
1756     
1757     if (subUrl.protocolIsAbout() || subUrl.isEmpty() || topUrl.protocolIsAbout() || topUrl.isEmpty()) {
1758         completionHandler(false);
1759         return;
1760     }
1761     
1762     for (auto& processPool : processPools()) {
1763         if (auto* process = processPool->networkProcess()) {
1764             process->isRelationshipOnlyInDatabaseOnce(m_sessionID, WebCore::RegistrableDomain { subUrl }, WebCore::RegistrableDomain { topUrl }, WTFMove(completionHandler));
1765             return;
1766         }
1767     }
1768     completionHandler(false);
1769 }
1770
1771 void WebsiteDataStore::clearUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1772 {
1773     ASSERT(RunLoop::isMain());
1774     
1775     if (url.protocolIsAbout() || url.isEmpty()) {
1776         completionHandler();
1777         return;
1778     }
1779     
1780     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1781
1782     for (auto& processPool : processPools()) {
1783         if (auto* process = processPool->networkProcess())
1784             process->clearUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator] { });
1785     }
1786 }
1787
1788 void WebsiteDataStore::setGrandfathered(const URL& url, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
1789 {
1790     ASSERT(RunLoop::isMain());
1791     
1792     if (url.protocolIsAbout() || url.isEmpty()) {
1793         completionHandler();
1794         return;
1795     }
1796     
1797     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1798     
1799     for (auto& processPool : processPools()) {
1800         if (auto* process = processPool->networkProcess())
1801             process->setGrandfathered(m_sessionID, WebCore::RegistrableDomain { url }, isGrandfathered, [callbackAggregator] { });
1802     }
1803 }
1804
1805 void WebsiteDataStore::setUseITPDatabase(bool value, CompletionHandler<void()>&& completionHandler)
1806 {
1807     ASSERT(RunLoop::isMain());
1808     
1809     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1810     
1811     for (auto& processPool : processPools()) {
1812         if (auto* process = processPool->networkProcess())
1813             process->setUseITPDatabase(m_sessionID, value, [callbackAggregator] { });
1814     }
1815 }
1816
1817 void WebsiteDataStore::setCrossSiteLoadWithLinkDecorationForTesting(const URL& fromURL, const URL& toURL, CompletionHandler<void()>&& completionHandler)
1818 {
1819     ASSERT(RunLoop::isMain());
1820     
1821     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1822     
1823     for (auto& processPool : processPools()) {
1824         if (auto* process = processPool->networkProcess())
1825             process->setCrossSiteLoadWithLinkDecorationForTesting(m_sessionID, WebCore::RegistrableDomain { fromURL }, WebCore::RegistrableDomain { toURL }, [processPool, callbackAggregator] { });
1826     }
1827 }
1828
1829 void WebsiteDataStore::resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&& completionHandler)
1830 {
1831     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1832     
1833     for (auto& processPool : processPools()) {
1834         if (auto* networkProcess = processPool->networkProcess())
1835             networkProcess->resetCrossSiteLoadsWithLinkDecorationForTesting(m_sessionID, [callbackAggregator] { });
1836     }
1837 }
1838
1839 void WebsiteDataStore::deleteCookiesForTesting(const URL& url, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1840 {
1841     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1842     
1843     for (auto& processPool : processPools()) {
1844         if (auto* networkProcess = processPool->networkProcess())
1845             networkProcess->deleteCookiesForTesting(m_sessionID, WebCore::RegistrableDomain { url }, includeHttpOnlyCookies, [callbackAggregator] { });
1846     }
1847 }
1848
1849 void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1850 {
1851     for (auto& processPool : processPools()) {
1852         if (auto* networkProcess = processPool->networkProcess()) {
1853             networkProcess->hasLocalStorage(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1854             return;
1855         }
1856     }
1857     completionHandler(false);
1858 }
1859
1860 void WebsiteDataStore::hasIsolatedSessionForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1861 {
1862     for (auto& processPool : processPools()) {
1863         if (auto* networkProcess = processPool->networkProcess()) {
1864             networkProcess->hasIsolatedSession(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1865             return;
1866         }
1867     }
1868     completionHandler(false);
1869 }
1870
1871 void WebsiteDataStore::setResourceLoadStatisticsShouldDowngradeReferrerForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
1872 {
1873     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1874     
1875     for (auto& processPool : processPools()) {
1876         if (auto* networkProcess = processPool->networkProcess())
1877             networkProcess->setShouldDowngradeReferrerForTesting(enabled, [callbackAggregator] { });
1878     }
1879 }
1880
1881 #if !PLATFORM(COCOA)
1882 WebCore::ThirdPartyCookieBlockingMode WebsiteDataStore::thirdPartyCookieBlockingMode() const
1883 {
1884     if (!m_thirdPartyCookieBlockingMode)
1885         m_thirdPartyCookieBlockingMode = WebCore::ThirdPartyCookieBlockingMode::All;
1886     return *m_thirdPartyCookieBlockingMode;
1887 }
1888 #endif
1889
1890 void WebsiteDataStore::setResourceLoadStatisticsShouldBlockThirdPartyCookiesForTesting(bool enabled, bool onlyOnSitesWithoutUserInteraction, CompletionHandler<void()>&& completionHandler)
1891 {
1892     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1893     WebCore::ThirdPartyCookieBlockingMode blockingMode = WebCore::ThirdPartyCookieBlockingMode::OnlyAccordingToPerDomainPolicy;
1894     if (enabled)
1895         blockingMode = onlyOnSitesWithoutUserInteraction ? WebCore::ThirdPartyCookieBlockingMode::AllOnSitesWithoutUserInteraction : WebCore::ThirdPartyCookieBlockingMode::All;
1896     setThirdPartyCookieBlockingMode(blockingMode, WTFMove(completionHandler));
1897 }
1898
1899 void WebsiteDataStore::setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode blockingMode, CompletionHandler<void()>&& completionHandler)
1900 {
1901     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1902
1903     if (thirdPartyCookieBlockingMode() != blockingMode) {
1904         m_thirdPartyCookieBlockingMode = blockingMode;
1905         for (auto& webProcess : processes())
1906             webProcess.setThirdPartyCookieBlockingMode(blockingMode, [callbackAggregator] { });
1907     }
1908
1909     for (auto& processPool : processPools()) {
1910         if (auto* networkProcess = processPool->networkProcess())
1911             networkProcess->setThirdPartyCookieBlockingMode(m_sessionID, blockingMode, [callbackAggregator] { });
1912     }
1913 }
1914
1915 void WebsiteDataStore::setResourceLoadStatisticsShouldEnbleSameSiteStrictEnforcementForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
1916 {
1917     auto flag = enabled ? WebCore::SameSiteStrictEnforcementEnabled::Yes : WebCore::SameSiteStrictEnforcementEnabled::No;
1918
1919     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1920     for (auto& processPool : processPools()) {
1921         if (auto* networkProcess = processPool->networkProcess())
1922             networkProcess->setShouldEnbleSameSiteStrictEnforcementForTesting(m_sessionID, flag, [callbackAggregator] { });
1923     }
1924 }
1925
1926 void WebsiteDataStore::setResourceLoadStatisticsFirstPartyWebsiteDataRemovalModeForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
1927 {
1928     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1929     auto mode = enabled ? WebCore::FirstPartyWebsiteDataRemovalMode::AllButCookies : WebCore::FirstPartyWebsiteDataRemovalMode::None;
1930
1931     for (auto& processPool : processPools()) {
1932         if (auto* networkProcess = processPool->networkProcess())
1933             networkProcess->setFirstPartyWebsiteDataRemovalModeForTesting(m_sessionID, mode, [callbackAggregator] { });
1934     }
1935 }
1936
1937 void WebsiteDataStore::setResourceLoadStatisticsToSameSiteStrictCookiesForTesting(const URL& url, CompletionHandler<void()>&& completionHandler)
1938 {
1939     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1940
1941     for (auto& processPool : processPools()) {
1942         if (auto* networkProcess = processPool->networkProcess())
1943             networkProcess->setToSameSiteStrictCookiesForTesting(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator] { });
1944     }
1945 }
1946 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1947
1948 void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1949 {
1950 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1951     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1952     
1953     for (auto& processPool : processPools())
1954         processPool->ensureNetworkProcess().setCacheMaxAgeCapForPrevalentResources(m_sessionID, seconds, [callbackAggregator] { });
1955 #else
1956     UNUSED_PARAM(seconds);
1957     completionHandler();
1958 #endif
1959 }
1960
1961 void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&& completionHandler)
1962 {
1963 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1964     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1965     
1966     for (auto& processPool : processPools()) {
1967         if (auto* networkProcess = processPool->networkProcess())
1968             networkProcess->resetCacheMaxAgeCapForPrevalentResources(m_sessionID, [callbackAggregator] { });
1969     }
1970 #else
1971     completionHandler();
1972 #endif
1973 }
1974
1975 bool WebsiteDataStore::isAssociatedProcessPool(WebProcessPool& processPool) const
1976 {
1977     if (auto* processPoolDataStore = processPool.websiteDataStore())
1978         return processPoolDataStore == this;
1979     return false;
1980 }
1981
1982 HashSet<RefPtr<WebProcessPool>> WebsiteDataStore::processPools(size_t limit) const
1983 {
1984     HashSet<RefPtr<WebProcessPool>> processPools;
1985     for (auto& process : processes()) {
1986         if (auto* processPool = process.processPoolIfExists()) {
1987             processPools.add(processPool);
1988             if (processPools.size() == limit)
1989                 break;
1990         }
1991     }
1992
1993     if (processPools.isEmpty()) {
1994         // Check if we're one of the legacy data stores.
1995         for (auto& processPool : WebProcessPool::allProcessPools()) {
1996             if (!isAssociatedProcessPool(*processPool))
1997                 continue;
1998
1999             processPools.add(processPool);
2000             if (processPools.size() == limit)
2001                 break;
2002         }
2003     }
2004
2005     return processPools;
2006 }
2007
2008 HashSet<RefPtr<WebProcessPool>> WebsiteDataStore::ensureProcessPools() const
2009 {
2010     auto processPools = this->processPools();
2011     if (processPools.isEmpty())
2012         processPools.add(WebProcessPool::create(API::ProcessPoolConfiguration::create()));
2013     return processPools;
2014 }
2015
2016 #if ENABLE(NETSCAPE_PLUGIN_API)
2017 Vector<PluginModuleInfo> WebsiteDataStore::plugins() const
2018 {
2019     Vector<PluginModuleInfo> plugins;
2020
2021     for (auto& processPool : ensureProcessPools()) {
2022         for (auto& plugin : processPool->pluginInfoStore().plugins())
2023             plugins.append(plugin);
2024     }
2025
2026     return plugins;
2027 }
2028 #endif
2029
2030 static String computeMediaKeyFile(const String& mediaKeyDirectory)
2031 {
2032     return FileSystem::pathByAppendingComponent(mediaKeyDirectory, "SecureStop.plist");
2033 }
2034
2035 Vector<WebCore::SecurityOriginData> WebsiteDataStore::mediaKeyOrigins(const String& mediaKeysStorageDirectory)
2036 {
2037     ASSERT(!mediaKeysStorageDirectory.isEmpty());
2038
2039     Vector<WebCore::SecurityOriginData> origins;
2040
2041     for (const auto& originPath : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
2042         auto mediaKeyFile = computeMediaKeyFile(originPath);
2043         if (!FileSystem::fileExists(mediaKeyFile))
2044             continue;
2045
2046         auto mediaKeyIdentifier = FileSystem::pathGetFileName(originPath);
2047
2048         if (auto securityOrigin = WebCore::SecurityOriginData::fromDatabaseIdentifier(mediaKeyIdentifier))
2049             origins.append(*securityOrigin);
2050     }
2051
2052     return origins;
2053 }
2054
2055 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, WallTime modifiedSince)
2056 {
2057     ASSERT(!mediaKeysStorageDirectory.isEmpty());
2058
2059     for (const auto& mediaKeyDirectory : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
2060         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
2061
2062         auto modificationTime = FileSystem::getFileModificationTime(mediaKeyFile);
2063         if (!modificationTime)
2064             continue;
2065
2066         if (modificationTime.value() < modifiedSince)
2067             continue;
2068
2069         FileSystem::deleteFile(mediaKeyFile);
2070         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
2071     }
2072 }
2073
2074 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, const HashSet<WebCore::SecurityOriginData>& origins)
2075 {
2076     ASSERT(!mediaKeysStorageDirectory.isEmpty());
2077
2078     for (const auto& origin : origins) {
2079         auto mediaKeyDirectory = FileSystem::pathByAppendingComponent(mediaKeysStorageDirectory, origin.databaseIdentifier());
2080         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
2081
2082         FileSystem::deleteFile(mediaKeyFile);
2083         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
2084     }
2085 }
2086
2087 bool WebsiteDataStore::resourceLoadStatisticsEnabled() const
2088 {
2089 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2090     return m_resourceLoadStatisticsEnabled;
2091 #else
2092     return false;
2093 #endif
2094 }
2095
2096 bool WebsiteDataStore::resourceLoadStatisticsDebugMode() const
2097 {
2098 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2099     return m_resourceLoadStatisticsDebugMode;
2100 #else
2101     return false;
2102 #endif
2103 }
2104
2105 void WebsiteDataStore::setResourceLoadStatisticsEnabled(bool enabled)
2106 {
2107 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2108     if (enabled == resourceLoadStatisticsEnabled())
2109         return;
2110
2111     if (enabled) {
2112         m_resourceLoadStatisticsEnabled = true;
2113         
2114         resolveDirectoriesIfNecessary();
2115         
2116         for (auto& processPool : processPools()) {
2117             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(m_sessionID, true));
2118             processPool->sendToAllProcessesForSession(Messages::WebProcess::SetResourceLoadStatisticsEnabled(true), m_sessionID);
2119         }
2120         return;
2121     }
2122
2123     for (auto& processPool : processPools()) {
2124         processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(m_sessionID, false));
2125         processPool->sendToAllProcessesForSession(Messages::WebProcess::SetResourceLoadStatisticsEnabled(false), m_sessionID);
2126     }
2127
2128     m_resourceLoadStatisticsEnabled = false;
2129 #else
2130     UNUSED_PARAM(enabled);
2131 #endif
2132 }
2133
2134 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2135 void WebsiteDataStore::setStatisticsTestingCallback(Function<void(const String&)>&& callback)
2136 {
2137     if (callback) {
2138         for (auto& processPool : processPools())
2139             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsLogTestingEvent(true));
2140     }
2141     
2142     m_statisticsTestingCallback = WTFMove(callback);
2143 }
2144 #endif
2145
2146 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled)
2147 {
2148     setResourceLoadStatisticsDebugMode(enabled, []() { });
2149 }
2150
2151 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled, CompletionHandler<void()>&& completionHandler)
2152 {
2153 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2154     m_resourceLoadStatisticsDebugMode = enabled;
2155
2156     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2157     
2158     for (auto& processPool : processPools())
2159         processPool->ensureNetworkProcess().setResourceLoadStatisticsDebugMode(m_sessionID, enabled, [callbackAggregator] { });
2160 #else
2161     UNUSED_PARAM(enabled);
2162     UNUSED_PARAM(completionHandler);
2163 #endif
2164 }
2165
2166 void WebsiteDataStore::isResourceLoadStatisticsEphemeral(CompletionHandler<void(bool)>&& completionHandler) const
2167 {
2168 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2169     if (!resourceLoadStatisticsEnabled() || !m_sessionID.isEphemeral()) {
2170         completionHandler(false);
2171         return;
2172     }
2173
2174     for (auto& processPool : processPools()) {
2175         if (auto* networkProcess = processPool->networkProcess()) {
2176             networkProcess->isResourceLoadStatisticsEphemeral(m_sessionID, WTFMove(completionHandler));
2177             return;
2178         }
2179     }
2180 #endif
2181     completionHandler(false);
2182 }
2183
2184 void WebsiteDataStore::setAdClickAttributionDebugMode(bool enabled)
2185 {
2186     for (auto& processPool : processPools())
2187         processPool->ensureNetworkProcess().setAdClickAttributionDebugMode(enabled);
2188 }
2189
2190 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2191 void WebsiteDataStore::logTestingEvent(const String& event)
2192 {
2193     ASSERT(RunLoop::isMain());
2194     
2195     if (m_statisticsTestingCallback)
2196         m_statisticsTestingCallback(event);
2197 }
2198
2199 void WebsiteDataStore::clearResourceLoadStatisticsInWebProcesses(CompletionHandler<void()>&& callback)
2200 {
2201     if (resourceLoadStatisticsEnabled()) {
2202         for (auto& processPool : processPools())
2203             processPool->sendToAllProcessesForSession(Messages::WebProcess::ClearResourceLoadStatistics(), m_sessionID);
2204     }
2205     callback();
2206 }
2207 #endif
2208
2209 Vector<WebCore::Cookie> WebsiteDataStore::pendingCookies() const
2210 {
2211     return copyToVector(m_pendingCookies);
2212 }
2213
2214 void WebsiteDataStore::addPendingCookie(const WebCore::Cookie& cookie)
2215 {
2216     m_pendingCookies.removeIf([&cookie](auto& pendingCookie) {
2217         return pendingCookie.isKeyEqual(cookie);
2218     });
2219     m_pendingCookies.add(cookie);
2220 }
2221
2222 void WebsiteDataStore::removePendingCookie(const WebCore::Cookie& cookie)
2223 {
2224     m_pendingCookies.remove(cookie);
2225 }
2226     
2227 void WebsiteDataStore::clearPendingCookies()
2228 {
2229     m_pendingCookies.clear();
2230 }
2231
2232 uint64_t WebsiteDataStore::perThirdPartyOriginStorageQuota() const
2233 {
2234     // FIXME: Consider whether allowing to set a perThirdPartyOriginStorageQuota from a WebsiteDataStore.
2235     return WebCore::StorageQuotaManager::defaultThirdPartyQuotaFromPerOriginQuota(perOriginStorageQuota());
2236 }
2237
2238 void WebsiteDataStore::setCacheModelSynchronouslyForTesting(CacheModel cacheModel)
2239 {
2240     for (auto processPool : WebProcessPool::allProcessPools())
2241         processPool->setCacheModelSynchronouslyForTesting(cacheModel);
2242 }
2243
2244 WebsiteDataStoreParameters WebsiteDataStore::parameters()
2245 {
2246     WebsiteDataStoreParameters parameters;
2247
2248     resolveDirectoriesIfNecessary();
2249
2250     parameters.pendingCookies = pendingCookies();
2251
2252     auto resourceLoadStatisticsDirectory = m_configuration->resourceLoadStatisticsDirectory();
2253     SandboxExtension::Handle resourceLoadStatisticsDirectoryHandle;
2254     if (!resourceLoadStatisticsDirectory.isEmpty())
2255         SandboxExtension::createHandleForReadWriteDirectory(resourceLoadStatisticsDirectory, resourceLoadStatisticsDirectoryHandle);
2256
2257     auto networkCacheDirectory = resolvedNetworkCacheDirectory();
2258     SandboxExtension::Handle networkCacheDirectoryExtensionHandle;
2259     if (!networkCacheDirectory.isEmpty())
2260         SandboxExtension::createHandleForReadWriteDirectory(networkCacheDirectory, networkCacheDirectoryExtensionHandle);
2261
2262     bool shouldIncludeLocalhostInResourceLoadStatistics = false;
2263     bool enableResourceLoadStatisticsDebugMode = false;
2264     auto firstPartyWebsiteDataRemovalMode = WebCore::FirstPartyWebsiteDataRemovalMode::AllButCookies;
2265     WebCore::RegistrableDomain standaloneApplicationDomain;
2266     HashSet<WebCore::RegistrableDomain> appBoundDomains;
2267 #if PLATFORM(COCOA)
2268     if (isAppBoundITPRelaxationEnabled)
2269         appBoundDomains = appBoundDomainsIfInitialized().valueOr(HashSet<WebCore::RegistrableDomain> { });
2270 #endif
2271     WebCore::RegistrableDomain resourceLoadStatisticsManualPrevalentResource;
2272     ResourceLoadStatisticsParameters resourceLoadStatisticsParameters = {
2273         WTFMove(resourceLoadStatisticsDirectory),
2274         WTFMove(resourceLoadStatisticsDirectoryHandle),
2275         resourceLoadStatisticsEnabled(),
2276 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2277         isItpStateExplicitlySet(),
2278         hasStatisticsTestingCallback(),
2279 #else
2280         false,
2281         false,
2282 #endif
2283         shouldIncludeLocalhostInResourceLoadStatistics,
2284         enableResourceLoadStatisticsDebugMode,
2285 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2286         thirdPartyCookieBlockingMode(),
2287         WebCore::SameSiteStrictEnforcementEnabled::No,
2288 #endif
2289         firstPartyWebsiteDataRemovalMode,
2290         WTFMove(standaloneApplicationDomain),
2291         WTFMove(appBoundDomains),
2292         WTFMove(resourceLoadStatisticsManualPrevalentResource),
2293     };
2294
2295     NetworkSessionCreationParameters networkSessionParameters;
2296     networkSessionParameters.sessionID = m_sessionID;
2297     networkSessionParameters.boundInterfaceIdentifier = configuration().boundInterfaceIdentifier();
2298     networkSessionParameters.allowsCellularAccess = configuration().allowsCellularAccess() ? AllowsCellularAccess::Yes : AllowsCellularAccess::No;
2299     networkSessionParameters.deviceManagementRestrictionsEnabled = m_configuration->deviceManagementRestrictionsEnabled();
2300     networkSessionParameters.allLoadsBlockedByDeviceManagementRestrictionsForTesting = m_configuration->allLoadsBlockedByDeviceManagementRestrictionsForTesting();
2301     networkSessionParameters.networkCacheDirectory = WTFMove(networkCacheDirectory);
2302     networkSessionParameters.networkCacheDirectoryExtensionHandle = WTFMove(networkCacheDirectoryExtensionHandle);
2303     networkSessionParameters.dataConnectionServiceType = m_configuration->dataConnectionServiceType();
2304     networkSessionParameters.fastServerTrustEvaluationEnabled = m_configuration->fastServerTrustEvaluationEnabled();
2305     networkSessionParameters.networkCacheSpeculativeValidationEnabled = m_configuration->networkCacheSpeculativeValidationEnabled();
2306     networkSessionParameters.shouldUseTestingNetworkSession = m_configuration->testingSessionEnabled();
2307     networkSessionParameters.staleWhileRevalidateEnabled = m_configuration->staleWhileRevalidateEnabled();
2308     networkSessionParameters.testSpeedMultiplier = m_configuration->testSpeedMultiplier();
2309     networkSessionParameters.suppressesConnectionTerminationOnSystemChange = m_configuration->suppressesConnectionTerminationOnSystemChange();
2310     networkSessionParameters.allowsServerPreconnect = m_configuration->allowsServerPreconnect();
2311     networkSessionParameters.resourceLoadStatisticsParameters = WTFMove(resourceLoadStatisticsParameters);
2312     networkSessionParameters.requiresSecureHTTPSProxyConnection = m_configuration->requiresSecureHTTPSProxyConnection();
2313     networkSessionParameters.preventsSystemHTTPProxyAuthentication = m_configuration->preventsSystemHTTPProxyAuthentication();
2314
2315     parameters.networkSessionParameters = WTFMove(networkSessionParameters);
2316
2317 #if ENABLE(INDEXED_DATABASE)
2318     parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
2319     if (!parameters.indexedDatabaseDirectory.isEmpty())
2320         SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
2321 #endif
2322
2323 #if ENABLE(SERVICE_WORKER)
2324     parameters.serviceWorkerRegistrationDirectory = resolvedServiceWorkerRegistrationDirectory();
2325     if (!parameters.serviceWorkerRegistrationDirectory.isEmpty())
2326         SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
2327     parameters.serviceWorkerProcessTerminationDelayEnabled = m_configuration->serviceWorkerProcessTerminationDelayEnabled();
2328 #endif
2329
2330     auto localStorageDirectory = resolvedLocalStorageDirectory();
2331     if (!localStorageDirectory.isEmpty()) {
2332         parameters.localStorageDirectory = localStorageDirectory;
2333         SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
2334     }
2335
2336     auto cacheStorageDirectory = this->cacheStorageDirectory();
2337     if (!cacheStorageDirectory.isEmpty()) {
2338         parameters.cacheStorageDirectory = cacheStorageDirectory;
2339         SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
2340     }
2341
2342     parameters.perOriginStorageQuota = perOriginStorageQuota();
2343     parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
2344
2345 #if ENABLE(RESOURCE_LOAD_STATISTICS)
2346     parameters.networkSessionParameters.resourceLoadStatisticsParameters.enabled = m_resourceLoadStatisticsEnabled;
2347 #endif
2348     platformSetNetworkParameters(parameters);
2349
2350     return parameters;
2351 }
2352
2353 #if HAVE(SEC_KEY_PROXY)
2354 void WebsiteDataStore::addSecKeyProxyStore(Ref<SecKeyProxyStore>&& store)
2355 {
2356     m_secKeyProxyStores.append(WTFMove(store));
2357 }
2358 #endif
2359
2360 #if ENABLE(WEB_AUTHN)
2361 void WebsiteDataStore::setMockWebAuthenticationConfiguration(WebCore::MockWebAuthenticationConfiguration&& configuration)
2362 {
2363     if (!m_authenticatorManager->isMock()) {
2364         m_authenticatorManager = makeUniqueRef<MockAuthenticatorManager>(WTFMove(configuration));
2365         return;
2366     }
2367     static_cast<MockAuthenticatorManager*>(&m_authenticatorManager)->setTestConfiguration(WTFMove(configuration));
2368 }
2369 #endif
2370
2371 API::HTTPCookieStore& WebsiteDataStore::cookieStore()
2372 {
2373     if (!m_cookieStore)
2374         m_cookieStore = API::HTTPCookieStore::create(*this);
2375
2376     return *m_cookieStore;
2377 }
2378
2379 void WebsiteDataStore::didCreateNetworkProcess()
2380 {
2381 }
2382
2383 void WebsiteDataStore::getLocalStorageDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2384 {
2385     if (!isPersistent()) {
2386         completionHandler({ });
2387         return;
2388     }
2389
2390     for (auto& processPool : ensureProcessPools()) {
2391         processPool->ensureNetworkProcess(this).getLocalStorageDetails(m_sessionID, [completionHandler = WTFMove(completionHandler)](auto&& details) {
2392             completionHandler(WTFMove(details));
2393         });
2394         // FIXME: Support fetching from multiple pools.
2395         break;
2396     }
2397     ASSERT(!completionHandler);
2398 }
2399
2400 void WebsiteDataStore::resetQuota(CompletionHandler<void()>&& completionHandler)
2401 {
2402     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2403     for (auto& processPool : processPools()) {
2404         if (auto* process = processPool->networkProcess())
2405             process->resetQuota(m_sessionID, [callbackAggregator] { });
2406     }
2407 }
2408
2409 #if !PLATFORM(COCOA)
2410 WTF::String WebsiteDataStore::defaultMediaCacheDirectory()
2411 {
2412     // FIXME: Implement. https://bugs.webkit.org/show_bug.cgi?id=156369 and https://bugs.webkit.org/show_bug.cgi?id=156370
2413     return WTF::String();
2414 }
2415
2416 WTF::String WebsiteDataStore::defaultAlternativeServicesDirectory()
2417 {
2418     // FIXME: Implement.
2419     return WTF::String();
2420 }
2421
2422 WTF::String WebsiteDataStore::defaultJavaScriptConfigurationDirectory()
2423 {
2424     // FIXME: Implement.
2425     return WTF::String();
2426 }
2427
2428 bool WebsiteDataStore::http3Enabled()
2429 {
2430     return false;
2431 }
2432 #endif
2433
2434 #if !USE(GLIB)
2435 WTF::String WebsiteDataStore::defaultDeviceIdHashSaltsStorageDirectory()
2436 {
2437     // Not implemented.
2438     return WTF::String();
2439 }
2440 #endif
2441
2442 void WebsiteDataStore::hasAppBoundSession(CompletionHandler<void(bool)>&& completionHandler) const
2443 {
2444     for (auto& processPool : processPools()) {
2445         if (auto* networkProcess = processPool->networkProcess()) {
2446             networkProcess->hasAppBoundSession(m_sessionID, WTFMove(completionHandler));
2447             return;
2448         }
2449     }
2450     completionHandler(false);
2451 }
2452
2453 void WebsiteDataStore::clearAppBoundSession(CompletionHandler<void()>&& completionHandler)
2454 {
2455     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2456
2457     for (auto& processPool : processPools()) {
2458         if (auto* networkProcess = processPool->networkProcess())
2459             networkProcess->clearAppBoundSession(m_sessionID, [processPool, callbackAggregator] { });
2460     }
2461 }
2462
2463 void WebsiteDataStore::renameOriginInWebsiteData(URL&& oldName, URL&& newName, OptionSet<WebsiteDataType> dataTypes, CompletionHandler<void()>&& completionHandler)
2464 {
2465     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2466     for (auto& processPool : WebProcessPool::allProcessPools()) {
2467         if (auto* networkProcess = processPool->networkProcess()) {
2468             networkProcess->addSession(*this);
2469             networkProcess->renameOriginInWebsiteData(m_sessionID, oldName, newName, dataTypes, [callbackAggregator] { });
2470         }
2471     }
2472 }
2473
2474 #if PLATFORM(COCOA)
2475 void WebsiteDataStore::forwardAppBoundDomainsToITPIfInitialized(CompletionHandler<void()>&& completionHandler)
2476 {
2477     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2478     auto appBoundDomains = appBoundDomainsIfInitialized();
2479     if (!appBoundDomains)
2480         return;
2481
2482     auto propagateAppBoundDomains = [callbackAggregator] (WebsiteDataStore* store, const HashSet<WebCore::RegistrableDomain>& domains) {
2483         if (!store)
2484             return;
2485
2486         if (store->thirdPartyCookieBlockingMode() != WebCore::ThirdPartyCookieBlockingMode::AllExceptBetweenAppBoundDomains)
2487             store->setThirdPartyCookieBlockingMode(WebCore::ThirdPartyCookieBlockingMode::AllExceptBetweenAppBoundDomains, [callbackAggregator] { });
2488
2489         store->setAppBoundDomainsForITP(domains, [callbackAggregator] { });
2490     };
2491
2492     propagateAppBoundDomains(globalDefaultDataStore().get(), *appBoundDomains);
2493
2494     for (auto* store : nonDefaultDataStores().values())
2495         propagateAppBoundDomains(store, *appBoundDomains);
2496 }
2497
2498 void WebsiteDataStore::setAppBoundDomainsForITP(const HashSet<WebCore::RegistrableDomain>& domains, CompletionHandler<void()>&& completionHandler)
2499 {
2500     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2501
2502     for (auto& processPool : processPools()) {
2503         if (auto* networkProcess = processPool->networkProcess())
2504             networkProcess->setAppBoundDomainsForResourceLoadStatistics(m_sessionID, domains, [callbackAggregator] { });
2505     }
2506 }
2507 #endif
2508
2509 void WebsiteDataStore::updateBundleIdentifierInNetworkProcess(const String& bundleIdentifier, CompletionHandler<void()>&& completionHandler)
2510 {
2511     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2512
2513     for (auto& processPool : processPools())
2514         processPool->ensureNetworkProcess().updateBundleIdentifier(bundleIdentifier, [callbackAggregator] { });
2515 }
2516
2517 void WebsiteDataStore::clearBundleIdentifierInNetworkProcess(CompletionHandler<void()>&& completionHandler)
2518 {
2519     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
2520
2521     for (auto& processPool : processPools())
2522         processPool->ensureNetworkProcess().clearBundleIdentifier([callbackAggregator] { });
2523 }
2524
2525 }