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