Unreviewed, rolling out r250324.
[WebKit-https.git] / Source / WebKit / UIProcess / WebsiteData / WebsiteDataStore.cpp
1 /*
2  * Copyright (C) 2014-2019 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 "MockAuthenticatorManager.h"
35 #include "NetworkProcessMessages.h"
36 #include "ShouldGrandfatherStatistics.h"
37 #include "StorageAccessStatus.h"
38 #include "WebKit2Initialize.h"
39 #include "WebPageProxy.h"
40 #include "WebProcessCache.h"
41 #include "WebProcessMessages.h"
42 #include "WebProcessPool.h"
43 #include "WebResourceLoadStatisticsStore.h"
44 #include "WebsiteData.h"
45 #include "WebsiteDataStoreClient.h"
46 #include "WebsiteDataStoreParameters.h"
47 #include <WebCore/ApplicationCacheStorage.h>
48 #include <WebCore/CredentialStorage.h>
49 #include <WebCore/DatabaseTracker.h>
50 #include <WebCore/HTMLMediaElement.h>
51 #include <WebCore/OriginLock.h>
52 #include <WebCore/RegistrableDomain.h>
53 #include <WebCore/SecurityOrigin.h>
54 #include <WebCore/SecurityOriginData.h>
55 #include <WebCore/StorageQuotaManager.h>
56 #include <wtf/CallbackAggregator.h>
57 #include <wtf/CompletionHandler.h>
58 #include <wtf/CrossThreadCopier.h>
59 #include <wtf/FileSystem.h>
60 #include <wtf/ProcessPrivilege.h>
61 #include <wtf/RunLoop.h>
62
63 #if ENABLE(NETSCAPE_PLUGIN_API)
64 #include "PluginProcessManager.h"
65 #endif
66
67 #if HAVE(SEC_KEY_PROXY)
68 #include "SecKeyProxyStore.h"
69 #endif
70
71 #if HAVE(APP_SSO)
72 #include "SOAuthorizationCoordinator.h"
73 #endif
74
75 namespace WebKit {
76
77 static bool allowsWebsiteDataRecordsForAllOrigins;
78 void WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins()
79 {
80     allowsWebsiteDataRecordsForAllOrigins = true;
81 }
82
83 static HashMap<PAL::SessionID, WebsiteDataStore*>& nonDefaultDataStores()
84 {
85     RELEASE_ASSERT(isUIThread());
86     static NeverDestroyed<HashMap<PAL::SessionID, WebsiteDataStore*>> map;
87     return map;
88 }
89
90 Ref<WebsiteDataStore> WebsiteDataStore::createNonPersistent()
91 {
92     return adoptRef(*new WebsiteDataStore(PAL::SessionID::generateEphemeralSessionID()));
93 }
94
95 Ref<WebsiteDataStore> WebsiteDataStore::create(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
96 {
97     return adoptRef(*new WebsiteDataStore(WTFMove(configuration), sessionID));
98 }
99
100 WebsiteDataStore::WebsiteDataStore(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
101     : m_sessionID(sessionID)
102     , m_resolvedConfiguration(WTFMove(configuration))
103     , m_configuration(m_resolvedConfiguration->copy())
104     , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String()))
105     , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore"))
106 #if ENABLE(WEB_AUTHN)
107     , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>())
108 #endif
109     , m_client(makeUniqueRef<WebsiteDataStoreClient>())
110 #if HAVE(APP_SSO)
111     , m_soAuthorizationCoordinator(makeUniqueRef<SOAuthorizationCoordinator>())
112 #endif
113 {
114     WTF::setProcessPrivileges(allPrivileges());
115     maybeRegisterWithSessionIDMap();
116     platformInitialize();
117
118     ASSERT(RunLoop::isMain());
119 }
120
121 WebsiteDataStore::WebsiteDataStore(PAL::SessionID sessionID)
122     : m_sessionID(sessionID)
123     , m_resolvedConfiguration(WebsiteDataStoreConfiguration::create())
124     , m_configuration(m_resolvedConfiguration->copy())
125     , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String()))
126     , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore"))
127 #if ENABLE(WEB_AUTHN)
128     , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>())
129 #endif
130     , m_client(makeUniqueRef<WebsiteDataStoreClient>())
131 #if HAVE(APP_SSO)
132     , m_soAuthorizationCoordinator(makeUniqueRef<SOAuthorizationCoordinator>())
133 #endif
134 {
135     maybeRegisterWithSessionIDMap();
136     platformInitialize();
137
138     ASSERT(RunLoop::isMain());
139 }
140
141 WebsiteDataStore::~WebsiteDataStore()
142 {
143     ASSERT(RunLoop::isMain());
144
145     platformDestroy();
146
147     if (m_sessionID != PAL::SessionID::defaultSessionID()) {
148         ASSERT(nonDefaultDataStores().get(m_sessionID) == this);
149         nonDefaultDataStores().remove(m_sessionID);
150         for (auto& processPool : WebProcessPool::allProcessPools()) {
151             if (auto* networkProcess = processPool->networkProcess())
152                 networkProcess->removeSession(m_sessionID);
153         }
154     }
155 }
156
157 static RefPtr<WebsiteDataStore>& globalDefaultDataStore()
158 {
159     static NeverDestroyed<RefPtr<WebsiteDataStore>> globalDefaultDataStore;
160     return globalDefaultDataStore.get();
161 }
162
163 Ref<WebsiteDataStore> WebsiteDataStore::defaultDataStore()
164 {
165     InitializeWebKit2();
166
167     auto& store = globalDefaultDataStore();
168     if (!store)
169         store = adoptRef(new WebsiteDataStore(defaultDataStoreConfiguration(), PAL::SessionID::defaultSessionID()));
170
171     return *store;
172 }
173
174 void WebsiteDataStore::deleteDefaultDataStoreForTesting()
175 {
176     globalDefaultDataStore() = nullptr;
177 }
178
179 bool WebsiteDataStore::defaultDataStoreExists()
180 {
181     return !!globalDefaultDataStore();
182 }
183
184 Ref<WebKit::WebsiteDataStoreConfiguration> WebsiteDataStore::defaultDataStoreConfiguration()
185 {
186     auto configuration = WebsiteDataStoreConfiguration::create();
187
188     configuration->setPersistent(true);
189
190     configuration->setApplicationCacheDirectory(defaultApplicationCacheDirectory());
191     configuration->setCacheStorageDirectory(defaultCacheStorageDirectory());
192     configuration->setNetworkCacheDirectory(defaultNetworkCacheDirectory());
193     configuration->setMediaCacheDirectory(defaultMediaCacheDirectory());
194
195     configuration->setIndexedDBDatabaseDirectory(defaultIndexedDBDatabaseDirectory());
196     configuration->setServiceWorkerRegistrationDirectory(defaultServiceWorkerRegistrationDirectory());
197     configuration->setWebSQLDatabaseDirectory(defaultWebSQLDatabaseDirectory());
198     configuration->setLocalStorageDirectory(defaultLocalStorageDirectory());
199     configuration->setMediaKeysStorageDirectory(defaultMediaKeysStorageDirectory());
200     configuration->setResourceLoadStatisticsDirectory(defaultResourceLoadStatisticsDirectory());
201     configuration->setDeviceIdHashSaltsStorageDirectory(defaultDeviceIdHashSaltsStorageDirectory());
202
203     configuration->setJavaScriptConfigurationDirectory(defaultJavaScriptConfigurationDirectory());
204
205     return configuration;
206 }
207
208 void WebsiteDataStore::maybeRegisterWithSessionIDMap()
209 {
210     if (m_sessionID != PAL::SessionID::defaultSessionID()) {
211         auto result = nonDefaultDataStores().add(m_sessionID, this);
212         ASSERT_UNUSED(result, result.isNewEntry);
213     }
214 }
215
216 WebsiteDataStore* WebsiteDataStore::existingNonDefaultDataStoreForSessionID(PAL::SessionID sessionID)
217 {
218     return sessionID != PAL::SessionID::defaultSessionID() ? nonDefaultDataStores().get(sessionID) : nullptr;
219 }
220
221 void WebsiteDataStore::registerProcess(WebProcessProxy& process)
222 {
223     ASSERT(process.pageCount() || process.provisionalPageCount());
224     m_processes.add(process);
225 }
226
227 void WebsiteDataStore::unregisterProcess(WebProcessProxy& process)
228 {
229     ASSERT(!process.pageCount());
230     ASSERT(!process.provisionalPageCount());
231     m_processes.remove(process);
232 }
233
234 WebProcessPool* WebsiteDataStore::processPoolForCookieStorageOperations()
235 {
236     auto pools = processPools(1, false);
237     return pools.isEmpty() ? nullptr : pools.begin()->get();
238 }
239
240 void WebsiteDataStore::resolveDirectoriesIfNecessary()
241 {
242     if (m_hasResolvedDirectories)
243         return;
244     m_hasResolvedDirectories = true;
245
246     // Resolve directory paths.
247     if (!m_configuration->applicationCacheDirectory().isEmpty())
248         m_resolvedConfiguration->setApplicationCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory()));
249     if (!m_configuration->mediaCacheDirectory().isEmpty())
250         m_resolvedConfiguration->setMediaCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory()));
251     if (!m_configuration->mediaKeysStorageDirectory().isEmpty())
252         m_resolvedConfiguration->setMediaKeysStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory()));
253     if (!m_configuration->webSQLDatabaseDirectory().isEmpty())
254         m_resolvedConfiguration->setWebSQLDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory()));
255     if (!m_configuration->indexedDBDatabaseDirectory().isEmpty())
256         m_resolvedConfiguration->setIndexedDBDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory()));
257     if (!m_configuration->deviceIdHashSaltsStorageDirectory().isEmpty())
258         m_resolvedConfiguration->setDeviceIdHashSaltsStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->deviceIdHashSaltsStorageDirectory()));
259     if (!m_configuration->networkCacheDirectory().isEmpty())
260         m_resolvedConfiguration->setNetworkCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->networkCacheDirectory()));
261     if (!m_configuration->resourceLoadStatisticsDirectory().isEmpty())
262         m_resolvedConfiguration->setResourceLoadStatisticsDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->resourceLoadStatisticsDirectory()));
263     if (!m_configuration->serviceWorkerRegistrationDirectory().isEmpty() && m_resolvedConfiguration->serviceWorkerRegistrationDirectory().isEmpty())
264         m_resolvedConfiguration->setServiceWorkerRegistrationDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->serviceWorkerRegistrationDirectory()));
265     if (!m_configuration->javaScriptConfigurationDirectory().isEmpty())
266         m_resolvedConfiguration->setJavaScriptConfigurationDirectory(resolvePathForSandboxExtension(m_configuration->javaScriptConfigurationDirectory()));
267     if (!m_configuration->cacheStorageDirectory().isEmpty() && m_resolvedConfiguration->cacheStorageDirectory().isEmpty())
268         m_resolvedConfiguration->setCacheStorageDirectory(resolvePathForSandboxExtension(m_configuration->cacheStorageDirectory()));
269
270     // Resolve directories for file paths.
271     if (!m_configuration->cookieStorageFile().isEmpty()) {
272         m_resolvedConfiguration->setCookieStorageFile(resolveAndCreateReadWriteDirectoryForSandboxExtension(FileSystem::directoryName(m_configuration->cookieStorageFile())));
273         m_resolvedConfiguration->setCookieStorageFile(FileSystem::pathByAppendingComponent(m_resolvedConfiguration->cookieStorageFile(), FileSystem::pathGetFileName(m_configuration->cookieStorageFile())));
274     }
275 }
276
277 enum class ProcessAccessType {
278     None,
279     OnlyIfLaunched,
280     Launch,
281 };
282
283 static ProcessAccessType computeNetworkProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
284 {
285     for (auto dataType : dataTypes) {
286         if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network) {
287             if (isNonPersistentStore)
288                 return ProcessAccessType::OnlyIfLaunched;
289             return ProcessAccessType::Launch;
290         }
291     }
292     return ProcessAccessType::None;
293 }
294
295 static ProcessAccessType computeWebProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
296 {
297     UNUSED_PARAM(isNonPersistentStore);
298
299     ProcessAccessType processAccessType = ProcessAccessType::None;
300
301     if (dataTypes.contains(WebsiteDataType::MemoryCache))
302         return ProcessAccessType::OnlyIfLaunched;
303
304     return processAccessType;
305 }
306
307 void WebsiteDataStore::fetchData(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void(Vector<WebsiteDataRecord>)>&& completionHandler)
308 {
309     fetchDataAndApply(dataTypes, fetchOptions, nullptr, WTFMove(completionHandler));
310 }
311
312 void WebsiteDataStore::fetchDataAndApply(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply)
313 {
314     struct CallbackAggregator final : ThreadSafeRefCounted<CallbackAggregator> {
315         CallbackAggregator(OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply, WebsiteDataStore& dataStore)
316             : fetchOptions(fetchOptions)
317             , queue(WTFMove(queue))
318             , apply(WTFMove(apply))
319             , protectedDataStore(dataStore)
320         {
321             ASSERT(RunLoop::isMain());
322         }
323
324         ~CallbackAggregator()
325         {
326             ASSERT(!pendingCallbacks);
327
328             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
329             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
330         }
331
332         void addPendingCallback()
333         {
334             pendingCallbacks++;
335         }
336
337         void removePendingCallback(WebsiteData websiteData)
338         {
339             ASSERT(pendingCallbacks);
340             --pendingCallbacks;
341
342             for (auto& entry : websiteData.entries) {
343                 auto displayName = WebsiteDataRecord::displayNameForOrigin(entry.origin);
344                 if (!displayName) {
345                     if (!allowsWebsiteDataRecordsForAllOrigins)
346                         continue;
347
348                     displayName = makeString(entry.origin.protocol, " ", entry.origin.host);
349                 }
350
351                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
352                 if (!record.displayName)
353                     record.displayName = WTFMove(displayName);
354
355                 record.add(entry.type, entry.origin);
356
357                 if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes)) {
358                     if (!record.size)
359                         record.size = WebsiteDataRecord::Size { 0, { } };
360
361                     record.size->totalSize += entry.size;
362                     record.size->typeSizes.add(static_cast<unsigned>(entry.type), 0).iterator->value += entry.size;
363                 }
364             }
365
366             for (auto& hostName : websiteData.hostNamesWithCookies) {
367                 auto displayName = WebsiteDataRecord::displayNameForCookieHostName(hostName);
368                 if (!displayName)
369                     continue;
370
371                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
372                 if (!record.displayName)
373                     record.displayName = WTFMove(displayName);
374
375                 record.addCookieHostName(hostName);
376             }
377
378 #if ENABLE(NETSCAPE_PLUGIN_API)
379             for (auto& hostName : websiteData.hostNamesWithPluginData) {
380                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
381                 if (!displayName)
382                     continue;
383
384                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
385                 if (!record.displayName)
386                     record.displayName = WTFMove(displayName);
387
388                 record.addPluginDataHostName(hostName);
389             }
390 #endif
391
392             for (auto& hostName : websiteData.hostNamesWithHSTSCache) {
393                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
394                 if (!displayName)
395                     continue;
396                 
397                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
398                 if (!record.displayName)
399                     record.displayName = WTFMove(displayName);
400
401                 record.addHSTSCacheHostname(hostName);
402             }
403
404             callIfNeeded();
405         }
406
407         void callIfNeeded()
408         {
409             if (pendingCallbacks)
410                 return;
411
412             Vector<WebsiteDataRecord> records;
413             records.reserveInitialCapacity(m_websiteDataRecords.size());
414             for (auto& record : m_websiteDataRecords.values())
415                 records.uncheckedAppend(WTFMove(record));
416
417             auto processRecords = [apply = WTFMove(apply), records = WTFMove(records)] () mutable {
418                 apply(WTFMove(records));
419             };
420
421             if (queue)
422                 queue->dispatch(WTFMove(processRecords));
423             else
424                 RunLoop::main().dispatch(WTFMove(processRecords));
425         }
426
427         const OptionSet<WebsiteDataFetchOption> fetchOptions;
428
429         unsigned pendingCallbacks = 0;
430         RefPtr<WorkQueue> queue;
431         Function<void(Vector<WebsiteDataRecord>)> apply;
432
433         HashMap<String, WebsiteDataRecord> m_websiteDataRecords;
434         Ref<WebsiteDataStore> protectedDataStore;
435     };
436
437     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(fetchOptions, WTFMove(queue), WTFMove(apply), *this));
438
439 #if ENABLE(VIDEO)
440     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
441         callbackAggregator->addPendingCallback();
442         m_queue->dispatch([mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
443             // FIXME: Make HTMLMediaElement::originsInMediaCache return a collection of SecurityOriginDatas.
444             HashSet<RefPtr<WebCore::SecurityOrigin>> origins = WebCore::HTMLMediaElement::originsInMediaCache(mediaCacheDirectory);
445             WebsiteData websiteData;
446             
447             for (auto& origin : origins) {
448                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::DiskCache, 0 };
449                 websiteData.entries.append(WTFMove(entry));
450             }
451             
452             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
453                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
454             });
455         });
456     }
457 #endif
458
459     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
460     if (networkProcessAccessType != ProcessAccessType::None) {
461         for (auto& processPool : processPools()) {
462             switch (networkProcessAccessType) {
463             case ProcessAccessType::OnlyIfLaunched:
464                 if (!processPool->networkProcess())
465                     continue;
466                 break;
467
468             case ProcessAccessType::Launch:
469                 processPool->ensureNetworkProcess(this);
470                 break;
471
472             case ProcessAccessType::None:
473                 ASSERT_NOT_REACHED();
474             }
475
476             callbackAggregator->addPendingCallback();
477             processPool->networkProcess()->fetchWebsiteData(m_sessionID, dataTypes, fetchOptions, [callbackAggregator, processPool](WebsiteData websiteData) {
478                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
479             });
480         }
481     }
482
483     auto webProcessAccessType = computeWebProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
484     if (webProcessAccessType != ProcessAccessType::None) {
485         for (auto& process : processes()) {
486             switch (webProcessAccessType) {
487             case ProcessAccessType::OnlyIfLaunched:
488                 if (process.state() != WebProcessProxy::State::Running)
489                     continue;
490                 break;
491
492             case ProcessAccessType::Launch:
493                 // FIXME: Handle this.
494                 ASSERT_NOT_REACHED();
495                 break;
496
497             case ProcessAccessType::None:
498                 ASSERT_NOT_REACHED();
499             }
500
501             callbackAggregator->addPendingCallback();
502             process.fetchWebsiteData(m_sessionID, dataTypes, [callbackAggregator](WebsiteData websiteData) {
503                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
504             });
505         }
506     }
507
508     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt)) {
509         callbackAggregator->addPendingCallback();
510
511         m_deviceIdHashSaltStorage->getDeviceIdHashSaltOrigins([callbackAggregator](auto&& origins) {
512             WebsiteData websiteData;
513
514             while (!origins.isEmpty())
515                 websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::DeviceIdHashSalt, 0 });
516
517             callbackAggregator->removePendingCallback(WTFMove(websiteData));
518         });
519     }
520
521     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
522         callbackAggregator->addPendingCallback();
523
524         m_queue->dispatch([fetchOptions, applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
525             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
526
527             WebsiteData websiteData;
528
529             // FIXME: getOriginsWithCache should return a collection of SecurityOriginDatas.
530             auto origins = storage->originsWithCache();
531
532             for (auto& origin : origins) {
533                 uint64_t size = fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes) ? storage->diskUsageForOrigin(origin) : 0;
534                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::OfflineWebApplicationCache, size };
535
536                 websiteData.entries.append(WTFMove(entry));
537             }
538
539             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
540                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
541             });
542         });
543     }
544
545     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
546         callbackAggregator->addPendingCallback();
547
548         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator] {
549             auto origins = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->origins();
550             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
551                 WebsiteData websiteData;
552                 for (auto& origin : origins)
553                     websiteData.entries.append(WebsiteData::Entry { WTFMove(origin), WebsiteDataType::WebSQLDatabases, 0 });
554                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
555             });
556         });
557     }
558
559     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
560         callbackAggregator->addPendingCallback();
561
562         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator] {
563             auto origins = mediaKeyOrigins(mediaKeysStorageDirectory);
564
565             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
566                 WebsiteData websiteData;
567                 for (auto& origin : origins)
568                     websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataType::MediaKeys, 0 });
569
570                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
571             });
572         });
573     }
574
575 #if ENABLE(NETSCAPE_PLUGIN_API)
576     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
577         class State {
578         public:
579             static void fetchData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
580             {
581                 new State(WTFMove(callbackAggregator), WTFMove(plugins));
582             }
583
584         private:
585             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
586                 : m_callbackAggregator(WTFMove(callbackAggregator))
587                 , m_plugins(WTFMove(plugins))
588             {
589                 m_callbackAggregator->addPendingCallback();
590
591                 fetchWebsiteDataForNextPlugin();
592             }
593
594             ~State()
595             {
596                 ASSERT(m_plugins.isEmpty());
597             }
598
599             void fetchWebsiteDataForNextPlugin()
600             {
601                 if (m_plugins.isEmpty()) {
602                     WebsiteData websiteData;
603                     websiteData.hostNamesWithPluginData = WTFMove(m_hostNames);
604
605                     m_callbackAggregator->removePendingCallback(WTFMove(websiteData));
606
607                     delete this;
608                     return;
609                 }
610
611                 auto plugin = m_plugins.takeLast();
612                 PluginProcessManager::singleton().fetchWebsiteData(plugin, m_callbackAggregator->fetchOptions, [this](Vector<String> hostNames) {
613                     for (auto& hostName : hostNames)
614                         m_hostNames.add(WTFMove(hostName));
615                     fetchWebsiteDataForNextPlugin();
616                 });
617             }
618
619             Ref<CallbackAggregator> m_callbackAggregator;
620             Vector<PluginModuleInfo> m_plugins;
621             HashSet<String> m_hostNames;
622         };
623
624         State::fetchData(*callbackAggregator, plugins());
625     }
626 #endif
627
628     callbackAggregator->callIfNeeded();
629 }
630
631 #if ENABLE(RESOURCE_LOAD_STATISTICS)
632 void WebsiteDataStore::fetchDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(Vector<WebsiteDataRecord>&&, HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
633 {
634     fetchDataAndApply(dataTypes, fetchOptions, m_queue.copyRef(), [domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)] (auto&& existingDataRecords) mutable {
635         ASSERT(!RunLoop::isMain());
636         
637         Vector<WebsiteDataRecord> matchingDataRecords;
638         HashSet<WebCore::RegistrableDomain> domainsWithMatchingDataRecords;
639         for (auto&& dataRecord : existingDataRecords) {
640             for (auto& domain : domains) {
641                 if (dataRecord.matches(domain)) {
642                     matchingDataRecords.append(WTFMove(dataRecord));
643                     domainsWithMatchingDataRecords.add(domain.isolatedCopy());
644                     break;
645                 }
646             }
647         }
648         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), matchingDataRecords = WTFMove(matchingDataRecords), domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords)] () mutable {
649             completionHandler(WTFMove(matchingDataRecords), WTFMove(domainsWithMatchingDataRecords));
650         });
651     });
652 }
653 #endif
654
655 static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
656 {
657     ProcessAccessType processAccessType = ProcessAccessType::None;
658
659     for (auto dataType : dataTypes) {
660         if (dataType == WebsiteDataType::Cookies) {
661             if (isNonPersistentStore)
662                 processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
663             else
664                 processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
665         } else if (WebsiteData::ownerProcess(dataType) == WebsiteDataProcessType::Network)
666             return ProcessAccessType::Launch;
667     }
668     
669     return processAccessType;
670 }
671
672 static ProcessAccessType computeWebProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
673 {
674     UNUSED_PARAM(isNonPersistentStore);
675
676     ProcessAccessType processAccessType = ProcessAccessType::None;
677
678     if (dataTypes.contains(WebsiteDataType::MemoryCache))
679         processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
680
681     return processAccessType;
682 }
683
684 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, Function<void()>&& completionHandler)
685 {
686     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
687         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
688             : completionHandler(WTFMove(completionHandler))
689             , protectedDataStore(dataStore)
690         {
691             ASSERT(RunLoop::isMain());
692         }
693
694         ~CallbackAggregator()
695         {
696             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
697             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
698         }
699
700         void addPendingCallback()
701         {
702             pendingCallbacks++;
703         }
704
705         void removePendingCallback()
706         {
707             ASSERT(pendingCallbacks);
708             --pendingCallbacks;
709
710             callIfNeeded();
711         }
712
713         void callIfNeeded()
714         {
715             if (!pendingCallbacks)
716                 RunLoop::main().dispatch(WTFMove(completionHandler));
717         }
718
719         unsigned pendingCallbacks = 0;
720         Function<void()> completionHandler;
721         Ref<WebsiteDataStore> protectedDataStore;
722     };
723
724     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
725
726 #if ENABLE(VIDEO)
727     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
728         callbackAggregator->addPendingCallback();
729         m_queue->dispatch([modifiedSince, mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
730             WebCore::HTMLMediaElement::clearMediaCache(mediaCacheDirectory, modifiedSince);
731             
732             WTF::RunLoop::main().dispatch([callbackAggregator] {
733                 callbackAggregator->removePendingCallback();
734             });
735         });
736     }
737 #endif
738
739 #if ENABLE(RESOURCE_LOAD_STATISTICS)
740     bool didNotifyNetworkProcessToDeleteWebsiteData = false;
741 #endif
742     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
743     if (networkProcessAccessType != ProcessAccessType::None) {
744         for (auto& processPool : processPools()) {
745             switch (networkProcessAccessType) {
746             case ProcessAccessType::OnlyIfLaunched:
747                 if (!processPool->networkProcess())
748                     continue;
749                 break;
750
751             case ProcessAccessType::Launch:
752                 processPool->ensureNetworkProcess(this);
753                 break;
754
755             case ProcessAccessType::None:
756                 ASSERT_NOT_REACHED();
757             }
758
759             callbackAggregator->addPendingCallback();
760             processPool->networkProcess()->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator, processPool] {
761                 callbackAggregator->removePendingCallback();
762             });
763 #if ENABLE(RESOURCE_LOAD_STATISTICS)
764             didNotifyNetworkProcessToDeleteWebsiteData = true;
765 #endif
766         }
767     }
768
769     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
770     if (webProcessAccessType != ProcessAccessType::None) {
771         for (auto& processPool : processPools()) {
772             processPool->clearSuspendedPages(AllowProcessCaching::No);
773             processPool->webProcessCache().clear();
774         }
775
776         for (auto& process : processes()) {
777             switch (webProcessAccessType) {
778             case ProcessAccessType::OnlyIfLaunched:
779                 if (process.state() != WebProcessProxy::State::Running)
780                     continue;
781                 break;
782
783             case ProcessAccessType::Launch:
784                 // FIXME: Handle this.
785                 ASSERT_NOT_REACHED();
786                 break;
787
788             case ProcessAccessType::None:
789                 ASSERT_NOT_REACHED();
790             }
791
792             callbackAggregator->addPendingCallback();
793             process.deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator] {
794                 callbackAggregator->removePendingCallback();
795             });
796         }
797     }
798
799     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
800         callbackAggregator->addPendingCallback();
801
802         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltOriginsModifiedSince(modifiedSince, [callbackAggregator] {
803             callbackAggregator->removePendingCallback();
804         });
805     }
806
807     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
808         callbackAggregator->addPendingCallback();
809
810         m_queue->dispatch([applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
811             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
812
813             storage->deleteAllCaches();
814
815             WTF::RunLoop::main().dispatch([callbackAggregator] {
816                 callbackAggregator->removePendingCallback();
817             });
818         });
819     }
820
821     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
822         callbackAggregator->addPendingCallback();
823
824         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
825             WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->deleteDatabasesModifiedSince(modifiedSince);
826
827             RunLoop::main().dispatch([callbackAggregator] {
828                 callbackAggregator->removePendingCallback();
829             });
830         });
831     }
832
833     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
834         callbackAggregator->addPendingCallback();
835
836         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
837             removeMediaKeys(mediaKeysStorageDirectory, modifiedSince);
838
839             RunLoop::main().dispatch([callbackAggregator] {
840                 callbackAggregator->removePendingCallback();
841             });
842         });
843     }
844
845     if (dataTypes.contains(WebsiteDataType::SearchFieldRecentSearches) && isPersistent()) {
846         callbackAggregator->addPendingCallback();
847
848         m_queue->dispatch([modifiedSince, callbackAggregator] {
849             platformRemoveRecentSearches(modifiedSince);
850
851             RunLoop::main().dispatch([callbackAggregator] {
852                 callbackAggregator->removePendingCallback();
853             });
854         });
855     }
856
857 #if ENABLE(NETSCAPE_PLUGIN_API)
858     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
859         class State {
860         public:
861             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
862             {
863                 new State(WTFMove(callbackAggregator), WTFMove(plugins), modifiedSince);
864             }
865
866         private:
867             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
868                 : m_callbackAggregator(WTFMove(callbackAggregator))
869                 , m_plugins(WTFMove(plugins))
870                 , m_modifiedSince(modifiedSince)
871             {
872                 m_callbackAggregator->addPendingCallback();
873
874                 deleteWebsiteDataForNextPlugin();
875             }
876
877             ~State()
878             {
879                 ASSERT(m_plugins.isEmpty());
880             }
881
882             void deleteWebsiteDataForNextPlugin()
883             {
884                 if (m_plugins.isEmpty()) {
885                     m_callbackAggregator->removePendingCallback();
886
887                     delete this;
888                     return;
889                 }
890
891                 auto plugin = m_plugins.takeLast();
892                 PluginProcessManager::singleton().deleteWebsiteData(plugin, m_modifiedSince, [this] {
893                     deleteWebsiteDataForNextPlugin();
894                 });
895             }
896
897             Ref<CallbackAggregator> m_callbackAggregator;
898             Vector<PluginModuleInfo> m_plugins;
899             WallTime m_modifiedSince;
900         };
901
902         State::deleteData(*callbackAggregator, plugins(), modifiedSince);
903     }
904 #endif
905
906 #if ENABLE(RESOURCE_LOAD_STATISTICS)
907     if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics)) {
908         if (!didNotifyNetworkProcessToDeleteWebsiteData) {
909             for (auto& processPool : processPools()) {
910                 if (auto* process = processPool->networkProcess()) {
911                     callbackAggregator->addPendingCallback();
912                     process->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator] {
913                         callbackAggregator->removePendingCallback();
914                     });
915                 }
916             }
917         }
918
919         callbackAggregator->addPendingCallback();
920         clearResourceLoadStatisticsInWebProcesses([callbackAggregator] {
921             callbackAggregator->removePendingCallback();
922         });
923     }
924 #endif
925
926     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
927     callbackAggregator->callIfNeeded();
928 }
929
930 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, const Vector<WebsiteDataRecord>& dataRecords, Function<void()>&& completionHandler)
931 {
932     Vector<WebCore::SecurityOriginData> origins;
933
934     for (const auto& dataRecord : dataRecords) {
935         for (auto& origin : dataRecord.origins)
936             origins.append(origin);
937     }
938
939     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
940         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
941             : completionHandler(WTFMove(completionHandler))
942             , protectedDataStore(dataStore)
943         {
944             ASSERT(RunLoop::isMain());
945         }
946
947         ~CallbackAggregator()
948         {
949             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
950             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
951         }
952
953         void addPendingCallback()
954         {
955             pendingCallbacks++;
956         }
957
958         void removePendingCallback()
959         {
960             ASSERT(pendingCallbacks);
961             --pendingCallbacks;
962
963             callIfNeeded();
964         }
965
966         void callIfNeeded()
967         {
968             if (!pendingCallbacks)
969                 RunLoop::main().dispatch(WTFMove(completionHandler));
970         }
971
972         unsigned pendingCallbacks = 0;
973         Function<void()> completionHandler;
974         Ref<WebsiteDataStore> protectedDataStore;
975     };
976
977     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
978     
979     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
980         HashSet<WebCore::SecurityOriginData> origins;
981         for (const auto& dataRecord : dataRecords) {
982             for (const auto& origin : dataRecord.origins)
983                 origins.add(origin);
984         }
985         
986 #if ENABLE(VIDEO)
987         callbackAggregator->addPendingCallback();
988         m_queue->dispatch([origins = WTFMove(origins), mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
989
990             // FIXME: Move SecurityOrigin::toRawString to SecurityOriginData and
991             // make HTMLMediaElement::clearMediaCacheForOrigins take SecurityOriginData.
992             HashSet<RefPtr<WebCore::SecurityOrigin>> securityOrigins;
993             for (auto& origin : origins)
994                 securityOrigins.add(origin.securityOrigin());
995             WebCore::HTMLMediaElement::clearMediaCacheForOrigins(mediaCacheDirectory, securityOrigins);
996             
997             WTF::RunLoop::main().dispatch([callbackAggregator] {
998                 callbackAggregator->removePendingCallback();
999             });
1000         });
1001 #endif
1002     }
1003     
1004     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
1005     if (networkProcessAccessType != ProcessAccessType::None) {
1006         for (auto& processPool : processPools()) {
1007             switch (networkProcessAccessType) {
1008             case ProcessAccessType::OnlyIfLaunched:
1009                 if (!processPool->networkProcess())
1010                     continue;
1011                 break;
1012
1013             case ProcessAccessType::Launch:
1014                 processPool->ensureNetworkProcess(this);
1015                 break;
1016
1017             case ProcessAccessType::None:
1018                 ASSERT_NOT_REACHED();
1019             }
1020
1021             Vector<String> cookieHostNames;
1022             Vector<String> HSTSCacheHostNames;
1023             for (const auto& dataRecord : dataRecords) {
1024                 for (auto& hostName : dataRecord.cookieHostNames)
1025                     cookieHostNames.append(hostName);
1026                 for (auto& hostName : dataRecord.HSTSCacheHostNames)
1027                     HSTSCacheHostNames.append(hostName);
1028             }
1029
1030             callbackAggregator->addPendingCallback();
1031             processPool->networkProcess()->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, [callbackAggregator, processPool] {
1032                 callbackAggregator->removePendingCallback();
1033             });
1034         }
1035     }
1036
1037     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
1038     if (webProcessAccessType != ProcessAccessType::None) {
1039         for (auto& process : processes()) {
1040             switch (webProcessAccessType) {
1041             case ProcessAccessType::OnlyIfLaunched:
1042                 if (process.state() != WebProcessProxy::State::Running)
1043                     continue;
1044                 break;
1045
1046             case ProcessAccessType::Launch:
1047                 // FIXME: Handle this.
1048                 ASSERT_NOT_REACHED();
1049                 break;
1050
1051             case ProcessAccessType::None:
1052                 ASSERT_NOT_REACHED();
1053             }
1054
1055             callbackAggregator->addPendingCallback();
1056
1057             process.deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, [callbackAggregator] {
1058                 callbackAggregator->removePendingCallback();
1059             });
1060         }
1061     }
1062
1063     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
1064         callbackAggregator->addPendingCallback();
1065
1066         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltForOrigins(origins, [callbackAggregator] {
1067             callbackAggregator->removePendingCallback();
1068         });
1069     }
1070
1071     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
1072         HashSet<WebCore::SecurityOriginData> origins;
1073         for (const auto& dataRecord : dataRecords) {
1074             for (const auto& origin : dataRecord.origins)
1075                 origins.add(origin);
1076         }
1077
1078         callbackAggregator->addPendingCallback();
1079         m_queue->dispatch([origins = WTFMove(origins), applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
1080             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
1081
1082             for (const auto& origin : origins)
1083                 storage->deleteCacheForOrigin(origin.securityOrigin());
1084
1085             WTF::RunLoop::main().dispatch([callbackAggregator] {
1086                 callbackAggregator->removePendingCallback();
1087             });
1088         });
1089     }
1090
1091     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
1092         HashSet<WebCore::SecurityOriginData> origins;
1093         for (const auto& dataRecord : dataRecords) {
1094             for (const auto& origin : dataRecord.origins)
1095                 origins.add(origin);
1096         }
1097
1098         callbackAggregator->addPendingCallback();
1099         m_queue->dispatch([origins = WTFMove(origins), callbackAggregator, webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy()] {
1100             auto databaseTracker = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory);
1101             for (auto& origin : origins)
1102                 databaseTracker->deleteOrigin(origin);
1103             RunLoop::main().dispatch([callbackAggregator] {
1104                 callbackAggregator->removePendingCallback();
1105             });
1106         });
1107     }
1108
1109     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
1110         HashSet<WebCore::SecurityOriginData> origins;
1111         for (const auto& dataRecord : dataRecords) {
1112             for (const auto& origin : dataRecord.origins)
1113                 origins.add(origin);
1114         }
1115
1116         callbackAggregator->addPendingCallback();
1117         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, origins = WTFMove(origins)] {
1118
1119             removeMediaKeys(mediaKeysStorageDirectory, origins);
1120
1121             RunLoop::main().dispatch([callbackAggregator] {
1122                 callbackAggregator->removePendingCallback();
1123             });
1124         });
1125     }
1126
1127 #if ENABLE(NETSCAPE_PLUGIN_API)
1128     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
1129         Vector<String> hostNames;
1130         for (const auto& dataRecord : dataRecords) {
1131             for (const auto& hostName : dataRecord.pluginDataHostNames)
1132                 hostNames.append(hostName);
1133         }
1134
1135
1136         class State {
1137         public:
1138             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1139             {
1140                 new State(WTFMove(callbackAggregator), WTFMove(plugins), WTFMove(hostNames));
1141             }
1142
1143         private:
1144             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1145                 : m_callbackAggregator(WTFMove(callbackAggregator))
1146                 , m_plugins(WTFMove(plugins))
1147                 , m_hostNames(WTFMove(hostNames))
1148             {
1149                 m_callbackAggregator->addPendingCallback();
1150
1151                 deleteWebsiteDataForNextPlugin();
1152             }
1153
1154             ~State()
1155             {
1156                 ASSERT(m_plugins.isEmpty());
1157             }
1158
1159             void deleteWebsiteDataForNextPlugin()
1160             {
1161                 if (m_plugins.isEmpty()) {
1162                     m_callbackAggregator->removePendingCallback();
1163
1164                     delete this;
1165                     return;
1166                 }
1167
1168                 auto plugin = m_plugins.takeLast();
1169                 PluginProcessManager::singleton().deleteWebsiteDataForHostNames(plugin, m_hostNames, [this] {
1170                     deleteWebsiteDataForNextPlugin();
1171                 });
1172             }
1173
1174             Ref<CallbackAggregator> m_callbackAggregator;
1175             Vector<PluginModuleInfo> m_plugins;
1176             Vector<String> m_hostNames;
1177         };
1178
1179         if (!hostNames.isEmpty())
1180             State::deleteData(*callbackAggregator, plugins(), WTFMove(hostNames));
1181     }
1182 #endif
1183
1184     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
1185     callbackAggregator->callIfNeeded();
1186 }
1187
1188 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1189 void WebsiteDataStore::setMaxStatisticsEntries(size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
1190 {
1191     ASSERT(RunLoop::isMain());
1192
1193     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1194
1195     for (auto& processPool : processPools())
1196         processPool->ensureNetworkProcess().setMaxStatisticsEntries(m_sessionID, maximumEntryCount, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1197 }
1198
1199 void WebsiteDataStore::setPruneEntriesDownTo(size_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
1200 {
1201     ASSERT(RunLoop::isMain());
1202     
1203     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1204
1205     for (auto& processPool : processPools()) {
1206         processPool->ensureNetworkProcess().setPruneEntriesDownTo(m_sessionID, pruneTargetCount, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1207     }
1208 }
1209
1210 void WebsiteDataStore::setGrandfatheringTime(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1211 {
1212     ASSERT(RunLoop::isMain());
1213
1214     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1215
1216     for (auto& processPool : processPools())
1217         processPool->ensureNetworkProcess().setGrandfatheringTime(m_sessionID, seconds, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1218 }
1219
1220 void WebsiteDataStore::setMinimumTimeBetweenDataRecordsRemoval(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1221 {
1222     ASSERT(RunLoop::isMain());
1223
1224     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1225
1226     for (auto& processPool : processPools())
1227         processPool->ensureNetworkProcess().setMinimumTimeBetweenDataRecordsRemoval(m_sessionID, seconds, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1228 }
1229     
1230 void WebsiteDataStore::dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&& completionHandler)
1231 {
1232     ASSERT(RunLoop::isMain());
1233
1234     for (auto& processPool : processPools()) {
1235         if (auto* process = processPool->networkProcess()) {
1236             process->dumpResourceLoadStatistics(m_sessionID, WTFMove(completionHandler));
1237             RELEASE_ASSERT(processPools().size() == 1);
1238             break;
1239         }
1240     }
1241 }
1242
1243 void WebsiteDataStore::isPrevalentResource(const URL& url, CompletionHandler<void(bool isPrevalent)>&& completionHandler)
1244 {
1245     ASSERT(RunLoop::isMain());
1246     
1247     if (url.protocolIsAbout() || url.isEmpty()) {
1248         completionHandler(false);
1249         return;
1250     }
1251
1252     for (auto& processPool : processPools()) {
1253         if (auto* process = processPool->networkProcess()) {
1254             process->isPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1255             RELEASE_ASSERT(processPools().size() == 1);
1256             break;
1257         }
1258     }
1259 }
1260
1261 void WebsiteDataStore::setPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1262 {
1263     ASSERT(RunLoop::isMain());
1264     
1265     if (url.protocolIsAbout() || url.isEmpty()) {
1266         completionHandler();
1267         return;
1268     }
1269     
1270     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1271
1272     for (auto& processPool : processPools()) {
1273         processPool->ensureNetworkProcess().setPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1274     }
1275 }
1276
1277 void WebsiteDataStore::setPrevalentResourceForDebugMode(const URL& url, CompletionHandler<void()>&& completionHandler)
1278 {
1279     ASSERT(RunLoop::isMain());
1280     
1281     if (url.protocolIsAbout() || url.isEmpty()) {
1282         completionHandler();
1283         return;
1284     }
1285     
1286     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1287     
1288     for (auto& processPool : processPools()) {
1289         if (auto* process = processPool->networkProcess())
1290             process->setPrevalentResourceForDebugMode(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1291     }
1292 }
1293
1294 void WebsiteDataStore::isVeryPrevalentResource(const URL& url, CompletionHandler<void(bool isVeryPrevalent)>&& completionHandler)
1295 {
1296     ASSERT(RunLoop::isMain());
1297     
1298     if (url.protocolIsAbout() || url.isEmpty()) {
1299         completionHandler(false);
1300         return;
1301     }
1302     
1303     for (auto& processPool : processPools()) {
1304         if (auto* process = processPool->networkProcess()) {
1305             process->isVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1306             ASSERT(processPools().size() == 1);
1307             break;
1308         }
1309     }
1310 }
1311
1312 void WebsiteDataStore::setVeryPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1313 {
1314     ASSERT(RunLoop::isMain());
1315     
1316     if (url.protocolIsAbout() || url.isEmpty()) {
1317         completionHandler();
1318         return;
1319     }
1320     
1321     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1322     
1323     for (auto& processPool : processPools()) {
1324         if (auto* process = processPool->networkProcess())
1325             process->setVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1326     }
1327 }
1328
1329 void WebsiteDataStore::setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value, CompletionHandler<void()>&& completionHandler)
1330 {
1331     ASSERT(RunLoop::isMain());
1332     
1333     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1334
1335     for (auto& processPool : processPools())
1336         processPool->ensureNetworkProcess().setShouldClassifyResourcesBeforeDataRecordsRemoval(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1337 }
1338
1339 void WebsiteDataStore::setSubframeUnderTopFrameDomain(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1340 {
1341     ASSERT(RunLoop::isMain());
1342     
1343     if (subFrameURL.protocolIsAbout() || subFrameURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1344         completionHandler();
1345         return;
1346     }
1347
1348     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1349     
1350     for (auto& processPool : processPools()) {
1351         if (auto* process = processPool->networkProcess())
1352             process->setSubframeUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1353     }
1354 }
1355
1356 void WebsiteDataStore::isRegisteredAsSubFrameUnder(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1357 {
1358     ASSERT(RunLoop::isMain());
1359
1360     for (auto& processPool : processPools()) {
1361         if (auto* process = processPool->networkProcess()) {
1362             process->isRegisteredAsSubFrameUnder(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1363             ASSERT(processPools().size() == 1);
1364             break;
1365         }
1366     }
1367 }
1368
1369 void WebsiteDataStore::setSubresourceUnderTopFrameDomain(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1370 {
1371     ASSERT(RunLoop::isMain());
1372     
1373     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1374         completionHandler();
1375         return;
1376     }
1377
1378     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1379     
1380     for (auto& processPool : processPools()) {
1381         if (auto* process = processPool->networkProcess())
1382             process->setSubresourceUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1383     }
1384 }
1385
1386 void WebsiteDataStore::isRegisteredAsSubresourceUnder(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1387 {
1388     ASSERT(RunLoop::isMain());
1389     
1390     for (auto& processPool : processPools()) {
1391         if (auto* process = processPool->networkProcess()) {
1392             process->isRegisteredAsSubresourceUnder(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1393             ASSERT(processPools().size() == 1);
1394             break;
1395         }
1396     }
1397 }
1398
1399 void WebsiteDataStore::setSubresourceUniqueRedirectTo(const URL& subresourceURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1400 {
1401     ASSERT(RunLoop::isMain());
1402     
1403     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1404         completionHandler();
1405         return;
1406     }
1407
1408     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1409     
1410     for (auto& processPool : processPools()) {
1411         if (auto* process = processPool->networkProcess())
1412             process->setSubresourceUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1413     }
1414 }
1415
1416 void WebsiteDataStore::setSubresourceUniqueRedirectFrom(const URL& subresourceURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1417 {
1418     ASSERT(RunLoop::isMain());
1419     
1420     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1421         completionHandler();
1422         return;
1423     }
1424
1425     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1426     
1427     for (auto& processPool : processPools()) {
1428         if (auto* process = processPool->networkProcess())
1429             process->setSubresourceUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1430     }
1431 }
1432
1433 void WebsiteDataStore::setTopFrameUniqueRedirectTo(const URL& topFrameURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1434 {
1435     ASSERT(RunLoop::isMain());
1436     
1437     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1438         completionHandler();
1439         return;
1440     }
1441
1442     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1443     
1444     for (auto& processPool : processPools()) {
1445         if (auto* process = processPool->networkProcess())
1446             process->setTopFrameUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1447     }
1448 }
1449
1450 void WebsiteDataStore::setTopFrameUniqueRedirectFrom(const URL& topFrameURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1451 {
1452     ASSERT(RunLoop::isMain());
1453     
1454     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1455         completionHandler();
1456         return;
1457     }
1458
1459     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1460     
1461     for (auto& processPool : processPools()) {
1462         if (auto* process = processPool->networkProcess())
1463             process->setTopFrameUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1464     }
1465 }
1466
1467 void WebsiteDataStore::isRegisteredAsRedirectingTo(const URL& urlRedirectedFrom, const URL& urlRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
1468 {
1469     ASSERT(RunLoop::isMain());
1470     
1471     for (auto& processPool : processPools()) {
1472         if (auto* process = processPool->networkProcess()) {
1473             process->isRegisteredAsRedirectingTo(m_sessionID, WebCore::RegistrableDomain { urlRedirectedFrom }, WebCore::RegistrableDomain { urlRedirectedTo }, WTFMove(completionHandler));
1474             ASSERT(processPools().size() == 1);
1475             break;
1476         }
1477     }
1478 }
1479
1480 void WebsiteDataStore::clearPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1481 {
1482     ASSERT(RunLoop::isMain());
1483         
1484     if (url.protocolIsAbout() || url.isEmpty()) {
1485         completionHandler();
1486         return;
1487     }
1488
1489     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1490
1491     for (auto& processPool : processPools()) {
1492         if (auto* process = processPool->networkProcess())
1493             process->clearPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1494     }
1495 }
1496
1497 void WebsiteDataStore::resetParametersToDefaultValues(CompletionHandler<void()>&& completionHandler)
1498 {
1499     ASSERT(RunLoop::isMain());
1500
1501     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1502     
1503     for (auto& processPool : processPools()) {
1504         if (auto* process = processPool->networkProcess())
1505             process->resetParametersToDefaultValues(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1506     }
1507 }
1508
1509 void WebsiteDataStore::submitTelemetry()
1510 {
1511     ASSERT(RunLoop::isMain());
1512     
1513     for (auto& processPool : processPools()) {
1514         if (auto* process = processPool->networkProcess())
1515             process->submitTelemetry(m_sessionID, [] { });
1516     }
1517 }
1518
1519 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1520 {
1521     ASSERT(RunLoop::isMain());
1522     
1523     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1524
1525     for (auto& processPool : processPools()) {
1526         if (auto* process = processPool->networkProcess())
1527             process->scheduleClearInMemoryAndPersistent(m_sessionID, modifiedSince, shouldGrandfather, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1528     }
1529 }
1530
1531 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1532 {
1533     ASSERT(RunLoop::isMain());
1534     
1535     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1536
1537     for (auto& processPool : processPools()) {
1538         if (auto* process = processPool->networkProcess())
1539             process->scheduleClearInMemoryAndPersistent(m_sessionID, { }, shouldGrandfather, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1540     }
1541 }
1542
1543 void WebsiteDataStore::scheduleCookieBlockingUpdate(CompletionHandler<void()>&& completionHandler)
1544 {
1545     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1546
1547     for (auto& processPool : processPools()) {
1548         if (auto* process = processPool->networkProcess())
1549             process->scheduleCookieBlockingUpdate(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1550     }
1551 }
1552
1553 void WebsiteDataStore::scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&& completionHandler)
1554 {
1555     ASSERT(RunLoop::isMain());
1556     
1557     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1558     
1559     for (auto& processPool : processPools()) {
1560         if (auto* process = processPool->networkProcess())
1561             process->scheduleStatisticsAndDataRecordsProcessing(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1562     }
1563 }
1564
1565 void WebsiteDataStore::setLastSeen(const URL& url, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1566 {
1567     if (url.protocolIsAbout() || url.isEmpty()) {
1568         completionHandler();
1569         return;
1570     }
1571
1572     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1573
1574     for (auto& processPool : processPools()) {
1575         if (auto* process = processPool->networkProcess())
1576             process->setLastSeen(m_sessionID, WebCore::RegistrableDomain { url }, seconds, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1577     }
1578 }
1579
1580 void WebsiteDataStore::setNotifyPagesWhenDataRecordsWereScanned(bool value, CompletionHandler<void()>&& completionHandler)
1581 {
1582     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1583
1584     for (auto& processPool : processPools())
1585         processPool->ensureNetworkProcess().setNotifyPagesWhenDataRecordsWereScanned(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1586 }
1587
1588 void WebsiteDataStore::setIsRunningResourceLoadStatisticsTest(bool value, CompletionHandler<void()>&& completionHandler)
1589 {
1590     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1591     
1592     for (auto& processPool : processPools())
1593         processPool->ensureNetworkProcess().setIsRunningResourceLoadStatisticsTest(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1594 }
1595
1596 void WebsiteDataStore::setNotifyPagesWhenTelemetryWasCaptured(bool value, CompletionHandler<void()>&& completionHandler)
1597 {
1598     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1599     
1600     for (auto& processPool : processPools())
1601         processPool->ensureNetworkProcess().setNotifyPagesWhenTelemetryWasCaptured(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1602 }
1603
1604 void WebsiteDataStore::getAllStorageAccessEntries(WebPageProxyIdentifier pageID, CompletionHandler<void(Vector<String>&& domains)>&& completionHandler)
1605 {
1606     auto* webPage = WebProcessProxy::webPage(pageID);
1607     if (!webPage) {
1608         completionHandler({ });
1609         return;
1610     }
1611     
1612     auto& networkProcess = webPage->process().processPool().ensureNetworkProcess();
1613     networkProcess.getAllStorageAccessEntries(m_sessionID, WTFMove(completionHandler));
1614 }
1615
1616
1617 void WebsiteDataStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1618 {
1619     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1620     
1621     for (auto& processPool : processPools())
1622         processPool->ensureNetworkProcess().setTimeToLiveUserInteraction(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
1623 }
1624
1625 void WebsiteDataStore::logUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1626 {
1627     ASSERT(RunLoop::isMain());
1628     
1629     if (url.protocolIsAbout() || url.isEmpty()) {
1630         completionHandler();
1631         return;
1632     }
1633     
1634     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1635
1636     for (auto& processPool : processPools()) {
1637         if (auto* process = processPool->networkProcess())
1638             process->logUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator = callbackAggregator.copyRef()] { });
1639     }
1640 }
1641
1642 void WebsiteDataStore::hasHadUserInteraction(const URL& url, CompletionHandler<void(bool)>&& completionHandler)
1643 {
1644     ASSERT(RunLoop::isMain());
1645     
1646     if (url.protocolIsAbout() || url.isEmpty()) {
1647         completionHandler(false);
1648         return;
1649     }
1650     
1651     for (auto& processPool : processPools()) {
1652         if (auto* process = processPool->networkProcess()) {
1653             process->hasHadUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1654             ASSERT(processPools().size() == 1);
1655             break;
1656         }
1657     }
1658 }
1659
1660 void WebsiteDataStore::clearUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1661 {
1662     ASSERT(RunLoop::isMain());
1663     
1664     if (url.protocolIsAbout() || url.isEmpty()) {
1665         completionHandler();
1666         return;
1667     }
1668     
1669     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1670
1671     for (auto& processPool : processPools()) {
1672         if (auto* process = processPool->networkProcess())
1673             process->clearUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator = callbackAggregator.copyRef()] { });
1674     }
1675 }
1676
1677 void WebsiteDataStore::setGrandfathered(const URL& url, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
1678 {
1679     ASSERT(RunLoop::isMain());
1680     
1681     if (url.protocolIsAbout() || url.isEmpty()) {
1682         completionHandler();
1683         return;
1684     }
1685     
1686     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1687     
1688     for (auto& processPool : processPools()) {
1689         if (auto* process = processPool->networkProcess())
1690             process->setGrandfathered(m_sessionID, WebCore::RegistrableDomain { url }, isGrandfathered, [callbackAggregator = callbackAggregator.copyRef()] { });
1691     }
1692 }
1693
1694 void WebsiteDataStore::setCrossSiteLoadWithLinkDecorationForTesting(const URL& fromURL, const URL& toURL, CompletionHandler<void()>&& completionHandler)
1695 {
1696     ASSERT(RunLoop::isMain());
1697     
1698     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1699     
1700     for (auto& processPool : processPools()) {
1701         if (auto* process = processPool->networkProcess())
1702             process->setCrossSiteLoadWithLinkDecorationForTesting(m_sessionID, WebCore::RegistrableDomain { fromURL }, WebCore::RegistrableDomain { toURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1703     }
1704 }
1705
1706 void WebsiteDataStore::resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&& completionHandler)
1707 {
1708     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1709     
1710     for (auto& processPool : processPools()) {
1711         if (auto* networkProcess = processPool->networkProcess())
1712             networkProcess->resetCrossSiteLoadsWithLinkDecorationForTesting(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
1713     }
1714 }
1715
1716 void WebsiteDataStore::deleteCookiesForTesting(const URL& url, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1717 {
1718     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1719     
1720     for (auto& processPool : processPools()) {
1721         if (auto* networkProcess = processPool->networkProcess())
1722             networkProcess->deleteCookiesForTesting(m_sessionID, WebCore::RegistrableDomain { url }, includeHttpOnlyCookies, [callbackAggregator = callbackAggregator.copyRef()] { });
1723     }
1724 }
1725
1726 void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1727 {
1728     for (auto& processPool : processPools()) {
1729         if (auto* networkProcess = processPool->networkProcess()) {
1730             networkProcess->hasLocalStorage(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1731             ASSERT(processPools().size() == 1);
1732             break;
1733         }
1734     }
1735     ASSERT(!completionHandler);
1736 }
1737
1738 void WebsiteDataStore::hasIsolatedSessionForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1739 {
1740     for (auto& processPool : processPools()) {
1741         if (auto* networkProcess = processPool->networkProcess()) {
1742             networkProcess->hasIsolatedSession(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1743             ASSERT(processPools().size() == 1);
1744             break;
1745         }
1746     }
1747     ASSERT(!completionHandler);
1748 }
1749 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1750
1751 void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1752 {
1753 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1754     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1755     
1756     for (auto& processPool : processPools())
1757         processPool->ensureNetworkProcess().setCacheMaxAgeCapForPrevalentResources(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
1758 #else
1759     UNUSED_PARAM(seconds);
1760     completionHandler();
1761 #endif
1762 }
1763
1764 void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&& completionHandler)
1765 {
1766 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1767     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1768     
1769     for (auto& processPool : processPools()) {
1770         if (auto* networkProcess = processPool->networkProcess())
1771             networkProcess->resetCacheMaxAgeCapForPrevalentResources(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
1772     }
1773 #else
1774     completionHandler();
1775 #endif
1776 }
1777
1778 bool WebsiteDataStore::isAssociatedProcessPool(WebProcessPool& processPool) const
1779 {
1780     if (auto* processPoolDataStore = processPool.websiteDataStore())
1781         return processPoolDataStore == this;
1782     return false;
1783 }
1784
1785 HashSet<RefPtr<WebProcessPool>> WebsiteDataStore::processPools(size_t count, bool ensureAPoolExists) const
1786 {
1787     HashSet<RefPtr<WebProcessPool>> processPools;
1788     for (auto& process : processes()) {
1789         if (auto* processPool = process.processPoolIfExists())
1790             processPools.add(processPool);
1791     }
1792
1793     if (processPools.isEmpty()) {
1794         // Check if we're one of the legacy data stores.
1795         for (auto& processPool : WebProcessPool::allProcessPools()) {
1796             if (!isAssociatedProcessPool(*processPool))
1797                 continue;
1798
1799             processPools.add(processPool);
1800
1801             if (processPools.size() == count)
1802                 break;
1803         }
1804     }
1805
1806     if (processPools.isEmpty() && count && ensureAPoolExists) {
1807         auto processPool = WebProcessPool::create(API::ProcessPoolConfiguration::create());
1808         processPools.add(processPool.ptr());
1809     }
1810
1811     return processPools;
1812 }
1813
1814 #if ENABLE(NETSCAPE_PLUGIN_API)
1815 Vector<PluginModuleInfo> WebsiteDataStore::plugins() const
1816 {
1817     Vector<PluginModuleInfo> plugins;
1818
1819     for (auto& processPool : processPools()) {
1820         for (auto& plugin : processPool->pluginInfoStore().plugins())
1821             plugins.append(plugin);
1822     }
1823
1824     return plugins;
1825 }
1826 #endif
1827
1828 static String computeMediaKeyFile(const String& mediaKeyDirectory)
1829 {
1830     return FileSystem::pathByAppendingComponent(mediaKeyDirectory, "SecureStop.plist");
1831 }
1832
1833 Vector<WebCore::SecurityOriginData> WebsiteDataStore::mediaKeyOrigins(const String& mediaKeysStorageDirectory)
1834 {
1835     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1836
1837     Vector<WebCore::SecurityOriginData> origins;
1838
1839     for (const auto& originPath : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1840         auto mediaKeyFile = computeMediaKeyFile(originPath);
1841         if (!FileSystem::fileExists(mediaKeyFile))
1842             continue;
1843
1844         auto mediaKeyIdentifier = FileSystem::pathGetFileName(originPath);
1845
1846         if (auto securityOrigin = WebCore::SecurityOriginData::fromDatabaseIdentifier(mediaKeyIdentifier))
1847             origins.append(*securityOrigin);
1848     }
1849
1850     return origins;
1851 }
1852
1853 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, WallTime modifiedSince)
1854 {
1855     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1856
1857     for (const auto& mediaKeyDirectory : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1858         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1859
1860         auto modificationTime = FileSystem::getFileModificationTime(mediaKeyFile);
1861         if (!modificationTime)
1862             continue;
1863
1864         if (modificationTime.value() < modifiedSince)
1865             continue;
1866
1867         FileSystem::deleteFile(mediaKeyFile);
1868         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1869     }
1870 }
1871
1872 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, const HashSet<WebCore::SecurityOriginData>& origins)
1873 {
1874     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1875
1876     for (const auto& origin : origins) {
1877         auto mediaKeyDirectory = FileSystem::pathByAppendingComponent(mediaKeysStorageDirectory, origin.databaseIdentifier());
1878         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1879
1880         FileSystem::deleteFile(mediaKeyFile);
1881         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1882     }
1883 }
1884
1885 bool WebsiteDataStore::resourceLoadStatisticsEnabled() const
1886 {
1887 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1888     return m_resourceLoadStatisticsEnabled;
1889 #else
1890     return false;
1891 #endif
1892 }
1893
1894 bool WebsiteDataStore::resourceLoadStatisticsDebugMode() const
1895 {
1896 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1897     return m_resourceLoadStatisticsDebugMode;
1898 #else
1899     return false;
1900 #endif
1901 }
1902
1903 void WebsiteDataStore::setResourceLoadStatisticsEnabled(bool enabled)
1904 {
1905 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1906     if (m_sessionID.isEphemeral() || enabled == resourceLoadStatisticsEnabled())
1907         return;
1908
1909     if (enabled) {
1910         m_resourceLoadStatisticsEnabled = true;
1911         
1912         resolveDirectoriesIfNecessary();
1913         
1914         for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false)) {
1915             processPool->setResourceLoadStatisticsEnabled(true);
1916             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(true));
1917         }
1918         return;
1919     }
1920
1921     for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false)) {
1922         processPool->setResourceLoadStatisticsEnabled(false);
1923         processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(false));
1924     }
1925
1926     m_resourceLoadStatisticsEnabled = false;
1927 #else
1928     UNUSED_PARAM(enabled);
1929 #endif
1930 }
1931
1932 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1933 void WebsiteDataStore::setStatisticsTestingCallback(Function<void(const String&)>&& callback)
1934 {
1935     if (callback) {
1936         for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false))
1937             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsLogTestingEvent(true));
1938     }
1939     
1940     m_statisticsTestingCallback = WTFMove(callback);
1941 }
1942 #endif
1943
1944 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled)
1945 {
1946     setResourceLoadStatisticsDebugMode(enabled, []() { });
1947 }
1948
1949 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled, CompletionHandler<void()>&& completionHandler)
1950 {
1951 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1952     m_resourceLoadStatisticsDebugMode = enabled;
1953
1954     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1955     
1956     for (auto& processPool : processPools())
1957         processPool->ensureNetworkProcess().setResourceLoadStatisticsDebugMode(m_sessionID, enabled, [callbackAggregator = callbackAggregator.copyRef()] { });
1958 #else
1959     UNUSED_PARAM(enabled);
1960     UNUSED_PARAM(completionHandler);
1961 #endif
1962 }
1963
1964 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1965 void WebsiteDataStore::logTestingEvent(const String& event)
1966 {
1967     ASSERT(RunLoop::isMain());
1968     
1969     if (m_statisticsTestingCallback)
1970         m_statisticsTestingCallback(event);
1971 }
1972
1973 void WebsiteDataStore::clearResourceLoadStatisticsInWebProcesses(CompletionHandler<void()>&& callback)
1974 {
1975     if (resourceLoadStatisticsEnabled()) {
1976         for (auto& processPool : processPools())
1977             processPool->clearResourceLoadStatistics();
1978     }
1979     callback();
1980 }
1981 #endif
1982
1983 Vector<WebCore::Cookie> WebsiteDataStore::pendingCookies() const
1984 {
1985     return copyToVector(m_pendingCookies);
1986 }
1987
1988 void WebsiteDataStore::addPendingCookie(const WebCore::Cookie& cookie)
1989 {
1990     m_pendingCookies.removeIf([&cookie](auto& pendingCookie) {
1991         return pendingCookie.isKeyEqual(cookie);
1992     });
1993     m_pendingCookies.add(cookie);
1994 }
1995
1996 void WebsiteDataStore::removePendingCookie(const WebCore::Cookie& cookie)
1997 {
1998     m_pendingCookies.remove(cookie);
1999 }
2000     
2001 void WebsiteDataStore::clearPendingCookies()
2002 {
2003     m_pendingCookies.clear();
2004 }
2005
2006 uint64_t WebsiteDataStore::perThirdPartyOriginStorageQuota() const
2007 {
2008     // FIXME: Consider whether allowing to set a perThirdPartyOriginStorageQuota from a WebsiteDataStore.
2009     return WebCore::StorageQuotaManager::defaultThirdPartyQuotaFromPerOriginQuota(perOriginStorageQuota());
2010 }
2011
2012 #if !PLATFORM(COCOA)
2013 WebsiteDataStoreParameters WebsiteDataStore::parameters()
2014 {
2015     WebsiteDataStoreParameters parameters;
2016     parameters.networkSessionParameters.sessionID = m_sessionID;
2017
2018     resolveDirectoriesIfNecessary();
2019
2020     auto localStorageDirectory = resolvedLocalStorageDirectory();
2021     if (!localStorageDirectory.isEmpty()) {
2022         parameters.localStorageDirectory = localStorageDirectory;
2023         SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
2024     }
2025
2026 #if ENABLE(INDEXED_DATABASE)
2027     parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
2028     if (!parameters.indexedDatabaseDirectory.isEmpty())
2029         SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
2030 #endif
2031
2032 #if ENABLE(SERVICE_WORKER)
2033     parameters.serviceWorkerRegistrationDirectory = resolvedServiceWorkerRegistrationDirectory();
2034     if (!parameters.serviceWorkerRegistrationDirectory.isEmpty())
2035         SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
2036 #endif
2037
2038     parameters.perOriginStorageQuota = perOriginStorageQuota();
2039     parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
2040
2041     platformSetNetworkParameters(parameters);
2042
2043     return parameters;
2044 }
2045 #endif
2046
2047 #if HAVE(SEC_KEY_PROXY)
2048 void WebsiteDataStore::addSecKeyProxyStore(Ref<SecKeyProxyStore>&& store)
2049 {
2050     m_secKeyProxyStores.append(WTFMove(store));
2051 }
2052 #endif
2053
2054 #if ENABLE(WEB_AUTHN)
2055 void WebsiteDataStore::setMockWebAuthenticationConfiguration(MockWebAuthenticationConfiguration&& configuration)
2056 {
2057     if (!m_authenticatorManager->isMock()) {
2058         m_authenticatorManager = makeUniqueRef<MockAuthenticatorManager>(WTFMove(configuration));
2059         return;
2060     }
2061     static_cast<MockAuthenticatorManager*>(&m_authenticatorManager)->setTestConfiguration(WTFMove(configuration));
2062 }
2063 #endif
2064
2065 API::HTTPCookieStore& WebsiteDataStore::cookieStore()
2066 {
2067     if (!m_cookieStore)
2068         m_cookieStore = API::HTTPCookieStore::create(*this);
2069
2070     return *m_cookieStore;
2071 }
2072
2073 void WebsiteDataStore::didCreateNetworkProcess()
2074 {
2075 }
2076
2077 bool WebsiteDataStore::setSourceApplicationSecondaryIdentifier(String&& identifier)
2078 {
2079     if (m_networkingHasBegun)
2080         return false;
2081     m_resolvedConfiguration->setSourceApplicationSecondaryIdentifier(WTFMove(identifier));
2082     return true;
2083 }
2084
2085 bool WebsiteDataStore::setSourceApplicationBundleIdentifier(String&& identifier)
2086 {
2087     if (m_networkingHasBegun)
2088         return false;
2089     m_resolvedConfiguration->setSourceApplicationBundleIdentifier(WTFMove(identifier));
2090     return true;
2091 }
2092
2093 void WebsiteDataStore::getLocalStorageDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2094 {
2095     if (!isPersistent()) {
2096         completionHandler({ });
2097         return;
2098     }
2099
2100     for (auto& processPool : processPools()) {
2101         processPool->ensureNetworkProcess(this);
2102         processPool->networkProcess()->getLocalStorageDetails(m_sessionID, [completionHandler = WTFMove(completionHandler)](auto&& details) {
2103             completionHandler(WTFMove(details));
2104         });
2105         // FIXME: Support fetching from multiple pools.
2106         break;
2107     }
2108     ASSERT(!completionHandler);
2109 }
2110
2111 #if !PLATFORM(COCOA)
2112 WTF::String WebsiteDataStore::defaultMediaCacheDirectory()
2113 {
2114     // FIXME: Implement. https://bugs.webkit.org/show_bug.cgi?id=156369 and https://bugs.webkit.org/show_bug.cgi?id=156370
2115     return WTF::String();
2116 }
2117
2118 WTF::String WebsiteDataStore::defaultJavaScriptConfigurationDirectory()
2119 {
2120     // FIXME: Implement.
2121     return WTF::String();
2122 }
2123 #endif
2124
2125 #if !USE(GLIB)
2126 WTF::String WebsiteDataStore::defaultDeviceIdHashSaltsStorageDirectory()
2127 {
2128     // Not implemented.
2129     return WTF::String();
2130 }
2131 #endif
2132
2133 }