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