ea7e649fff5d16aa84ae1be0526b6c58c57d2e34
[WebKit-https.git] / Source / WebKit / NetworkProcess / Classifier / ResourceLoadStatisticsDatabaseStore.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 "ResourceLoadStatisticsStore.h"
31 #include "WebResourceLoadStatisticsStore.h"
32 #include <WebCore/SQLiteDatabase.h>
33 #include <WebCore/SQLiteStatement.h>
34 #include <wtf/CompletionHandler.h>
35 #include <wtf/StdSet.h>
36 #include <wtf/Vector.h>
37 #include <wtf/WorkQueue.h>
38
39 namespace WebCore {
40 class SQLiteDatabase;
41 class SQLiteStatement;
42 enum class StorageAccessPromptWasShown : bool;
43 enum class StorageAccessWasGranted : bool;
44 struct ResourceLoadStatistics;
45 }
46
47 namespace WebKit {
48
49 class ResourceLoadStatisticsMemoryStore;
50
51 // This is always constructed / used / destroyed on the WebResourceLoadStatisticsStore's statistics queue.
52 class ResourceLoadStatisticsDatabaseStore final : public ResourceLoadStatisticsStore {
53 public:
54     ResourceLoadStatisticsDatabaseStore(WebResourceLoadStatisticsStore&, WorkQueue&, ShouldIncludeLocalhost, const String& storageDirectoryPath, PAL::SessionID);
55
56     void populateFromMemoryStore(const ResourceLoadStatisticsMemoryStore&);
57     void mergeStatistics(Vector<ResourceLoadStatistics>&&) override;
58     void clear(CompletionHandler<void()>&&) override;
59     bool isEmpty() const override;
60
61     void updateCookieBlocking(CompletionHandler<void()>&&) override;
62
63     void classifyPrevalentResources() override;
64     void syncStorageIfNeeded() override;
65     void syncStorageImmediately() override;
66
67     void requestStorageAccessUnderOpener(DomainInNeedOfStorageAccess&&, WebCore::PageIdentifier openerID, OpenerDomain&&) override;
68
69     void grandfatherDataForDomains(const HashSet<RegistrableDomain>&) override;
70
71     bool isRegisteredAsSubresourceUnder(const SubResourceDomain&, const TopFrameDomain&) const override;
72     bool isRegisteredAsSubFrameUnder(const SubFrameDomain&, const TopFrameDomain&) const override;
73     bool isRegisteredAsRedirectingTo(const RedirectedFromDomain&, const RedirectedToDomain&) const override;
74
75     void clearPrevalentResource(const RegistrableDomain&) override;
76     void dumpResourceLoadStatistics(CompletionHandler<void(const String&)>&&) final;
77     bool isPrevalentResource(const RegistrableDomain&) const override;
78     bool isVeryPrevalentResource(const RegistrableDomain&) const override;
79     void setPrevalentResource(const RegistrableDomain&) override;
80     void setVeryPrevalentResource(const RegistrableDomain&) override;
81
82     void setGrandfathered(const RegistrableDomain&, bool value) override;
83     bool isGrandfathered(const RegistrableDomain&) const override;
84
85     void setSubframeUnderTopFrameDomain(const SubFrameDomain&, const TopFrameDomain&) override;
86     void setSubresourceUnderTopFrameDomain(const SubResourceDomain&, const TopFrameDomain&) override;
87     void setSubresourceUniqueRedirectTo(const SubResourceDomain&, const RedirectDomain&) override;
88     void setSubresourceUniqueRedirectFrom(const SubResourceDomain&, const RedirectDomain&) override;
89     void setTopFrameUniqueRedirectTo(const TopFrameDomain&, const RedirectDomain&) override;
90     void setTopFrameUniqueRedirectFrom(const TopFrameDomain&, const RedirectDomain&) override;
91
92     void calculateAndSubmitTelemetry() const override;
93
94     void hasStorageAccess(const SubFrameDomain&, const TopFrameDomain&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, CompletionHandler<void(bool)>&&) override;
95     void requestStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, CompletionHandler<void(StorageAccessStatus)>&&) override;
96     void grantStorageAccess(SubFrameDomain&&, TopFrameDomain&&, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&) override;
97
98     void logFrameNavigation(const NavigatedToDomain&, const TopFrameDomain&, const NavigatedFromDomain&, bool isRedirect, bool isMainFrame) override;
99     void logUserInteraction(const TopFrameDomain&) override;
100     void logCrossSiteLoadWithLinkDecoration(const NavigatedFromDomain&, const NavigatedToDomain&) override;
101
102     void clearUserInteraction(const RegistrableDomain&) override;
103     bool hasHadUserInteraction(const RegistrableDomain&, OperatingDatesWindow) override;
104
105     void setLastSeen(const RegistrableDomain&, Seconds) override;
106
107 private:
108     void mergeStatistic(const ResourceLoadStatistics&);
109     void merge(WebCore::SQLiteStatement&, const ResourceLoadStatistics&);
110     void clearDatabaseContents();
111     bool insertObservedDomain(const ResourceLoadStatistics&);
112     void insertDomainRelationships(const ResourceLoadStatistics&);
113     bool insertDomainRelationship(WebCore::SQLiteStatement&, unsigned domainID, const RegistrableDomain& topFrameDomain);
114     bool relationshipExists(WebCore::SQLiteStatement&, Optional<unsigned> firstDomainID, const RegistrableDomain& secondDomain) const;
115     Optional<unsigned> domainID(const RegistrableDomain&) const;
116     bool domainExists(const RegistrableDomain&) const;
117     void updateLastSeen(const RegistrableDomain&, WallTime);
118     void updateDataRecordsRemoved(const RegistrableDomain&, int);
119     void setUserInteraction(const RegistrableDomain&, bool hadUserInteraction, WallTime);
120     Vector<RegistrableDomain> domainsToBlockAndDeleteCookiesFor() const;
121     Vector<RegistrableDomain> domainsToBlockButKeepCookiesFor() const;
122
123     struct PrevalentDomainData {
124         unsigned domainID;
125         RegistrableDomain registrableDomain;
126         WallTime mostRecentUserInteractionTime;
127         bool hadUserInteraction;
128         bool grandfathered;
129     };
130     Vector<PrevalentDomainData> prevalentDomains() const;
131     bool hasHadUnexpiredRecentUserInteraction(const PrevalentDomainData&, OperatingDatesWindow);
132     Vector<unsigned> findExpiredUserInteractions() const;
133     void clearExpiredUserInteractions();
134     void clearGrandfathering(Vector<unsigned>&&);
135     WebCore::StorageAccessPromptWasShown hasUserGrantedStorageAccessThroughPrompt(unsigned domainID, const RegistrableDomain&) const;
136     void incrementRecordsDeletedCountForDomains(HashSet<RegistrableDomain>&&) override;
137
138     void reclassifyResources();
139     struct NotVeryPrevalentResources {
140         RegistrableDomain registrableDomain;
141         ResourceLoadPrevalence prevalence;
142         unsigned subresourceUnderTopFrameDomainsCount;
143         unsigned subresourceUniqueRedirectsToCount;
144         unsigned subframeUnderTopFrameDomainsCount;
145         unsigned topFrameUniqueRedirectsToCount;
146     };
147     HashMap<unsigned, NotVeryPrevalentResources> findNotVeryPrevalentResources();
148
149     bool predicateValueForDomain(WebCore::SQLiteStatement&, const RegistrableDomain&) const;
150
151     enum class CookieTreatmentResult { Allow, BlockAndKeep, BlockAndPurge };
152     CookieTreatmentResult cookieTreatmentForOrigin(const RegistrableDomain&) const;
153     
154     void setPrevalentResource(const RegistrableDomain&, ResourceLoadPrevalence);
155     unsigned recursivelyFindNonPrevalentDomainsThatRedirectedToThisDomain(unsigned primaryDomainID, StdSet<unsigned>& nonPrevalentRedirectionSources, unsigned numberOfRecursiveCalls);
156     void setDomainsAsPrevalent(StdSet<unsigned>&&);
157     void grantStorageAccessInternal(SubFrameDomain&&, TopFrameDomain&&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&);
158     void markAsPrevalentIfHasRedirectedToPrevalent();
159     Vector<RegistrableDomain> ensurePrevalentResourcesForDebugMode() override;
160     void removeDataRecords(CompletionHandler<void()>&&);
161     void pruneStatisticsIfNeeded() override;
162     enum class AddedRecord { No, Yes };
163     std::pair<AddedRecord, unsigned> ensureResourceStatisticsForRegistrableDomain(const RegistrableDomain&);
164     bool shouldRemoveAllWebsiteDataFor(const PrevalentDomainData&, bool shouldCheckForGrandfathering);
165     bool shouldRemoveAllButCookiesFor(const PrevalentDomainData&, bool shouldCheckForGrandfathering) const;
166     Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>> registrableDomainsToRemoveWebsiteDataFor() override;
167     bool isDatabaseStore() const final { return true; }
168
169     bool createSchema();
170     bool prepareStatements();
171     
172     const String m_storageDirectoryPath;
173     mutable WebCore::SQLiteDatabase m_database;
174     mutable WebCore::SQLiteStatement m_observedDomainCount;
175     WebCore::SQLiteStatement m_insertObservedDomainStatement;
176     WebCore::SQLiteStatement m_insertTopLevelDomainStatement;
177     mutable WebCore::SQLiteStatement m_domainIDFromStringStatement;
178     WebCore::SQLiteStatement m_storageAccessUnderTopFrameDomainsStatement;
179     WebCore::SQLiteStatement m_storageAccessUnderTopFrameDomainsExistsStatement;
180     WebCore::SQLiteStatement m_topFrameUniqueRedirectsTo;
181     mutable WebCore::SQLiteStatement m_topFrameUniqueRedirectsToExists;
182     WebCore::SQLiteStatement m_topFrameUniqueRedirectsFrom;
183     mutable WebCore::SQLiteStatement m_topFrameUniqueRedirectsFromExists;
184     WebCore::SQLiteStatement m_topFrameLinkDecorationsFrom;
185     mutable WebCore::SQLiteStatement m_topFrameLinkDecorationsFromExists;
186     WebCore::SQLiteStatement m_subframeUnderTopFrameDomains;
187     mutable WebCore::SQLiteStatement m_subframeUnderTopFrameDomainExists;
188     WebCore::SQLiteStatement m_subresourceUnderTopFrameDomains;
189     mutable WebCore::SQLiteStatement m_subresourceUnderTopFrameDomainExists;
190     WebCore::SQLiteStatement m_subresourceUniqueRedirectsTo;
191     mutable WebCore::SQLiteStatement m_subresourceUniqueRedirectsToExists;
192     WebCore::SQLiteStatement m_subresourceUniqueRedirectsFrom;
193     mutable WebCore::SQLiteStatement m_subresourceUniqueRedirectsFromExists;
194     WebCore::SQLiteStatement m_mostRecentUserInteractionStatement;
195     WebCore::SQLiteStatement m_updateLastSeenStatement;
196     mutable WebCore::SQLiteStatement m_updateDataRecordsRemovedStatement;
197     WebCore::SQLiteStatement m_updatePrevalentResourceStatement;
198     mutable WebCore::SQLiteStatement m_isPrevalentResourceStatement;
199     WebCore::SQLiteStatement m_updateVeryPrevalentResourceStatement;
200     mutable WebCore::SQLiteStatement m_isVeryPrevalentResourceStatement;
201     WebCore::SQLiteStatement m_clearPrevalentResourceStatement;
202     mutable WebCore::SQLiteStatement m_hadUserInteractionStatement;
203     WebCore::SQLiteStatement m_updateGrandfatheredStatement;
204     mutable WebCore::SQLiteStatement m_isGrandfatheredStatement;
205     mutable WebCore::SQLiteStatement m_findExpiredUserInteractionStatement;
206     PAL::SessionID m_sessionID;
207 };
208
209 } // namespace WebKit
210
211 SPECIALIZE_TYPE_TRAITS_BEGIN(WebKit::ResourceLoadStatisticsDatabaseStore)
212     static bool isType(const WebKit::ResourceLoadStatisticsStore& store) { return store.isDatabaseStore(); }
213 SPECIALIZE_TYPE_TRAITS_END()
214
215 #endif