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