Resource Load Statistics: Make it possible exclude localhost from classification
[WebKit-https.git] / Source / WebKit / NetworkProcess / Classifier / ResourceLoadStatisticsStore.h
1 /*
2  * Copyright (C) 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 "ResourceLoadStatisticsClassifier.h"
31 #include "WebResourceLoadStatisticsStore.h"
32 #include <wtf/CompletionHandler.h>
33 #include <wtf/Vector.h>
34 #include <wtf/WeakPtr.h>
35 #include <wtf/WorkQueue.h>
36
37 #if HAVE(CORE_PREDICTION)
38 #include "ResourceLoadStatisticsClassifierCocoa.h"
39 #endif
40
41 namespace WebCore {
42 class KeyedDecoder;
43 class KeyedEncoder;
44 struct ResourceLoadStatistics;
45 }
46
47 namespace WebKit {
48
49 class ResourceLoadStatisticsPersistentStorage;
50
51 class OperatingDate {
52 public:
53     OperatingDate() = default;
54     
55     static OperatingDate fromWallTime(WallTime);
56     static OperatingDate today();
57     Seconds secondsSinceEpoch() const;
58     bool operator==(const OperatingDate& other) const;
59     bool operator<(const OperatingDate& other) const;
60     bool operator<=(const OperatingDate& other) const;
61     
62 private:
63     OperatingDate(int year, int month, int monthDay)
64         : m_year(year)
65         , m_month(month)
66         , m_monthDay(monthDay)
67     { }
68
69     int m_year { 0 };
70     int m_month { 0 }; // [0, 11].
71     int m_monthDay { 0 }; // [1, 31].
72 };
73
74 // This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
75 class ResourceLoadStatisticsStore : public CanMakeWeakPtr<ResourceLoadStatisticsStore> {
76 public:
77     using ResourceLoadStatistics = WebCore::ResourceLoadStatistics;
78     using RegistrableDomain = WebCore::RegistrableDomain;
79     using TopFrameDomain = WebCore::RegistrableDomain;
80     using SubFrameDomain = WebCore::RegistrableDomain;
81     using SubResourceDomain = WebCore::RegistrableDomain;
82     using RedirectDomain = WebCore::RegistrableDomain;
83     using RedirectedFromDomain = WebCore::RegistrableDomain;
84     using RedirectedToDomain = WebCore::RegistrableDomain;
85     using NavigatedFromDomain = WebCore::RegistrableDomain;
86     using NavigatedToDomain = WebCore::RegistrableDomain;
87     using DomainInNeedOfStorageAccess = WebCore::RegistrableDomain;
88     using OpenerDomain = WebCore::RegistrableDomain;
89     using OpenerPageID = uint64_t;
90     using PageID = uint64_t;
91     using FrameID = uint64_t;
92     
93     virtual ~ResourceLoadStatisticsStore();
94
95     virtual void clear(CompletionHandler<void()>&&) = 0;
96     virtual bool isEmpty() const = 0;
97
98     virtual void updateCookieBlocking(CompletionHandler<void()>&&) = 0;
99     void updateCookieBlockingForDomains(const Vector<RegistrableDomain>& domainsToBlock, CompletionHandler<void()>&&);
100     void clearBlockingStateForDomains(const Vector<RegistrableDomain>& domains, CompletionHandler<void()>&&);
101
102     void includeTodayAsOperatingDateIfNecessary();
103     void processStatisticsAndDataRecords();
104
105     virtual void classifyPrevalentResources() = 0;
106     virtual void syncStorageIfNeeded() = 0;
107     virtual void syncStorageImmediately() = 0;
108
109     virtual void requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&&, OpenerPageID, OpenerDomain&&) = 0;
110     void removeAllStorageAccess(CompletionHandler<void()>&&);
111
112     void grandfatherExistingWebsiteData(CompletionHandler<void()>&&);
113     void cancelPendingStatisticsProcessingRequest();
114
115     virtual bool isRegisteredAsSubresourceUnder(const SubResourceDomain&, const TopFrameDomain&) const = 0;
116     virtual bool isRegisteredAsSubFrameUnder(const SubFrameDomain&, const TopFrameDomain&) const = 0;
117     virtual bool isRegisteredAsRedirectingTo(const RedirectedFromDomain&, const RedirectedToDomain&) const = 0;
118
119     virtual void clearPrevalentResource(const RegistrableDomain&) = 0;
120     virtual String dumpResourceLoadStatistics() const = 0;
121     virtual bool isPrevalentResource(const RegistrableDomain&) const = 0;
122     virtual bool isVeryPrevalentResource(const RegistrableDomain&) const = 0;
123     virtual void setPrevalentResource(const RegistrableDomain&) = 0;
124     virtual void setVeryPrevalentResource(const RegistrableDomain&) = 0;
125
126     virtual void setGrandfathered(const RegistrableDomain&, bool value) = 0;
127     virtual bool isGrandfathered(const RegistrableDomain&) const = 0;
128
129     virtual void incrementRecordsDeletedCountForDomains(HashSet<RegistrableDomain>&&) = 0;
130     virtual void grandfatherDataForDomains(const HashSet<RegistrableDomain>&) = 0;
131
132     virtual void setSubframeUnderTopFrameDomain(const SubFrameDomain&, const TopFrameDomain&) = 0;
133     virtual void setSubresourceUnderTopFrameDomain(const SubResourceDomain&, const TopFrameDomain&) = 0;
134     virtual void setSubresourceUniqueRedirectTo(const SubResourceDomain&, const RedirectDomain&) = 0;
135     virtual void setSubresourceUniqueRedirectFrom(const SubResourceDomain&, const RedirectDomain&) = 0;
136     virtual void setTopFrameUniqueRedirectTo(const TopFrameDomain&, const RedirectDomain&) = 0;
137     virtual void setTopFrameUniqueRedirectFrom(const TopFrameDomain&, const RedirectDomain&) = 0;
138
139     void logTestingEvent(const String&);
140
141     void setMaxStatisticsEntries(size_t maximumEntryCount);
142     void setPruneEntriesDownTo(size_t pruneTargetCount);
143     void resetParametersToDefaultValues();
144     Optional<Seconds> statisticsEpirationTime() const;
145
146     virtual void calculateAndSubmitTelemetry() const = 0;
147
148     void setNotifyPagesWhenDataRecordsWereScanned(bool);
149     void setIsRunningTest(bool);
150     bool shouldSkip(const RegistrableDomain&) const;
151     void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool);
152     void setShouldSubmitTelemetry(bool);
153     void setTimeToLiveUserInteraction(Seconds);
154     void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
155     void setGrandfatheringTime(Seconds);
156     void setResourceLoadStatisticsDebugMode(bool);
157     bool isDebugModeEnabled() const { return m_debugModeEnabled; };
158     void setPrevalentResourceForDebugMode(const RegistrableDomain&);
159
160     virtual void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<FrameID>, PageID, CompletionHandler<void(bool)>&&) = 0;
161     virtual void requestStorageAccess(SubFrameDomain&&, TopFrameDomain&&, FrameID, PageID, bool promptEnabled, CompletionHandler<void(StorageAccessStatus)>&&) = 0;
162     virtual void grantStorageAccess(SubFrameDomain&&, TopFrameDomain&&, FrameID, PageID, bool userWasPromptedNow, CompletionHandler<void(bool)>&&) = 0;
163
164     virtual void logFrameNavigation(const NavigatedToDomain&, const TopFrameDomain&, const NavigatedFromDomain&, bool isRedirect, bool isMainFrame) = 0;
165     virtual void logUserInteraction(const TopFrameDomain&) = 0;
166     virtual void logSubresourceLoading(const SubResourceDomain&, const TopFrameDomain&, WallTime lastSeen) = 0;
167     virtual void logSubresourceRedirect(const RedirectedFromDomain&, const RedirectedToDomain&) = 0;
168     virtual void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&) = 0;
169
170     virtual void clearUserInteraction(const RegistrableDomain&) = 0;
171     virtual bool hasHadUserInteraction(const RegistrableDomain&) = 0;
172
173     virtual void setLastSeen(const RegistrableDomain& primaryDomain, Seconds) = 0;
174
175     void didCreateNetworkProcess();
176
177     const WebResourceLoadStatisticsStore& store() const { return m_store; }
178
179     static constexpr unsigned maxImportance { 3 };
180
181     virtual bool isMemoryStore() const { return false; }
182     virtual bool isDatabaseStore()const { return false; }
183
184 protected:
185     static unsigned computeImportance(const WebCore::ResourceLoadStatistics&);
186     static Vector<OperatingDate> mergeOperatingDates(const Vector<OperatingDate>& existingDates, Vector<OperatingDate>&& newDates);
187     static void debugLogDomainsInBatches(const char* action, const Vector<RegistrableDomain>& domains);
188
189     ResourceLoadStatisticsStore(WebResourceLoadStatisticsStore&, WorkQueue&, ShouldIncludeLocalhost);
190
191     bool hasStatisticsExpired(const ResourceLoadStatistics&) const;
192     bool hasStatisticsExpired(WallTime mostRecentUserInteractionTime) const;
193 #if PLATFORM(COCOA)
194     void registerUserDefaultsIfNeeded();
195 #endif
196     void scheduleStatisticsProcessingRequestIfNecessary();
197     void mergeOperatingDates(Vector<OperatingDate>&&);
198     virtual Vector<RegistrableDomain> ensurePrevalentResourcesForDebugMode() = 0;
199     virtual Vector<RegistrableDomain> registrableDomainsToRemoveWebsiteDataFor() = 0;
200     virtual void pruneStatisticsIfNeeded() = 0;
201
202     WebResourceLoadStatisticsStore& store() { return m_store; }
203     Ref<WorkQueue>& workQueue() { return m_workQueue; }
204 #if HAVE(CORE_PREDICTION)
205     ResourceLoadStatisticsClassifierCocoa& classifier() { return m_resourceLoadStatisticsClassifier; }
206 #else
207     ResourceLoadStatisticsClassifier& classifier() { return m_resourceLoadStatisticsClassifier; }
208 #endif
209
210     struct Parameters {
211         size_t pruneEntriesDownTo { 800 };
212         size_t maxStatisticsEntries { 1000 };
213         Optional<Seconds> timeToLiveUserInteraction;
214         Seconds minimumTimeBetweenDataRecordsRemoval { 1_h };
215         Seconds grandfatheringTime { 24_h * 7 };
216         Seconds cacheMaxAgeCapTime { 24_h * 7 };
217         Seconds clientSideCookiesAgeCapTime { 24_h * 7 };
218         bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
219         bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
220         bool shouldSubmitTelemetry { true };
221         bool isRunningTest { false };
222     };
223     const Parameters& parameters() const { return m_parameters; }
224     const Vector<OperatingDate>& operatingDates() const { return m_operatingDates; }
225     void clearOperatingDates() { m_operatingDates.clear(); }
226     WallTime& endOfGrandfatheringTimestamp() { return m_endOfGrandfatheringTimestamp; }
227     const WallTime& endOfGrandfatheringTimestamp() const { return m_endOfGrandfatheringTimestamp; }
228     void setEndOfGrandfatheringTimestamp(const WallTime& grandfatheringTime) { m_endOfGrandfatheringTimestamp = grandfatheringTime; }
229     void clearEndOfGrandfatheringTimeStamp() { m_endOfGrandfatheringTimestamp = { }; }
230     const RegistrableDomain& debugManualPrevalentResource() const { return m_debugManualPrevalentResource; }
231     const RegistrableDomain& debugStaticPrevalentResource() const { return m_debugStaticPrevalentResource; }
232     bool debugLoggingEnabled() const { return m_debugLoggingEnabled; };
233     bool debugModeEnabled() const { return m_debugModeEnabled; }
234     bool storageAccessPromptsEnabled() const { return m_storageAccessPromptsEnabled; }
235
236     static constexpr unsigned maxNumberOfRecursiveCallsInRedirectTraceBack { 50 };
237
238 private:
239     void setStorageAccessPromptsEnabled(bool enabled) { m_storageAccessPromptsEnabled  = enabled; }
240     bool shouldRemoveDataRecords() const;
241     void setDebugLogggingEnabled(bool enabled) { m_debugLoggingEnabled  = enabled; }
242     void setDataRecordsBeingRemoved(bool);
243     void removeDataRecords(CompletionHandler<void()>&&);
244     void setCacheMaxAgeCap(Seconds);
245     void updateCacheMaxAgeCap();
246     void setAgeCapForClientSideCookies(Seconds);
247     void updateClientSideCookiesAgeCap();
248
249     WebResourceLoadStatisticsStore& m_store;
250     Ref<WorkQueue> m_workQueue;
251 #if HAVE(CORE_PREDICTION)
252     ResourceLoadStatisticsClassifierCocoa m_resourceLoadStatisticsClassifier;
253 #else
254     ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
255 #endif
256 #if ENABLE(NETSCAPE_PLUGIN_API)
257     HashSet<uint64_t> m_activePluginTokens;
258 #endif
259     Parameters m_parameters;
260     Vector<OperatingDate> m_operatingDates;
261     WallTime m_endOfGrandfatheringTimestamp;
262     RegistrableDomain m_debugManualPrevalentResource;
263     MonotonicTime m_lastTimeDataRecordsWereRemoved;
264     uint64_t m_lastStatisticsProcessingRequestIdentifier { 0 };
265     Optional<uint64_t> m_pendingStatisticsProcessingRequestIdentifier;
266     const RegistrableDomain m_debugStaticPrevalentResource { URL { URL(), "https://3rdpartytestwebkit.org"_s } };
267     bool m_debugLoggingEnabled { false };
268     bool m_debugModeEnabled { false };
269     bool m_storageAccessPromptsEnabled { false };
270     bool m_dataRecordsBeingRemoved { false };
271     ShouldIncludeLocalhost m_shouldIncludeLocalhost { ShouldIncludeLocalhost::Yes };
272 };
273
274 } // namespace WebKit
275
276 #endif