627d2d99cb3ec7270b8767ba306d8fb509a8bdc1
[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::isGrandfathered(const URL& url, CompletionHandler<void(bool isPrevalent)>&& completionHandler)
1218 {
1219     ASSERT(RunLoop::isMain());
1220     
1221     if (url.protocolIsAbout() || url.isEmpty()) {
1222         completionHandler(false);
1223         return;
1224     }
1225
1226     for (auto& processPool : processPools()) {
1227         if (auto* process = processPool->networkProcess()) {
1228             process->isGrandfathered(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1229             RELEASE_ASSERT(processPools().size() == 1);
1230             break;
1231         }
1232     }
1233 }
1234
1235 void WebsiteDataStore::setPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1236 {
1237     ASSERT(RunLoop::isMain());
1238     
1239     if (url.protocolIsAbout() || url.isEmpty()) {
1240         completionHandler();
1241         return;
1242     }
1243     
1244     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1245
1246     for (auto& processPool : processPools()) {
1247         processPool->ensureNetworkProcess().setPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1248     }
1249 }
1250
1251 void WebsiteDataStore::setPrevalentResourceForDebugMode(const URL& url, CompletionHandler<void()>&& completionHandler)
1252 {
1253     ASSERT(RunLoop::isMain());
1254     
1255     if (url.protocolIsAbout() || url.isEmpty()) {
1256         completionHandler();
1257         return;
1258     }
1259     
1260     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1261     
1262     for (auto& processPool : processPools()) {
1263         if (auto* process = processPool->networkProcess())
1264             process->setPrevalentResourceForDebugMode(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1265     }
1266 }
1267
1268 void WebsiteDataStore::isVeryPrevalentResource(const URL& url, CompletionHandler<void(bool isVeryPrevalent)>&& completionHandler)
1269 {
1270     ASSERT(RunLoop::isMain());
1271     
1272     if (url.protocolIsAbout() || url.isEmpty()) {
1273         completionHandler(false);
1274         return;
1275     }
1276     
1277     for (auto& processPool : processPools()) {
1278         if (auto* process = processPool->networkProcess()) {
1279             process->isVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1280             ASSERT(processPools().size() == 1);
1281             break;
1282         }
1283     }
1284 }
1285
1286 void WebsiteDataStore::setVeryPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1287 {
1288     ASSERT(RunLoop::isMain());
1289     
1290     if (url.protocolIsAbout() || url.isEmpty()) {
1291         completionHandler();
1292         return;
1293     }
1294     
1295     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1296     
1297     for (auto& processPool : processPools()) {
1298         if (auto* process = processPool->networkProcess())
1299             process->setVeryPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1300     }
1301 }
1302
1303 void WebsiteDataStore::setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value, CompletionHandler<void()>&& completionHandler)
1304 {
1305     ASSERT(RunLoop::isMain());
1306     
1307     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1308
1309     for (auto& processPool : processPools())
1310         processPool->ensureNetworkProcess().setShouldClassifyResourcesBeforeDataRecordsRemoval(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1311 }
1312
1313 void WebsiteDataStore::setSubframeUnderTopFrameDomain(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1314 {
1315     ASSERT(RunLoop::isMain());
1316     
1317     if (subFrameURL.protocolIsAbout() || subFrameURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1318         completionHandler();
1319         return;
1320     }
1321
1322     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1323     
1324     for (auto& processPool : processPools()) {
1325         if (auto* process = processPool->networkProcess())
1326             process->setSubframeUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1327     }
1328 }
1329
1330 void WebsiteDataStore::isRegisteredAsSubFrameUnder(const URL& subFrameURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1331 {
1332     ASSERT(RunLoop::isMain());
1333
1334     for (auto& processPool : processPools()) {
1335         if (auto* process = processPool->networkProcess()) {
1336             process->isRegisteredAsSubFrameUnder(m_sessionID, WebCore::RegistrableDomain { subFrameURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1337             ASSERT(processPools().size() == 1);
1338             break;
1339         }
1340     }
1341 }
1342
1343 void WebsiteDataStore::setSubresourceUnderTopFrameDomain(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void()>&& completionHandler)
1344 {
1345     ASSERT(RunLoop::isMain());
1346     
1347     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || topFrameURL.protocolIsAbout() || topFrameURL.isEmpty()) {
1348         completionHandler();
1349         return;
1350     }
1351
1352     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1353     
1354     for (auto& processPool : processPools()) {
1355         if (auto* process = processPool->networkProcess())
1356             process->setSubresourceUnderTopFrameDomain(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1357     }
1358 }
1359
1360 void WebsiteDataStore::isRegisteredAsSubresourceUnder(const URL& subresourceURL, const URL& topFrameURL, CompletionHandler<void(bool)>&& completionHandler)
1361 {
1362     ASSERT(RunLoop::isMain());
1363     
1364     for (auto& processPool : processPools()) {
1365         if (auto* process = processPool->networkProcess()) {
1366             process->isRegisteredAsSubresourceUnder(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { topFrameURL }, WTFMove(completionHandler));
1367             ASSERT(processPools().size() == 1);
1368             break;
1369         }
1370     }
1371 }
1372
1373 void WebsiteDataStore::setSubresourceUniqueRedirectTo(const URL& subresourceURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1374 {
1375     ASSERT(RunLoop::isMain());
1376     
1377     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1378         completionHandler();
1379         return;
1380     }
1381
1382     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1383     
1384     for (auto& processPool : processPools()) {
1385         if (auto* process = processPool->networkProcess())
1386             process->setSubresourceUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1387     }
1388 }
1389
1390 void WebsiteDataStore::setSubresourceUniqueRedirectFrom(const URL& subresourceURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1391 {
1392     ASSERT(RunLoop::isMain());
1393     
1394     if (subresourceURL.protocolIsAbout() || subresourceURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1395         completionHandler();
1396         return;
1397     }
1398
1399     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1400     
1401     for (auto& processPool : processPools()) {
1402         if (auto* process = processPool->networkProcess())
1403             process->setSubresourceUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { subresourceURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1404     }
1405 }
1406
1407 void WebsiteDataStore::setTopFrameUniqueRedirectTo(const URL& topFrameURL, const URL& urlRedirectedTo, CompletionHandler<void()>&& completionHandler)
1408 {
1409     ASSERT(RunLoop::isMain());
1410     
1411     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedTo.protocolIsAbout() || urlRedirectedTo.isEmpty()) {
1412         completionHandler();
1413         return;
1414     }
1415
1416     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1417     
1418     for (auto& processPool : processPools()) {
1419         if (auto* process = processPool->networkProcess())
1420             process->setTopFrameUniqueRedirectTo(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedTo }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1421     }
1422 }
1423
1424 void WebsiteDataStore::setTopFrameUniqueRedirectFrom(const URL& topFrameURL, const URL& urlRedirectedFrom, CompletionHandler<void()>&& completionHandler)
1425 {
1426     ASSERT(RunLoop::isMain());
1427     
1428     if (topFrameURL.protocolIsAbout() || topFrameURL.isEmpty() || urlRedirectedFrom.protocolIsAbout() || urlRedirectedFrom.isEmpty()) {
1429         completionHandler();
1430         return;
1431     }
1432
1433     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1434     
1435     for (auto& processPool : processPools()) {
1436         if (auto* process = processPool->networkProcess())
1437             process->setTopFrameUniqueRedirectFrom(m_sessionID, WebCore::RegistrableDomain { topFrameURL }, WebCore::RegistrableDomain { urlRedirectedFrom }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1438     }
1439 }
1440
1441 void WebsiteDataStore::isRegisteredAsRedirectingTo(const URL& urlRedirectedFrom, const URL& urlRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
1442 {
1443     ASSERT(RunLoop::isMain());
1444     
1445     for (auto& processPool : processPools()) {
1446         if (auto* process = processPool->networkProcess()) {
1447             process->isRegisteredAsRedirectingTo(m_sessionID, WebCore::RegistrableDomain { urlRedirectedFrom }, WebCore::RegistrableDomain { urlRedirectedTo }, WTFMove(completionHandler));
1448             ASSERT(processPools().size() == 1);
1449             break;
1450         }
1451     }
1452 }
1453
1454 void WebsiteDataStore::clearPrevalentResource(const URL& url, CompletionHandler<void()>&& completionHandler)
1455 {
1456     ASSERT(RunLoop::isMain());
1457         
1458     if (url.protocolIsAbout() || url.isEmpty()) {
1459         completionHandler();
1460         return;
1461     }
1462
1463     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1464
1465     for (auto& processPool : processPools()) {
1466         if (auto* process = processPool->networkProcess())
1467             process->clearPrevalentResource(m_sessionID, WebCore::RegistrableDomain { url }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1468     }
1469 }
1470
1471 void WebsiteDataStore::resetParametersToDefaultValues(CompletionHandler<void()>&& completionHandler)
1472 {
1473     ASSERT(RunLoop::isMain());
1474
1475     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1476     
1477     for (auto& processPool : processPools()) {
1478         if (auto* process = processPool->networkProcess())
1479             process->resetParametersToDefaultValues(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1480     }
1481 }
1482
1483 void WebsiteDataStore::submitTelemetry()
1484 {
1485     ASSERT(RunLoop::isMain());
1486     
1487     for (auto& processPool : processPools()) {
1488         if (auto* process = processPool->networkProcess())
1489             process->submitTelemetry(m_sessionID, [] { });
1490     }
1491 }
1492
1493 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1494 {
1495     ASSERT(RunLoop::isMain());
1496     
1497     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1498
1499     for (auto& processPool : processPools()) {
1500         if (auto* process = processPool->networkProcess())
1501             process->scheduleClearInMemoryAndPersistent(m_sessionID, modifiedSince, shouldGrandfather, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1502     }
1503 }
1504
1505 void WebsiteDataStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
1506 {
1507     ASSERT(RunLoop::isMain());
1508     
1509     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1510
1511     for (auto& processPool : processPools()) {
1512         if (auto* process = processPool->networkProcess())
1513             process->scheduleClearInMemoryAndPersistent(m_sessionID, { }, shouldGrandfather, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1514     }
1515 }
1516
1517 void WebsiteDataStore::scheduleCookieBlockingUpdate(CompletionHandler<void()>&& completionHandler)
1518 {
1519     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1520
1521     for (auto& processPool : processPools()) {
1522         if (auto* process = processPool->networkProcess())
1523             process->scheduleCookieBlockingUpdate(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1524     }
1525 }
1526
1527 void WebsiteDataStore::scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&& completionHandler)
1528 {
1529     ASSERT(RunLoop::isMain());
1530     
1531     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1532     
1533     for (auto& processPool : processPools()) {
1534         if (auto* process = processPool->networkProcess())
1535             process->scheduleStatisticsAndDataRecordsProcessing(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1536     }
1537 }
1538
1539 void WebsiteDataStore::setLastSeen(const URL& url, Seconds seconds, CompletionHandler<void()>&& completionHandler)
1540 {
1541     if (url.protocolIsAbout() || url.isEmpty()) {
1542         completionHandler();
1543         return;
1544     }
1545
1546     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1547
1548     for (auto& processPool : processPools()) {
1549         if (auto* process = processPool->networkProcess())
1550             process->setLastSeen(m_sessionID, WebCore::RegistrableDomain { url }, seconds, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1551     }
1552 }
1553
1554 void WebsiteDataStore::mergeStatisticForTesting(const URL& url , const URL& topFrameUrl, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
1555 {
1556     if (url.protocolIsAbout() || url.isEmpty()) {
1557         completionHandler();
1558         return;
1559     }
1560
1561     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1562
1563     for (auto& processPool : processPools()) {
1564         if (auto* process = processPool->networkProcess())
1565             process->mergeStatisticForTesting(m_sessionID, WebCore::RegistrableDomain { url }, WebCore::RegistrableDomain { topFrameUrl }, lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1566     }
1567 }
1568
1569 void WebsiteDataStore::setNotifyPagesWhenDataRecordsWereScanned(bool value, CompletionHandler<void()>&& completionHandler)
1570 {
1571     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1572
1573     for (auto& processPool : processPools())
1574         processPool->ensureNetworkProcess().setNotifyPagesWhenDataRecordsWereScanned(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1575 }
1576
1577 void WebsiteDataStore::setIsRunningResourceLoadStatisticsTest(bool value, CompletionHandler<void()>&& completionHandler)
1578 {
1579     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1580     
1581     for (auto& processPool : processPools())
1582         processPool->ensureNetworkProcess().setIsRunningResourceLoadStatisticsTest(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1583 }
1584
1585 void WebsiteDataStore::setNotifyPagesWhenTelemetryWasCaptured(bool value, CompletionHandler<void()>&& completionHandler)
1586 {
1587     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1588     
1589     for (auto& processPool : processPools())
1590         processPool->ensureNetworkProcess().setNotifyPagesWhenTelemetryWasCaptured(m_sessionID, value, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1591 }
1592
1593 void WebsiteDataStore::getAllStorageAccessEntries(WebPageProxyIdentifier pageID, CompletionHandler<void(Vector<String>&& domains)>&& completionHandler)
1594 {
1595     auto* webPage = WebProcessProxy::webPage(pageID);
1596     if (!webPage) {
1597         completionHandler({ });
1598         return;
1599     }
1600     
1601     auto& networkProcess = webPage->process().processPool().ensureNetworkProcess();
1602     networkProcess.getAllStorageAccessEntries(m_sessionID, WTFMove(completionHandler));
1603 }
1604
1605
1606 void WebsiteDataStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1607 {
1608     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1609     
1610     for (auto& processPool : processPools())
1611         processPool->ensureNetworkProcess().setTimeToLiveUserInteraction(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
1612 }
1613
1614 void WebsiteDataStore::logUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1615 {
1616     ASSERT(RunLoop::isMain());
1617     
1618     if (url.protocolIsAbout() || url.isEmpty()) {
1619         completionHandler();
1620         return;
1621     }
1622     
1623     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1624
1625     for (auto& processPool : processPools()) {
1626         if (auto* process = processPool->networkProcess())
1627             process->logUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator = callbackAggregator.copyRef()] { });
1628     }
1629 }
1630
1631 void WebsiteDataStore::hasHadUserInteraction(const URL& url, CompletionHandler<void(bool)>&& completionHandler)
1632 {
1633     ASSERT(RunLoop::isMain());
1634     
1635     if (url.protocolIsAbout() || url.isEmpty()) {
1636         completionHandler(false);
1637         return;
1638     }
1639     
1640     for (auto& processPool : processPools()) {
1641         if (auto* process = processPool->networkProcess()) {
1642             process->hasHadUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1643             ASSERT(processPools().size() == 1);
1644             break;
1645         }
1646     }
1647 }
1648
1649 void WebsiteDataStore::clearUserInteraction(const URL& url, CompletionHandler<void()>&& completionHandler)
1650 {
1651     ASSERT(RunLoop::isMain());
1652     
1653     if (url.protocolIsAbout() || url.isEmpty()) {
1654         completionHandler();
1655         return;
1656     }
1657     
1658     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1659
1660     for (auto& processPool : processPools()) {
1661         if (auto* process = processPool->networkProcess())
1662             process->clearUserInteraction(m_sessionID, WebCore::RegistrableDomain { url }, [callbackAggregator = callbackAggregator.copyRef()] { });
1663     }
1664 }
1665
1666 void WebsiteDataStore::setGrandfathered(const URL& url, bool isGrandfathered, CompletionHandler<void()>&& completionHandler)
1667 {
1668     ASSERT(RunLoop::isMain());
1669     
1670     if (url.protocolIsAbout() || url.isEmpty()) {
1671         completionHandler();
1672         return;
1673     }
1674     
1675     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1676     
1677     for (auto& processPool : processPools()) {
1678         if (auto* process = processPool->networkProcess())
1679             process->setGrandfathered(m_sessionID, WebCore::RegistrableDomain { url }, isGrandfathered, [callbackAggregator = callbackAggregator.copyRef()] { });
1680     }
1681 }
1682
1683 void WebsiteDataStore::setUseITPDatabase(bool value)
1684 {
1685     ASSERT(RunLoop::isMain());
1686
1687     for (auto& processPool : processPools())
1688         processPool->ensureNetworkProcess().setUseITPDatabase(m_sessionID, value);
1689 }
1690
1691 void WebsiteDataStore::setCrossSiteLoadWithLinkDecorationForTesting(const URL& fromURL, const URL& toURL, CompletionHandler<void()>&& completionHandler)
1692 {
1693     ASSERT(RunLoop::isMain());
1694     
1695     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1696     
1697     for (auto& processPool : processPools()) {
1698         if (auto* process = processPool->networkProcess())
1699             process->setCrossSiteLoadWithLinkDecorationForTesting(m_sessionID, WebCore::RegistrableDomain { fromURL }, WebCore::RegistrableDomain { toURL }, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1700     }
1701 }
1702
1703 void WebsiteDataStore::resetCrossSiteLoadsWithLinkDecorationForTesting(CompletionHandler<void()>&& completionHandler)
1704 {
1705     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1706     
1707     for (auto& processPool : processPools()) {
1708         if (auto* networkProcess = processPool->networkProcess())
1709             networkProcess->resetCrossSiteLoadsWithLinkDecorationForTesting(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
1710     }
1711 }
1712
1713 void WebsiteDataStore::deleteCookiesForTesting(const URL& url, bool includeHttpOnlyCookies, CompletionHandler<void()>&& completionHandler)
1714 {
1715     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1716     
1717     for (auto& processPool : processPools()) {
1718         if (auto* networkProcess = processPool->networkProcess())
1719             networkProcess->deleteCookiesForTesting(m_sessionID, WebCore::RegistrableDomain { url }, includeHttpOnlyCookies, [callbackAggregator = callbackAggregator.copyRef()] { });
1720     }
1721 }
1722
1723 void WebsiteDataStore::hasLocalStorageForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1724 {
1725     for (auto& processPool : processPools()) {
1726         if (auto* networkProcess = processPool->networkProcess()) {
1727             networkProcess->hasLocalStorage(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1728             ASSERT(processPools().size() == 1);
1729             break;
1730         }
1731     }
1732     ASSERT(!completionHandler);
1733 }
1734
1735 void WebsiteDataStore::hasIsolatedSessionForTesting(const URL& url, CompletionHandler<void(bool)>&& completionHandler) const
1736 {
1737     for (auto& processPool : processPools()) {
1738         if (auto* networkProcess = processPool->networkProcess()) {
1739             networkProcess->hasIsolatedSession(m_sessionID, WebCore::RegistrableDomain { url }, WTFMove(completionHandler));
1740             ASSERT(processPools().size() == 1);
1741             break;
1742         }
1743     }
1744     ASSERT(!completionHandler);
1745 }
1746
1747 void WebsiteDataStore::setResourceLoadStatisticsShouldDowngradeReferrerForTesting(bool enabled, CompletionHandler<void()>&& completionHandler)
1748 {
1749     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1750     
1751     for (auto& processPool : processPools()) {
1752         if (auto* networkProcess = processPool->networkProcess()) {
1753             networkProcess->setShouldDowngradeReferrerForTesting(enabled, [callbackAggregator = callbackAggregator.copyRef()] { });
1754             ASSERT(processPools().size() == 1);
1755             break;
1756         }
1757     }
1758     ASSERT(!completionHandler);
1759 }
1760 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1761
1762 void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1763 {
1764 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1765     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1766     
1767     for (auto& processPool : processPools())
1768         processPool->ensureNetworkProcess().setCacheMaxAgeCapForPrevalentResources(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
1769 #else
1770     UNUSED_PARAM(seconds);
1771     completionHandler();
1772 #endif
1773 }
1774
1775 void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&& completionHandler)
1776 {
1777 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1778     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1779     
1780     for (auto& processPool : processPools()) {
1781         if (auto* networkProcess = processPool->networkProcess())
1782             networkProcess->resetCacheMaxAgeCapForPrevalentResources(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
1783     }
1784 #else
1785     completionHandler();
1786 #endif
1787 }
1788
1789 bool WebsiteDataStore::isAssociatedProcessPool(WebProcessPool& processPool) const
1790 {
1791     if (auto* processPoolDataStore = processPool.websiteDataStore())
1792         return processPoolDataStore == this;
1793     return false;
1794 }
1795
1796 HashSet<RefPtr<WebProcessPool>> WebsiteDataStore::processPools(size_t count, bool ensureAPoolExists) const
1797 {
1798     HashSet<RefPtr<WebProcessPool>> processPools;
1799     for (auto& process : processes()) {
1800         if (auto* processPool = process.processPoolIfExists())
1801             processPools.add(processPool);
1802     }
1803
1804     if (processPools.isEmpty()) {
1805         // Check if we're one of the legacy data stores.
1806         for (auto& processPool : WebProcessPool::allProcessPools()) {
1807             if (!isAssociatedProcessPool(*processPool))
1808                 continue;
1809
1810             processPools.add(processPool);
1811
1812             if (processPools.size() == count)
1813                 break;
1814         }
1815     }
1816
1817     if (processPools.isEmpty() && count && ensureAPoolExists) {
1818         auto processPool = WebProcessPool::create(API::ProcessPoolConfiguration::create());
1819         processPools.add(processPool.ptr());
1820     }
1821
1822     return processPools;
1823 }
1824
1825 #if ENABLE(NETSCAPE_PLUGIN_API)
1826 Vector<PluginModuleInfo> WebsiteDataStore::plugins() const
1827 {
1828     Vector<PluginModuleInfo> plugins;
1829
1830     for (auto& processPool : processPools()) {
1831         for (auto& plugin : processPool->pluginInfoStore().plugins())
1832             plugins.append(plugin);
1833     }
1834
1835     return plugins;
1836 }
1837 #endif
1838
1839 static String computeMediaKeyFile(const String& mediaKeyDirectory)
1840 {
1841     return FileSystem::pathByAppendingComponent(mediaKeyDirectory, "SecureStop.plist");
1842 }
1843
1844 Vector<WebCore::SecurityOriginData> WebsiteDataStore::mediaKeyOrigins(const String& mediaKeysStorageDirectory)
1845 {
1846     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1847
1848     Vector<WebCore::SecurityOriginData> origins;
1849
1850     for (const auto& originPath : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1851         auto mediaKeyFile = computeMediaKeyFile(originPath);
1852         if (!FileSystem::fileExists(mediaKeyFile))
1853             continue;
1854
1855         auto mediaKeyIdentifier = FileSystem::pathGetFileName(originPath);
1856
1857         if (auto securityOrigin = WebCore::SecurityOriginData::fromDatabaseIdentifier(mediaKeyIdentifier))
1858             origins.append(*securityOrigin);
1859     }
1860
1861     return origins;
1862 }
1863
1864 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, WallTime modifiedSince)
1865 {
1866     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1867
1868     for (const auto& mediaKeyDirectory : FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1869         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1870
1871         auto modificationTime = FileSystem::getFileModificationTime(mediaKeyFile);
1872         if (!modificationTime)
1873             continue;
1874
1875         if (modificationTime.value() < modifiedSince)
1876             continue;
1877
1878         FileSystem::deleteFile(mediaKeyFile);
1879         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1880     }
1881 }
1882
1883 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, const HashSet<WebCore::SecurityOriginData>& origins)
1884 {
1885     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1886
1887     for (const auto& origin : origins) {
1888         auto mediaKeyDirectory = FileSystem::pathByAppendingComponent(mediaKeysStorageDirectory, origin.databaseIdentifier());
1889         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1890
1891         FileSystem::deleteFile(mediaKeyFile);
1892         FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1893     }
1894 }
1895
1896 bool WebsiteDataStore::resourceLoadStatisticsEnabled() const
1897 {
1898 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1899     return m_resourceLoadStatisticsEnabled;
1900 #else
1901     return false;
1902 #endif
1903 }
1904
1905 bool WebsiteDataStore::resourceLoadStatisticsDebugMode() const
1906 {
1907 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1908     return m_resourceLoadStatisticsDebugMode;
1909 #else
1910     return false;
1911 #endif
1912 }
1913
1914 void WebsiteDataStore::setResourceLoadStatisticsEnabled(bool enabled)
1915 {
1916 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1917     if (m_sessionID.isEphemeral() || enabled == resourceLoadStatisticsEnabled())
1918         return;
1919
1920     if (enabled) {
1921         m_resourceLoadStatisticsEnabled = true;
1922         
1923         resolveDirectoriesIfNecessary();
1924         
1925         for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false))
1926             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(m_sessionID, true));
1927         return;
1928     }
1929
1930     for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false))
1931         processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsEnabled(m_sessionID, false));
1932
1933     m_resourceLoadStatisticsEnabled = false;
1934 #else
1935     UNUSED_PARAM(enabled);
1936 #endif
1937 }
1938
1939 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1940 void WebsiteDataStore::setStatisticsTestingCallback(Function<void(const String&)>&& callback)
1941 {
1942     if (callback) {
1943         for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false))
1944             processPool->sendToNetworkingProcess(Messages::NetworkProcess::SetResourceLoadStatisticsLogTestingEvent(true));
1945     }
1946     
1947     m_statisticsTestingCallback = WTFMove(callback);
1948 }
1949 #endif
1950
1951 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled)
1952 {
1953     setResourceLoadStatisticsDebugMode(enabled, []() { });
1954 }
1955
1956 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled, CompletionHandler<void()>&& completionHandler)
1957 {
1958 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1959     m_resourceLoadStatisticsDebugMode = enabled;
1960
1961     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1962     
1963     for (auto& processPool : processPools())
1964         processPool->ensureNetworkProcess().setResourceLoadStatisticsDebugMode(m_sessionID, enabled, [callbackAggregator = callbackAggregator.copyRef()] { });
1965 #else
1966     UNUSED_PARAM(enabled);
1967     UNUSED_PARAM(completionHandler);
1968 #endif
1969 }
1970
1971 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1972 void WebsiteDataStore::logTestingEvent(const String& event)
1973 {
1974     ASSERT(RunLoop::isMain());
1975     
1976     if (m_statisticsTestingCallback)
1977         m_statisticsTestingCallback(event);
1978 }
1979
1980 void WebsiteDataStore::clearResourceLoadStatisticsInWebProcesses(CompletionHandler<void()>&& callback)
1981 {
1982     if (resourceLoadStatisticsEnabled()) {
1983         for (auto& processPool : processPools())
1984             processPool->clearResourceLoadStatistics();
1985     }
1986     callback();
1987 }
1988 #endif
1989
1990 Vector<WebCore::Cookie> WebsiteDataStore::pendingCookies() const
1991 {
1992     return copyToVector(m_pendingCookies);
1993 }
1994
1995 void WebsiteDataStore::addPendingCookie(const WebCore::Cookie& cookie)
1996 {
1997     m_pendingCookies.removeIf([&cookie](auto& pendingCookie) {
1998         return pendingCookie.isKeyEqual(cookie);
1999     });
2000     m_pendingCookies.add(cookie);
2001 }
2002
2003 void WebsiteDataStore::removePendingCookie(const WebCore::Cookie& cookie)
2004 {
2005     m_pendingCookies.remove(cookie);
2006 }
2007     
2008 void WebsiteDataStore::clearPendingCookies()
2009 {
2010     m_pendingCookies.clear();
2011 }
2012
2013 uint64_t WebsiteDataStore::perThirdPartyOriginStorageQuota() const
2014 {
2015     // FIXME: Consider whether allowing to set a perThirdPartyOriginStorageQuota from a WebsiteDataStore.
2016     return WebCore::StorageQuotaManager::defaultThirdPartyQuotaFromPerOriginQuota(perOriginStorageQuota());
2017 }
2018
2019 #if !PLATFORM(COCOA)
2020 WebsiteDataStoreParameters WebsiteDataStore::parameters()
2021 {
2022     WebsiteDataStoreParameters parameters;
2023     parameters.networkSessionParameters.sessionID = m_sessionID;
2024
2025     resolveDirectoriesIfNecessary();
2026
2027     auto localStorageDirectory = resolvedLocalStorageDirectory();
2028     if (!localStorageDirectory.isEmpty()) {
2029         parameters.localStorageDirectory = localStorageDirectory;
2030         SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
2031     }
2032
2033 #if ENABLE(INDEXED_DATABASE)
2034     parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
2035     if (!parameters.indexedDatabaseDirectory.isEmpty())
2036         SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
2037 #endif
2038
2039 #if ENABLE(SERVICE_WORKER)
2040     parameters.serviceWorkerRegistrationDirectory = resolvedServiceWorkerRegistrationDirectory();
2041     if (!parameters.serviceWorkerRegistrationDirectory.isEmpty())
2042         SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
2043 #endif
2044
2045     parameters.perOriginStorageQuota = perOriginStorageQuota();
2046     parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
2047
2048     platformSetNetworkParameters(parameters);
2049
2050     return parameters;
2051 }
2052 #endif
2053
2054 #if HAVE(SEC_KEY_PROXY)
2055 void WebsiteDataStore::addSecKeyProxyStore(Ref<SecKeyProxyStore>&& store)
2056 {
2057     m_secKeyProxyStores.append(WTFMove(store));
2058 }
2059 #endif
2060
2061 #if ENABLE(WEB_AUTHN)
2062 void WebsiteDataStore::setMockWebAuthenticationConfiguration(MockWebAuthenticationConfiguration&& configuration)
2063 {
2064     if (!m_authenticatorManager->isMock()) {
2065         m_authenticatorManager = makeUniqueRef<MockAuthenticatorManager>(WTFMove(configuration));
2066         return;
2067     }
2068     static_cast<MockAuthenticatorManager*>(&m_authenticatorManager)->setTestConfiguration(WTFMove(configuration));
2069 }
2070 #endif
2071
2072 API::HTTPCookieStore& WebsiteDataStore::cookieStore()
2073 {
2074     if (!m_cookieStore)
2075         m_cookieStore = API::HTTPCookieStore::create(*this);
2076
2077     return *m_cookieStore;
2078 }
2079
2080 void WebsiteDataStore::didCreateNetworkProcess()
2081 {
2082 }
2083
2084 bool WebsiteDataStore::setSourceApplicationSecondaryIdentifier(String&& identifier)
2085 {
2086     if (m_networkingHasBegun)
2087         return false;
2088     m_resolvedConfiguration->setSourceApplicationSecondaryIdentifier(WTFMove(identifier));
2089     return true;
2090 }
2091
2092 bool WebsiteDataStore::setSourceApplicationBundleIdentifier(String&& identifier)
2093 {
2094     if (m_networkingHasBegun)
2095         return false;
2096     m_resolvedConfiguration->setSourceApplicationBundleIdentifier(WTFMove(identifier));
2097     return true;
2098 }
2099
2100 void WebsiteDataStore::getLocalStorageDetails(Function<void(Vector<LocalStorageDatabaseTracker::OriginDetails>&&)>&& completionHandler)
2101 {
2102     if (!isPersistent()) {
2103         completionHandler({ });
2104         return;
2105     }
2106
2107     for (auto& processPool : processPools()) {
2108         processPool->ensureNetworkProcess(this);
2109         processPool->networkProcess()->getLocalStorageDetails(m_sessionID, [completionHandler = WTFMove(completionHandler)](auto&& details) {
2110             completionHandler(WTFMove(details));
2111         });
2112         // FIXME: Support fetching from multiple pools.
2113         break;
2114     }
2115     ASSERT(!completionHandler);
2116 }
2117
2118 #if !PLATFORM(COCOA)
2119 WTF::String WebsiteDataStore::defaultMediaCacheDirectory()
2120 {
2121     // FIXME: Implement. https://bugs.webkit.org/show_bug.cgi?id=156369 and https://bugs.webkit.org/show_bug.cgi?id=156370
2122     return WTF::String();
2123 }
2124
2125 WTF::String WebsiteDataStore::defaultJavaScriptConfigurationDirectory()
2126 {
2127     // FIXME: Implement.
2128     return WTF::String();
2129 }
2130 #endif
2131
2132 #if !USE(GLIB)
2133 WTF::String WebsiteDataStore::defaultDeviceIdHashSaltsStorageDirectory()
2134 {
2135     // Not implemented.
2136     return WTF::String();
2137 }
2138 #endif
2139
2140 }