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