c1ff38ed2b90e1aa304a7a0e80758fe9653a257d
[WebKit-https.git] / Source / WebKit / UIProcess / WebResourceLoadStatisticsStore.h
1 /*
2  * Copyright (C) 2016-2017 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 "Connection.h"
29 #include "ResourceLoadStatisticsClassifier.h"
30 #include "ResourceLoadStatisticsPersistentStorage.h"
31 #include "WebsiteDataType.h"
32 #include <wtf/CompletionHandler.h>
33 #include <wtf/HashSet.h>
34 #include <wtf/MonotonicTime.h>
35 #include <wtf/RunLoop.h>
36 #include <wtf/Vector.h>
37 #include <wtf/WallTime.h>
38 #include <wtf/text/WTFString.h>
39
40 #if HAVE(CORE_PREDICTION)
41 #include "ResourceLoadStatisticsClassifierCocoa.h"
42 #endif
43
44 namespace WTF {
45 class WorkQueue;
46 }
47
48 namespace WebCore {
49 class KeyedDecoder;
50 class KeyedEncoder;
51 class URL;
52 struct ResourceLoadStatistics;
53 }
54
55 namespace WebKit {
56
57 class OperatingDate;
58 class WebProcessProxy;
59
60 enum class ShouldClearFirst;
61
62 class WebResourceLoadStatisticsStore final : public IPC::Connection::WorkQueueMessageReceiver {
63 public:
64     using UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler = WTF::Function<void(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst)>;
65     using UpdateStorageAccessForPrevalentDomainsHandler = WTF::Function<void(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, bool value, WTF::Function<void(bool wasGranted)>&& callback)>;
66     using RemovePrevalentDomainsHandler = WTF::Function<void (const Vector<String>&)>;
67     static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler = [](const Vector<String>&, const Vector<String>&, const Vector<String>&, ShouldClearFirst) { }, UpdateStorageAccessForPrevalentDomainsHandler&& updateStorageAccessForPrevalentDomainsHandler = [](const String&, const String&, uint64_t, uint64_t, bool, WTF::Function<void(bool)>&&) { }, RemovePrevalentDomainsHandler&& removeDomainsHandler = [] (const Vector<String>&) { })
68     {
69         return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updatePrevalentDomainsToPartitionOrBlockCookiesHandler), WTFMove(updateStorageAccessForPrevalentDomainsHandler), WTFMove(removeDomainsHandler)));
70     }
71
72     ~WebResourceLoadStatisticsStore();
73
74     static const OptionSet<WebsiteDataType>& monitoredDataTypes();
75
76     bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
77     WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }
78
79     void setNotifyPagesWhenDataRecordsWereScanned(bool value) { m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned = value; }
80     void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value) { m_parameters.shouldClassifyResourcesBeforeDataRecordsRemoval = value; }
81     void setShouldSubmitTelemetry(bool value) { m_parameters.shouldSubmitTelemetry = value; }
82
83     void resourceLoadStatisticsUpdated(Vector<WebCore::ResourceLoadStatistics>&& origins);
84
85     void hasStorageAccess(String&& subFrameHost, String&& topFrameHost, WTF::CompletionHandler<void (bool)>&& callback);
86     void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback);
87     void requestStorageAccessCallback(bool wasGranted, uint64_t contextId);
88
89     void processWillOpenConnection(WebProcessProxy&, IPC::Connection&);
90     void processDidCloseConnection(WebProcessProxy&, IPC::Connection&);
91     void applicationWillTerminate();
92
93     void logUserInteraction(const WebCore::URL&);
94     void logNonRecentUserInteraction(const WebCore::URL&);
95     void clearUserInteraction(const WebCore::URL&);
96     void hasHadUserInteraction(const WebCore::URL&, WTF::Function<void (bool)>&&);
97     void setLastSeen(const WebCore::URL&, Seconds);
98     void setPrevalentResource(const WebCore::URL&);
99     void isPrevalentResource(const WebCore::URL&, WTF::Function<void (bool)>&&);
100     void isRegisteredAsSubFrameUnder(const WebCore::URL& subFrame, const WebCore::URL& topFrame, WTF::Function<void (bool)>&&);
101     void isRegisteredAsRedirectingTo(const WebCore::URL& hostRedirectedFrom, const WebCore::URL& hostRedirectedTo, WTF::Function<void (bool)>&&);
102     void clearPrevalentResource(const WebCore::URL&);
103     void setGrandfathered(const WebCore::URL&, bool);
104     void isGrandfathered(const WebCore::URL&, WTF::Function<void (bool)>&&);
105     void setSubframeUnderTopFrameOrigin(const WebCore::URL& subframe, const WebCore::URL& topFrame);
106     void setSubresourceUnderTopFrameOrigin(const WebCore::URL& subresource, const WebCore::URL& topFrame);
107     void setSubresourceUniqueRedirectTo(const WebCore::URL& subresource, const WebCore::URL& hostNameRedirectedTo);
108     void scheduleCookiePartitioningUpdate();
109     void scheduleCookiePartitioningUpdateForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst);
110     void scheduleClearPartitioningStateForDomains(const Vector<String>& domains);
111     void scheduleStatisticsAndDataRecordsProcessing();
112     void submitTelemetry();
113     void scheduleCookiePartitioningStateReset();
114
115     void scheduleClearInMemory();
116     
117     enum class ShouldGrandfather {
118         No,
119         Yes,
120     };
121     void scheduleClearInMemoryAndPersistent(ShouldGrandfather);
122     void scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince, ShouldGrandfather);
123
124     void setTimeToLiveUserInteraction(Seconds);
125     void setTimeToLiveCookiePartitionFree(Seconds);
126     void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
127     void setGrandfatheringTime(Seconds);
128     void setMaxStatisticsEntries(size_t);
129     void setPruneEntriesDownTo(size_t);
130     
131     void processStatistics(const WTF::Function<void (const WebCore::ResourceLoadStatistics&)>&) const;
132     void pruneStatisticsIfNeeded();
133
134     void resetParametersToDefaultValues();
135
136     std::unique_ptr<WebCore::KeyedEncoder> createEncoderFromData() const;
137     void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
138     void clearInMemory();
139     void grandfatherExistingWebsiteData();
140
141     void setStatisticsTestingCallback(Function<void (const String&)>&& callback) { m_statisticsTestingCallback = WTFMove(callback); }
142     void logTestingEvent(const String&);
143
144 private:
145     WebResourceLoadStatisticsStore(const String&, Function<void(const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&&, UpdateStorageAccessForPrevalentDomainsHandler&&, RemovePrevalentDomainsHandler&&);
146
147     void removeDataRecords();
148
149     // IPC::MessageReceiver
150     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
151
152     void performDailyTasks();
153     bool shouldRemoveDataRecords() const;
154     void setDataRecordsBeingRemoved(bool);
155
156     bool shouldPartitionCookies(const WebCore::ResourceLoadStatistics&) const;
157     bool shouldBlockCookies(const WebCore::ResourceLoadStatistics&) const;
158     bool hasStatisticsExpired(const WebCore::ResourceLoadStatistics&) const;
159     bool hasHadUnexpiredRecentUserInteraction(WebCore::ResourceLoadStatistics&) const;
160     void includeTodayAsOperatingDateIfNecessary();
161     Vector<String> topPrivatelyControlledDomainsToRemoveWebsiteDataFor();
162     void updateCookiePartitioning();
163     void updateCookiePartitioningForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst);
164     void clearPartitioningStateForDomains(const Vector<String>& domains);
165     void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
166     WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
167     void processStatisticsAndDataRecords();
168
169     void resetCookiePartitioningState();
170
171 #if PLATFORM(COCOA)
172     void registerUserDefaultsIfNeeded();
173 #endif
174
175     struct Parameters {
176         size_t pruneEntriesDownTo { 800 };
177         size_t maxStatisticsEntries { 1000 };
178         std::optional<Seconds> timeToLiveUserInteraction;
179         Seconds timeToLiveCookiePartitionFree { 24_h };
180         Seconds minimumTimeBetweenDataRecordsRemoval { 1_h };
181         Seconds grandfatheringTime { 24_h * 7 };
182         bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
183         bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
184         bool shouldSubmitTelemetry { true };
185     };
186
187     HashMap<String, WebCore::ResourceLoadStatistics> m_resourceStatisticsMap;
188 #if HAVE(CORE_PREDICTION)
189     ResourceLoadStatisticsClassifierCocoa m_resourceLoadStatisticsClassifier;
190 #else
191     ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
192 #endif
193     Ref<WTF::WorkQueue> m_statisticsQueue;
194     ResourceLoadStatisticsPersistentStorage m_persistentStorage;
195     Vector<OperatingDate> m_operatingDates;
196
197     UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler m_updatePrevalentDomainsToPartitionOrBlockCookiesHandler;
198     UpdateStorageAccessForPrevalentDomainsHandler m_updateStorageAccessForPrevalentDomainsHandler;
199     RemovePrevalentDomainsHandler m_removeDomainsHandler;
200
201     WallTime m_endOfGrandfatheringTimestamp;
202     RunLoop::Timer<WebResourceLoadStatisticsStore> m_dailyTasksTimer;
203     MonotonicTime m_lastTimeDataRecordsWereRemoved;
204
205     Parameters m_parameters;
206
207 #if ENABLE(NETSCAPE_PLUGIN_API)
208     HashSet<uint64_t> m_activePluginTokens;
209 #endif
210     bool m_dataRecordsBeingRemoved { false };
211
212     Function<void (const String&)> m_statisticsTestingCallback;
213 };
214
215 } // namespace WebKit