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
61namespace WebKit {
62using namespace WebCore;
63
64const 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
89void 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
99void 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
111void 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
123void 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
135void 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
145void WebResourceLoadStatisticsStore::setNotifyPagesWhenTelemetryWasCaptured(bool value, CompletionHandler<void()>&& completionHandler)
146{
147 ASSERT(RunLoop::isMain());
148
149 WebKit::WebResourceLoadStatisticsTelemetry::setNotifyPagesWhenTelemetryWasCaptured(value);
150 completionHandler();
151}
152
153WebResourceLoadStatisticsStore::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
180WebResourceLoadStatisticsStore::~WebResourceLoadStatisticsStore()
181{
182 ASSERT(RunLoop::isMain());
183
184 flushAndDestroyPersistentStore();
185}
186
187inline 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
195inline void WebResourceLoadStatisticsStore::postTaskReply(WTF::Function<void()>&& reply)
196{
197 ASSERT(!RunLoop::isMain());
198 RunLoop::main().dispatch(WTFMove(reply));
199}
200
201void 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
221void 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
232void 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
243void 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
254void 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
278void 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
301bool 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
306void 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
318void 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
365void 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
378void 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
399StorageAccessWasGranted 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
412void 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
419void WebResourceLoadStatisticsStore::didCreateNetworkProcess()
420{
421 ASSERT(RunLoop::isMain());
422
423 postTask([this] {
424 if (!m_statisticsStore)
425 return;
426 m_statisticsStore->didCreateNetworkProcess();
427 });
428}
429
430void 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
440void WebResourceLoadStatisticsStore::applicationWillTerminate()
441{
442 flushAndDestroyPersistentStore();
443}
444
445void 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
457void 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
469void 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
499void 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
507void 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
517void 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
527void 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
536void 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
547void 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
559void 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
570void 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
580void 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
591void 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
602void 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
613void 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
626void 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
639void 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
651void 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
663void 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
676void 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
689void 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
702void 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
713void 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
724void 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
737void 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
748void 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
759void 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
770void 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
781void 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
792void 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
803void 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
823void 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
842void 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
861void 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
893void 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
902void 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
912void 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
923void 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
934void 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
945void 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
955void WebResourceLoadStatisticsStore::removePrevalentDomains(const Vector<RegistrableDomain>& domains)
956{
957 if (m_networkSession)
958 m_networkSession->networkStorageSession().removePrevalentDomains(domains);
959}
960
961void WebResourceLoadStatisticsStore::callRemoveDomainsHandler(const Vector<RegistrableDomain>& domains)
962{
963 ASSERT(RunLoop::isMain());
964
965 removePrevalentDomains(domains);
966}
967
968void 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
979void 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
991void 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
1003void 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
1011void WebResourceLoadStatisticsStore::notifyResourceLoadStatisticsProcessed()
1012{
1013 ASSERT(RunLoop::isMain());
1014
1015 if (m_networkSession)
1016 m_networkSession->notifyResourceLoadStatisticsProcessed();
1017}
1018
1019NetworkSession* WebResourceLoadStatisticsStore::networkSession()
1020{
1021 return m_networkSession.get();
1022}
1023
1024void WebResourceLoadStatisticsStore::invalidateAndCancel()
1025{
1026 m_networkSession = nullptr;
1027}
1028
1029void WebResourceLoadStatisticsStore::deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType> dataTypes, HashMap<RegistrableDomain, WebsiteDataToRemove>&& domainsToRemoveWebsiteDataFor, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&& completionHandler)
1030{
1031 ASSERT(RunLoop::isMain());
1032
1033 if (m_networkSession) {
1034 m_networkSession->deleteWebsiteDataForRegistrableDomains(dataTypes, WTFMove(domainsToRemoveWebsiteDataFor), shouldNotifyPage, WTFMove(completionHandler));
1035 return;
1036 }
1037
1038 completionHandler({ });
1039}
1040
1041void WebResourceLoadStatisticsStore::registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType> dataTypes, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&& completionHandler)
1042{
1043 ASSERT(RunLoop::isMain());
1044
1045 if (m_networkSession) {
1046 m_networkSession->registrableDomainsWithWebsiteData(dataTypes, shouldNotifyPage, WTFMove(completionHandler));
1047 return;
1048 }
1049
1050 completionHandler({ });
1051}
1052
1053void WebResourceLoadStatisticsStore::sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample shouldSample) const
1054{
1055 if (m_networkSession)
1056 const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->logDiagnosticMessageWithValue(message, description, value, sigDigits, shouldSample);
1057}
1058
1059void WebResourceLoadStatisticsStore::notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const
1060{
1061 if (m_networkSession)
1062 const_cast<WebResourceLoadStatisticsStore*>(this)->networkSession()->notifyPageStatisticsTelemetryFinished(totalPrevalentResources, totalPrevalentResourcesWithUserInteraction, top3SubframeUnderTopFrameOrigins);
1063}
1064
1065} // namespace WebKit
1066
1067#endif
1068