2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
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>
40 #if HAVE(CORE_PREDICTION)
41 #include "ResourceLoadStatisticsClassifierCocoa.h"
52 struct ResourceLoadStatistics;
58 class WebProcessProxy;
60 enum class ShouldClearFirst;
62 class WebResourceLoadStatisticsStore final : public IPC::Connection::WorkQueueMessageReceiver {
64 using UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler = WTF::Function<void(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst)>;
65 using HasStorageAccessForPrevalentDomainsHandler = WTF::Function<void(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::Function<void(bool hasAccess)>&& callback)>;
66 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)>;
67 using RemovePrevalentDomainsHandler = WTF::Function<void (const Vector<String>&)>;
68 static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler = [](const Vector<String>&, const Vector<String>&, const Vector<String>&, ShouldClearFirst) { }, HasStorageAccessForPrevalentDomainsHandler&& hasStorageAccessForPrevalentDomainsHandler = [](const String&, const String&, uint64_t, uint64_t, WTF::Function<void(bool)>&&) { }, UpdateStorageAccessForPrevalentDomainsHandler&& updateStorageAccessForPrevalentDomainsHandler = [](const String&, const String&, uint64_t, uint64_t, bool, WTF::Function<void(bool)>&&) { }, RemovePrevalentDomainsHandler&& removeDomainsHandler = [] (const Vector<String>&) { })
70 return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updatePrevalentDomainsToPartitionOrBlockCookiesHandler), WTFMove(hasStorageAccessForPrevalentDomainsHandler), WTFMove(updateStorageAccessForPrevalentDomainsHandler), WTFMove(removeDomainsHandler)));
73 ~WebResourceLoadStatisticsStore();
75 static const OptionSet<WebsiteDataType>& monitoredDataTypes();
77 bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
78 WorkQueue& statisticsQueue() { return m_statisticsQueue.get(); }
80 void setNotifyPagesWhenDataRecordsWereScanned(bool value) { m_parameters.shouldNotifyPagesWhenDataRecordsWereScanned = value; }
81 void setShouldClassifyResourcesBeforeDataRecordsRemoval(bool value) { m_parameters.shouldClassifyResourcesBeforeDataRecordsRemoval = value; }
82 void setShouldSubmitTelemetry(bool value) { m_parameters.shouldSubmitTelemetry = value; }
84 void resourceLoadStatisticsUpdated(Vector<WebCore::ResourceLoadStatistics>&& origins);
86 void hasStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback);
87 void requestStorageAccess(String&& subFrameHost, String&& topFrameHost, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void (bool)>&& callback);
88 void requestStorageAccessCallback(bool wasGranted, uint64_t contextId);
90 void processWillOpenConnection(WebProcessProxy&, IPC::Connection&);
91 void processDidCloseConnection(WebProcessProxy&, IPC::Connection&);
92 void applicationWillTerminate();
94 void logUserInteraction(const WebCore::URL&);
95 void logNonRecentUserInteraction(const WebCore::URL&);
96 void clearUserInteraction(const WebCore::URL&);
97 void hasHadUserInteraction(const WebCore::URL&, WTF::Function<void (bool)>&&);
98 void setLastSeen(const WebCore::URL&, Seconds);
99 void setPrevalentResource(const WebCore::URL&);
100 void isPrevalentResource(const WebCore::URL&, WTF::Function<void (bool)>&&);
101 void isRegisteredAsSubFrameUnder(const WebCore::URL& subFrame, const WebCore::URL& topFrame, WTF::Function<void (bool)>&&);
102 void isRegisteredAsRedirectingTo(const WebCore::URL& hostRedirectedFrom, const WebCore::URL& hostRedirectedTo, WTF::Function<void (bool)>&&);
103 void clearPrevalentResource(const WebCore::URL&);
104 void setGrandfathered(const WebCore::URL&, bool);
105 void isGrandfathered(const WebCore::URL&, WTF::Function<void (bool)>&&);
106 void setSubframeUnderTopFrameOrigin(const WebCore::URL& subframe, const WebCore::URL& topFrame);
107 void setSubresourceUnderTopFrameOrigin(const WebCore::URL& subresource, const WebCore::URL& topFrame);
108 void setSubresourceUniqueRedirectTo(const WebCore::URL& subresource, const WebCore::URL& hostNameRedirectedTo);
109 void scheduleCookiePartitioningUpdate();
110 void scheduleCookiePartitioningUpdateForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst);
111 void scheduleClearPartitioningStateForDomains(const Vector<String>& domains);
112 void scheduleStatisticsAndDataRecordsProcessing();
113 void submitTelemetry();
114 void scheduleCookiePartitioningStateReset();
116 void scheduleClearInMemory();
118 enum class ShouldGrandfather {
122 void scheduleClearInMemoryAndPersistent(ShouldGrandfather);
123 void scheduleClearInMemoryAndPersistent(std::chrono::system_clock::time_point modifiedSince, ShouldGrandfather);
125 void setTimeToLiveUserInteraction(Seconds);
126 void setTimeToLiveCookiePartitionFree(Seconds);
127 void setMinimumTimeBetweenDataRecordsRemoval(Seconds);
128 void setGrandfatheringTime(Seconds);
129 void setMaxStatisticsEntries(size_t);
130 void setPruneEntriesDownTo(size_t);
132 void processStatistics(const WTF::Function<void (const WebCore::ResourceLoadStatistics&)>&) const;
133 void pruneStatisticsIfNeeded();
135 void resetParametersToDefaultValues();
137 std::unique_ptr<WebCore::KeyedEncoder> createEncoderFromData() const;
138 void mergeWithDataFromDecoder(WebCore::KeyedDecoder&);
139 void clearInMemory();
140 void grandfatherExistingWebsiteData();
142 void setStatisticsTestingCallback(Function<void (const String&)>&& callback) { m_statisticsTestingCallback = WTFMove(callback); }
143 void logTestingEvent(const String&);
146 WebResourceLoadStatisticsStore(const String&, Function<void(const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&&, HasStorageAccessForPrevalentDomainsHandler&&, UpdateStorageAccessForPrevalentDomainsHandler&&, RemovePrevalentDomainsHandler&&);
148 void removeDataRecords();
150 // IPC::MessageReceiver
151 void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
153 void performDailyTasks();
154 bool shouldRemoveDataRecords() const;
155 void setDataRecordsBeingRemoved(bool);
157 bool shouldPartitionCookies(const WebCore::ResourceLoadStatistics&) const;
158 bool shouldBlockCookies(const WebCore::ResourceLoadStatistics&) const;
159 bool hasStatisticsExpired(const WebCore::ResourceLoadStatistics&) const;
160 bool hasHadUnexpiredRecentUserInteraction(WebCore::ResourceLoadStatistics&) const;
161 void includeTodayAsOperatingDateIfNecessary();
162 Vector<String> topPrivatelyControlledDomainsToRemoveWebsiteDataFor();
163 void updateCookiePartitioning();
164 void updateCookiePartitioningForDomains(const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst);
165 void clearPartitioningStateForDomains(const Vector<String>& domains);
166 void mergeStatistics(Vector<WebCore::ResourceLoadStatistics>&&);
167 WebCore::ResourceLoadStatistics& ensureResourceStatisticsForPrimaryDomain(const String&);
168 void processStatisticsAndDataRecords();
170 void resetCookiePartitioningState();
173 void registerUserDefaultsIfNeeded();
177 size_t pruneEntriesDownTo { 800 };
178 size_t maxStatisticsEntries { 1000 };
179 std::optional<Seconds> timeToLiveUserInteraction;
180 Seconds timeToLiveCookiePartitionFree { 24_h };
181 Seconds minimumTimeBetweenDataRecordsRemoval { 1_h };
182 Seconds grandfatheringTime { 24_h * 7 };
183 bool shouldNotifyPagesWhenDataRecordsWereScanned { false };
184 bool shouldClassifyResourcesBeforeDataRecordsRemoval { true };
185 bool shouldSubmitTelemetry { true };
188 HashMap<String, WebCore::ResourceLoadStatistics> m_resourceStatisticsMap;
189 #if HAVE(CORE_PREDICTION)
190 ResourceLoadStatisticsClassifierCocoa m_resourceLoadStatisticsClassifier;
192 ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
194 Ref<WTF::WorkQueue> m_statisticsQueue;
195 ResourceLoadStatisticsPersistentStorage m_persistentStorage;
196 Vector<OperatingDate> m_operatingDates;
198 UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler m_updatePrevalentDomainsToPartitionOrBlockCookiesHandler;
199 HasStorageAccessForPrevalentDomainsHandler m_hasStorageAccessForPrevalentDomainsHandler;
200 UpdateStorageAccessForPrevalentDomainsHandler m_updateStorageAccessForPrevalentDomainsHandler;
201 RemovePrevalentDomainsHandler m_removeDomainsHandler;
203 WallTime m_endOfGrandfatheringTimestamp;
204 RunLoop::Timer<WebResourceLoadStatisticsStore> m_dailyTasksTimer;
205 MonotonicTime m_lastTimeDataRecordsWereRemoved;
207 Parameters m_parameters;
209 #if ENABLE(NETSCAPE_PLUGIN_API)
210 HashSet<uint64_t> m_activePluginTokens;
212 bool m_dataRecordsBeingRemoved { false };
214 Function<void (const String&)> m_statisticsTestingCallback;
217 } // namespace WebKit