e5495ab595c077f1eadcdae6251ece6a40ee6200
[WebKit-https.git] / Source / WebKit / UIProcess / ResourceLoadStatisticsMemoryStore.h
1 /*
2  * Copyright (C) 2017-2018 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 #include "ResourceLoadStatisticsClassifier.h"
29 #include "WebResourceLoadStatisticsStore.h"
30 #include <wtf/CompletionHandler.h>
31 #include <wtf/Vector.h>
32 #include <wtf/WeakPtr.h>
33 #include <wtf/WorkQueue.h>
34
35 #if HAVE(CORE_PREDICTION)
36 #include "ResourceLoadStatisticsClassifierCocoa.h"
37 #endif
38
39 namespace WebCore {
40 class KeyedDecoder;
41 class KeyedEncoder;
42 struct ResourceLoadStatistics;
43 }
44
45 namespace WebKit {
46
47 class OperatingDate;
48 class ResourceLoadStatisticsPersistentStorage;
49
50 // This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
51 class ResourceLoadStatisticsMemoryStore : public CanMakeWeakPtr<ResourceLoadStatisticsMemoryStore> {
52 public:
53     ResourceLoadStatisticsMemoryStore(WebResourceLoadStatisticsStore&, WorkQueue&);
54     ~ResourceLoadStatisticsMemoryStore();
55
56     void setPersistentStorage(ResourceLoadStatisticsPersistentStorage&);
57
58     void clear(CompletionHandler<void()>&&);
59     bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
60
61     std::unique_ptr<WebCore::KeyedEncoder> createEncoderFromData() const;
62     void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
63
64     void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
65     void processStatistics(const Function<void(const WebCore::ResourceLoadStatistics&)>&) const;
66
67     void resetCookieBlockingState();
68     void updateCookieBlocking(CompletionHandler<void()>&&);
69     void updateCookieBlockingForDomains(const Vector<String>& domainsToBlock, ShouldClearFirst, CompletionHandler<void()>&&);
70     void clearBlockingStateForDomains(const Vector<String>& domains, CompletionHandler<void()>&&);
71
72     void includeTodayAsOperatingDateIfNecessary();
73     void processStatisticsAndDataRecords();
74
75     void requestStorageAccessUnderOpener(String&& primaryDomainInNeedOfStorageAccess, uint64_t openerPageID, String&& openerPrimaryDomain);
76     void removeAllStorageAccess(CompletionHandler<void()>&&);
77
78     void grandfatherExistingWebsiteData(CompletionHandler<void()>&&);
79     void cancelPendingStatisticsProcessingRequest();
80
81     bool isRegisteredAsSubresourceUnder(const String& subresourcePrimaryDomain, const String& topFramePrimaryDomain) const;
82     bool isRegisteredAsSubFrameUnder(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain) const;
83     bool isRegisteredAsRedirectingTo(const String& hostRedirectedFromPrimaryDomain, const String& hostRedirectedToPrimaryDomain) const;
84
85     void clearPrevalentResource(const String& primaryDomain);
86     String dumpResourceLoadStatistics() const;
87     bool isPrevalentResource(const String& primaryDomain) const;
88     bool isVeryPrevalentResource(const String& primaryDomain) const;
89     void setPrevalentResource(const String& primaryDomain);
90     void setVeryPrevalentResource(const String& primaryDomain);
91
92     void setGrandfathered(const String& primaryDomain, bool value);
93     bool isGrandfathered(const String& primaryDomain) const;
94
95     void setSubframeUnderTopFrameOrigin(const String& primarySubFrameDomain, const String& primaryTopFrameDomain);
96     void setSubresourceUnderTopFrameOrigin(const String& primarySubresourceDomain, const String& primaryTopFrameDomain);
97     void setSubresourceUniqueRedirectTo(const String& primarySubresourceDomain, const String& primaryRedirectDomain);
98     void setSubresourceUniqueRedirectFrom(const String& primarySubresourceDomain, const String& primaryRedirectDomain);
99     void setTopFrameUniqueRedirectTo(const String& topFramePrimaryDomain, const String& primaryRedirectDomain);
100     void setTopFrameUniqueRedirectFrom(const String& topFramePrimaryDomain, const String& primaryRedirectDomain);
101
102     void logTestingEvent(const String&);
103
104     void setMaxStatisticsEntries(size_t maximumEntryCount);
105     void setPruneEntriesDownTo(size_t pruneTargetCount);
106     void resetParametersToDefaultValues();
107
108     void calculateAndSubmitTelemetry() const;
109
110     void setNotifyPagesWhenDataRecordsWereScanned(bool);
111     void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool);
112     void setShouldSubmitTelemetry(bool);
113     void setTimeToLiveUserInteraction(Seconds);
114     void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
115     void setGrandfatheringTime(Seconds);
116     void setCacheMaxAgeCap(Seconds);
117     void setResourceLoadStatisticsDebugMode(bool);
118     bool isDebugModeEnabled() const { return m_debugModeEnabled; };
119     void setPrevalentResourceForDebugMode(const String& domain);
120
121     void hasStorageAccess(const String& subFramePrimaryDomain, const String& topFramePrimaryDomain, uint64_t frameID, uint64_t pageID, CompletionHandler<void(bool)>&&);
122     void requestStorageAccess(String&& subFramePrimaryDomain, String&& topFramePrimaryDomain, uint64_t frameID, uint64_t pageID, bool promptEnabled, CompletionHandler<void(StorageAccessStatus)>&&);
123     void grantStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, bool userWasPromptedNow, CompletionHandler<void(bool)>&&);
124
125     void logFrameNavigation(const String& targetPrimaryDomain, const String& mainFramePrimaryDomain, const String& sourcePrimaryDomain, const String& targetHost, const String& mainFrameHost, bool isRedirect, bool isMainFrame);
126     void logUserInteraction(const String& primaryDomain);
127
128     void clearUserInteraction(const String& primaryDomain);
129     bool hasHadUserInteraction(const String& primaryDomain);
130
131     void setLastSeen(const String& primaryDomain, Seconds);
132
133 private:
134     static bool shouldBlockAndKeepCookies(const WebCore::ResourceLoadStatistics&);
135     static bool shouldBlockAndPurgeCookies(const WebCore::ResourceLoadStatistics&);
136     static bool hasUserGrantedStorageAccessThroughPrompt(const WebCore::ResourceLoadStatistics&, const String& firstPartyPrimaryDomain);
137     bool hasHadUnexpiredRecentUserInteraction(WebCore::ResourceLoadStatistics&) const;
138     bool hasStatisticsExpired(const WebCore::ResourceLoadStatistics&) const;
139     bool wasAccessedAsFirstPartyDueToUserInteraction(const WebCore::ResourceLoadStatistics& current, const WebCore::ResourceLoadStatistics& updated) const;
140     void setPrevalentResource(WebCore::ResourceLoadStatistics&, ResourceLoadPrevalence);
141     unsigned recursivelyGetAllDomainsThatHaveRedirectedToThisDomain(const WebCore::ResourceLoadStatistics&, HashSet<String>& domainsThatHaveRedirectedTo, unsigned numberOfRecursiveCalls) const;
142     void setStorageAccessPromptsEnabled(bool enabled) { m_storageAccessPromptsEnabled  = enabled; }
143     bool shouldRemoveDataRecords() const;
144     void setDebugLogggingEnabled(bool enabled) { m_debugLoggingEnabled  = enabled; }
145     void setDataRecordsBeingRemoved(bool);
146     void scheduleStatisticsProcessingRequestIfNecessary();
147     void grantStorageAccessInternal(String&& subFrameHost, String&& topFrameHost, std::optional<uint64_t> frameID, uint64_t pageID, bool userWasPromptedNowOrEarlier, CompletionHandler<void(bool)>&&);
148     void markAsPrevalentIfHasRedirectedToPrevalent(WebCore::ResourceLoadStatistics&);
149     bool isPrevalentDueToDebugMode(WebCore::ResourceLoadStatistics&);
150     Vector<String> ensurePrevalentResourcesForDebugMode();
151     void removeDataRecords(CompletionHandler<void()>&&);
152     void pruneStatisticsIfNeeded();
153     WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
154     Vector<String> topPrivatelyControlledDomainsToRemoveWebsiteDataFor();
155
156 #if PLATFORM(COCOA)
157     void registerUserDefaultsIfNeeded();
158 #endif
159
160     struct Parameters {
161         size_t pruneEntriesDownTo { 800 };
162         size_t maxStatisticsEntries { 1000 };
163         std::optional<Seconds> timeToLiveUserInteraction;
164         Seconds minimumTimeBetweenDataRecordsRemoval { 1_h };
165         Seconds grandfatheringTime { 24_h * 7 };
166         bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
167         bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
168         bool shouldSubmitTelemetry { true };
169     };
170
171     WebResourceLoadStatisticsStore& m_store;
172     Ref<WorkQueue> m_workQueue;
173     WeakPtr<ResourceLoadStatisticsPersistentStorage> m_persistentStorage;
174     HashMap<String, WebCore::ResourceLoadStatistics> m_resourceStatisticsMap;
175 #if HAVE(CORE_PREDICTION)
176     ResourceLoadStatisticsClassifierCocoa m_resourceLoadStatisticsClassifier;
177 #else
178     ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
179 #endif
180 #if ENABLE(NETSCAPE_PLUGIN_API)
181     HashSet<uint64_t> m_activePluginTokens;
182 #endif
183     Parameters m_parameters;
184     Vector<OperatingDate> m_operatingDates;
185     WallTime m_endOfGrandfatheringTimestamp;
186     bool m_debugLoggingEnabled { false };
187     bool m_debugModeEnabled { false };
188     String m_debugManualPrevalentResource;
189     bool m_storageAccessPromptsEnabled { false };
190     bool m_dataRecordsBeingRemoved { false };
191     MonotonicTime m_lastTimeDataRecordsWereRemoved;
192
193     uint64_t m_lastStatisticsProcessingRequestIdentifier { 0 };
194     std::optional<uint64_t> m_pendingStatisticsProcessingRequestIdentifier;
195 };
196
197 } // namespace WebKit