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