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