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#pragma once
27
28#if ENABLE(RESOURCE_LOAD_STATISTICS)
29
30#include "Connection.h"
31#include "StorageAccessStatus.h"
32#include "WebsiteDataType.h"
33#include <WebCore/PageIdentifier.h>
34#include <WebCore/RegistrableDomain.h>
35#include <wtf/CompletionHandler.h>
36#include <wtf/RunLoop.h>
37#include <wtf/ThreadSafeRefCounted.h>
38#include <wtf/Vector.h>
39#include <wtf/WallTime.h>
40#include <wtf/WeakPtr.h>
41#include <wtf/text/WTFString.h>
42
43namespace WTF {
44class WorkQueue;
45}
46
47namespace WebCore {
48class ResourceRequest;
49struct ResourceLoadStatistics;
50enum class ShouldSample : bool;
51enum class IncludeHttpOnlyCookies : bool;
52enum class StorageAccessPromptWasShown : bool;
53enum class StorageAccessWasGranted : bool;
54}
55
56namespace WebKit {
57
58class NetworkSession;
59class ResourceLoadStatisticsStore;
60class ResourceLoadStatisticsPersistentStorage;
61class WebFrameProxy;
62class WebProcessProxy;
63enum class ShouldGrandfatherStatistics : bool;
64enum class ShouldIncludeLocalhost : bool { No, Yes };
65enum class EnableResourceLoadStatisticsDebugMode : bool { No, Yes };
66enum class WebsiteDataToRemove : uint8_t {
67 All,
68 AllButHttpOnlyCookies,
69 AllButCookies
70};
71
72class WebResourceLoadStatisticsStore final : public ThreadSafeRefCounted<WebResourceLoadStatisticsStore, WTF::DestructionThread::Main> {
73public:
74 using ResourceLoadStatistics = WebCore::ResourceLoadStatistics;
75 using RegistrableDomain = WebCore::RegistrableDomain;
76 using TopFrameDomain = WebCore::RegistrableDomain;
77 using SubFrameDomain = WebCore::RegistrableDomain;
78 using SubResourceDomain = WebCore::RegistrableDomain;
79 using RedirectDomain = WebCore::RegistrableDomain;
80 using RedirectedFromDomain = WebCore::RegistrableDomain;
81 using RedirectedToDomain = WebCore::RegistrableDomain;
82 using NavigatedFromDomain = WebCore::RegistrableDomain;
83 using NavigatedToDomain = WebCore::RegistrableDomain;
84 using DomainInNeedOfStorageAccess = WebCore::RegistrableDomain;
85 using OpenerDomain = WebCore::RegistrableDomain;
86 using FrameID = uint64_t;
87 using StorageAccessWasGranted = WebCore::StorageAccessWasGranted;
88 using StorageAccessPromptWasShown = WebCore::StorageAccessPromptWasShown;
89
90 static Ref<WebResourceLoadStatisticsStore> create(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost)
91 {
92 return adoptRef(*new WebResourceLoadStatisticsStore(networkSession, resourceLoadStatisticsDirectory, shouldIncludeLocalhost));
93 }
94
95 ~WebResourceLoadStatisticsStore();
96
97 static const OptionSet<WebsiteDataType>& monitoredDataTypes();
98
99 WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }
100
101 void setNotifyPagesWhenDataRecordsWereScanned(bool);
102 void setNotifyPagesWhenTelemetryWasCaptured(bool, CompletionHandler<void()>&&);
103 void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool, CompletionHandler<void()>&&);
104 void setShouldSubmitTelemetry(bool);
105
106 void grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, FrameID, WebCore::PageIdentifier, StorageAccessPromptWasShown, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&&);
107
108 void applicationWillTerminate();
109
110 void logFrameNavigation(const WebFrameProxy&, const URL& pageURL, const WebCore::ResourceRequest&, const URL& redirectURL);
111 void logFrameNavigation(const NavigatedToDomain&, const TopFrameDomain&, const NavigatedFromDomain&, bool isRedirect, bool isMainFrame);
112 void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
113 void logWebSocketLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen, CompletionHandler<void()>&&);
114 void logSubresourceLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen, CompletionHandler<void()>&&);
115 void logSubresourceRedirect(const RedirectedFromDomain&, const RedirectedToDomain&, CompletionHandler<void()>&&);
116 void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&, CompletionHandler<void()>&&);
117 void clearUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
118 void deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType>, HashMap<RegistrableDomain, WebsiteDataToRemove>&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
119 void registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType>, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&&);
120 StorageAccessWasGranted grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, WebCore::PageIdentifier);
121 void hasHadUserInteraction(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
122 void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
123 bool hasStorageAccessForFrame(const SubFrameDomain&, const TopFrameDomain&, FrameID, WebCore::PageIdentifier);
124 void requestStorageAccess(const SubFrameDomain&, const TopFrameDomain&, FrameID, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&&);
125 void setLastSeen(const RegistrableDomain&, Seconds, CompletionHandler<void()>&&);
126 void setPrevalentResource(const RegistrableDomain&, CompletionHandler<void()>&&);
127 void setVeryPrevalentResource(const RegistrableDomain&, CompletionHandler<void()>&&);
128 void dumpResourceLoadStatistics(CompletionHandler<void(String)>&&);
129 void tryDumpResourceLoadStatistics();
130 void isPrevalentResource(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
131 void isVeryPrevalentResource(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
132 void isRegisteredAsSubresourceUnder(const SubResourceDomain&, const TopFrameDomain&, CompletionHandler<void(bool)>&&);
133 void isRegisteredAsSubFrameUnder(const SubFrameDomain&, const TopFrameDomain&, CompletionHandler<void(bool)>&&);
134 void isRegisteredAsRedirectingTo(const RedirectedFromDomain&, const RedirectedToDomain&, CompletionHandler<void(bool)>&&);
135 void clearPrevalentResource(const RegistrableDomain&, CompletionHandler<void()>&&);
136 void setGrandfathered(const RegistrableDomain&, bool, CompletionHandler<void()>&&);
137 void isGrandfathered(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
138 void removePrevalentDomains(const Vector<RegistrableDomain>&);
139 void setNotifyPagesWhenDataRecordsWereScanned(bool, CompletionHandler<void()>&&);
140 void setIsRunningTest(bool, CompletionHandler<void()>&&);
141 void setSubframeUnderTopFrameDomain(const SubFrameDomain&, const TopFrameDomain&, CompletionHandler<void()>&&);
142 void setSubresourceUnderTopFrameDomain(const SubResourceDomain&, const TopFrameDomain&, CompletionHandler<void()>&&);
143 void setSubresourceUniqueRedirectTo(const SubResourceDomain&, const RedirectedToDomain&, CompletionHandler<void()>&&);
144 void setSubresourceUniqueRedirectFrom(const SubResourceDomain&, const RedirectedFromDomain&, CompletionHandler<void()>&&);
145 void setTopFrameUniqueRedirectTo(const TopFrameDomain&, const RedirectedToDomain&, CompletionHandler<void()>&&);
146 void setTopFrameUniqueRedirectFrom(const TopFrameDomain&, const RedirectedFromDomain&, CompletionHandler<void()>&&);
147 void scheduleCookieBlockingUpdate(CompletionHandler<void()>&&);
148 void scheduleCookieBlockingUpdateForDomains(const Vector<RegistrableDomain>&, CompletionHandler<void()>&&);
149 void scheduleClearBlockingStateForDomains(const Vector<RegistrableDomain>&, CompletionHandler<void()>&&);
150 void scheduleStatisticsAndDataRecordsProcessing(CompletionHandler<void()>&&);
151 void submitTelemetry(CompletionHandler<void()>&&);
152 void scheduleClearInMemoryAndPersistent(ShouldGrandfatherStatistics, CompletionHandler<void()>&&);
153 void scheduleClearInMemoryAndPersistent(WallTime modifiedSince, ShouldGrandfatherStatistics, CompletionHandler<void()>&&);
154
155 void setTimeToLiveUserInteraction(Seconds, CompletionHandler<void()>&&);
156 void setMinimumTimeBetweenDataRecordsRemoval(Seconds, CompletionHandler<void()>&&);
157 void setGrandfatheringTime(Seconds, CompletionHandler<void()>&&);
158 void setCacheMaxAgeCap(Seconds, CompletionHandler<void()>&&);
159 void setMaxStatisticsEntries(size_t, CompletionHandler<void()>&&);
160 void setPruneEntriesDownTo(size_t, CompletionHandler<void()>&&);
161
162 void resetParametersToDefaultValues(CompletionHandler<void()>&&);
163
164 void setResourceLoadStatisticsDebugMode(bool, CompletionHandler<void()>&&);
165 void setPrevalentResourceForDebugMode(const RegistrableDomain&, CompletionHandler<void()>&&);
166
167 void logTestingEvent(const String&);
168 void callGrantStorageAccessHandler(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessWasGranted)>&&);
169 void removeAllStorageAccess(CompletionHandler<void()>&&);
170 void callUpdatePrevalentDomainsToBlockCookiesForHandler(const Vector<RegistrableDomain>&, CompletionHandler<void()>&&);
171 void callRemoveDomainsHandler(const Vector<RegistrableDomain>&);
172 void callHasStorageAccessForFrameHandler(const SubFrameDomain&, const TopFrameDomain&, FrameID, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&);
173
174 void didCreateNetworkProcess();
175
176 void notifyResourceLoadStatisticsProcessed();
177
178 NetworkSession* networkSession();
179 void invalidateAndCancel();
180
181 void sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample) const;
182 void notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const;
183
184 void resourceLoadStatisticsUpdated(Vector<ResourceLoadStatistics>&&);
185 void requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&&, WebCore::PageIdentifier openerID, OpenerDomain&&);
186
187private:
188 explicit WebResourceLoadStatisticsStore(NetworkSession&, const String&, ShouldIncludeLocalhost);
189
190 void postTask(WTF::Function<void()>&&);
191 static void postTaskReply(WTF::Function<void()>&&);
192
193 void performDailyTasks();
194
195 StorageAccessStatus storageAccessStatus(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain);
196
197 void flushAndDestroyPersistentStore();
198
199 WeakPtr<NetworkSession> m_networkSession;
200 Ref<WorkQueue> m_statisticsQueue;
201 std::unique_ptr<ResourceLoadStatisticsStore> m_statisticsStore;
202 std::unique_ptr<ResourceLoadStatisticsPersistentStorage> m_persistentStorage;
203
204 RunLoop::Timer<WebResourceLoadStatisticsStore> m_dailyTasksTimer;
205
206 bool m_hasScheduledProcessStats { false };
207
208 bool m_firstNetworkProcessCreated { false };
209
210 CompletionHandler<void(String)> m_dumpResourceLoadStatisticsCompletionHandler;
211};
212
213} // namespace WebKit
214
215#endif
216