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