WeakPtr breaks vtables when upcasting to base classes
[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     ASSERT(RunLoop::isMain());
159     
160     postTask([this, resourceLoadStatisticsDirectory = resourceLoadStatisticsDirectory.isolatedCopy(), shouldIncludeLocalhost] {
161         if (RuntimeEnabledFeatures::sharedFeatures().isITPDatabaseEnabled()) {
162             m_statisticsStore = std::make_unique<ResourceLoadStatisticsDatabaseStore>(*this, m_statisticsQueue, shouldIncludeLocalhost, resourceLoadStatisticsDirectory);
163
164             auto memoryStore = std::make_unique<ResourceLoadStatisticsMemoryStore>(*this, m_statisticsQueue, shouldIncludeLocalhost);
165             auto persistentStore = std::make_unique<ResourceLoadStatisticsPersistentStorage>(*memoryStore, m_statisticsQueue, resourceLoadStatisticsDirectory);
166
167             downcast<ResourceLoadStatisticsDatabaseStore>(*m_statisticsStore.get()).populateFromMemoryStore(*memoryStore);
168         } else {
169             m_statisticsStore = std::make_unique<ResourceLoadStatisticsMemoryStore>(*this, m_statisticsQueue, shouldIncludeLocalhost);
170             m_persistentStorage = std::make_unique<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     ASSERT(RunLoop::isMain());
183
184     flushAndDestroyPersistentStore();
185 }
186
187 inline void WebResourceLoadStatisticsStore::postTask(WTF::Function<void()>&& task)
188 {
189     ASSERT(RunLoop::isMain());
190     m_statisticsQueue->dispatch([protectedThis = makeRef(*this), task = WTFMove(task)] {
191         task();
192     });
193 }
194
195 inline void WebResourceLoadStatisticsStore::postTaskReply(WTF::Function<void()>&& reply)
196 {
197     ASSERT(!RunLoop::isMain());
198     RunLoop::main().dispatch(WTFMove(reply));
199 }
200
201 void WebResourceLoadStatisticsStore::flushAndDestroyPersistentStore()
202 {
203     ASSERT(RunLoop::isMain());
204
205     if (!m_persistentStorage && !m_statisticsStore)
206         return;
207
208     // Make sure we destroy the persistent store on the background queue and wait for it to die
209     // synchronously since it has a C++ reference to us. Blocking nature of this task allows us
210     // to not maintain a WebResourceLoadStatisticsStore reference for the duration of dispatch,
211     // avoiding double-deletion issues when this is invoked from the destructor.
212     BinarySemaphore semaphore;
213     m_statisticsQueue->dispatch([&semaphore, this] {
214         m_persistentStorage = nullptr;
215         m_statisticsStore = nullptr;
216         semaphore.signal();
217     });
218     semaphore.wait();
219 }
220
221 void WebResourceLoadStatisticsStore::setResourceLoadStatisticsDebugMode(bool value, CompletionHandler<void()>&& completionHandler)
222 {
223     ASSERT(RunLoop::isMain());
224
225     postTask([this, value, completionHandler = WTFMove(completionHandler)]() mutable {
226         if (m_statisticsStore)
227             m_statisticsStore->setResourceLoadStatisticsDebugMode(value);
228         postTaskReply(WTFMove(completionHandler));
229     });
230 }
231
232 void WebResourceLoadStatisticsStore::setPrevalentResourceForDebugMode(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
233 {
234     ASSERT(RunLoop::isMain());
235     
236     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
237         if (m_statisticsStore)
238             m_statisticsStore->setPrevalentResourceForDebugMode(domain);
239         postTaskReply(WTFMove(completionHandler));
240     });
241 }
242
243 void WebResourceLoadStatisticsStore::scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&& completionHandler)
244 {
245     ASSERT(RunLoop::isMain());
246     
247     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
248         if (m_statisticsStore)
249             m_statisticsStore->processStatisticsAndDataRecords();
250         postTaskReply(WTFMove(completionHandler));
251     });
252 }
253
254 void WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated(Vector<WebCore::ResourceLoadStatistics>&& origins)
255 {
256     ASSERT(RunLoop::isMain());
257
258     // It is safe to move the origins to the background queue without isolated copy here because this is an r-value
259     // coming from IPC. ResourceLoadStatistics only contains strings which are safe to move to other threads as long
260     // as nobody on this thread holds a reference to those strings.
261     postTask([this, origins = WTFMove(origins)]() mutable {
262         if (!m_statisticsStore || !is<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore))
263             return;
264
265         auto& memoryStore = downcast<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore);
266     
267         memoryStore.mergeStatistics(WTFMove(origins));
268
269         // We can cancel any pending request to process statistics since we're doing it synchronously below.
270         memoryStore.cancelPendingStatisticsProcessingRequest();
271
272         // Fire before processing statistics to propagate user interaction as fast as possible to the network process.
273         memoryStore.updateCookieBlocking([]() { });
274         memoryStore.processStatisticsAndDataRecords();
275     });
276 }
277
278 void WebResourceLoadStatisticsStore::hasStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, Optional<uint64_t> frameID, PageIdentifier pageID, CompletionHandler<void(bool)>&& completionHandler)
279 {
280     ASSERT(subFrameDomain != topFrameDomain);
281     ASSERT(RunLoop::isMain());
282
283     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, completionHandler = WTFMove(completionHandler)]() mutable {
284         if (!m_statisticsStore) {
285             postTaskReply([completionHandler = WTFMove(completionHandler)]() mutable {
286                 completionHandler(false);
287             });
288             return;
289         }
290
291         if (m_statisticsStore) {
292             m_statisticsStore->hasStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID, [completionHandler = WTFMove(completionHandler)](bool hasStorageAccess) mutable {
293                 postTaskReply([completionHandler = WTFMove(completionHandler), hasStorageAccess]() mutable {
294                     completionHandler(hasStorageAccess);
295                 });
296             });
297         }
298     });
299 }
300
301 bool WebResourceLoadStatisticsStore::hasStorageAccessForFrame(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, uint64_t frameID, PageIdentifier pageID)
302 {
303     return m_networkSession ? m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID) : false;
304 }
305
306 void WebResourceLoadStatisticsStore::callHasStorageAccessForFrameHandler(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, uint64_t frameID, PageIdentifier pageID, CompletionHandler<void(bool hasAccess)>&& callback)
307 {
308     ASSERT(RunLoop::isMain());
309
310     if (m_networkSession) {
311         callback(m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
312         return;
313     }
314
315     callback(false);
316 }
317
318 void WebResourceLoadStatisticsStore::requestStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, uint64_t frameID, PageIdentifier pageID, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&& completionHandler)
319 {
320     if (subFrameDomain == topFrameDomain) {
321         completionHandler(StorageAccessWasGranted::Yes, StorageAccessPromptWasShown::No);
322         return;
323     }
324     
325     auto statusHandler = [this, protectedThis = makeRef(*this), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, completionHandler = WTFMove(completionHandler)](StorageAccessStatus status) mutable {
326         switch (status) {
327         case StorageAccessStatus::CannotRequestAccess:
328             completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::No);
329             return;
330         case StorageAccessStatus::RequiresUserPrompt:
331             {
332             CompletionHandler<void(bool)> requestConfirmationCompletionHandler = [this, protectedThis = protectedThis.copyRef(), subFrameDomain, topFrameDomain, frameID, pageID, completionHandler = WTFMove(completionHandler)] (bool userDidGrantAccess) mutable {
333                 if (userDidGrantAccess)
334                     grantStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID, StorageAccessPromptWasShown::Yes, WTFMove(completionHandler));
335                 else
336                     completionHandler(StorageAccessWasGranted::No, StorageAccessPromptWasShown::Yes);
337             };
338             m_networkSession->networkProcess().parentProcessConnection()->sendWithAsyncReply(Messages::NetworkProcessProxy::RequestStorageAccessConfirm(pageID, frameID, subFrameDomain, topFrameDomain), WTFMove(requestConfirmationCompletionHandler));
339             }
340             return;
341         case StorageAccessStatus::HasAccess:
342             completionHandler(StorageAccessWasGranted::Yes, StorageAccessPromptWasShown::No);
343             return;
344         }
345     };
346
347     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, statusHandler = WTFMove(statusHandler)]() mutable {
348         if (!m_statisticsStore) {
349             postTaskReply([statusHandler = WTFMove(statusHandler)]() mutable {
350                 statusHandler(StorageAccessStatus::CannotRequestAccess);
351             });
352             return;
353         }
354
355         if (m_statisticsStore) {
356             m_statisticsStore->requestStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, [statusHandler = WTFMove(statusHandler)](StorageAccessStatus status) mutable {
357                 postTaskReply([statusHandler = WTFMove(statusHandler), status]() mutable {
358                     statusHandler(status);
359                 });
360             });
361         }
362     });
363 }
364
365 void WebResourceLoadStatisticsStore::requestStorageAccessUnderOpener(RegistrableDomain&& domainInNeedOfStorageAccess, PageIdentifier openerPageID, RegistrableDomain&& openerDomain)
366 {
367     ASSERT(RunLoop::isMain());
368
369     // It is safe to move the strings to the background queue without isolated copy here because they are r-value references
370     // coming from IPC. Strings which are safe to move to other threads as long as nobody on this thread holds a reference
371     // to those strings.
372     postTask([this, domainInNeedOfStorageAccess = WTFMove(domainInNeedOfStorageAccess), openerPageID, openerDomain = WTFMove(openerDomain)]() mutable {
373         if (m_statisticsStore)
374             m_statisticsStore->requestStorageAccessUnderOpener(WTFMove(domainInNeedOfStorageAccess), openerPageID, WTFMove(openerDomain));
375     });
376 }
377
378 void WebResourceLoadStatisticsStore::grantStorageAccess(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, uint64_t frameID, PageIdentifier pageID, StorageAccessPromptWasShown promptWasShown, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&& completionHandler)
379 {
380     ASSERT(RunLoop::isMain());
381     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), frameID, pageID, promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
382         if (!m_statisticsStore) {
383             postTaskReply([promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
384                 completionHandler(StorageAccessWasGranted::No, promptWasShown);
385             });
386             return;
387         }
388
389         if (m_statisticsStore) {
390             m_statisticsStore->grantStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), frameID, pageID, promptWasShown, [promptWasShown, completionHandler = WTFMove(completionHandler)](StorageAccessWasGranted wasGrantedAccess) mutable {
391                 postTaskReply([wasGrantedAccess, promptWasShown, completionHandler = WTFMove(completionHandler)]() mutable {
392                     completionHandler(wasGrantedAccess, promptWasShown);
393                 });
394             });
395         }
396     });
397 }
398
399 StorageAccessWasGranted WebResourceLoadStatisticsStore::grantStorageAccess(const RegistrableDomain& resourceDomain, const RegistrableDomain& firstPartyDomain, Optional<uint64_t> frameID, PageIdentifier pageID)
400 {
401     bool isStorageGranted = false;
402
403     if (m_networkSession) {
404         m_networkSession->networkStorageSession().grantStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID);
405         ASSERT(m_networkSession->networkStorageSession().hasStorageAccess(resourceDomain, firstPartyDomain, frameID, pageID));
406         isStorageGranted = true;
407     }
408
409     return isStorageGranted ? StorageAccessWasGranted::Yes : StorageAccessWasGranted::No;
410 }
411
412 void WebResourceLoadStatisticsStore::callGrantStorageAccessHandler(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, Optional<uint64_t> frameID, PageIdentifier pageID, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
413 {
414     ASSERT(RunLoop::isMain());
415
416     completionHandler(grantStorageAccess(subFrameDomain, topFrameDomain, frameID, pageID));
417 }
418
419 void WebResourceLoadStatisticsStore::didCreateNetworkProcess()
420 {
421     ASSERT(RunLoop::isMain());
422
423     postTask([this] {
424         if (!m_statisticsStore)
425             return;
426         m_statisticsStore->didCreateNetworkProcess();
427     });
428 }
429
430 void WebResourceLoadStatisticsStore::removeAllStorageAccess(CompletionHandler<void()>&& completionHandler)
431 {
432     ASSERT(RunLoop::isMain());
433
434     if (m_networkSession)
435         m_networkSession->networkStorageSession().removeAllStorageAccess();
436
437     completionHandler();
438 }
439
440 void WebResourceLoadStatisticsStore::applicationWillTerminate()
441 {
442     flushAndDestroyPersistentStore();
443 }
444
445 void WebResourceLoadStatisticsStore::performDailyTasks()
446 {
447     ASSERT(RunLoop::isMain());
448
449     postTask([this] {
450         if (m_statisticsStore) {
451             m_statisticsStore->includeTodayAsOperatingDateIfNecessary();
452             m_statisticsStore->calculateAndSubmitTelemetry();
453         }
454     });
455 }
456
457 void WebResourceLoadStatisticsStore::submitTelemetry(CompletionHandler<void()>&& completionHandler)
458 {
459     ASSERT(RunLoop::isMain());
460
461     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable  {
462         if (m_statisticsStore && is<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore))
463             WebResourceLoadStatisticsTelemetry::calculateAndSubmit(downcast<ResourceLoadStatisticsMemoryStore>(*m_statisticsStore));
464
465         postTaskReply(WTFMove(completionHandler));
466     });
467 }
468
469 void WebResourceLoadStatisticsStore::logFrameNavigation(const WebFrameProxy& frame, const URL& pageURL, const WebCore::ResourceRequest& request, const URL& redirectURL)
470 {
471     ASSERT(RunLoop::isMain());
472
473     auto sourceURL = redirectURL;
474     bool isRedirect = !redirectURL.isNull();
475     if (!isRedirect) {
476         sourceURL = frame.url();
477         if (sourceURL.isNull())
478             sourceURL = pageURL;
479     }
480
481     auto& targetURL = request.url();
482
483     if (!targetURL.isValid() || !pageURL.isValid())
484         return;
485
486     auto targetHost = targetURL.host();
487     auto mainFrameHost = pageURL.host();
488
489     if (targetHost.isEmpty() || mainFrameHost.isEmpty() || targetHost == sourceURL.host())
490         return;
491
492     RegistrableDomain targetDomain { targetURL };
493     RegistrableDomain topFrameDomain { pageURL };
494     RegistrableDomain sourceDomain { sourceURL };
495
496     logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, frame.isMainFrame());
497 }
498
499 void WebResourceLoadStatisticsStore::logFrameNavigation(const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, const RegistrableDomain& sourceDomain, bool isRedirect, bool isMainFrame)
500 {
501     postTask([this, targetDomain = targetDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), sourceDomain = sourceDomain.isolatedCopy(), isRedirect, isMainFrame] {
502         if (m_statisticsStore)
503             m_statisticsStore->logFrameNavigation(targetDomain, topFrameDomain, sourceDomain, isRedirect, isMainFrame);
504     });
505 }
506
507 void WebResourceLoadStatisticsStore::logWebSocketLoading(const RegistrableDomain& targetDomain, const RegistrableDomain& topFrameDomain, WallTime lastSeen, CompletionHandler<void()>&& completionHandler)
508 {
509     postTask([this, targetDomain = targetDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), lastSeen, completionHandler = WTFMove(completionHandler)]() mutable {
510         if (m_statisticsStore)
511             m_statisticsStore->logSubresourceLoading(targetDomain, topFrameDomain, lastSeen);
512
513         postTaskReply(WTFMove(completionHandler));
514     });
515 }
516
517 void WebResourceLoadStatisticsStore::logSubresourceLoading(const SubResourceDomain& targetDomain, const TopFrameDomain& topFrameDomain, WallTime lastSeen, CompletionHandler<void()>&& completionHandler)
518 {
519     postTask([this, targetDomain = targetDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), lastSeen, completionHandler = WTFMove(completionHandler)]() mutable {
520         if (m_statisticsStore)
521             m_statisticsStore->logSubresourceLoading(targetDomain, topFrameDomain, lastSeen);
522
523         postTaskReply(WTFMove(completionHandler));
524     });
525 }
526
527 void WebResourceLoadStatisticsStore::logSubresourceRedirect(const RegistrableDomain& sourceDomain, const RegistrableDomain& targetDomain, CompletionHandler<void()>&& completionHandler)
528 {
529     postTask([this, sourceDomain = sourceDomain.isolatedCopy(), targetDomain = targetDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
530         if (m_statisticsStore)
531             m_statisticsStore->logSubresourceRedirect(sourceDomain, targetDomain);
532         postTaskReply(WTFMove(completionHandler));
533     });
534 }
535
536 void WebResourceLoadStatisticsStore::logUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
537 {
538     ASSERT(RunLoop::isMain());
539
540     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
541         if (m_statisticsStore)
542             m_statisticsStore->logUserInteraction(domain);
543         postTaskReply(WTFMove(completionHandler));
544     });
545 }
546
547 void WebResourceLoadStatisticsStore::logCrossSiteLoadWithLinkDecoration(const RegistrableDomain& fromDomain, const RegistrableDomain& toDomain, CompletionHandler<void()>&& completionHandler)
548 {
549     ASSERT(RunLoop::isMain());
550     ASSERT(fromDomain != toDomain);
551     
552     postTask([this, fromDomain = fromDomain.isolatedCopy(), toDomain = toDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
553         if (m_statisticsStore)
554             m_statisticsStore->logCrossSiteLoadWithLinkDecoration(fromDomain, toDomain);
555         postTaskReply(WTFMove(completionHandler));
556     });
557 }
558
559 void WebResourceLoadStatisticsStore::clearUserInteraction(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
560 {
561     ASSERT(RunLoop::isMain());
562     
563     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
564         if (m_statisticsStore)
565             m_statisticsStore->clearUserInteraction(domain);
566         postTaskReply(WTFMove(completionHandler));
567     });
568 }
569
570 void WebResourceLoadStatisticsStore::hasHadUserInteraction(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
571 {
572     postTask([this, domain, completionHandler = WTFMove(completionHandler)]() mutable {
573         bool hadUserInteraction = m_statisticsStore ? m_statisticsStore->hasHadUserInteraction(domain, OperatingDatesWindow::Long) : false;
574         postTaskReply([hadUserInteraction, completionHandler = WTFMove(completionHandler)]() mutable {
575             completionHandler(hadUserInteraction);
576         });
577     });
578 }
579
580 void WebResourceLoadStatisticsStore::setLastSeen(const RegistrableDomain& domain, Seconds seconds, CompletionHandler<void()>&& completionHandler)
581 {
582     ASSERT(RunLoop::isMain());
583     
584     postTask([this, domain = domain.isolatedCopy(), seconds, completionHandler = WTFMove(completionHandler)]() mutable {
585         if (m_statisticsStore)
586             m_statisticsStore->setLastSeen(domain, seconds);
587         postTaskReply(WTFMove(completionHandler));
588     });
589 }
590     
591 void WebResourceLoadStatisticsStore::setPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
592 {
593     ASSERT(RunLoop::isMain());
594
595     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
596         if (m_statisticsStore)
597             m_statisticsStore->setPrevalentResource(domain);
598         postTaskReply(WTFMove(completionHandler));
599     });
600 }
601
602 void WebResourceLoadStatisticsStore::setVeryPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
603 {
604     ASSERT(RunLoop::isMain());
605
606     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
607         if (m_statisticsStore)
608             m_statisticsStore->setVeryPrevalentResource(domain);
609         postTaskReply(WTFMove(completionHandler));
610     });
611 }
612     
613 void WebResourceLoadStatisticsStore::dumpResourceLoadStatistics(CompletionHandler<void(String)>&& completionHandler)
614 {
615     ASSERT(RunLoop::isMain());
616
617     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
618         ASSERT(!m_dumpResourceLoadStatisticsCompletionHandler);
619         m_dumpResourceLoadStatisticsCompletionHandler = WTFMove(completionHandler);
620         if (m_statisticsStore && m_statisticsStore->dataRecordsBeingRemoved())
621             return;
622         tryDumpResourceLoadStatistics();
623     });
624 }
625
626 void WebResourceLoadStatisticsStore::tryDumpResourceLoadStatistics()
627 {
628     ASSERT(!RunLoop::isMain());
629
630     if (!m_dumpResourceLoadStatisticsCompletionHandler)
631         return;
632
633     String result = m_statisticsStore ? m_statisticsStore->dumpResourceLoadStatistics() : emptyString();
634     postTaskReply([result = result.isolatedCopy(), completionHandler = WTFMove(m_dumpResourceLoadStatisticsCompletionHandler)]() mutable {
635         completionHandler(result);
636     });
637 }
638
639 void WebResourceLoadStatisticsStore::isPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
640 {
641     ASSERT(RunLoop::isMain());
642     
643     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
644         bool isPrevalentResource = m_statisticsStore ? m_statisticsStore->isPrevalentResource(domain) : false;
645         postTaskReply([isPrevalentResource, completionHandler = WTFMove(completionHandler)]() mutable {
646             completionHandler(isPrevalentResource);
647         });
648     });
649 }
650     
651 void WebResourceLoadStatisticsStore::isVeryPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
652 {
653     ASSERT(RunLoop::isMain());
654     
655     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
656         bool isVeryPrevalentResource = m_statisticsStore ? m_statisticsStore->isVeryPrevalentResource(domain) : false;
657         postTaskReply([isVeryPrevalentResource, completionHandler = WTFMove(completionHandler)]() mutable {
658             completionHandler(isVeryPrevalentResource);
659         });
660     });
661 }
662
663 void WebResourceLoadStatisticsStore::isRegisteredAsSubresourceUnder(const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
664 {
665     ASSERT(RunLoop::isMain());
666
667     postTask([this, subresourceDomain = subresourceDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
668         bool isRegisteredAsSubresourceUnder = m_statisticsStore ? m_statisticsStore->isRegisteredAsSubresourceUnder(subresourceDomain, topFrameDomain)
669             : false;
670         postTaskReply([isRegisteredAsSubresourceUnder, completionHandler = WTFMove(completionHandler)]() mutable {
671             completionHandler(isRegisteredAsSubresourceUnder);
672         });
673     });
674 }
675
676 void WebResourceLoadStatisticsStore::isRegisteredAsSubFrameUnder(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void(bool)>&& completionHandler)
677 {
678     ASSERT(RunLoop::isMain());
679
680     postTask([this, subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
681         bool isRegisteredAsSubFrameUnder = m_statisticsStore ? m_statisticsStore->isRegisteredAsSubFrameUnder(subFrameDomain, topFrameDomain)
682             : false;
683         postTaskReply([isRegisteredAsSubFrameUnder, completionHandler = WTFMove(completionHandler)]() mutable {
684             completionHandler(isRegisteredAsSubFrameUnder);
685         });
686     });
687 }
688
689 void WebResourceLoadStatisticsStore::isRegisteredAsRedirectingTo(const RegistrableDomain& domainRedirectedFrom, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void(bool)>&& completionHandler)
690 {
691     ASSERT(RunLoop::isMain());
692
693     postTask([this, domainRedirectedFrom = domainRedirectedFrom.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
694         bool isRegisteredAsRedirectingTo = m_statisticsStore ? m_statisticsStore->isRegisteredAsRedirectingTo(domainRedirectedFrom, domainRedirectedTo)
695             : false;
696         postTaskReply([isRegisteredAsRedirectingTo, completionHandler = WTFMove(completionHandler)]() mutable {
697             completionHandler(isRegisteredAsRedirectingTo);
698         });
699     });
700 }
701
702 void WebResourceLoadStatisticsStore::clearPrevalentResource(const RegistrableDomain& domain, CompletionHandler<void()>&& completionHandler)
703 {
704     ASSERT(RunLoop::isMain());
705     
706     postTask([this, domain = domain.isolatedCopy(), completionHandler = WTFMove(completionHandler)]() mutable {
707         if (m_statisticsStore)
708             m_statisticsStore->clearPrevalentResource(domain);
709         postTaskReply(WTFMove(completionHandler));
710     });
711 }
712
713 void WebResourceLoadStatisticsStore::setGrandfathered(const RegistrableDomain& domain, bool value, CompletionHandler<void()>&& completionHandler)
714 {
715     ASSERT(RunLoop::isMain());
716
717     postTask([this, domain = domain.isolatedCopy(), value, completionHandler = WTFMove(completionHandler)]() mutable {
718         if (m_statisticsStore)
719             m_statisticsStore->setGrandfathered(domain, value);
720         postTaskReply(WTFMove(completionHandler));
721     });
722 }
723     
724 void WebResourceLoadStatisticsStore::isGrandfathered(const RegistrableDomain& domain, CompletionHandler<void(bool)>&& completionHandler)
725 {
726     ASSERT(RunLoop::isMain());
727
728     postTask([this, completionHandler = WTFMove(completionHandler), domain = domain.isolatedCopy()]() mutable {
729         bool isGrandFathered = m_statisticsStore ? m_statisticsStore->isGrandfathered(domain)
730             : false;
731         postTaskReply([isGrandFathered, completionHandler = WTFMove(completionHandler)]() mutable {
732             completionHandler(isGrandFathered);
733         });
734     });
735 }
736
737 void WebResourceLoadStatisticsStore::setSubframeUnderTopFrameDomain(const RegistrableDomain& subFrameDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
738 {
739     ASSERT(RunLoop::isMain());
740     
741     postTask([this, completionHandler = WTFMove(completionHandler), subFrameDomain = subFrameDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy()]() mutable {
742         if (m_statisticsStore)
743             m_statisticsStore->setSubframeUnderTopFrameDomain(subFrameDomain, topFrameDomain);
744         postTaskReply(WTFMove(completionHandler));
745     });
746 }
747
748 void WebResourceLoadStatisticsStore::setSubresourceUnderTopFrameDomain(const RegistrableDomain& subresourceDomain, const RegistrableDomain& topFrameDomain, CompletionHandler<void()>&& completionHandler)
749 {
750     ASSERT(RunLoop::isMain());
751     
752     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), topFrameDomain = topFrameDomain.isolatedCopy()]() mutable {
753         if (m_statisticsStore)
754             m_statisticsStore->setSubresourceUnderTopFrameDomain(subresourceDomain, topFrameDomain);
755         postTaskReply(WTFMove(completionHandler));
756     });
757 }
758
759 void WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectTo(const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
760 {
761     ASSERT(RunLoop::isMain());
762     
763     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy()]() mutable {
764         if (m_statisticsStore)
765             m_statisticsStore->setSubresourceUniqueRedirectTo(subresourceDomain, domainRedirectedTo);
766         postTaskReply(WTFMove(completionHandler));
767     });
768 }
769
770 void WebResourceLoadStatisticsStore::setSubresourceUniqueRedirectFrom(const RegistrableDomain& subresourceDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
771 {
772     ASSERT(RunLoop::isMain());
773     
774     postTask([this, completionHandler = WTFMove(completionHandler), subresourceDomain = subresourceDomain.isolatedCopy(), domainRedirectedFrom = domainRedirectedFrom.isolatedCopy()]() mutable {
775         if (m_statisticsStore)
776             m_statisticsStore->setSubresourceUniqueRedirectFrom(subresourceDomain, domainRedirectedFrom);
777         postTaskReply(WTFMove(completionHandler));
778     });
779 }
780
781 void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectTo(const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedTo, CompletionHandler<void()>&& completionHandler)
782 {
783     ASSERT(RunLoop::isMain());
784     
785     postTask([this, completionHandler = WTFMove(completionHandler), topFrameDomain = topFrameDomain.isolatedCopy(), domainRedirectedTo = domainRedirectedTo.isolatedCopy()]() mutable {
786         if (m_statisticsStore)
787             m_statisticsStore->setTopFrameUniqueRedirectTo(topFrameDomain, domainRedirectedTo);
788         postTaskReply(WTFMove(completionHandler));
789     });
790 }
791
792 void WebResourceLoadStatisticsStore::setTopFrameUniqueRedirectFrom(const RegistrableDomain& topFrameDomain, const RegistrableDomain& domainRedirectedFrom, CompletionHandler<void()>&& completionHandler)
793 {
794     ASSERT(RunLoop::isMain());
795     
796     postTask([this, completionHandler = WTFMove(completionHandler), topFrameDomain = topFrameDomain.isolatedCopy(), domainRedirectedFrom = domainRedirectedFrom.isolatedCopy()]() mutable {
797         if (m_statisticsStore)
798             m_statisticsStore->setTopFrameUniqueRedirectFrom(topFrameDomain, domainRedirectedFrom);
799         postTaskReply(WTFMove(completionHandler));
800     });
801 }
802
803 void WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdate(CompletionHandler<void()>&& completionHandler)
804 {
805     // Helper function used by testing system. Should only be called from the main thread.
806     ASSERT(RunLoop::isMain());
807
808     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
809         if (!m_statisticsStore) {
810             postTaskReply(WTFMove(completionHandler));
811             return;
812         }
813
814         auto callbackAggregator = CallbackAggregator::create([completionHandler = WTFMove(completionHandler)] () mutable {
815             postTaskReply(WTFMove(completionHandler));
816         });
817         
818         if (m_statisticsStore)
819             m_statisticsStore->updateCookieBlocking([callbackAggregator = callbackAggregator.copyRef()]() { });
820     });
821 }
822
823 void WebResourceLoadStatisticsStore::scheduleCookieBlockingUpdateForDomains(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
824 {
825     // Helper function used by testing system. Should only be called from the main thread.
826     ASSERT(RunLoop::isMain());
827     postTask([this, domainsToBlock = crossThreadCopy(domainsToBlock), completionHandler = WTFMove(completionHandler)]() mutable {
828         if (!m_statisticsStore) {
829             postTaskReply(WTFMove(completionHandler));
830             return;
831         }
832
833         auto callbackAggregator = CallbackAggregator::create([completionHandler = WTFMove(completionHandler)] () mutable {
834             postTaskReply(WTFMove(completionHandler));
835         });
836
837         if (m_statisticsStore)
838             m_statisticsStore->updateCookieBlockingForDomains(domainsToBlock, [callbackAggregator = callbackAggregator.copyRef()]() { });
839     });
840 }
841
842 void WebResourceLoadStatisticsStore::scheduleClearBlockingStateForDomains(const Vector<RegistrableDomain>& domains, CompletionHandler<void()>&& completionHandler)
843 {
844     // Helper function used by testing system. Should only be called from the main thread.
845     ASSERT(RunLoop::isMain());
846     postTask([this, domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)]() mutable {
847         if (!m_statisticsStore) {
848             postTaskReply(WTFMove(completionHandler));
849             return;
850         }
851
852         auto callbackAggregator = CallbackAggregator::create([completionHandler = WTFMove(completionHandler)] () mutable {
853             postTaskReply(WTFMove(completionHandler));
854         });
855
856         if (m_statisticsStore)
857             m_statisticsStore->clearBlockingStateForDomains(domains, [callbackAggregator = callbackAggregator.copyRef()]() { });
858     });
859 }
860
861 void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& completionHandler)
862 {
863     ASSERT(RunLoop::isMain());
864     postTask([this, protectedThis = makeRef(*this), shouldGrandfather, completionHandler = WTFMove(completionHandler)]() mutable {
865         if (m_persistentStorage)
866             m_persistentStorage->clear();
867
868         if (!m_statisticsStore) {
869             if (shouldGrandfather == ShouldGrandfatherStatistics::Yes)
870                 RELEASE_LOG(ResourceLoadStatistics, "WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent Before being cleared, m_statisticsStore is null when trying to grandfather data.");
871
872             postTaskReply(WTFMove(completionHandler));
873             return;
874         }
875
876         auto callbackAggregator = CallbackAggregator::create([completionHandler = WTFMove(completionHandler)] () mutable {
877             postTaskReply(WTFMove(completionHandler));
878         });
879
880         if (m_statisticsStore) {
881             m_statisticsStore->clear([this, protectedThis = protectedThis.copyRef(), shouldGrandfather, callbackAggregator = callbackAggregator.copyRef()] () mutable {
882                 if (shouldGrandfather == ShouldGrandfatherStatistics::Yes) {
883                     if (m_statisticsStore)
884                         m_statisticsStore->grandfatherExistingWebsiteData([callbackAggregator = WTFMove(callbackAggregator)]() mutable { });
885                     else
886                         RELEASE_LOG(ResourceLoadStatistics, "WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent After being cleared, m_statisticsStore is null when trying to grandfather data.");
887                 }
888             });
889         }
890     });
891 }
892
893 void WebResourceLoadStatisticsStore::scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics shouldGrandfather, CompletionHandler<void()>&& callback)
894 {
895     ASSERT(RunLoop::isMain());
896
897     // For now, be conservative and clear everything regardless of modifiedSince.
898     UNUSED_PARAM(modifiedSince);
899     scheduleClearInMemoryAndPersistent(shouldGrandfather, WTFMove(callback));
900 }
901
902 void WebResourceLoadStatisticsStore::setTimeToLiveUserInteraction(Seconds seconds, CompletionHandler<void()>&& completionHandler)
903 {
904     ASSERT(RunLoop::isMain());
905     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable {
906         if (m_statisticsStore)
907             m_statisticsStore->setTimeToLiveUserInteraction(seconds);
908         postTaskReply(WTFMove(completionHandler));
909     });
910 }
911
912 void WebResourceLoadStatisticsStore::setMinimumTimeBetweenDataRecordsRemoval(Seconds seconds, CompletionHandler<void()>&& completionHandler)
913 {
914     ASSERT(RunLoop::isMain());
915     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable  {
916         if (m_statisticsStore)
917             m_statisticsStore->setMinimumTimeBetweenDataRecordsRemoval(seconds);
918
919         postTaskReply(WTFMove(completionHandler));
920     });
921 }
922
923 void WebResourceLoadStatisticsStore::setGrandfatheringTime(Seconds seconds, CompletionHandler<void()>&& completionHandler)
924 {
925     ASSERT(RunLoop::isMain());
926     postTask([this, seconds, completionHandler = WTFMove(completionHandler)]() mutable  {
927         if (m_statisticsStore)
928             m_statisticsStore->setGrandfatheringTime(seconds);
929
930         postTaskReply(WTFMove(completionHandler));
931     });
932 }
933
934 void WebResourceLoadStatisticsStore::setCacheMaxAgeCap(Seconds seconds, CompletionHandler<void()>&& completionHandler)
935 {
936     ASSERT(RunLoop::isMain());
937     ASSERT(seconds >= 0_s);
938     
939     if (m_networkSession)
940         m_networkSession->networkStorageSession().setCacheMaxAgeCapForPrevalentResources(seconds);
941
942     completionHandler();
943 }
944
945 void WebResourceLoadStatisticsStore::callUpdatePrevalentDomainsToBlockCookiesForHandler(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&& completionHandler)
946 {
947     ASSERT(RunLoop::isMain());
948
949     if (m_networkSession)
950         m_networkSession->networkStorageSession().setPrevalentDomainsToBlockCookiesFor(domainsToBlock);
951
952     completionHandler();
953 }
954
955 void WebResourceLoadStatisticsStore::removePrevalentDomains(const Vector<RegistrableDomain>& domains)
956 {
957     if (m_networkSession)
958         m_networkSession->networkStorageSession().removePrevalentDomains(domains);
959 }
960
961 void WebResourceLoadStatisticsStore::callRemoveDomainsHandler(const Vector<RegistrableDomain>& domains)
962 {
963     ASSERT(RunLoop::isMain());
964
965     removePrevalentDomains(domains);
966 }
967     
968 void WebResourceLoadStatisticsStore::setMaxStatisticsEntries(size_t maximumEntryCount, CompletionHandler<void()>&& completionHandler)
969 {
970     ASSERT(RunLoop::isMain());
971     postTask([this, maximumEntryCount, completionHandler = WTFMove(completionHandler)]() mutable  {
972         if (m_statisticsStore)
973             m_statisticsStore->setMaxStatisticsEntries(maximumEntryCount);
974
975         postTaskReply(WTFMove(completionHandler));
976     });
977 }
978     
979 void WebResourceLoadStatisticsStore::setPruneEntriesDownTo(size_t pruneTargetCount, CompletionHandler<void()>&& completionHandler)
980 {
981     ASSERT(RunLoop::isMain());
982
983     postTask([this, pruneTargetCount, completionHandler = WTFMove(completionHandler)]() mutable  {
984         if (m_statisticsStore)
985             m_statisticsStore->setPruneEntriesDownTo(pruneTargetCount);
986
987         postTaskReply(WTFMove(completionHandler));
988     });
989 }
990
991 void WebResourceLoadStatisticsStore::resetParametersToDefaultValues(CompletionHandler<void()>&& completionHandler)
992 {
993     ASSERT(RunLoop::isMain());
994
995     postTask([this, completionHandler = WTFMove(completionHandler)]() mutable {
996         if (m_statisticsStore)
997             m_statisticsStore->resetParametersToDefaultValues();
998
999         postTaskReply(WTFMove(completionHandler));
1000     });
1001 }
1002
1003 void WebResourceLoadStatisticsStore::logTestingEvent(const String& event)
1004 {
1005     ASSERT(RunLoop::isMain());
1006
1007     if (m_networkSession)
1008         m_networkSession->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::LogTestingEvent(m_networkSession->sessionID(), event), 0);
1009 }
1010
1011 void WebResourceLoadStatisticsStore::notifyResourceLoadStatisticsProcessed()
1012 {
1013     ASSERT(RunLoop::isMain());
1014     
1015     if (m_networkSession)
1016         m_networkSession->notifyResourceLoadStatisticsProcessed();
1017 }
1018
1019 NetworkSession* WebResourceLoadStatisticsStore::networkSession()
1020 {
1021     return m_networkSession.get();
1022 }
1023
1024 void WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domainsToRemoveWebsiteDataFor, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1025 {
1026     ASSERT(RunLoop::isMain());
1027     
1028     if (m_networkSession) {
1029         m_networkSession->deleteWebsiteDataForRegistrableDomains(dataTypes, WTFMove(domainsToRemoveWebsiteDataFor), shouldNotifyPage, WTFMove(completionHandler));
1030         return;
1031     }
1032
1033     completionHandler({ });
1034 }
1035
1036 void WebResourceLoadStatisticsStore::registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1037 {
1038     ASSERT(RunLoop::isMain());
1039     
1040     if (m_networkSession) {
1041         m_networkSession->registrableDomainsWithWebsiteData(dataTypes, shouldNotifyPage, WTFMove(completionHandler));
1042         return;
1043     }
1044
1045     completionHandler({ });
1046 }
1047
1048 void WebResourceLoadStatisticsStore::sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample shouldSample) const
1049 {
1050     if (m_networkSession)
1051         const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->logDiagnosticMessageWithValue(message, description, value, sigDigits, shouldSample);
1052 }
1053
1054 void WebResourceLoadStatisticsStore::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const
1055 {
1056     if (m_networkSession)
1057         const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->notifyPageStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
1058 }
1059
1060 } // namespace WebKit
1061
1062 #endif