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 | |
43 | namespace WTF { |
44 | class WorkQueue; |
45 | } |
46 | |
47 | namespace WebCore { |
48 | class ResourceRequest; |
49 | struct ResourceLoadStatistics; |
50 | enum class ShouldSample : bool; |
51 | enum class IncludeHttpOnlyCookies : bool; |
52 | enum class StorageAccessPromptWasShown : bool; |
53 | enum class StorageAccessWasGranted : bool; |
54 | } |
55 | |
56 | namespace WebKit { |
57 | |
58 | class NetworkSession; |
59 | class ResourceLoadStatisticsStore; |
60 | class ResourceLoadStatisticsPersistentStorage; |
61 | class WebFrameProxy; |
62 | class WebProcessProxy; |
63 | enum class ShouldGrandfatherStatistics : bool; |
64 | enum class ShouldIncludeLocalhost : bool { No, Yes }; |
65 | enum class EnableResourceLoadStatisticsDebugMode : bool { No, Yes }; |
66 | enum class WebsiteDataToRemove : uint8_t { |
67 | All, |
68 | AllButHttpOnlyCookies, |
69 | AllButCookies |
70 | }; |
71 | |
72 | class WebResourceLoadStatisticsStore final : public ThreadSafeRefCounted<WebResourceLoadStatisticsStore, WTF::DestructionThread::Main> { |
73 | public: |
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 | |
187 | private: |
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 | |