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