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