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::invalidateAndCancel() |
1025 | { |
1026 | m_networkSession = nullptr; |
1027 | } |
1028 | |
1029 | void 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 | |
1041 | void 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 | |
1053 | void 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 | |
1059 | void 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 | |