Domain relationships in the ITP Database should be inserted in a single query and...
[WebKit-https.git] / Source / WebKit / NetworkProcess / Classifier / WebResourceLoadStatisticsStore.cpp
1 /*
2  * Copyright (C) 2016-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 "WebResourceLoadStatisticsStore.h"
28
29 #if ENABLE(RESOURCE_LOAD_STATISTICS)
30
31 #include "APIDictionary.h"
32 #include "Logging.h"
33 #include "NetworkProcess.h"
34 #include "NetworkSession.h"
35 #include "ResourceLoadStatisticsDatabaseStore.h"
36 #include "ResourceLoadStatisticsMemoryStore.h"
37 #include "ResourceLoadStatisticsPersistentStorage.h"
38 #include "ShouldGrandfatherStatistics.h"
39 #include "StorageAccessStatus.h"
40 #include "WebFrameProxy.h"
41 #include "WebPageProxy.h"
42 #include "WebProcessMessages.h"
43 #include "WebProcessPool.h"
44 #include "WebProcessProxy.h"
45 #include "WebResourceLoadStatisticsTelemetry.h"
46 #include "WebsiteDataFetchOption.h"
47 #include <WebCore/CookieJar.h>
48 #include <WebCore/DiagnosticLoggingClient.h>
49 #include <WebCore/DiagnosticLoggingKeys.h>
50 #include <WebCore/DocumentStorageAccess.h>
51 #include <WebCore/NetworkStorageSession.h>
52 #include <WebCore/ResourceLoadStatistics.h>
53 #include <WebCore/RuntimeEnabledFeatures.h>
54 #include <WebCore/SQLiteDatabase.h>
55 #include <WebCore/SQLiteStatement.h>
56 #include <wtf/CallbackAggregator.h>
57 #include <wtf/CrossThreadCopier.h>
58 #include <wtf/NeverDestroyed.h>
59 #include <wtf/threads/BinarySemaphore.h>
60
61 namespace WebKit {
62 using namespace WebCore;
63
64 const OptionSet<WebsiteDataType>& WebResourceLoadStatisticsStore::monitoredDataTypes()
65 {
66     static NeverDestroyed<OptionSet<WebsiteDataType>> dataTypes(std::initializer_list<WebsiteDataType>({
67         WebsiteDataType::Cookies,
68         WebsiteDataType::DOMCache,
69         WebsiteDataType::IndexedDBDatabases,
70         WebsiteDataType::LocalStorage,
71         WebsiteDataType::MediaKeys,
72         WebsiteDataType::OfflineWebApplicationCache,
73 #if ENABLE(NETSCAPE_PLUGIN_API)
74         WebsiteDataType::PlugInData,
75 #endif
76         WebsiteDataType::SearchFieldRecentSearches,
77         WebsiteDataType::SessionStorage,
78 #if ENABLE(SERVICE_WORKER)
79         WebsiteDataType::ServiceWorkerRegistrations,
80 #endif
81         WebsiteDataType::WebSQLDatabases,
82     }));
83
84     ASSERT(RunLoop::isMain());
85
86     return dataTypes;
87 }
88
89 void WebResourceLoadStatisticsStore::setNotifyPagesWhenDataRecordsWereScanned(bool value)
90 {
91     ASSERT(RunLoop::isMain());
92
93     postTask([this, value] {
94         if (m_statisticsStore)
95             m_statisticsStore->setNotifyPagesWhenDataRecordsWereScanned(value);
96     });
97 }
98
99 void WebResourceLoadStatisticsStore::setNotifyPagesWhenDataRecordsWereScanned(bool value, CompletionHandler<void()>&& completionHandler)
100 {
101     ASSERT(RunLoop::isMain());
102     
103     postTask([this, value, completionHandler = WTFMove(completionHandler)]() mutable {
104         if (m_statisticsStore)
105             m_statisticsStore->setNotifyPagesWhenDataRecordsWereScanned(value);
106
107         postTaskReply(WTFMove(completionHandler));
108     });
109 }
110
111 void WebResourceLoadStatisticsStore::setIsRunningTest(bool value, CompletionHandler<void()>&& completionHandler)
112 {
113     ASSERT(RunLoop::isMain());
114     
115     postTask([this, value, completionHandler = WTFMove(completionHandler)]() mutable {
116         if (m_statisticsStore)
117             m_statisticsStore->setIsRunningTest(value);
118         
119         postTaskReply(WTFMove(completionHandler));
120     });
121 }
122
123 void WebResourceLoadStatisticsStore::setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value, CompletionHandler<void()>&& completionHandler)
124 {
125     ASSERT(RunLoop::isMain());
126
127     postTask([this, value, completionHandler = WTFMove(completionHandler)]() mutable {
128         if (m_statisticsStore)
129             m_statisticsStore->setShouldClassifyResourcesBeforeDataRecordsRemoval(value);
130
131         postTaskReply(WTFMove(completionHandler));
132     });
133 }
134
135 void WebResourceLoadStatisticsStore::setShouldSubmitTelemetry(bool value)
136 {
137     ASSERT(RunLoop::isMain());
138
139     postTask([this, value] {
140         if (m_statisticsStore)
141             m_statisticsStore->setShouldSubmitTelemetry(value);
142     });
143 }
144
145 void WebResourceLoadStatisticsStore::setNotifyPagesWhenTelemetryWasCaptured(bool value, CompletionHandler<void()>&& completionHandler)
146 {
147     ASSERT(RunLoop::isMain());
148
149     WebKit::WebResourceLoadStatisticsTelemetry::setNotifyPagesWhenTelemetryWasCaptured(value);
150     completionHandler();
151 }
152
153 WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost)
154     : m_networkSession(makeWeakPtr(networkSession))
155     , m_statisticsQueue(WorkQueue::create("WebResourceLoadStatisticsStore Process Data Queue", WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
156     , m_dailyTasksTimer(RunLoop::main(), this, &WebResourceLoadStatisticsStore::performDailyTasks)
157 {
158     RELEASE_ASSERT(RunLoop::isMain());
159
160     postTask([this, databaseEnabled = networkSession.networkProcess().isITPDatabaseEnabled(), resourceLoadStatisticsDirectory = resourceLoadStatisticsDirectory.isolatedCopy(), shouldIncludeLocalhost, sessionID = networkSession.sessionID()] {
161         if (databaseEnabled) {
162             m_statisticsStore = makeUnique<ResourceLoadStatisticsDatabaseStore>(*this, m_statisticsQueue, shouldIncludeLocalhost, resourceLoadStatisticsDirectory, sessionID);
163
164             auto memoryStore = makeUnique<ResourceLoadStatisticsMemoryStore>(*this, m_statisticsQueue, shouldIncludeLocalhost);
165             auto persistentStore = makeUnique<ResourceLoadStatisticsPersistentStorage>(*memoryStore, m_statisticsQueue, resourceLoadStatisticsDirectory);
166
167             downcast<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore.get()).populateFromMemoryStore(*memoryStore);
168         } else {
169             m_statisticsStore = makeUnique<ResourceLoadStatisticsMemoryStore>(*this, m_statisticsQueue, shouldIncludeLocalhost);
170             m_persistentStorage = makeUnique<ResourceLoadStatisticsPersistentStorage>(downcast<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore), m_statisticsQueue, resourceLoadStatisticsDirectory);
171         }
172
173         // FIXME(193297): This should be revised after the UIProcess version goes away.
174         m_statisticsStore->didCreateNetworkProcess();
175     });
176
177     m_dailyTasksTimer.startRepeating(24_h);
178 }
179
180 WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore()
181 {
182     RELEASE_ASSERT(RunLoop::isMain());
183     RELEASE_ASSERT(!m_statisticsStore);
184     RELEASE_ASSERT(!m_persistentStorage);
185 }
186
187 void WebResourceLoadStatisticsStore::didDestroyNetworkSession()
188 {
189     ASSERT(RunLoop::isMain());
190
191     m_networkSession = nullptr;
192     flushAndDestroyPersistentStore();
193 }
194
195 inline void WebResourceLoadStatisticsStore::postTask(WTF::Function<void()>&& task)
196 {
197     ASSERT(RunLoop::isMain());
198     m_statisticsQueue->dispatch([protectedThis = makeRef(*this), task = WTFMove(task)] {
199         task();
200     });
201 }
202
203 inline void WebResourceLoadStatisticsStore::postTaskReply(WTF::Function<void()>&& reply)
204 {
205     ASSERT(!RunLoop::isMain());
206     RunLoop::main().dispatch(WTFMove(reply));
207 }
208
209 void WebResourceLoadStatisticsStore::flushAndDestroyPersistentStore()
210 {
211     RELEASE_ASSERT(RunLoop::isMain());
212
213     // Make sure we destroy the persistent store on the background queue and wait for it to die
214     // synchronously since it has a C++ reference to us. Blocking nature of this task allows us
215     // to not maintain a WebResourceLoadStatisticsStore reference for the duration of dispatch,
216     // avoiding double-deletion issues when this is invoked from the destructor.
217     BinarySemaphore semaphore;
218     m_statisticsQueue->dispatch([&semaphore, this] {
219         m_persistentStorage = nullptr;
220         m_statisticsStore = nullptr;
221         semaphore.signal();
222     });
223     semaphore.wait();
224 }
225
226 void WebResourceLoadStatisticsStore::setResourceLoadStatisticsDebugMode(bool value, CompletionHandler<void()>&& completionHandler)
227 {
228     ASSERT(RunLoop::isMain());
229
230     postTask([this, value, completionHandler = WTFMove(completionHandler)]() mutable {
231         if (m_statisticsStore)
232             m_statisticsStore->setResourceLoadStatisticsDebugMode(value);
233         postTaskReply(WTFMove(completionHandler));
234     });
235 }
236
237 void WebResourceLoadStatisticsStore::setPrevalentResourceForDebugMode(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
238 {
239     ASSERT(RunLoop::isMain());
240     
241     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
242         if (m_statisticsStore)
243             m_statisticsStore->setPrevalentResourceForDebugMode(domain);
244         postTaskReply(WTFMove(completionHandler));
245     });
246 }
247
248 void WebResourceLoadStatisticsStore::scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&& completionHandler)
249 {
250     ASSERT(RunLoop::isMain());
251     
252     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
253         if (m_statisticsStore)
254             m_statisticsStore->processStatisticsAndDataRecords();
255         postTaskReply(WTFMove(completionHandler));
256     });
257 }
258
259 void WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated(Vector<ResourceLoadStatistics>&& statistics)
260 {
261     ASSERT(RunLoop::isMain());
262
263     // It is safe to move the origins to the background queue without isolated copy here because this is an r-value
264     // coming from IPC. ResourceLoadStatistics only contains strings which are safe to move to other threads as long
265     // as nobody on this thread holds a reference to those strings.
266     postTask([this, statistics = WTFMove(statistics)]() mutable {
267         if (!m_statisticsStore)
268             return;
269
270         m_statisticsStore->mergeStatistics(WTFMove(statistics));
271
272         // We can cancel any pending request to process statistics since we're doing it synchronously below.
273         m_statisticsStore->cancelPendingStatisticsProcessingRequest();
274
275         // Fire before processing statistics to propagate user interaction as fast as possible to the network process.
276         m_statisticsStore->updateCookieBlocking([]() { });
277         m_statisticsStore->processStatisticsAndDataRecords();
278     });
279 }
280
281 void WebResourceLoadStatisticsStore::hasStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID, CompletionHandler<void(bool)>&& completionHandler)
282 {
283     ASSERT(subFrameDomain != topFrameDomain);
284     ASSERT(RunLoop::isMain());
285
286     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, completionHandler = WTFMove(completionHandler)]() mutable {
287         if (!m_statisticsStore) {
288             postTaskReply([completionHandler = WTFMove(completionHandler)]() mutable {
289                 completionHandler(false);
290             });
291             return;
292         }
293
294         m_statisticsStore->hasStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID, [completionHandler = WTFMove(completionHandler)](bool hasStorageAccess) mutable {
295             postTaskReply([completionHandler = WTFMove(completionHandler), hasStorageAccess]() mutable {
296                 completionHandler(hasStorageAccess);
297             });
298         });
299     });
300 }
301
302 bool WebResourceLoadStatisticsStore::hasStorageAccessForFrame(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, FrameIdentifier frameID, PageIdentifier pageID)
303 {
304     ASSERT(RunLoop::isMain());
305
306     if (!m_networkSession)
307         return false;
308
309     if (auto* storageSession = m_networkSession->networkStorageSession())
310         return storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
311
312     return false;
313 }
314
315 void WebResourceLoadStatisticsStore::callHasStorageAccessForFrameHandler(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, FrameIdentifier frameID, PageIdentifier pageID, CompletionHandler<void(bool hasAccess)>&& callback)
316 {
317     ASSERT(RunLoop::isMain());
318
319     if (m_networkSession) {
320         if (auto* storageSession = m_networkSession->networkStorageSession()) {
321             callback(storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
322             return;
323         }
324     }
325
326     callback(false);
327 }
328
329 void WebResourceLoadStatisticsStore::requestStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, FrameIdentifier frameID, PageIdentifier webPageID, WebPageProxyIdentifier webPageProxyID, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&& completionHandler)
330 {
331     ASSERT(RunLoop::isMain());
332
333     if (subFrameDomain == topFrameDomain) {
334         completionHandler(StorageAccessWasGranted::Yes, StorageAccessPromptWasShown::No);
335         return;
336     }
337     
338     auto statusHandler = [this, protectedThis = makeRef(*this), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, webPageID, webPageProxyID, completionHandler = WTFMove(completionHandler)](StorageAccessStatus status) mutable {
339         switch (status) {
340         case StorageAccessStatus::CannotRequestAccess:
341             completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::No);
342             return;
343         case StorageAccessStatus::RequiresUserPrompt:
344             {
345             if (!m_networkSession)
346                 return completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::No);
347
348             CompletionHandler<void(bool)> requestConfirmationCompletionHandler = [this, protectedThis = protectedThis.copyRef(), subFrameDomain, topFrameDomain, frameID, webPageID, completionHandler = WTFMove(completionHandler)] (bool userDidGrantAccess) mutable {
349                 if (userDidGrantAccess)
350                     grantStorageAccess(subFrameDomain, topFrameDomain, frameID, webPageID, StorageAccessPromptWasShown::Yes, WTFMove(completionHandler));
351                 else
352                     completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::Yes);
353             };
354             m_networkSession->networkProcess().parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageAccessConfirm(webPageProxyID, frameID, subFrameDomain, topFrameDomain), WTFMove(requestConfirmationCompletionHandler));
355             }
356             return;
357         case StorageAccessStatus::HasAccess:
358             completionHandler(StorageAccessWasGranted::Yes, StorageAccessPromptWasShown::No);
359             return;
360         }
361     };
362
363     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, webPageID, statusHandler = WTFMove(statusHandler)]() mutable {
364         if (!m_statisticsStore) {
365             postTaskReply([statusHandler = WTFMove(statusHandler)]() mutable {
366                 statusHandler(StorageAccessStatus::CannotRequestAccess);
367             });
368             return;
369         }
370
371         m_statisticsStore->requestStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, webPageID, [statusHandler = WTFMove(statusHandler)](StorageAccessStatus status) mutable {
372             postTaskReply([statusHandler = WTFMove(statusHandler), status]() mutable {
373                 statusHandler(status);
374             });
375         });
376     });
377 }
378
379 void WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener(RegistrableDomain&& domainInNeedOfStorageAccess, PageIdentifier openerPageID, RegistrableDomain&& openerDomain)
380 {
381     ASSERT(RunLoop::isMain());
382
383     // It is safe to move the strings to the background queue without isolated copy here because they are r-value references
384     // coming from IPC. Strings which are safe to move to other threads as long as nobody on this thread holds a reference
385     // to those strings.
386     postTask([this, domainInNeedOfStorageAccess = WTFMove(domainInNeedOfStorageAccess), openerPageID, openerDomain = WTFMove(openerDomain)]() mutable {
387         if (m_statisticsStore)
388             m_statisticsStore->requestStorageAccessUnderOpener(WTFMove(domainInNeedOfStorageAccess), openerPageID, WTFMove(openerDomain));
389     });
390 }
391
392 void WebResourceLoadStatisticsStore::grantStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, FrameIdentifier frameID, PageIdentifier pageID, StorageAccessPromptWasShown promptWasShown, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&& completionHandler)
393 {
394     ASSERT(RunLoop::isMain());
395     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
396         if (!m_statisticsStore) {
397             postTaskReply([promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
398                 completionHandler(StorageAccessWasGranted::No, promptWasShown);
399             });
400             return;
401         }
402
403         m_statisticsStore->grantStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, promptWasShown, [promptWasShown, completionHandler = WTFMove(completionHandler)](StorageAccessWasGranted wasGrantedAccess) mutable {
404             postTaskReply([wasGrantedAccess, promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
405                 completionHandler(wasGrantedAccess, promptWasShown);
406             });
407         });
408     });
409 }
410
411 StorageAccessWasGranted WebResourceLoadStatisticsStore::grantStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID)
412 {
413     ASSERT(RunLoop::isMain());
414
415     bool isStorageGranted = false;
416
417     if (m_networkSession) {
418         if (auto* storageSession = m_networkSession->networkStorageSession()) {
419             storageSession->grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
420             ASSERT(storageSession->hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
421             isStorageGranted = true;
422         }
423     }
424
425     return isStorageGranted ? StorageAccessWasGranted::Yes : StorageAccessWasGranted::No;
426 }
427
428 void WebResourceLoadStatisticsStore::callGrantStorageAccessHandler(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, Optional<FrameIdentifier> frameID, PageIdentifier pageID, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
429 {
430     ASSERT(RunLoop::isMain());
431
432     completionHandler(grantStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID));
433 }
434
435 void WebResourceLoadStatisticsStore::hasCookies(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
436 {
437     ASSERT(RunLoop::isMain());
438
439     if (m_networkSession) {
440         if (auto* storageSession = m_networkSession->networkStorageSession()) {
441             storageSession->hasCookies(domain, WTFMove(completionHandler));
442             return;
443         }
444     }
445     
446     completionHandler(false);
447 }
448
449 void WebResourceLoadStatisticsStore::didCreateNetworkProcess()
450 {
451     ASSERT(RunLoop::isMain());
452
453     postTask([this] {
454         if (!m_statisticsStore)
455             return;
456         m_statisticsStore->didCreateNetworkProcess();
457     });
458 }
459
460 void WebResourceLoadStatisticsStore::removeAllStorageAccess(CompletionHandler<void()>&& completionHandler)
461 {
462     ASSERT(RunLoop::isMain());
463
464     if (m_networkSession) {
465         if (auto* storageSession = m_networkSession->networkStorageSession())
466             storageSession->removeAllStorageAccess();
467     }
468
469     completionHandler();
470 }
471
472 void WebResourceLoadStatisticsStore::applicationWillTerminate()
473 {
474     ASSERT(RunLoop::isMain());
475     flushAndDestroyPersistentStore();
476 }
477
478 void WebResourceLoadStatisticsStore::performDailyTasks()
479 {
480     ASSERT(RunLoop::isMain());
481
482     postTask([this] {
483         if (m_statisticsStore) {
484             m_statisticsStore->includeTodayAsOperatingDateIfNecessary();
485             m_statisticsStore->calculateAndSubmitTelemetry();
486         }
487     });
488 }
489
490 void WebResourceLoadStatisticsStore::submitTelemetry(CompletionHandler<void()>&& completionHandler)
491 {
492     ASSERT(RunLoop::isMain());
493
494     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable  {
495         if (m_statisticsStore && is<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore))
496             WebResourceLoadStatisticsTelemetry::calculateAndSubmit(downcast<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore));
497
498         postTaskReply(WTFMove(completionHandler));
499     });
500 }
501
502 void WebResourceLoadStatisticsStore::logFrameNavigation(const WebFrameProxy& frame, const URL& pageURL, const WebCore::ResourceRequest& request, const URL& redirectURL)
503 {
504     ASSERT(RunLoop::isMain());
505
506     auto sourceURL = redirectURL;
507     bool isRedirect = !redirectURL.isNull();
508     if (!isRedirect) {
509         sourceURL = frame.url();
510         if (sourceURL.isNull())
511             sourceURL = pageURL;
512     }
513
514     auto& targetURL = request.url();
515
516     if (!targetURL.isValid() || !pageURL.isValid())
517         return;
518
519     auto targetHost = targetURL.host();
520     auto mainFrameHost = pageURL.host();
521
522     if (targetHost.isEmpty() || mainFrameHost.isEmpty() || targetHost == sourceURL.host())
523         return;
524
525     RegistrableDomain targetDomain { targetURL };
526     RegistrableDomain topFrameDomain { pageURL };
527     RegistrableDomain sourceDomain { sourceURL };
528
529     logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, frame.isMainFrame());
530 }
531
532 void WebResourceLoadStatisticsStore::logFrameNavigation(const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, const RegistrableDomain& sourceDomain, bool isRedirect, bool isMainFrame)
533 {
534     ASSERT(RunLoop::isMain());
535
536     postTask([this, targetDomain = targetDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), sourceDomain = sourceDomain.isolatedCopy(), isRedirect, isMainFrame] {
537         if (m_statisticsStore)
538             m_statisticsStore->logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, isMainFrame);
539     });
540 }
541
542 void WebResourceLoadStatisticsStore::logUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
543 {
544     ASSERT(RunLoop::isMain());
545
546     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
547         if (m_statisticsStore)
548             m_statisticsStore->logUserInteraction(domain);
549         postTaskReply(WTFMove(completionHandler));
550     });
551 }
552
553 void WebResourceLoadStatisticsStore::logCrossSiteLoadWithLinkDecoration(const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
554 {
555     ASSERT(RunLoop::isMain());
556     ASSERT(fromDomain != toDomain);
557     
558     postTask([this, fromDomain = fromDomain.isolatedCopy(), toDomain = toDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
559         if (m_statisticsStore)
560             m_statisticsStore->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain);
561         postTaskReply(WTFMove(completionHandler));
562     });
563 }
564
565 void WebResourceLoadStatisticsStore::clearUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
566 {
567     ASSERT(RunLoop::isMain());
568     
569     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
570         if (m_statisticsStore)
571             m_statisticsStore->clearUserInteraction(domain);
572         postTaskReply(WTFMove(completionHandler));
573     });
574 }
575
576 void WebResourceLoadStatisticsStore::hasHadUserInteraction(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
577 {
578     ASSERT(RunLoop::isMain());
579
580     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
581         bool hadUserInteraction = m_statisticsStore ? m_statisticsStore->hasHadUserInteraction(domain, OperatingDatesWindow::Long) : false;
582         postTaskReply([hadUserInteraction, completionHandler = WTFMove(completionHandler)]() mutable {
583             completionHandler(hadUserInteraction);
584         });
585     });
586 }
587
588 void WebResourceLoadStatisticsStore::setLastSeen(const RegistrableDomain& domain, Seconds seconds, CompletionHandler<void()>&& completionHandler)
589 {
590     ASSERT(RunLoop::isMain());
591     
592     postTask([this, domain = domain.isolatedCopy(), seconds, completionHandler = WTFMove(completionHandler)]() mutable {
593         if (m_statisticsStore)
594             m_statisticsStore->setLastSeen(domain, seconds);
595         postTaskReply(WTFMove(completionHandler));
596     });
597 }
598
599 void WebResourceLoadStatisticsStore::mergeStatisticForTesting(const RegistrableDomain& domain, const RegistrableDomain& topFrameDomain1, const RegistrableDomain& topFrameDomain2, Seconds lastSeen, bool hadUserInteraction, Seconds mostRecentUserInteraction, bool isGrandfathered, bool isPrevalent, bool isVeryPrevalent, unsigned dataRecordsRemoved, CompletionHandler<void()>&& completionHandler)
600 {
601     ASSERT(RunLoop::isMain());
602
603     postTask([this, domain = domain.isolatedCopy(), topFrameDomain1 = topFrameDomain1.isolatedCopy(), topFrameDomain2 = topFrameDomain2.isolatedCopy(), lastSeen, hadUserInteraction, mostRecentUserInteraction, isGrandfathered, isPrevalent, isVeryPrevalent, dataRecordsRemoved, completionHandler = WTFMove(completionHandler)]() mutable {
604         if (m_statisticsStore) {
605             ResourceLoadStatistics statistic(domain);
606             statistic.lastSeen = WallTime::fromRawSeconds(lastSeen.seconds());
607             statistic.hadUserInteraction = hadUserInteraction;
608             statistic.mostRecentUserInteractionTime = WallTime::fromRawSeconds(mostRecentUserInteraction.seconds());
609             statistic.grandfathered = isGrandfathered;
610             statistic.isPrevalentResource = isPrevalent;
611             statistic.isVeryPrevalentResource = isVeryPrevalent;
612             statistic.dataRecordsRemoved = dataRecordsRemoved;
613             
614             HashSet<RegistrableDomain> topFrameDomains;
615             
616             if (!topFrameDomain1.isEmpty())
617                 topFrameDomains.add(topFrameDomain1);
618             
619             if (!topFrameDomain2.isEmpty())
620                 topFrameDomains.add(topFrameDomain2);
621
622             statistic.subframeUnderTopFrameDomains = WTFMove(topFrameDomains);
623
624             Vector<ResourceLoadStatistics> statistics;
625             statistics.append(WTFMove(statistic));
626             m_statisticsStore->mergeStatistics(WTFMove(statistics));
627         }
628         postTaskReply(WTFMove(completionHandler));
629     });
630 }
631
632 void WebResourceLoadStatisticsStore::isRelationshipOnlyInDatabaseOnce(const RegistrableDomain& subDomain, const RegistrableDomain& topDomain, CompletionHandler<void(bool)>&& completionHandler)
633 {
634     ASSERT(RunLoop::isMain());
635
636     postTask([this, subDomain = subDomain.isolatedCopy(), topDomain = topDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
637         if (!m_statisticsStore || !is<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore)) {
638             completionHandler(false);
639             return;
640         }
641         
642         bool isRelationshipOnlyInDatabaseOnce = downcast<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore).isCorrectSubStatisticsCount(subDomain, topDomain);
643         
644         postTaskReply([isRelationshipOnlyInDatabaseOnce, completionHandler = WTFMove(completionHandler)]() mutable {
645             completionHandler(isRelationshipOnlyInDatabaseOnce);
646         });
647     });
648 }
649     
650 void WebResourceLoadStatisticsStore::setPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
651 {
652     ASSERT(RunLoop::isMain());
653
654     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
655         if (m_statisticsStore)
656             m_statisticsStore->setPrevalentResource(domain);
657         postTaskReply(WTFMove(completionHandler));
658     });
659 }
660
661 void WebResourceLoadStatisticsStore::setVeryPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
662 {
663     ASSERT(RunLoop::isMain());
664
665     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
666         if (m_statisticsStore)
667             m_statisticsStore->setVeryPrevalentResource(domain);
668         postTaskReply(WTFMove(completionHandler));
669     });
670 }
671     
672 void WebResourceLoadStatisticsStore::dumpResourceLoadStatistics(CompletionHandler<void(String)>&& completionHandler)
673 {
674     ASSERT(RunLoop::isMain());
675
676     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
677         auto innerCompletionHandler = [completionHandler = WTFMove(completionHandler)](const String& result) mutable {
678             postTaskReply([result = result.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
679                 completionHandler(result);
680             });
681         };
682         if (!m_statisticsStore) {
683             innerCompletionHandler(emptyString());
684             return;
685         }
686         m_statisticsStore->dumpResourceLoadStatistics(WTFMove(innerCompletionHandler));
687     });
688 }
689
690 void WebResourceLoadStatisticsStore::isPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
691 {
692     ASSERT(RunLoop::isMain());
693     
694     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
695         bool isPrevalentResource = m_statisticsStore ? m_statisticsStore->isPrevalentResource(domain) : false;
696         postTaskReply([isPrevalentResource, completionHandler = WTFMove(completionHandler)]() mutable {
697             completionHandler(isPrevalentResource);
698         });
699     });
700 }
701     
702 void WebResourceLoadStatisticsStore::isVeryPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
703 {
704     ASSERT(RunLoop::isMain());
705     
706     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
707         bool isVeryPrevalentResource = m_statisticsStore ? m_statisticsStore->isVeryPrevalentResource(domain) : false;
708         postTaskReply([isVeryPrevalentResource, completionHandler = WTFMove(completionHandler)]() mutable {
709             completionHandler(isVeryPrevalentResource);
710         });
711     });
712 }
713
714 void WebResourceLoadStatisticsStore::isRegisteredAsSubresourceUnder(const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
715 {
716     ASSERT(RunLoop::isMain());
717
718     postTask([this, subresourceDomain = subresourceDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
719         bool isRegisteredAsSubresourceUnder = m_statisticsStore ? m_statisticsStore->isRegisteredAsSubresourceUnder(subresourceDomain, topFrameDomain)
720             : false;
721         postTaskReply([isRegisteredAsSubresourceUnder, completionHandler = WTFMove(completionHandler)]() mutable {
722             completionHandler(isRegisteredAsSubresourceUnder);
723         });
724     });
725 }
726
727 void WebResourceLoadStatisticsStore::isRegisteredAsSubFrameUnder(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
728 {
729     ASSERT(RunLoop::isMain());
730
731     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
732         bool isRegisteredAsSubFrameUnder = m_statisticsStore ? m_statisticsStore->isRegisteredAsSubFrameUnder(subFrameDomain, topFrameDomain)
733             : false;
734         postTaskReply([isRegisteredAsSubFrameUnder, completionHandler = WTFMove(completionHandler)]() mutable {
735             completionHandler(isRegisteredAsSubFrameUnder);
736         });
737     });
738 }
739
740 void WebResourceLoadStatisticsStore::isRegisteredAsRedirectingTo(const RegistrableDomain& domainRedirectedFrom, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
741 {
742     ASSERT(RunLoop::isMain());
743
744     postTask([this, domainRedirectedFrom = domainRedirectedFrom.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
745         bool isRegisteredAsRedirectingTo = m_statisticsStore ? m_statisticsStore->isRegisteredAsRedirectingTo(domainRedirectedFrom, domainRedirectedTo)
746             : false;
747         postTaskReply([isRegisteredAsRedirectingTo, completionHandler = WTFMove(completionHandler)]() mutable {
748             completionHandler(isRegisteredAsRedirectingTo);
749         });
750     });
751 }
752
753 void WebResourceLoadStatisticsStore::clearPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
754 {
755     ASSERT(RunLoop::isMain());
756     
757     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
758         if (m_statisticsStore)
759             m_statisticsStore->clearPrevalentResource(domain);
760         postTaskReply(WTFMove(completionHandler));
761     });
762 }
763
764 void WebResourceLoadStatisticsStore::setGrandfathered(const RegistrableDomain& domain, bool value, CompletionHandler<void()>&& completionHandler)
765 {
766     ASSERT(RunLoop::isMain());
767
768     postTask([this, domain = domain.isolatedCopy(), value, completionHandler = WTFMove(completionHandler)]() mutable {
769         if (m_statisticsStore)
770             m_statisticsStore->setGrandfathered(domain, value);
771         postTaskReply(WTFMove(completionHandler));
772     });
773 }
774     
775 void WebResourceLoadStatisticsStore::isGrandfathered(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
776 {
777     ASSERT(RunLoop::isMain());
778
779     postTask([this, completionHandler = WTFMove(completionHandler), domain = domain.isolatedCopy()]() mutable {
780         bool isGrandFathered = m_statisticsStore ? m_statisticsStore->isGrandfathered(domain)
781             : false;
782         postTaskReply([isGrandFathered, completionHandler = WTFMove(completionHandler)]() mutable {
783             completionHandler(isGrandFathered);
784         });
785     });
786 }
787
788 void WebResourceLoadStatisticsStore::setSubframeUnderTopFrameDomain(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
789 {
790     ASSERT(RunLoop::isMain());
791     
792     postTask([this, completionHandler = WTFMove(completionHandler), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy()]() mutable {
793         if (m_statisticsStore)
794             m_statisticsStore->setSubframeUnderTopFrameDomain(subFrameDomain, topFrameDomain);
795         postTaskReply(WTFMove(completionHandler));
796     });
797 }
798
799 void WebResourceLoadStatisticsStore::setSubresourceUnderTopFrameDomain(const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
800 {
801     ASSERT(RunLoop::isMain());
802     
803     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy()]() mutable {
804         if (m_statisticsStore)
805             m_statisticsStore->setSubresourceUnderTopFrameDomain(subresourceDomain, topFrameDomain);
806         postTaskReply(WTFMove(completionHandler));
807     });
808 }
809
810 void WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectTo(const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
811 {
812     ASSERT(RunLoop::isMain());
813     
814     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy()]() mutable {
815         if (m_statisticsStore)
816             m_statisticsStore->setSubresourceUniqueRedirectTo(subresourceDomain, domainRedirectedTo);
817         postTaskReply(WTFMove(completionHandler));
818     });
819 }
820
821 void WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectFrom(const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
822 {
823     ASSERT(RunLoop::isMain());
824     
825     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), domainRedirectedFrom = domainRedirectedFrom.isolatedCopy()]() mutable {
826         if (m_statisticsStore)
827             m_statisticsStore->setSubresourceUniqueRedirectFrom(subresourceDomain, domainRedirectedFrom);
828         postTaskReply(WTFMove(completionHandler));
829     });
830 }
831
832 void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectTo(const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
833 {
834     ASSERT(RunLoop::isMain());
835     
836     postTask([this, completionHandler = WTFMove(completionHandler), topFrameDomain = topFrameDomain.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy()]() mutable {
837         if (m_statisticsStore)
838             m_statisticsStore->setTopFrameUniqueRedirectTo(topFrameDomain, domainRedirectedTo);
839         postTaskReply(WTFMove(completionHandler));
840     });
841 }
842
843 void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectFrom(const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
844 {
845     ASSERT(RunLoop::isMain());
846     
847     postTask([this, completionHandler = WTFMove(completionHandler), topFrameDomain = topFrameDomain.isolatedCopy(), domainRedirectedFrom = domainRedirectedFrom.isolatedCopy()]() mutable {
848         if (m_statisticsStore)
849             m_statisticsStore->setTopFrameUniqueRedirectFrom(topFrameDomain, domainRedirectedFrom);
850         postTaskReply(WTFMove(completionHandler));
851     });
852 }
853
854 void WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdate(CompletionHandler<void()>&& completionHandler)
855 {
856     // Helper function used by testing system. Should only be called from the main thread.
857     ASSERT(RunLoop::isMain());
858
859     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
860         if (!m_statisticsStore) {
861             postTaskReply(WTFMove(completionHandler));
862             return;
863         }
864
865         m_statisticsStore->updateCookieBlocking([completionHandler = WTFMove(completionHandler)]() mutable {
866             postTaskReply(WTFMove(completionHandler));
867         });
868     });
869 }
870
871 void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
872 {
873     ASSERT(RunLoop::isMain());
874     postTask([this, protectedThis = makeRef(*this), shouldGrandfather, completionHandler = WTFMove(completionHandler)]() mutable {
875         if (m_persistentStorage)
876             m_persistentStorage->clear();
877
878         if (!m_statisticsStore) {
879             if (shouldGrandfather == ShouldGrandfatherStatistics::Yes)
880                 RELEASE_LOG(ResourceLoadStatistics, "WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent Before being cleared, m_statisticsStore is null when trying to grandfather data.");
881
882             postTaskReply(WTFMove(completionHandler));
883             return;
884         }
885
886         auto callbackAggregator = CallbackAggregator::create([completionHandler = WTFMove(completionHandler)] () mutable {
887             postTaskReply(WTFMove(completionHandler));
888         });
889
890         m_statisticsStore->clear([this, protectedThis = protectedThis.copyRef(), shouldGrandfather, callbackAggregator = callbackAggregator.copyRef()] () mutable {
891             if (shouldGrandfather == ShouldGrandfatherStatistics::Yes) {
892                 if (m_statisticsStore)
893                     m_statisticsStore->grandfatherExistingWebsiteData([callbackAggregator = WTFMove(callbackAggregator)]() mutable { });
894                 else
895                     RELEASE_LOG(ResourceLoadStatistics, "WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent After being cleared, m_statisticsStore is null when trying to grandfather data.");
896             }
897         });
898     });
899 }
900
901 void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& callback)
902 {
903     ASSERT(RunLoop::isMain());
904
905     // For now, be conservative and clear everything regardless of modifiedSince.
906     UNUSED_PARAM(modifiedSince);
907     scheduleClearInMemoryAndPersistent(shouldGrandfather, WTFMove(callback));
908 }
909
910 void WebResourceLoadStatisticsStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
911 {
912     ASSERT(RunLoop::isMain());
913     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable {
914         if (m_statisticsStore)
915             m_statisticsStore->setTimeToLiveUserInteraction(seconds);
916         postTaskReply(WTFMove(completionHandler));
917     });
918 }
919
920 void WebResourceLoadStatisticsStore::setMinimumTimeBetweenDataRecordsRemoval(Seconds seconds, CompletionHandler<void()>&& completionHandler)
921 {
922     ASSERT(RunLoop::isMain());
923     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable  {
924         if (m_statisticsStore)
925             m_statisticsStore->setMinimumTimeBetweenDataRecordsRemoval(seconds);
926
927         postTaskReply(WTFMove(completionHandler));
928     });
929 }
930
931 void WebResourceLoadStatisticsStore::setGrandfatheringTime(Seconds seconds, CompletionHandler<void()>&& completionHandler)
932 {
933     ASSERT(RunLoop::isMain());
934     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable  {
935         if (m_statisticsStore)
936             m_statisticsStore->setGrandfatheringTime(seconds);
937
938         postTaskReply(WTFMove(completionHandler));
939     });
940 }
941
942 void WebResourceLoadStatisticsStore::setCacheMaxAgeCap(Seconds seconds, CompletionHandler<void()>&& completionHandler)
943 {
944     ASSERT(RunLoop::isMain());
945     ASSERT(seconds >= 0_s);
946     
947     if (m_networkSession) {
948         if (auto* storageSession = m_networkSession->networkStorageSession())
949             storageSession->setCacheMaxAgeCapForPrevalentResources(seconds);
950     }
951
952     completionHandler();
953 }
954
955 void WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler(const RegistrableDomainsToBlockCookiesFor& domainsToBlock, CompletionHandler<void()>&& completionHandler)
956 {
957     ASSERT(RunLoop::isMain());
958
959     if (m_networkSession) {
960         if (auto* storageSession = m_networkSession->networkStorageSession()) {
961             storageSession->setPrevalentDomainsToBlockAndDeleteCookiesFor(domainsToBlock.domainsToBlockAndDeleteCookiesFor);
962             storageSession->setPrevalentDomainsToBlockButKeepCookiesFor(domainsToBlock.domainsToBlockButKeepCookiesFor);
963         }
964     }
965
966     completionHandler();
967 }
968
969 void WebResourceLoadStatisticsStore::removePrevalentDomains(const Vector<RegistrableDomain>& domains)
970 {
971     ASSERT(RunLoop::isMain());
972     if (!m_networkSession)
973         return;
974
975     if (auto* storageSession = m_networkSession->networkStorageSession())
976         storageSession->removePrevalentDomains(domains);
977 }
978
979 void WebResourceLoadStatisticsStore::callRemoveDomainsHandler(const Vector<RegistrableDomain>& domains)
980 {
981     ASSERT(RunLoop::isMain());
982
983     removePrevalentDomains(domains);
984 }
985     
986 void WebResourceLoadStatisticsStore::setMaxStatisticsEntries(size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
987 {
988     ASSERT(RunLoop::isMain());
989     postTask([this, maximumEntryCount, completionHandler = WTFMove(completionHandler)]() mutable  {
990         if (m_statisticsStore)
991             m_statisticsStore->setMaxStatisticsEntries(maximumEntryCount);
992
993         postTaskReply(WTFMove(completionHandler));
994     });
995 }
996     
997 void WebResourceLoadStatisticsStore::setPruneEntriesDownTo(size_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
998 {
999     ASSERT(RunLoop::isMain());
1000
1001     postTask([this, pruneTargetCount, completionHandler = WTFMove(completionHandler)]() mutable  {
1002         if (m_statisticsStore)
1003             m_statisticsStore->setPruneEntriesDownTo(pruneTargetCount);
1004
1005         postTaskReply(WTFMove(completionHandler));
1006     });
1007 }
1008
1009 void WebResourceLoadStatisticsStore::resetParametersToDefaultValues(CompletionHandler<void()>&& completionHandler)
1010 {
1011     ASSERT(RunLoop::isMain());
1012
1013     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
1014         if (m_statisticsStore)
1015             m_statisticsStore->resetParametersToDefaultValues();
1016
1017         postTaskReply(WTFMove(completionHandler));
1018     });
1019 }
1020
1021 void WebResourceLoadStatisticsStore::logTestingEvent(const String& event)
1022 {
1023     ASSERT(RunLoop::isMain());
1024
1025     if (m_networkSession && m_networkSession->enableResourceLoadStatisticsLogTestingEvent())
1026         m_networkSession->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::LogTestingEvent(m_networkSession->sessionID(), event), 0);
1027 }
1028
1029 void WebResourceLoadStatisticsStore::notifyResourceLoadStatisticsProcessed()
1030 {
1031     ASSERT(RunLoop::isMain());
1032     
1033     if (m_networkSession)
1034         m_networkSession->notifyResourceLoadStatisticsProcessed();
1035 }
1036
1037 NetworkSession* WebResourceLoadStatisticsStore::networkSession()
1038 {
1039     ASSERT(RunLoop::isMain());
1040     return m_networkSession.get();
1041 }
1042
1043 void WebResourceLoadStatisticsStore::invalidateAndCancel()
1044 {
1045     ASSERT(RunLoop::isMain());
1046     m_networkSession = nullptr;
1047 }
1048
1049 void WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>>&& domainsToRemoveWebsiteDataFor, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1050 {
1051     ASSERT(RunLoop::isMain());
1052     
1053     if (m_networkSession) {
1054         m_networkSession->deleteWebsiteDataForRegistrableDomains(dataTypes, WTFMove(domainsToRemoveWebsiteDataFor), shouldNotifyPage, WTFMove(completionHandler));
1055         return;
1056     }
1057
1058     completionHandler({ });
1059 }
1060
1061 void WebResourceLoadStatisticsStore::registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1062 {
1063     ASSERT(RunLoop::isMain());
1064     
1065     if (m_networkSession) {
1066         m_networkSession->registrableDomainsWithWebsiteData(dataTypes, shouldNotifyPage, WTFMove(completionHandler));
1067         return;
1068     }
1069
1070     completionHandler({ });
1071 }
1072
1073 void WebResourceLoadStatisticsStore::sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample shouldSample) const
1074 {
1075     ASSERT(RunLoop::isMain());
1076     if (m_networkSession)
1077         const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->logDiagnosticMessageWithValue(message, description, value, sigDigits, shouldSample);
1078 }
1079
1080 void WebResourceLoadStatisticsStore::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const
1081 {
1082     ASSERT(RunLoop::isMain());
1083     if (m_networkSession)
1084         const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->notifyPageStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
1085 }
1086
1087 } // namespace WebKit
1088
1089 #endif