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/RegistrableDomain.h>
34#include <wtf/CompletionHandler.h>
35#include <wtf/RunLoop.h>
36#include <wtf/ThreadSafeRefCounted.h>
37#include <wtf/Vector.h>
38#include <wtf/WallTime.h>
39#include <wtf/WeakPtr.h>
40#include <wtf/text/WTFString.h>
41
42namespace WTF {
43class WorkQueue;
44}
45
46namespace WebCore {
47class ResourceRequest;
48struct ResourceLoadStatistics;
49enum class ShouldSample : bool;
50enum class IncludeHttpOnlyCookies : bool;
51enum class StorageAccessPromptWasShown : bool;
52enum class StorageAccessWasGranted : bool;
53}
54
55namespace WebKit {
56
57class NetworkSession;
58class ResourceLoadStatisticsStore;
59class ResourceLoadStatisticsPersistentStorage;
60class WebFrameProxy;
61class WebProcessProxy;
62enum class ShouldGrandfatherStatistics : bool;
63enum class ShouldIncludeLocalhost : bool { No, Yes };
64enum class EnableResourceLoadStatisticsDebugMode : bool { No, Yes };
65enum class WebsiteDataToRemove : uint8_t {
66 All,
67 AllButHttpOnlyCookies,
68 AllButCookies
69};
70
71class WebResourceLoadStatisticsStore final : public ThreadSafeRefCounted<WebResourceLoadStatisticsStore, WTF::DestructionThread::Main> {
72public:
73 using ResourceLoadStatistics = WebCore::ResourceLoadStatistics;
74 using RegistrableDomain = WebCore::RegistrableDomain;
75 using TopFrameDomain = WebCore::RegistrableDomain;
76 using SubFrameDomain = WebCore::RegistrableDomain;
77 using SubResourceDomain = WebCore::RegistrableDomain;
78 using RedirectDomain = WebCore::RegistrableDomain;
79 using RedirectedFromDomain = WebCore::RegistrableDomain;
80 using RedirectedToDomain = WebCore::RegistrableDomain;
81 using NavigatedFromDomain = WebCore::RegistrableDomain;
82 using NavigatedToDomain = WebCore::RegistrableDomain;
83 using DomainInNeedOfStorageAccess = WebCore::RegistrableDomain;
84 using OpenerDomain = WebCore::RegistrableDomain;
85 using OpenerPageID = uint64_t;
86 using PageID = uint64_t;
87 using FrameID = uint64_t;
88 using StorageAccessWasGranted = WebCore::StorageAccessWasGranted;
89 using StorageAccessPromptWasShown = WebCore::StorageAccessPromptWasShown;
90
91 static Ref<WebResourceLoadStatisticsStore> create(NetworkSession& networkSession, const String& resourceLoadStatisticsDirectory, ShouldIncludeLocalhost shouldIncludeLocalhost)
92 {
93 return adoptRef(*new WebResourceLoadStatisticsStore(networkSession, resourceLoadStatisticsDirectory, shouldIncludeLocalhost));
94 }
95
96 ~WebResourceLoadStatisticsStore();
97
98 static const OptionSet<WebsiteDataType>& monitoredDataTypes();
99
100 WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }
101
102 void setNotifyPagesWhenDataRecordsWereScanned(bool);
103 void setNotifyPagesWhenTelemetryWasCaptured(bool, CompletionHandler<void()>&&);
104 void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool, CompletionHandler<void()>&&);
105 void setShouldSubmitTelemetry(bool);
106
107 void grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, FrameID, PageID, StorageAccessPromptWasShown, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&&);
108
109 void applicationWillTerminate();
110
111 void logFrameNavigation(const WebFrameProxy&, const URL& pageURL, const WebCore::ResourceRequest&, const URL& redirectURL);
112 void logFrameNavigation(const NavigatedToDomain&, const TopFrameDomain&, const NavigatedFromDomain&, bool isRedirect, bool isMainFrame);
113 void logUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
114 void logWebSocketLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen, CompletionHandler<void()>&&);
115 void logSubresourceLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen, CompletionHandler<void()>&&);
116 void logSubresourceRedirect(const RedirectedFromDomain&, const RedirectedToDomain&, CompletionHandler<void()>&&);
117 void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&, CompletionHandler<void()>&&);
118 void clearUserInteraction(const TopFrameDomain&, CompletionHandler<void()>&&);
119 void deleteWebsiteDataForRegistrableDomains(OptionSet<WebsiteDataType>, HashMap<RegistrableDomain, WebsiteDataToRemove>&&, bool shouldNotifyPage, CompletionHandler<void(const HashSet<RegistrableDomain>&)>&&);
120 void registrableDomainsWithWebsiteData(OptionSet<WebsiteDataType>, bool shouldNotifyPage, CompletionHandler<void(HashSet<RegistrableDomain>&&)>&&);
121 StorageAccessWasGranted grantStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, PageID);
122 void hasHadUserInteraction(const RegistrableDomain&, CompletionHandler<void(bool)>&&);
123 void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, PageID, CompletionHandler<void(bool)>&&);
124 bool hasStorageAccessForFrame(const SubFrameDomain&, const TopFrameDomain&, FrameID, PageID);
125 void requestStorageAccess(const SubFrameDomain&, const TopFrameDomain&, FrameID, PageID, CompletionHandler<void(StorageAccessWasGranted, StorageAccessPromptWasShown)>&&);
126 void setLastSeen(const RegistrableDomain&, Seconds, CompletionHandler<void()>&&);
127 void setPrevalentResource(const RegistrableDomain&, CompletionHandler<void()>&&);
128 void setVeryPrevalentResource(const RegistrableDomain&, CompletionHandler<void()>&&);
129 void dumpResourceLoadStatistics(CompletionHandler<void(String)>&&);
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>, PageID, 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, PageID, CompletionHandler<void(bool)>&&);
173
174 void didCreateNetworkProcess();
175
176 void notifyResourceLoadStatisticsProcessed();
177
178 NetworkSession* networkSession() { return m_networkSession.get(); }
179
180 void sendDiagnosticMessageWithValue(const String& message, const String& description, unsigned value, unsigned sigDigits, WebCore::ShouldSample) const;
181 void notifyPageStatisticsTelemetryFinished(unsigned totalPrevalentResources, unsigned totalPrevalentResourcesWithUserInteraction, unsigned top3SubframeUnderTopFrameOrigins) const;
182
183 void resourceLoadStatisticsUpdated(Vector<ResourceLoadStatistics>&&);
184 void requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&&, uint64_t openerPageID, OpenerDomain&&);
185
186private:
187 explicit WebResourceLoadStatisticsStore(NetworkSession&, const String&, ShouldIncludeLocalhost);
188
189 void postTask(WTF::Function<void()>&&);
190 static void postTaskReply(WTF::Function<void()>&&);
191
192 void performDailyTasks();
193
194 StorageAccessStatus storageAccessStatus(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain);
195
196 void flushAndDestroyPersistentStore();
197
198 WeakPtr<NetworkSession> m_networkSession;
199 Ref<WorkQueue> m_statisticsQueue;
200 std::unique_ptr<ResourceLoadStatisticsStore> m_statisticsStore;
201 std::unique_ptr<ResourceLoadStatisticsPersistentStorage> m_persistentStorage;
202
203 RunLoop::Timer<WebResourceLoadStatisticsStore> m_dailyTasksTimer;
204
205 bool m_hasScheduledProcessStats { false };
206
207 bool m_firstNetworkProcessCreated { false };
208};
209
210} // namespace WebKit
211
212#endif
213