f1d5655deebcdb047cdd96d2e935634ceac01d3a
[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
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 clearDatabaseContents();
109     bool insertObservedDomain(const ResourceLoadStatistics&);
110     void insertDomainRelationships(const ResourceLoadStatistics&);
111     bool insertDomainRelationship(WebCore::SQLiteStatement&, unsigned domainID, const RegistrableDomain& topFrameDomain);
112     bool relationshipExists(WebCore::SQLiteStatement&, Optional<unsigned> firstDomainID, const RegistrableDomain& secondDomain) const;
113     Optional<unsigned> domainID(const RegistrableDomain&) const;
114 #ifndef NDEBUG
115     bool confirmDomainDoesNotExist(const RegistrableDomain&) const;
116 #endif
117     void updateLastSeen(const RegistrableDomain&, WallTime);
118     void setUserInteraction(const RegistrableDomain&, bool hadUserInteraction, WallTime);
119     Vector<RegistrableDomain> domainsToBlockAndDeleteCookiesFor() const;
120     Vector<RegistrableDomain> domainsToBlockButKeepCookiesFor() const;
121
122     struct PrevalentDomainData {
123         unsigned domainID;
124         RegistrableDomain registrableDomain;
125         WallTime mostRecentUserInteractionTime;
126         bool hadUserInteraction;
127         bool grandfathered;
128     };
129     Vector<PrevalentDomainData> prevalentDomains() const;
130     bool hasHadUnexpiredRecentUserInteraction(const PrevalentDomainData&, OperatingDatesWindow);
131     Vector<unsigned> findExpiredUserInteractions() const;
132     void clearExpiredUserInteractions();
133     void clearGrandfathering(Vector<unsigned>&&);
134     WebCore::StorageAccessPromptWasShown hasUserGrantedStorageAccessThroughPrompt(unsigned domainID, const RegistrableDomain&) const;
135     void incrementRecordsDeletedCountForDomains(HashSet<RegistrableDomain>&&) override;
136
137     void reclassifyResources();
138     struct NotVeryPrevalentResources {
139         RegistrableDomain registrableDomain;
140         ResourceLoadPrevalence prevalence;
141         unsigned subresourceUnderTopFrameDomainsCount;
142         unsigned subresourceUniqueRedirectsToCount;
143         unsigned subframeUnderTopFrameDomainsCount;
144         unsigned topFrameUniqueRedirectsToCount;
145     };
146     HashMap<unsigned, NotVeryPrevalentResources> findNotVeryPrevalentResources();
147
148     bool predicateValueForDomain(WebCore::SQLiteStatement&, const RegistrableDomain&) const;
149
150     enum class CookieTreatmentResult { Allow, BlockAndKeep, BlockAndPurge };
151     CookieTreatmentResult cookieTreatmentForOrigin(const RegistrableDomain&) const;
152     
153     void setPrevalentResource(const RegistrableDomain&, ResourceLoadPrevalence);
154     unsigned recursivelyFindNonPrevalentDomainsThatRedirectedToThisDomain(unsigned primaryDomainID, StdSet<unsigned>& nonPrevalentRedirectionSources, unsigned numberOfRecursiveCalls);
155     void setDomainsAsPrevalent(StdSet<unsigned>&&);
156     void grantStorageAccessInternal(SubFrameDomain&&, TopFrameDomain&&, Optional<WebCore::FrameIdentifier>, WebCore::PageIdentifier, WebCore::StorageAccessPromptWasShown, CompletionHandler<void(WebCore::StorageAccessWasGranted)>&&);
157     void markAsPrevalentIfHasRedirectedToPrevalent();
158     Vector<RegistrableDomain> ensurePrevalentResourcesForDebugMode() override;
159     void removeDataRecords(CompletionHandler<void()>&&);
160     void pruneStatisticsIfNeeded() override;
161     enum class AddedRecord { No, Yes };
162     std::pair<AddedRecord, unsigned> ensureResourceStatisticsForRegistrableDomain(const RegistrableDomain&);
163     bool shouldRemoveAllWebsiteDataFor(const PrevalentDomainData&, bool shouldCheckForGrandfathering);
164     bool shouldRemoveAllButCookiesFor(const PrevalentDomainData&, bool shouldCheckForGrandfathering) const;
165     Vector<std::pair<RegistrableDomain, WebsiteDataToRemove>> registrableDomainsToRemoveWebsiteDataFor() override;
166     bool isDatabaseStore() const final { return true; }
167
168     bool createSchema();
169     bool prepareStatements();
170     
171     const String m_storageDirectoryPath;
172     mutable WebCore::SQLiteDatabase m_database;
173     mutable WebCore::SQLiteStatement m_observedDomainCount;
174     WebCore::SQLiteStatement m_insertObservedDomainStatement;
175     WebCore::SQLiteStatement m_insertTopLevelDomainStatement;
176     mutable WebCore::SQLiteStatement m_domainIDFromStringStatement;
177     WebCore::SQLiteStatement m_storageAccessUnderTopFrameDomainsStatement;
178     WebCore::SQLiteStatement m_topFrameUniqueRedirectsTo;
179     mutable WebCore::SQLiteStatement m_topFrameUniqueRedirectsToExists;
180     WebCore::SQLiteStatement m_topFrameUniqueRedirectsFrom;
181     mutable WebCore::SQLiteStatement m_topFrameUniqueRedirectsFromExists;
182     WebCore::SQLiteStatement m_topFrameLinkDecorationsFrom;
183     mutable WebCore::SQLiteStatement m_topFrameLinkDecorationsFromExists;
184     WebCore::SQLiteStatement m_subframeUnderTopFrameDomains;
185     mutable WebCore::SQLiteStatement m_subframeUnderTopFrameDomainExists;
186     WebCore::SQLiteStatement m_subresourceUnderTopFrameDomains;
187     mutable WebCore::SQLiteStatement m_subresourceUnderTopFrameDomainExists;
188     WebCore::SQLiteStatement m_subresourceUniqueRedirectsTo;
189     mutable WebCore::SQLiteStatement m_subresourceUniqueRedirectsToExists;
190     WebCore::SQLiteStatement m_subresourceUniqueRedirectsFrom;
191     mutable WebCore::SQLiteStatement m_subresourceUniqueRedirectsFromExists;
192     WebCore::SQLiteStatement m_mostRecentUserInteractionStatement;
193     WebCore::SQLiteStatement m_updateLastSeenStatement;
194     WebCore::SQLiteStatement m_updatePrevalentResourceStatement;
195     mutable WebCore::SQLiteStatement m_isPrevalentResourceStatement;
196     WebCore::SQLiteStatement m_updateVeryPrevalentResourceStatement;
197     mutable WebCore::SQLiteStatement m_isVeryPrevalentResourceStatement;
198     WebCore::SQLiteStatement m_clearPrevalentResourceStatement;
199     mutable WebCore::SQLiteStatement m_hadUserInteractionStatement;
200     WebCore::SQLiteStatement m_updateGrandfatheredStatement;
201     mutable WebCore::SQLiteStatement m_isGrandfatheredStatement;
202     mutable WebCore::SQLiteStatement m_findExpiredUserInteractionStatement;
203     PAL::SessionID m_sessionID;
204 };
205
206 } // namespace WebKit
207
208 SPECIALIZE_TYPE_TRAITS_BEGIN(WebKit::ResourceLoadStatisticsDatabaseStore)
209     static bool isType(const WebKit::ResourceLoadStatisticsStore& store) { return store.isDatabaseStore(); }
210 SPECIALIZE_TYPE_TRAITS_END()
211
212 #endif