DeviceID hash salt manager can be NULL
[WebKit-https.git] / Source / WebKit / UIProcess / WebsiteData / WebsiteDataStore.cpp
1 /*
2  * Copyright (C) 2014-2017 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 "StorageManager.h"
37 #include "WebCookieManagerProxy.h"
38 #include "WebProcessMessages.h"
39 #include "WebProcessPool.h"
40 #include "WebResourceLoadStatisticsStore.h"
41 #include "WebResourceLoadStatisticsStoreMessages.h"
42 #include "WebsiteData.h"
43 #include "WebsiteDataStoreParameters.h"
44 #include <WebCore/ApplicationCacheStorage.h>
45 #include <WebCore/DatabaseTracker.h>
46 #include <WebCore/FileSystem.h>
47 #include <WebCore/HTMLMediaElement.h>
48 #include <WebCore/OriginLock.h>
49 #include <WebCore/SecurityOrigin.h>
50 #include <WebCore/SecurityOriginData.h>
51 #include <wtf/CallbackAggregator.h>
52 #include <wtf/CompletionHandler.h>
53 #include <wtf/CrossThreadCopier.h>
54 #include <wtf/ProcessPrivilege.h>
55 #include <wtf/RunLoop.h>
56
57 #if ENABLE(NETSCAPE_PLUGIN_API)
58 #include "PluginProcessManager.h"
59 #endif
60
61 #if HAVE(SEC_KEY_PROXY)
62 #include "SecKeyProxyStore.h"
63 #endif
64
65 namespace WebKit {
66
67 static bool allowsWebsiteDataRecordsForAllOrigins;
68 void WebsiteDataStore::allowWebsiteDataRecordsForAllOrigins()
69 {
70     allowsWebsiteDataRecordsForAllOrigins = true;
71 }
72
73 static HashMap<PAL::SessionID, WebsiteDataStore*>& nonDefaultDataStores()
74 {
75     RELEASE_ASSERT(isUIThread());
76     static NeverDestroyed<HashMap<PAL::SessionID, WebsiteDataStore*>> map;
77     return map;
78 }
79
80 Ref<WebsiteDataStore> WebsiteDataStore::createNonPersistent()
81 {
82     return adoptRef(*new WebsiteDataStore(PAL::SessionID::generateEphemeralSessionID()));
83 }
84
85 Ref<WebsiteDataStore> WebsiteDataStore::create(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
86 {
87     return adoptRef(*new WebsiteDataStore(WTFMove(configuration), sessionID));
88 }
89
90 WebsiteDataStore::WebsiteDataStore(Ref<WebsiteDataStoreConfiguration>&& configuration, PAL::SessionID sessionID)
91     : m_sessionID(sessionID)
92     , m_resolvedConfiguration(WTFMove(configuration))
93     , m_configuration(m_resolvedConfiguration->copy())
94     , m_storageManager(StorageManager::create(m_configuration->localStorageDirectory()))
95     , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String()))
96     , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore"))
97 #if ENABLE(WEB_AUTHN)
98     , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>())
99 #endif
100 {
101     WTF::setProcessPrivileges(allPrivileges());
102     maybeRegisterWithSessionIDMap();
103     platformInitialize();
104
105     ASSERT(RunLoop::isMain());
106 }
107
108 WebsiteDataStore::WebsiteDataStore(PAL::SessionID sessionID)
109     : m_sessionID(sessionID)
110     , m_resolvedConfiguration(WebsiteDataStoreConfiguration::create())
111     , m_configuration(m_resolvedConfiguration->copy())
112     , m_deviceIdHashSaltStorage(DeviceIdHashSaltStorage::create(isPersistent() ? m_configuration->deviceIdHashSaltsStorageDirectory() : String()))
113     , m_queue(WorkQueue::create("com.apple.WebKit.WebsiteDataStore"))
114 #if ENABLE(WEB_AUTHN)
115     , m_authenticatorManager(makeUniqueRef<AuthenticatorManager>())
116 #endif
117 {
118     maybeRegisterWithSessionIDMap();
119     platformInitialize();
120
121     ASSERT(RunLoop::isMain());
122 }
123
124 WebsiteDataStore::~WebsiteDataStore()
125 {
126     ASSERT(RunLoop::isMain());
127
128     platformDestroy();
129
130     unregisterWebResourceLoadStatisticsStoreAsMessageReceiver();
131
132     if (m_sessionID.isValid() && m_sessionID != PAL::SessionID::defaultSessionID()) {
133         ASSERT(nonDefaultDataStores().get(m_sessionID) == this);
134         nonDefaultDataStores().remove(m_sessionID);
135         for (auto& processPool : WebProcessPool::allProcessPools()) {
136             if (auto* networkProcess = processPool->networkProcess())
137                 networkProcess->removeSession(m_sessionID);
138         }
139     }
140 }
141
142 void WebsiteDataStore::maybeRegisterWithSessionIDMap()
143 {
144     if (m_sessionID.isValid() && m_sessionID != PAL::SessionID::defaultSessionID()) {
145         auto result = nonDefaultDataStores().add(m_sessionID, this);
146         ASSERT_UNUSED(result, result.isNewEntry);
147     }
148 }
149
150 WebsiteDataStore* WebsiteDataStore::existingNonDefaultDataStoreForSessionID(PAL::SessionID sessionID)
151 {
152     return sessionID.isValid() && sessionID != PAL::SessionID::defaultSessionID() ? nonDefaultDataStores().get(sessionID) : nullptr;
153 }
154
155 WebProcessPool* WebsiteDataStore::processPoolForCookieStorageOperations()
156 {
157     auto pools = processPools(1, false);
158     return pools.isEmpty() ? nullptr : pools.begin()->get();
159 }
160
161 void WebsiteDataStore::resolveDirectoriesIfNecessary()
162 {
163     if (m_hasResolvedDirectories)
164         return;
165     m_hasResolvedDirectories = true;
166
167     // Resolve directory paths.
168     if (!m_configuration->applicationCacheDirectory().isEmpty())
169         m_resolvedConfiguration->setApplicationCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->applicationCacheDirectory()));
170     if (!m_configuration->mediaCacheDirectory().isEmpty())
171         m_resolvedConfiguration->setMediaCacheDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaCacheDirectory()));
172     if (!m_configuration->mediaKeysStorageDirectory().isEmpty())
173         m_resolvedConfiguration->setMediaKeysStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->mediaKeysStorageDirectory()));
174     if (!m_configuration->webSQLDatabaseDirectory().isEmpty())
175         m_resolvedConfiguration->setWebSQLDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->webSQLDatabaseDirectory()));
176     if (!m_configuration->indexedDBDatabaseDirectory().isEmpty())
177         m_resolvedConfiguration->setIndexedDBDatabaseDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->indexedDBDatabaseDirectory()));
178     if (!m_configuration->deviceIdHashSaltsStorageDirectory().isEmpty())
179         m_resolvedConfiguration->setDeviceIdHashSaltsStorageDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->deviceIdHashSaltsStorageDirectory()));
180     if (!m_configuration->resourceLoadStatisticsDirectory().isEmpty())
181         m_resolvedConfiguration->setResourceLoadStatisticsDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->resourceLoadStatisticsDirectory()));
182     if (!m_configuration->serviceWorkerRegistrationDirectory().isEmpty() && m_resolvedConfiguration->serviceWorkerRegistrationDirectory().isEmpty())
183         m_resolvedConfiguration->setServiceWorkerRegistrationDirectory(resolveAndCreateReadWriteDirectoryForSandboxExtension(m_configuration->serviceWorkerRegistrationDirectory()));
184     if (!m_configuration->javaScriptConfigurationDirectory().isEmpty())
185         m_resolvedConfiguration->setJavaScriptConfigurationDirectory(resolvePathForSandboxExtension(m_configuration->javaScriptConfigurationDirectory()));
186     if (!m_configuration->cacheStorageDirectory().isEmpty() && m_resolvedConfiguration->cacheStorageDirectory().isEmpty())
187         m_resolvedConfiguration->setCacheStorageDirectory(resolvePathForSandboxExtension(m_configuration->cacheStorageDirectory()));
188
189     // Resolve directories for file paths.
190     if (!m_configuration->cookieStorageFile().isEmpty()) {
191         m_resolvedConfiguration->setCookieStorageFile(resolveAndCreateReadWriteDirectoryForSandboxExtension(WebCore::FileSystem::directoryName(m_configuration->cookieStorageFile())));
192         m_resolvedConfiguration->setCookieStorageFile(WebCore::FileSystem::pathByAppendingComponent(m_resolvedConfiguration->cookieStorageFile(), WebCore::FileSystem::pathGetFileName(m_configuration->cookieStorageFile())));
193     }
194 }
195
196 void WebsiteDataStore::cloneSessionData(WebPageProxy& sourcePage, WebPageProxy& newPage)
197 {
198     auto& sourceDataStore = sourcePage.websiteDataStore();
199     auto& newDataStore = newPage.websiteDataStore();
200
201     // FIXME: Handle this.
202     if (&sourceDataStore != &newDataStore)
203         return;
204
205     if (!sourceDataStore.m_storageManager)
206         return;
207
208     sourceDataStore.m_storageManager->cloneSessionStorageNamespace(sourcePage.pageID(), newPage.pageID());
209 }
210
211 enum class ProcessAccessType {
212     None,
213     OnlyIfLaunched,
214     Launch,
215 };
216
217 static ProcessAccessType computeNetworkProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
218 {
219     ProcessAccessType processAccessType = ProcessAccessType::None;
220
221     if (dataTypes.contains(WebsiteDataType::Cookies)) {
222         if (isNonPersistentStore)
223             processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
224         else
225             processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
226     }
227
228     if (dataTypes.contains(WebsiteDataType::DiskCache) && !isNonPersistentStore)
229         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
230
231     if (dataTypes.contains(WebsiteDataType::DOMCache))
232         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
233     
234     if (dataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !isNonPersistentStore)
235         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
236
237 #if ENABLE(SERVICE_WORKER)
238     if (dataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !isNonPersistentStore)
239         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
240 #endif
241
242     return processAccessType;
243 }
244
245 static ProcessAccessType computeWebProcessAccessTypeForDataFetch(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
246 {
247     UNUSED_PARAM(isNonPersistentStore);
248
249     ProcessAccessType processAccessType = ProcessAccessType::None;
250
251     if (dataTypes.contains(WebsiteDataType::MemoryCache))
252         return ProcessAccessType::OnlyIfLaunched;
253
254     return processAccessType;
255 }
256
257 void WebsiteDataStore::fetchData(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void(Vector<WebsiteDataRecord>)>&& completionHandler)
258 {
259     fetchDataAndApply(dataTypes, fetchOptions, nullptr, WTFMove(completionHandler));
260 }
261
262 void WebsiteDataStore::fetchDataAndApply(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply)
263 {
264     struct CallbackAggregator final : ThreadSafeRefCounted<CallbackAggregator> {
265         CallbackAggregator(OptionSet<WebsiteDataFetchOption> fetchOptions, RefPtr<WorkQueue>&& queue, Function<void(Vector<WebsiteDataRecord>)>&& apply, WebsiteDataStore& dataStore)
266             : fetchOptions(fetchOptions)
267             , queue(WTFMove(queue))
268             , apply(WTFMove(apply))
269             , protectedDataStore(dataStore)
270         {
271             ASSERT(RunLoop::isMain());
272         }
273
274         ~CallbackAggregator()
275         {
276             ASSERT(!pendingCallbacks);
277
278             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
279             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
280         }
281
282         void addPendingCallback()
283         {
284             pendingCallbacks++;
285         }
286
287         void removePendingCallback(WebsiteData websiteData)
288         {
289             ASSERT(pendingCallbacks);
290             --pendingCallbacks;
291
292             for (auto& entry : websiteData.entries) {
293                 auto displayName = WebsiteDataRecord::displayNameForOrigin(entry.origin);
294                 if (!displayName) {
295                     if (!allowsWebsiteDataRecordsForAllOrigins)
296                         continue;
297
298                     displayName = makeString(entry.origin.protocol, " ", entry.origin.host);
299                 }
300
301                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
302                 if (!record.displayName)
303                     record.displayName = WTFMove(displayName);
304
305                 record.add(entry.type, entry.origin);
306
307                 if (fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes)) {
308                     if (!record.size)
309                         record.size = WebsiteDataRecord::Size { 0, { } };
310
311                     record.size->totalSize += entry.size;
312                     record.size->typeSizes.add(static_cast<unsigned>(entry.type), 0).iterator->value += entry.size;
313                 }
314             }
315
316             for (auto& hostName : websiteData.hostNamesWithCookies) {
317                 auto displayName = WebsiteDataRecord::displayNameForCookieHostName(hostName);
318                 if (!displayName)
319                     continue;
320
321                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
322                 if (!record.displayName)
323                     record.displayName = WTFMove(displayName);
324
325                 record.addCookieHostName(hostName);
326             }
327
328 #if ENABLE(NETSCAPE_PLUGIN_API)
329             for (auto& hostName : websiteData.hostNamesWithPluginData) {
330                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
331                 if (!displayName)
332                     continue;
333
334                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
335                 if (!record.displayName)
336                     record.displayName = WTFMove(displayName);
337
338                 record.addPluginDataHostName(hostName);
339             }
340 #endif
341
342             for (auto& origin : websiteData.originsWithCredentials) {
343                 auto& record = m_websiteDataRecords.add(origin, WebsiteDataRecord { }).iterator->value;
344                 
345                 record.addOriginWithCredential(origin);
346             }
347
348             for (auto& hostName : websiteData.hostNamesWithHSTSCache) {
349                 auto displayName = WebsiteDataRecord::displayNameForHostName(hostName);
350                 if (!displayName)
351                     continue;
352                 
353                 auto& record = m_websiteDataRecords.add(displayName, WebsiteDataRecord { }).iterator->value;
354                 if (!record.displayName)
355                     record.displayName = WTFMove(displayName);
356
357                 record.addHSTSCacheHostname(hostName);
358             }
359
360             callIfNeeded();
361         }
362
363         void callIfNeeded()
364         {
365             if (pendingCallbacks)
366                 return;
367
368             Vector<WebsiteDataRecord> records;
369             records.reserveInitialCapacity(m_websiteDataRecords.size());
370             for (auto& record : m_websiteDataRecords.values())
371                 records.uncheckedAppend(WTFMove(record));
372
373             auto processRecords = [apply = WTFMove(apply), records = WTFMove(records)] () mutable {
374                 apply(WTFMove(records));
375             };
376
377             if (queue)
378                 queue->dispatch(WTFMove(processRecords));
379             else
380                 RunLoop::main().dispatch(WTFMove(processRecords));
381         }
382
383         const OptionSet<WebsiteDataFetchOption> fetchOptions;
384
385         unsigned pendingCallbacks = 0;
386         RefPtr<WorkQueue> queue;
387         Function<void(Vector<WebsiteDataRecord>)> apply;
388
389         HashMap<String, WebsiteDataRecord> m_websiteDataRecords;
390         Ref<WebsiteDataStore> protectedDataStore;
391     };
392
393     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(fetchOptions, WTFMove(queue), WTFMove(apply), *this));
394
395 #if ENABLE(VIDEO)
396     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
397         callbackAggregator->addPendingCallback();
398         m_queue->dispatch([mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
399             // FIXME: Make HTMLMediaElement::originsInMediaCache return a collection of SecurityOriginDatas.
400             HashSet<RefPtr<WebCore::SecurityOrigin>> origins = WebCore::HTMLMediaElement::originsInMediaCache(mediaCacheDirectory);
401             WebsiteData websiteData;
402             
403             for (auto& origin : origins) {
404                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::DiskCache, 0 };
405                 websiteData.entries.append(WTFMove(entry));
406             }
407             
408             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
409                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
410             });
411         });
412     }
413 #endif
414
415     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
416     if (networkProcessAccessType != ProcessAccessType::None) {
417         for (auto& processPool : processPools()) {
418             switch (networkProcessAccessType) {
419             case ProcessAccessType::OnlyIfLaunched:
420                 if (!processPool->networkProcess())
421                     continue;
422                 break;
423
424             case ProcessAccessType::Launch:
425                 processPool->ensureNetworkProcess(this);
426                 break;
427
428             case ProcessAccessType::None:
429                 ASSERT_NOT_REACHED();
430             }
431
432             callbackAggregator->addPendingCallback();
433             processPool->networkProcess()->fetchWebsiteData(m_sessionID, dataTypes, fetchOptions, [callbackAggregator, processPool](WebsiteData websiteData) {
434                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
435             });
436         }
437     }
438
439     auto webProcessAccessType = computeWebProcessAccessTypeForDataFetch(dataTypes, !isPersistent());
440     if (webProcessAccessType != ProcessAccessType::None) {
441         for (auto& process : processes()) {
442             switch (webProcessAccessType) {
443             case ProcessAccessType::OnlyIfLaunched:
444                 if (!process->canSendMessage())
445                     continue;
446                 break;
447
448             case ProcessAccessType::Launch:
449                 // FIXME: Handle this.
450                 ASSERT_NOT_REACHED();
451                 break;
452
453             case ProcessAccessType::None:
454                 ASSERT_NOT_REACHED();
455             }
456
457             callbackAggregator->addPendingCallback();
458             process->fetchWebsiteData(m_sessionID, dataTypes, [callbackAggregator](WebsiteData websiteData) {
459                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
460             });
461         }
462     }
463
464     if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) {
465         callbackAggregator->addPendingCallback();
466
467         m_storageManager->getSessionStorageOrigins([callbackAggregator](HashSet<WebCore::SecurityOriginData>&& origins) {
468             WebsiteData websiteData;
469
470             while (!origins.isEmpty())
471                 websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::SessionStorage, 0 });
472
473             callbackAggregator->removePendingCallback(WTFMove(websiteData));
474         });
475     }
476
477     if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) {
478         callbackAggregator->addPendingCallback();
479
480         m_storageManager->getLocalStorageOrigins([callbackAggregator](HashSet<WebCore::SecurityOriginData>&& origins) {
481             WebsiteData websiteData;
482
483             while (!origins.isEmpty())
484                 websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::LocalStorage, 0 });
485
486             callbackAggregator->removePendingCallback(WTFMove(websiteData));
487         });
488     }
489
490     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt)) {
491         callbackAggregator->addPendingCallback();
492
493         m_deviceIdHashSaltStorage->getDeviceIdHashSaltOrigins([callbackAggregator](auto&& origins) {
494             WebsiteData websiteData;
495
496             while (!origins.isEmpty())
497                 websiteData.entries.append(WebsiteData::Entry { origins.takeAny(), WebsiteDataType::DeviceIdHashSalt, 0 });
498
499             callbackAggregator->removePendingCallback(WTFMove(websiteData));
500         });
501     }
502
503     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
504         callbackAggregator->addPendingCallback();
505
506         m_queue->dispatch([fetchOptions, applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
507             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
508
509             WebsiteData websiteData;
510
511             // FIXME: getOriginsWithCache should return a collection of SecurityOriginDatas.
512             auto origins = storage->originsWithCache();
513
514             for (auto& origin : origins) {
515                 uint64_t size = fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes) ? storage->diskUsageForOrigin(origin) : 0;
516                 WebsiteData::Entry entry { origin->data(), WebsiteDataType::OfflineWebApplicationCache, size };
517
518                 websiteData.entries.append(WTFMove(entry));
519             }
520
521             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins), websiteData = WTFMove(websiteData)]() mutable {
522                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
523             });
524         });
525     }
526
527     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
528         callbackAggregator->addPendingCallback();
529
530         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator] {
531             auto origins = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->origins();
532             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
533                 WebsiteData websiteData;
534                 for (auto& origin : origins)
535                     websiteData.entries.append(WebsiteData::Entry { WTFMove(origin), WebsiteDataType::WebSQLDatabases, 0 });
536                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
537             });
538         });
539     }
540
541     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
542         callbackAggregator->addPendingCallback();
543
544         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator] {
545             auto origins = mediaKeyOrigins(mediaKeysStorageDirectory);
546
547             RunLoop::main().dispatch([callbackAggregator, origins = WTFMove(origins)]() mutable {
548                 WebsiteData websiteData;
549                 for (auto& origin : origins)
550                     websiteData.entries.append(WebsiteData::Entry { origin, WebsiteDataType::MediaKeys, 0 });
551
552                 callbackAggregator->removePendingCallback(WTFMove(websiteData));
553             });
554         });
555     }
556
557 #if ENABLE(NETSCAPE_PLUGIN_API)
558     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
559         class State {
560         public:
561             static void fetchData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
562             {
563                 new State(WTFMove(callbackAggregator), WTFMove(plugins));
564             }
565
566         private:
567             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins)
568                 : m_callbackAggregator(WTFMove(callbackAggregator))
569                 , m_plugins(WTFMove(plugins))
570             {
571                 m_callbackAggregator->addPendingCallback();
572
573                 fetchWebsiteDataForNextPlugin();
574             }
575
576             ~State()
577             {
578                 ASSERT(m_plugins.isEmpty());
579             }
580
581             void fetchWebsiteDataForNextPlugin()
582             {
583                 if (m_plugins.isEmpty()) {
584                     WebsiteData websiteData;
585                     websiteData.hostNamesWithPluginData = WTFMove(m_hostNames);
586
587                     m_callbackAggregator->removePendingCallback(WTFMove(websiteData));
588
589                     delete this;
590                     return;
591                 }
592
593                 auto plugin = m_plugins.takeLast();
594                 PluginProcessManager::singleton().fetchWebsiteData(plugin, m_callbackAggregator->fetchOptions, [this](Vector<String> hostNames) {
595                     for (auto& hostName : hostNames)
596                         m_hostNames.add(WTFMove(hostName));
597                     fetchWebsiteDataForNextPlugin();
598                 });
599             }
600
601             Ref<CallbackAggregator> m_callbackAggregator;
602             Vector<PluginModuleInfo> m_plugins;
603             HashSet<String> m_hostNames;
604         };
605
606         State::fetchData(*callbackAggregator, plugins());
607     }
608 #endif
609
610     callbackAggregator->callIfNeeded();
611 }
612
613 void WebsiteDataStore::fetchDataForTopPrivatelyControlledDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<String>& topPrivatelyControlledDomains, Function<void(Vector<WebsiteDataRecord>&&, HashSet<String>&&)>&& completionHandler)
614 {
615     fetchDataAndApply(dataTypes, fetchOptions, m_queue.copyRef(), [topPrivatelyControlledDomains = crossThreadCopy(topPrivatelyControlledDomains), completionHandler = WTFMove(completionHandler)] (auto&& existingDataRecords) mutable {
616         ASSERT(!RunLoop::isMain());
617
618         Vector<WebsiteDataRecord> matchingDataRecords;
619         HashSet<String> domainsWithMatchingDataRecords;
620         for (auto&& dataRecord : existingDataRecords) {
621             for (auto& topPrivatelyControlledDomain : topPrivatelyControlledDomains) {
622                 if (dataRecord.matchesTopPrivatelyControlledDomain(topPrivatelyControlledDomain)) {
623                     matchingDataRecords.append(WTFMove(dataRecord));
624                     domainsWithMatchingDataRecords.add(topPrivatelyControlledDomain.isolatedCopy());
625                     break;
626                 }
627             }
628         }
629         RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), matchingDataRecords = WTFMove(matchingDataRecords), domainsWithMatchingDataRecords = WTFMove(domainsWithMatchingDataRecords)] () mutable {
630             completionHandler(WTFMove(matchingDataRecords), WTFMove(domainsWithMatchingDataRecords));
631         });
632     });
633 }
634     
635 void WebsiteDataStore::topPrivatelyControlledDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, Function<void(HashSet<String>&&)>&& completionHandler)
636 {
637     fetchData(dataTypes, fetchOptions, [completionHandler = WTFMove(completionHandler), protectedThis = makeRef(*this)](auto&& existingDataRecords) {
638         HashSet<String> domainsWithDataRecords;
639         for (auto&& dataRecord : existingDataRecords) {
640             String domain = dataRecord.topPrivatelyControlledDomain();
641             if (domain.isEmpty())
642                 continue;
643             domainsWithDataRecords.add(WTFMove(domain));
644         }
645         completionHandler(WTFMove(domainsWithDataRecords));
646     });
647 }
648
649 static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
650 {
651     ProcessAccessType processAccessType = ProcessAccessType::None;
652
653     if (dataTypes.contains(WebsiteDataType::Cookies)) {
654         if (isNonPersistentStore)
655             processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
656         else
657             processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
658     }
659
660     if (dataTypes.contains(WebsiteDataType::DiskCache) && !isNonPersistentStore)
661         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
662
663     if (dataTypes.contains(WebsiteDataType::HSTSCache))
664         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
665
666     if (dataTypes.contains(WebsiteDataType::Credentials))
667         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
668
669     if (dataTypes.contains(WebsiteDataType::DOMCache))
670         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
671
672     if (dataTypes.contains(WebsiteDataType::IndexedDBDatabases) && !isNonPersistentStore)
673         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
674     
675 #if ENABLE(SERVICE_WORKER)
676     if (dataTypes.contains(WebsiteDataType::ServiceWorkerRegistrations) && !isNonPersistentStore)
677         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
678 #endif
679
680     return processAccessType;
681 }
682
683 static ProcessAccessType computeWebProcessAccessTypeForDataRemoval(OptionSet<WebsiteDataType> dataTypes, bool isNonPersistentStore)
684 {
685     UNUSED_PARAM(isNonPersistentStore);
686
687     ProcessAccessType processAccessType = ProcessAccessType::None;
688
689     if (dataTypes.contains(WebsiteDataType::MemoryCache))
690         processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
691
692     if (dataTypes.contains(WebsiteDataType::Credentials))
693         processAccessType = std::max(processAccessType, ProcessAccessType::OnlyIfLaunched);
694
695     return processAccessType;
696 }
697
698 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, WallTime modifiedSince, Function<void()>&& completionHandler)
699 {
700     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
701         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
702             : completionHandler(WTFMove(completionHandler))
703             , protectedDataStore(dataStore)
704         {
705             ASSERT(RunLoop::isMain());
706         }
707
708         ~CallbackAggregator()
709         {
710             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
711             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
712         }
713
714         void addPendingCallback()
715         {
716             pendingCallbacks++;
717         }
718
719         void removePendingCallback()
720         {
721             ASSERT(pendingCallbacks);
722             --pendingCallbacks;
723
724             callIfNeeded();
725         }
726
727         void callIfNeeded()
728         {
729             if (!pendingCallbacks)
730                 RunLoop::main().dispatch(WTFMove(completionHandler));
731         }
732
733         unsigned pendingCallbacks = 0;
734         Function<void()> completionHandler;
735         Ref<WebsiteDataStore> protectedDataStore;
736     };
737
738     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
739
740 #if ENABLE(VIDEO)
741     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
742         callbackAggregator->addPendingCallback();
743         m_queue->dispatch([modifiedSince, mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
744             WebCore::HTMLMediaElement::clearMediaCache(mediaCacheDirectory, modifiedSince);
745             
746             WTF::RunLoop::main().dispatch([callbackAggregator] {
747                 callbackAggregator->removePendingCallback();
748             });
749         });
750     }
751 #endif
752
753     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
754     if (networkProcessAccessType != ProcessAccessType::None) {
755         for (auto& processPool : processPools()) {
756             switch (networkProcessAccessType) {
757             case ProcessAccessType::OnlyIfLaunched:
758                 if (!processPool->networkProcess())
759                     continue;
760                 break;
761
762             case ProcessAccessType::Launch:
763                 processPool->ensureNetworkProcess(this);
764                 break;
765
766             case ProcessAccessType::None:
767                 ASSERT_NOT_REACHED();
768             }
769
770             callbackAggregator->addPendingCallback();
771             processPool->networkProcess()->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator, processPool] {
772                 callbackAggregator->removePendingCallback();
773             });
774         }
775     }
776
777     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
778     if (webProcessAccessType != ProcessAccessType::None) {
779         for (auto& process : processes()) {
780             switch (webProcessAccessType) {
781             case ProcessAccessType::OnlyIfLaunched:
782                 if (!process->canSendMessage())
783                     continue;
784                 break;
785
786             case ProcessAccessType::Launch:
787                 // FIXME: Handle this.
788                 ASSERT_NOT_REACHED();
789                 break;
790
791             case ProcessAccessType::None:
792                 ASSERT_NOT_REACHED();
793             }
794
795             callbackAggregator->addPendingCallback();
796             process->deleteWebsiteData(m_sessionID, dataTypes, modifiedSince, [callbackAggregator] {
797                 callbackAggregator->removePendingCallback();
798             });
799         }
800     }
801
802     if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) {
803         callbackAggregator->addPendingCallback();
804
805         m_storageManager->deleteSessionStorageOrigins([callbackAggregator] {
806             callbackAggregator->removePendingCallback();
807         });
808     }
809
810     if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) {
811         callbackAggregator->addPendingCallback();
812
813         m_storageManager->deleteLocalStorageOriginsModifiedSince(modifiedSince, [callbackAggregator] {
814             callbackAggregator->removePendingCallback();
815         });
816     }
817
818     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
819         callbackAggregator->addPendingCallback();
820
821         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltOriginsModifiedSince(modifiedSince, [callbackAggregator] {
822             callbackAggregator->removePendingCallback();
823         });
824     }
825
826     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
827         callbackAggregator->addPendingCallback();
828
829         m_queue->dispatch([applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
830             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
831
832             storage->deleteAllCaches();
833
834             WTF::RunLoop::main().dispatch([callbackAggregator] {
835                 callbackAggregator->removePendingCallback();
836             });
837         });
838     }
839
840     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
841         callbackAggregator->addPendingCallback();
842
843         m_queue->dispatch([webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
844             WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory)->deleteDatabasesModifiedSince(modifiedSince);
845
846             RunLoop::main().dispatch([callbackAggregator] {
847                 callbackAggregator->removePendingCallback();
848             });
849         });
850     }
851
852     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
853         callbackAggregator->addPendingCallback();
854
855         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, modifiedSince] {
856             removeMediaKeys(mediaKeysStorageDirectory, modifiedSince);
857
858             RunLoop::main().dispatch([callbackAggregator] {
859                 callbackAggregator->removePendingCallback();
860             });
861         });
862     }
863
864     if (dataTypes.contains(WebsiteDataType::SearchFieldRecentSearches) && isPersistent()) {
865         callbackAggregator->addPendingCallback();
866
867         m_queue->dispatch([modifiedSince, callbackAggregator] {
868             platformRemoveRecentSearches(modifiedSince);
869
870             RunLoop::main().dispatch([callbackAggregator] {
871                 callbackAggregator->removePendingCallback();
872             });
873         });
874     }
875
876 #if ENABLE(NETSCAPE_PLUGIN_API)
877     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
878         class State {
879         public:
880             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
881             {
882                 new State(WTFMove(callbackAggregator), WTFMove(plugins), modifiedSince);
883             }
884
885         private:
886             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, WallTime modifiedSince)
887                 : m_callbackAggregator(WTFMove(callbackAggregator))
888                 , m_plugins(WTFMove(plugins))
889                 , m_modifiedSince(modifiedSince)
890             {
891                 m_callbackAggregator->addPendingCallback();
892
893                 deleteWebsiteDataForNextPlugin();
894             }
895
896             ~State()
897             {
898                 ASSERT(m_plugins.isEmpty());
899             }
900
901             void deleteWebsiteDataForNextPlugin()
902             {
903                 if (m_plugins.isEmpty()) {
904                     m_callbackAggregator->removePendingCallback();
905
906                     delete this;
907                     return;
908                 }
909
910                 auto plugin = m_plugins.takeLast();
911                 PluginProcessManager::singleton().deleteWebsiteData(plugin, m_modifiedSince, [this] {
912                     deleteWebsiteDataForNextPlugin();
913                 });
914             }
915
916             Ref<CallbackAggregator> m_callbackAggregator;
917             Vector<PluginModuleInfo> m_plugins;
918             WallTime m_modifiedSince;
919         };
920
921         State::deleteData(*callbackAggregator, plugins(), modifiedSince);
922     }
923 #endif
924
925     if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics) {
926         auto deletedTypesRaw = dataTypes.toRaw();
927         auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
928         
929         // If we are deleting all of the data types that the resource load statistics store monitors
930         // we do not need to re-grandfather old data.
931         callbackAggregator->addPendingCallback();
932         if ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw)
933             m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, WebResourceLoadStatisticsStore::ShouldGrandfather::No, [callbackAggregator] {
934                 callbackAggregator->removePendingCallback();
935             });
936         else
937             m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(modifiedSince, WebResourceLoadStatisticsStore::ShouldGrandfather::Yes, [callbackAggregator] {
938                 callbackAggregator->removePendingCallback();
939             });
940
941         callbackAggregator->addPendingCallback();
942         clearResourceLoadStatisticsInWebProcesses([callbackAggregator] {
943             callbackAggregator->removePendingCallback();
944         });
945     }
946
947     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
948     callbackAggregator->callIfNeeded();
949 }
950
951 void WebsiteDataStore::removeData(OptionSet<WebsiteDataType> dataTypes, const Vector<WebsiteDataRecord>& dataRecords, Function<void()>&& completionHandler)
952 {
953     Vector<WebCore::SecurityOriginData> origins;
954
955     for (const auto& dataRecord : dataRecords) {
956         for (auto& origin : dataRecord.origins)
957             origins.append(origin);
958     }
959
960     struct CallbackAggregator : ThreadSafeRefCounted<CallbackAggregator> {
961         CallbackAggregator(WebsiteDataStore& dataStore, Function<void()>&& completionHandler)
962             : completionHandler(WTFMove(completionHandler))
963             , protectedDataStore(dataStore)
964         {
965             ASSERT(RunLoop::isMain());
966         }
967
968         ~CallbackAggregator()
969         {
970             // Make sure the data store gets destroyed on the main thread even though the CallbackAggregator can get destroyed on a background queue.
971             RunLoop::main().dispatch([protectedDataStore = WTFMove(protectedDataStore)] { });
972         }
973
974         void addPendingCallback()
975         {
976             pendingCallbacks++;
977         }
978
979         void removePendingCallback()
980         {
981             ASSERT(pendingCallbacks);
982             --pendingCallbacks;
983
984             callIfNeeded();
985         }
986
987         void callIfNeeded()
988         {
989             if (!pendingCallbacks)
990                 RunLoop::main().dispatch(WTFMove(completionHandler));
991         }
992
993         unsigned pendingCallbacks = 0;
994         Function<void()> completionHandler;
995         Ref<WebsiteDataStore> protectedDataStore;
996     };
997
998     RefPtr<CallbackAggregator> callbackAggregator = adoptRef(new CallbackAggregator(*this, WTFMove(completionHandler)));
999     
1000     if (dataTypes.contains(WebsiteDataType::DiskCache)) {
1001         HashSet<WebCore::SecurityOriginData> origins;
1002         for (const auto& dataRecord : dataRecords) {
1003             for (const auto& origin : dataRecord.origins)
1004                 origins.add(origin);
1005         }
1006         
1007 #if ENABLE(VIDEO)
1008         callbackAggregator->addPendingCallback();
1009         m_queue->dispatch([origins = WTFMove(origins), mediaCacheDirectory = m_configuration->mediaCacheDirectory().isolatedCopy(), callbackAggregator] {
1010
1011             // FIXME: Move SecurityOrigin::toRawString to SecurityOriginData and
1012             // make HTMLMediaElement::clearMediaCacheForOrigins take SecurityOriginData.
1013             HashSet<RefPtr<WebCore::SecurityOrigin>> securityOrigins;
1014             for (auto& origin : origins)
1015                 securityOrigins.add(origin.securityOrigin());
1016             WebCore::HTMLMediaElement::clearMediaCacheForOrigins(mediaCacheDirectory, securityOrigins);
1017             
1018             WTF::RunLoop::main().dispatch([callbackAggregator] {
1019                 callbackAggregator->removePendingCallback();
1020             });
1021         });
1022 #endif
1023     }
1024     
1025     auto networkProcessAccessType = computeNetworkProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
1026     if (networkProcessAccessType != ProcessAccessType::None) {
1027         for (auto& processPool : processPools()) {
1028             switch (networkProcessAccessType) {
1029             case ProcessAccessType::OnlyIfLaunched:
1030                 if (!processPool->networkProcess())
1031                     continue;
1032                 break;
1033
1034             case ProcessAccessType::Launch:
1035                 processPool->ensureNetworkProcess(this);
1036                 break;
1037
1038             case ProcessAccessType::None:
1039                 ASSERT_NOT_REACHED();
1040             }
1041
1042             Vector<String> cookieHostNames;
1043             Vector<String> HSTSCacheHostNames;
1044             for (const auto& dataRecord : dataRecords) {
1045                 for (auto& hostName : dataRecord.cookieHostNames)
1046                     cookieHostNames.append(hostName);
1047                 for (auto& hostName : dataRecord.HSTSCacheHostNames)
1048                     HSTSCacheHostNames.append(hostName);
1049             }
1050
1051             callbackAggregator->addPendingCallback();
1052             processPool->networkProcess()->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, cookieHostNames, HSTSCacheHostNames, [callbackAggregator, processPool] {
1053                 callbackAggregator->removePendingCallback();
1054             });
1055         }
1056     }
1057
1058     auto webProcessAccessType = computeWebProcessAccessTypeForDataRemoval(dataTypes, !isPersistent());
1059     if (webProcessAccessType != ProcessAccessType::None) {
1060         for (auto& process : processes()) {
1061             switch (webProcessAccessType) {
1062             case ProcessAccessType::OnlyIfLaunched:
1063                 if (!process->canSendMessage())
1064                     continue;
1065                 break;
1066
1067             case ProcessAccessType::Launch:
1068                 // FIXME: Handle this.
1069                 ASSERT_NOT_REACHED();
1070                 break;
1071
1072             case ProcessAccessType::None:
1073                 ASSERT_NOT_REACHED();
1074             }
1075
1076             callbackAggregator->addPendingCallback();
1077
1078             process->deleteWebsiteDataForOrigins(m_sessionID, dataTypes, origins, [callbackAggregator] {
1079                 callbackAggregator->removePendingCallback();
1080             });
1081         }
1082     }
1083
1084     if (dataTypes.contains(WebsiteDataType::SessionStorage) && m_storageManager) {
1085         callbackAggregator->addPendingCallback();
1086
1087         m_storageManager->deleteSessionStorageEntriesForOrigins(origins, [callbackAggregator] {
1088             callbackAggregator->removePendingCallback();
1089         });
1090     }
1091
1092     if (dataTypes.contains(WebsiteDataType::LocalStorage) && m_storageManager) {
1093         callbackAggregator->addPendingCallback();
1094
1095         m_storageManager->deleteLocalStorageEntriesForOrigins(origins, [callbackAggregator] {
1096             callbackAggregator->removePendingCallback();
1097         });
1098     }
1099
1100     if (dataTypes.contains(WebsiteDataType::DeviceIdHashSalt) || (dataTypes.contains(WebsiteDataType::Cookies))) {
1101         callbackAggregator->addPendingCallback();
1102
1103         m_deviceIdHashSaltStorage->deleteDeviceIdHashSaltForOrigins(origins, [callbackAggregator] {
1104             callbackAggregator->removePendingCallback();
1105         });
1106     }
1107
1108     if (dataTypes.contains(WebsiteDataType::OfflineWebApplicationCache) && isPersistent()) {
1109         HashSet<WebCore::SecurityOriginData> origins;
1110         for (const auto& dataRecord : dataRecords) {
1111             for (const auto& origin : dataRecord.origins)
1112                 origins.add(origin);
1113         }
1114
1115         callbackAggregator->addPendingCallback();
1116         m_queue->dispatch([origins = WTFMove(origins), applicationCacheDirectory = m_configuration->applicationCacheDirectory().isolatedCopy(), applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName().isolatedCopy(), callbackAggregator] {
1117             auto storage = WebCore::ApplicationCacheStorage::create(applicationCacheDirectory, applicationCacheFlatFileSubdirectoryName);
1118
1119             for (const auto& origin : origins)
1120                 storage->deleteCacheForOrigin(origin.securityOrigin());
1121
1122             WTF::RunLoop::main().dispatch([callbackAggregator] {
1123                 callbackAggregator->removePendingCallback();
1124             });
1125         });
1126     }
1127
1128     if (dataTypes.contains(WebsiteDataType::WebSQLDatabases) && isPersistent()) {
1129         HashSet<WebCore::SecurityOriginData> origins;
1130         for (const auto& dataRecord : dataRecords) {
1131             for (const auto& origin : dataRecord.origins)
1132                 origins.add(origin);
1133         }
1134
1135         callbackAggregator->addPendingCallback();
1136         m_queue->dispatch([origins = WTFMove(origins), callbackAggregator, webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory().isolatedCopy()] {
1137             auto databaseTracker = WebCore::DatabaseTracker::trackerWithDatabasePath(webSQLDatabaseDirectory);
1138             for (auto& origin : origins)
1139                 databaseTracker->deleteOrigin(origin);
1140             RunLoop::main().dispatch([callbackAggregator] {
1141                 callbackAggregator->removePendingCallback();
1142             });
1143         });
1144     }
1145
1146     if (dataTypes.contains(WebsiteDataType::MediaKeys) && isPersistent()) {
1147         HashSet<WebCore::SecurityOriginData> origins;
1148         for (const auto& dataRecord : dataRecords) {
1149             for (const auto& origin : dataRecord.origins)
1150                 origins.add(origin);
1151         }
1152
1153         callbackAggregator->addPendingCallback();
1154         m_queue->dispatch([mediaKeysStorageDirectory = m_configuration->mediaKeysStorageDirectory().isolatedCopy(), callbackAggregator, origins = WTFMove(origins)] {
1155
1156             removeMediaKeys(mediaKeysStorageDirectory, origins);
1157
1158             RunLoop::main().dispatch([callbackAggregator] {
1159                 callbackAggregator->removePendingCallback();
1160             });
1161         });
1162     }
1163
1164 #if ENABLE(NETSCAPE_PLUGIN_API)
1165     if (dataTypes.contains(WebsiteDataType::PlugInData) && isPersistent()) {
1166         Vector<String> hostNames;
1167         for (const auto& dataRecord : dataRecords) {
1168             for (const auto& hostName : dataRecord.pluginDataHostNames)
1169                 hostNames.append(hostName);
1170         }
1171
1172
1173         class State {
1174         public:
1175             static void deleteData(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1176             {
1177                 new State(WTFMove(callbackAggregator), WTFMove(plugins), WTFMove(hostNames));
1178             }
1179
1180         private:
1181             State(Ref<CallbackAggregator>&& callbackAggregator, Vector<PluginModuleInfo>&& plugins, Vector<String>&& hostNames)
1182                 : m_callbackAggregator(WTFMove(callbackAggregator))
1183                 , m_plugins(WTFMove(plugins))
1184                 , m_hostNames(WTFMove(hostNames))
1185             {
1186                 m_callbackAggregator->addPendingCallback();
1187
1188                 deleteWebsiteDataForNextPlugin();
1189             }
1190
1191             ~State()
1192             {
1193                 ASSERT(m_plugins.isEmpty());
1194             }
1195
1196             void deleteWebsiteDataForNextPlugin()
1197             {
1198                 if (m_plugins.isEmpty()) {
1199                     m_callbackAggregator->removePendingCallback();
1200
1201                     delete this;
1202                     return;
1203                 }
1204
1205                 auto plugin = m_plugins.takeLast();
1206                 PluginProcessManager::singleton().deleteWebsiteDataForHostNames(plugin, m_hostNames, [this] {
1207                     deleteWebsiteDataForNextPlugin();
1208                 });
1209             }
1210
1211             Ref<CallbackAggregator> m_callbackAggregator;
1212             Vector<PluginModuleInfo> m_plugins;
1213             Vector<String> m_hostNames;
1214         };
1215
1216         if (!hostNames.isEmpty())
1217             State::deleteData(*callbackAggregator, plugins(), WTFMove(hostNames));
1218     }
1219 #endif
1220
1221     // FIXME <rdar://problem/33491222>; scheduleClearInMemoryAndPersistent does not have a completion handler,
1222     // so the completion handler for this removeData() call can be called prematurely.
1223     if (dataTypes.contains(WebsiteDataType::ResourceLoadStatistics) && m_resourceLoadStatistics) {
1224         auto deletedTypesRaw = dataTypes.toRaw();
1225         auto monitoredTypesRaw = WebResourceLoadStatisticsStore::monitoredDataTypes().toRaw();
1226
1227         // If we are deleting all of the data types that the resource load statistics store monitors
1228         // we do not need to re-grandfather old data.
1229         callbackAggregator->addPendingCallback();
1230         if ((monitoredTypesRaw & deletedTypesRaw) == monitoredTypesRaw)
1231             m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(WebResourceLoadStatisticsStore::ShouldGrandfather::No, [callbackAggregator] {
1232                 callbackAggregator->removePendingCallback();
1233             });
1234         else
1235             m_resourceLoadStatistics->scheduleClearInMemoryAndPersistent(WebResourceLoadStatisticsStore::ShouldGrandfather::Yes, [callbackAggregator] {
1236                 callbackAggregator->removePendingCallback();
1237             });
1238
1239         callbackAggregator->addPendingCallback();
1240         clearResourceLoadStatisticsInWebProcesses([callbackAggregator] {
1241             callbackAggregator->removePendingCallback();
1242         });
1243     }
1244
1245     // There's a chance that we don't have any pending callbacks. If so, we want to dispatch the completion handler right away.
1246     callbackAggregator->callIfNeeded();
1247 }
1248
1249 void WebsiteDataStore::removeDataForTopPrivatelyControlledDomains(OptionSet<WebsiteDataType> dataTypes, OptionSet<WebsiteDataFetchOption> fetchOptions, const Vector<String>& topPrivatelyControlledDomains, Function<void(HashSet<String>&&)>&& completionHandler)
1250 {
1251     fetchDataForTopPrivatelyControlledDomains(dataTypes, fetchOptions, topPrivatelyControlledDomains, [dataTypes, completionHandler = WTFMove(completionHandler), this, protectedThis = makeRef(*this)](Vector<WebsiteDataRecord>&& websiteDataRecords, HashSet<String>&& domainsWithDataRecords) mutable {
1252         this->removeData(dataTypes, websiteDataRecords, [domainsWithDataRecords = WTFMove(domainsWithDataRecords), completionHandler = WTFMove(completionHandler)]() mutable {
1253             completionHandler(WTFMove(domainsWithDataRecords));
1254         });
1255     });
1256 }
1257
1258 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1259 void WebsiteDataStore::updatePrevalentDomainsToBlockCookiesFor(const Vector<String>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
1260 {
1261     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1262
1263     for (auto& processPool : processPools()) {
1264         if (auto* process = processPool->networkProcess())
1265             process->updatePrevalentDomainsToBlockCookiesFor(m_sessionID, domainsToBlock, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1266     }
1267 }
1268
1269 void WebsiteDataStore::setAgeCapForClientSideCookies(Optional<Seconds> seconds, CompletionHandler<void()>&& completionHandler)
1270 {
1271     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1272     
1273     for (auto& processPool : processPools()) {
1274         if (auto* process = processPool->networkProcess())
1275             process->setAgeCapForClientSideCookies(m_sessionID, seconds, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1276     }
1277 }
1278
1279 void WebsiteDataStore::hasStorageAccessForFrameHandler(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool hasAccess)>&& completionHandler)
1280 {
1281     auto* webPage = WebProcessProxy::webPage(pageID);
1282     if (!webPage) {
1283         completionHandler(false);
1284         return;
1285     }
1286
1287     auto& networkProcess = webPage->process().processPool().ensureNetworkProcess();
1288     networkProcess.hasStorageAccessForFrame(m_sessionID, resourceDomain, firstPartyDomain, frameID, pageID, WTFMove(completionHandler));
1289 }
1290
1291 void WebsiteDataStore::getAllStorageAccessEntries(uint64_t pageID, CompletionHandler<void(Vector<String>&& domains)>&& completionHandler)
1292 {
1293     auto* webPage = WebProcessProxy::webPage(pageID);
1294     if (!webPage) {
1295         completionHandler({ });
1296         return;
1297     }
1298     
1299     auto& networkProcess = webPage->process().processPool().ensureNetworkProcess();
1300     networkProcess.getAllStorageAccessEntries(m_sessionID, WTFMove(completionHandler));
1301 }
1302
1303 void WebsiteDataStore::grantStorageAccessHandler(const String& resourceDomain, const String& firstPartyDomain, Optional<uint64_t> frameID, uint64_t pageID, CompletionHandler<void(bool wasGranted)>&& completionHandler)
1304 {
1305     auto* webPage = WebProcessProxy::webPage(pageID);
1306     if (!webPage) {
1307         completionHandler(false);
1308         return;
1309     }
1310
1311     auto& networkProcess = webPage->process().processPool().ensureNetworkProcess();
1312     networkProcess.grantStorageAccess(m_sessionID, resourceDomain, firstPartyDomain, frameID, pageID, WTFMove(completionHandler));
1313 }
1314
1315 void WebsiteDataStore::removeAllStorageAccessHandler(CompletionHandler<void()>&& completionHandler)
1316 {
1317     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1318     
1319     for (auto& processPool : processPools()) {
1320         if (auto networkProcess = processPool->networkProcess())
1321             networkProcess->removeAllStorageAccess(m_sessionID, [processPool, callbackAggregator = callbackAggregator.copyRef()] { });
1322     }
1323 }
1324
1325 void WebsiteDataStore::removePrevalentDomains(const Vector<String>& domains)
1326 {
1327     for (auto& processPool : processPools())
1328         processPool->sendToNetworkingProcess(Messages::NetworkProcess::RemovePrevalentDomains(m_sessionID, domains));
1329 }
1330
1331 void WebsiteDataStore::hasStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool)>&& completionHandler)
1332 {
1333     if (!resourceLoadStatisticsEnabled()) {
1334         completionHandler(false);
1335         return;
1336     }
1337     
1338     m_resourceLoadStatistics->hasStorageAccess(WTFMove(subFrameHost), WTFMove(topFrameHost), frameID, pageID, WTFMove(completionHandler));
1339 }
1340
1341 void WebsiteDataStore::requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool promptEnabled, CompletionHandler<void(StorageAccessStatus)>&& completionHandler)
1342 {
1343     if (!resourceLoadStatisticsEnabled()) {
1344         completionHandler(StorageAccessStatus::CannotRequestAccess);
1345         return;
1346     }
1347     
1348     m_resourceLoadStatistics->requestStorageAccess(WTFMove(subFrameHost), WTFMove(topFrameHost), frameID, pageID, promptEnabled, WTFMove(completionHandler));
1349 }
1350
1351 void WebsiteDataStore::grantStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool userWasPrompted, CompletionHandler<void(bool)>&& completionHandler)
1352 {
1353     if (!resourceLoadStatisticsEnabled()) {
1354         completionHandler(false);
1355         return;
1356     }
1357     
1358     m_resourceLoadStatistics->grantStorageAccess(WTFMove(subFrameHost), WTFMove(topFrameHost), frameID, pageID, userWasPrompted, WTFMove(completionHandler));
1359 }
1360 #endif // ENABLE(RESOURCE_LOAD_STATISTICS)
1361
1362 void WebsiteDataStore::setCacheMaxAgeCapForPrevalentResources(Seconds seconds, CompletionHandler<void()>&& completionHandler)
1363 {
1364 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1365     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1366     
1367     for (auto& processPool : processPools()) {
1368         if (auto* networkProcess = processPool->networkProcess())
1369             networkProcess->setCacheMaxAgeCapForPrevalentResources(m_sessionID, seconds, [callbackAggregator = callbackAggregator.copyRef()] { });
1370     }
1371 #else
1372     UNUSED_PARAM(seconds);
1373     completionHandler();
1374 #endif
1375 }
1376
1377 void WebsiteDataStore::resetCacheMaxAgeCapForPrevalentResources(CompletionHandler<void()>&& completionHandler)
1378 {
1379 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1380     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
1381     
1382     for (auto& processPool : processPools()) {
1383         if (auto* networkProcess = processPool->networkProcess())
1384             networkProcess->resetCacheMaxAgeCapForPrevalentResources(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
1385     }
1386 #else
1387     completionHandler();
1388 #endif
1389 }
1390
1391 void WebsiteDataStore::webPageWasAdded(WebPageProxy& webPageProxy)
1392 {
1393     if (m_storageManager)
1394         m_storageManager->createSessionStorageNamespace(webPageProxy.pageID(), std::numeric_limits<unsigned>::max());
1395 }
1396
1397 void WebsiteDataStore::webPageWasInvalidated(WebPageProxy& webPageProxy)
1398 {
1399     if (m_storageManager)
1400         m_storageManager->destroySessionStorageNamespace(webPageProxy.pageID());
1401 }
1402
1403 void WebsiteDataStore::webProcessWillOpenConnection(WebProcessProxy& webProcessProxy, IPC::Connection& connection)
1404 {
1405     if (m_storageManager)
1406         m_storageManager->processWillOpenConnection(webProcessProxy, connection);
1407
1408     if (m_resourceLoadStatistics)
1409         webProcessProxy.addMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName(), *m_resourceLoadStatistics);
1410 }
1411
1412 void WebsiteDataStore::webPageWillOpenConnection(WebPageProxy& webPageProxy, IPC::Connection& connection)
1413 {
1414     if (m_storageManager)
1415         m_storageManager->setAllowedSessionStorageNamespaceConnection(webPageProxy.pageID(), &connection);
1416 }
1417
1418 void WebsiteDataStore::webPageDidCloseConnection(WebPageProxy& webPageProxy, IPC::Connection&)
1419 {
1420     if (m_storageManager)
1421         m_storageManager->setAllowedSessionStorageNamespaceConnection(webPageProxy.pageID(), nullptr);
1422 }
1423
1424 void WebsiteDataStore::webProcessDidCloseConnection(WebProcessProxy& webProcessProxy, IPC::Connection& connection)
1425 {
1426     if (m_resourceLoadStatistics)
1427         webProcessProxy.removeMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName());
1428
1429     if (m_storageManager)
1430         m_storageManager->processDidCloseConnection(webProcessProxy, connection);
1431 }
1432
1433 bool WebsiteDataStore::isAssociatedProcessPool(WebProcessPool& processPool) const
1434 {
1435     if (auto* processPoolDataStore = processPool.websiteDataStore())
1436         return &processPoolDataStore->websiteDataStore() == this;
1437     return false;
1438 }
1439
1440 HashSet<RefPtr<WebProcessPool>> WebsiteDataStore::processPools(size_t count, bool ensureAPoolExists) const
1441 {
1442     HashSet<RefPtr<WebProcessPool>> processPools;
1443     for (auto& process : processes())
1444         processPools.add(&process->processPool());
1445
1446     if (processPools.isEmpty()) {
1447         // Check if we're one of the legacy data stores.
1448         for (auto& processPool : WebProcessPool::allProcessPools()) {
1449             if (!isAssociatedProcessPool(*processPool))
1450                 continue;
1451
1452             processPools.add(processPool);
1453
1454             if (processPools.size() == count)
1455                 break;
1456         }
1457     }
1458
1459     if (processPools.isEmpty() && count && ensureAPoolExists) {
1460         auto processPool = WebProcessPool::create(API::ProcessPoolConfiguration::createWithWebsiteDataStoreConfiguration(m_configuration));
1461         processPools.add(processPool.ptr());
1462     }
1463
1464     return processPools;
1465 }
1466
1467 #if ENABLE(NETSCAPE_PLUGIN_API)
1468 Vector<PluginModuleInfo> WebsiteDataStore::plugins() const
1469 {
1470     Vector<PluginModuleInfo> plugins;
1471
1472     for (auto& processPool : processPools()) {
1473         for (auto& plugin : processPool->pluginInfoStore().plugins())
1474             plugins.append(plugin);
1475     }
1476
1477     return plugins;
1478 }
1479 #endif
1480
1481 static String computeMediaKeyFile(const String& mediaKeyDirectory)
1482 {
1483     return WebCore::FileSystem::pathByAppendingComponent(mediaKeyDirectory, "SecureStop.plist");
1484 }
1485
1486 Vector<WebCore::SecurityOriginData> WebsiteDataStore::mediaKeyOrigins(const String& mediaKeysStorageDirectory)
1487 {
1488     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1489
1490     Vector<WebCore::SecurityOriginData> origins;
1491
1492     for (const auto& originPath : WebCore::FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1493         auto mediaKeyFile = computeMediaKeyFile(originPath);
1494         if (!WebCore::FileSystem::fileExists(mediaKeyFile))
1495             continue;
1496
1497         auto mediaKeyIdentifier = WebCore::FileSystem::pathGetFileName(originPath);
1498
1499         if (auto securityOrigin = WebCore::SecurityOriginData::fromDatabaseIdentifier(mediaKeyIdentifier))
1500             origins.append(*securityOrigin);
1501     }
1502
1503     return origins;
1504 }
1505
1506 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, WallTime modifiedSince)
1507 {
1508     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1509
1510     for (const auto& mediaKeyDirectory : WebCore::FileSystem::listDirectory(mediaKeysStorageDirectory, "*")) {
1511         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1512
1513         auto modificationTime = WebCore::FileSystem::getFileModificationTime(mediaKeyFile);
1514         if (!modificationTime)
1515             continue;
1516
1517         if (modificationTime.value() < modifiedSince)
1518             continue;
1519
1520         WebCore::FileSystem::deleteFile(mediaKeyFile);
1521         WebCore::FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1522     }
1523 }
1524
1525 void WebsiteDataStore::removeMediaKeys(const String& mediaKeysStorageDirectory, const HashSet<WebCore::SecurityOriginData>& origins)
1526 {
1527     ASSERT(!mediaKeysStorageDirectory.isEmpty());
1528
1529     for (const auto& origin : origins) {
1530         auto mediaKeyDirectory = WebCore::FileSystem::pathByAppendingComponent(mediaKeysStorageDirectory, origin.databaseIdentifier());
1531         auto mediaKeyFile = computeMediaKeyFile(mediaKeyDirectory);
1532
1533         WebCore::FileSystem::deleteFile(mediaKeyFile);
1534         WebCore::FileSystem::deleteEmptyDirectory(mediaKeyDirectory);
1535     }
1536 }
1537
1538 bool WebsiteDataStore::resourceLoadStatisticsEnabled() const
1539 {
1540     return !!m_resourceLoadStatistics;
1541 }
1542
1543 void WebsiteDataStore::setResourceLoadStatisticsEnabled(bool enabled)
1544 {
1545     if (m_sessionID.isEphemeral() || enabled == resourceLoadStatisticsEnabled())
1546         return;
1547
1548     if (enabled) {
1549         ASSERT(!m_resourceLoadStatistics);
1550         enableResourceLoadStatisticsAndSetTestingCallback(nullptr);
1551         return;
1552     }
1553
1554
1555     unregisterWebResourceLoadStatisticsStoreAsMessageReceiver();
1556     m_resourceLoadStatistics = nullptr;
1557
1558     auto existingProcessPools = processPools(std::numeric_limits<size_t>::max(), false);
1559     for (auto& processPool : existingProcessPools)
1560         processPool->setResourceLoadStatisticsEnabled(false);
1561 }
1562
1563 void WebsiteDataStore::unregisterWebResourceLoadStatisticsStoreAsMessageReceiver()
1564 {
1565     if (!m_resourceLoadStatistics)
1566         return;
1567
1568     for (auto* webProcessProxy : processes())
1569         webProcessProxy->removeMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName());
1570 }
1571
1572 void WebsiteDataStore::registerWebResourceLoadStatisticsStoreAsMessageReceiver()
1573 {
1574     ASSERT(m_resourceLoadStatistics);
1575     if (!m_resourceLoadStatistics)
1576         return;
1577
1578     for (auto* webProcessProxy : processes())
1579         webProcessProxy->addMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName(), *m_resourceLoadStatistics);
1580 }
1581
1582 bool WebsiteDataStore::resourceLoadStatisticsDebugMode() const
1583 {
1584     return m_resourceLoadStatisticsDebugMode;
1585 }
1586
1587 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled)
1588 {
1589     setResourceLoadStatisticsDebugMode(enabled, []() { });
1590 }
1591
1592 void WebsiteDataStore::setResourceLoadStatisticsDebugMode(bool enabled, CompletionHandler<void()>&& completionHandler)
1593 {
1594     m_resourceLoadStatisticsDebugMode = enabled;
1595     if (m_resourceLoadStatistics)
1596         m_resourceLoadStatistics->setResourceLoadStatisticsDebugMode(enabled, WTFMove(completionHandler));
1597     else
1598         completionHandler();
1599 }
1600
1601 void WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback(Function<void (const String&)>&& callback)
1602 {
1603     ASSERT(!m_sessionID.isEphemeral());
1604
1605     if (m_resourceLoadStatistics) {
1606         m_resourceLoadStatistics->setStatisticsTestingCallback(WTFMove(callback));
1607         return;
1608     }
1609
1610     resolveDirectoriesIfNecessary();
1611     m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(*this);
1612     m_resourceLoadStatistics->setStatisticsTestingCallback(WTFMove(callback));
1613
1614     registerWebResourceLoadStatisticsStoreAsMessageReceiver();
1615
1616     for (auto& processPool : processPools(std::numeric_limits<size_t>::max(), false))
1617         processPool->setResourceLoadStatisticsEnabled(true);
1618 }
1619
1620 void WebsiteDataStore::clearResourceLoadStatisticsInWebProcesses(CompletionHandler<void()>&& callback)
1621 {
1622     if (resourceLoadStatisticsEnabled()) {
1623         for (auto& processPool : processPools())
1624             processPool->clearResourceLoadStatistics();
1625     }
1626     callback();
1627 }
1628
1629 Vector<WebCore::Cookie> WebsiteDataStore::pendingCookies() const
1630 {
1631     return copyToVector(m_pendingCookies);
1632 }
1633
1634 void WebsiteDataStore::addPendingCookie(const WebCore::Cookie& cookie)
1635 {
1636     m_pendingCookies.add(cookie);
1637 }
1638
1639 void WebsiteDataStore::removePendingCookie(const WebCore::Cookie& cookie)
1640 {
1641     m_pendingCookies.remove(cookie);
1642 }
1643     
1644 void WebsiteDataStore::clearPendingCookies()
1645 {
1646     m_pendingCookies.clear();
1647 }
1648
1649 #if !PLATFORM(COCOA)
1650 WebsiteDataStoreParameters WebsiteDataStore::parameters()
1651 {
1652     // FIXME: Implement cookies.
1653     WebsiteDataStoreParameters parameters;
1654     parameters.networkSessionParameters.sessionID = m_sessionID;
1655
1656     resolveDirectoriesIfNecessary();
1657
1658 #if ENABLE(INDEXED_DATABASE)
1659     parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
1660     if (!parameters.indexedDatabaseDirectory.isEmpty())
1661         SandboxExtension::createHandleForReadWriteDirectory(parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
1662 #endif
1663
1664 #if ENABLE(SERVICE_WORKER)
1665     parameters.serviceWorkerRegistrationDirectory = resolvedServiceWorkerRegistrationDirectory();
1666     if (!parameters.serviceWorkerRegistrationDirectory.isEmpty())
1667         SandboxExtension::createHandleForReadWriteDirectory(parameters.serviceWorkerRegistrationDirectory, parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
1668 #endif
1669
1670 #if USE(CURL)
1671     platformSetParameters(parameters);
1672 #endif
1673
1674     return parameters;
1675 }
1676 #endif
1677
1678 #if HAVE(SEC_KEY_PROXY)
1679 void WebsiteDataStore::addSecKeyProxyStore(Ref<SecKeyProxyStore>&& store)
1680 {
1681     m_secKeyProxyStores.append(WTFMove(store));
1682 }
1683 #endif
1684
1685 #if ENABLE(WEB_AUTHN)
1686 void WebsiteDataStore::setMockWebAuthenticationConfiguration(MockWebAuthenticationConfiguration&& configuration)
1687 {
1688     if (!m_authenticatorManager->isMock()) {
1689         m_authenticatorManager = makeUniqueRef<MockAuthenticatorManager>(WTFMove(configuration));
1690         return;
1691     }
1692     static_cast<MockAuthenticatorManager*>(&m_authenticatorManager)->setTestConfiguration(WTFMove(configuration));
1693 }
1694 #endif
1695
1696 void WebsiteDataStore::didCreateNetworkProcess()
1697 {
1698     if (m_resourceLoadStatistics)
1699         m_resourceLoadStatistics->didCreateNetworkProcess();
1700 }
1701
1702 }