1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #ifndef mozilla_BounceTrackingProtectionStorage_h__
5 #define mozilla_BounceTrackingProtectionStorage_h__
7 #include "mozIStorageFunction.h"
8 #include "mozilla/Logging.h"
9 #include "mozilla/Monitor.h"
10 #include "mozilla/ThreadSafety.h"
11 #include "mozilla/WeakPtr.h"
12 #include "mozilla/dom/FlippedOnce.h"
13 #include "nsIAsyncShutdown.h"
15 #include "nsIObserver.h"
16 #include "nsISupports.h"
17 #include "nsTHashMap.h"
18 #include "mozIStorageConnection.h"
19 #include "mozilla/OriginAttributesHashKey.h"
22 class mozIStorageConnection
;
26 class BounceTrackingStateGlobal
;
27 class BounceTrackingState
;
28 class OriginAttributes
;
30 extern LazyLogModule gBounceTrackingProtectionLog
;
32 class BounceTrackingProtectionStorage final
: public nsIObserver
,
33 public nsIAsyncShutdownBlocker
,
34 public SupportsWeakPtr
{
35 friend class BounceTrackingStateGlobal
;
37 NS_DECL_THREADSAFE_ISUPPORTS
39 NS_DECL_NSIASYNCSHUTDOWNBLOCKER
42 BounceTrackingProtectionStorage()
43 : mMonitor("mozilla::BounceTrackingProtectionStorage::mMonitor"),
46 // Initialises the storage including the on-disk database.
47 [[nodiscard
]] nsresult
Init();
49 // Getters for mStateGlobal.
50 RefPtr
<BounceTrackingStateGlobal
> GetStateGlobal(
51 const OriginAttributes
& aOriginAttributes
);
53 RefPtr
<BounceTrackingStateGlobal
> GetStateGlobal(nsIPrincipal
* aPrincipal
);
55 RefPtr
<BounceTrackingStateGlobal
> GetOrCreateStateGlobal(
56 const OriginAttributes
& aOriginAttributes
);
58 RefPtr
<BounceTrackingStateGlobal
> GetOrCreateStateGlobal(
59 nsIPrincipal
* aPrincipal
);
61 RefPtr
<BounceTrackingStateGlobal
> GetOrCreateStateGlobal(
62 BounceTrackingState
* aBounceTrackingState
);
64 using StateGlobalMap
=
65 nsTHashMap
<OriginAttributesHashKey
, RefPtr
<BounceTrackingStateGlobal
>>;
66 // Provides a read-only reference to the state global map.
67 const StateGlobalMap
& StateGlobalMapRef() { return mStateGlobal
; }
69 // The enum values match the database type field. Updating them requires a DB
71 enum class EntryType
: uint8_t { BounceTracker
= 0, UserActivation
= 1 };
73 // Clear all user activation or bounce tracker entries.
74 [[nodiscard
]] nsresult
ClearByType(
75 BounceTrackingProtectionStorage::EntryType aType
);
77 // Clear all state for a given site host. If aOriginAttributes is passed, only
78 // entries for that OA will be deleted.
79 [[nodiscard
]] nsresult
ClearBySiteHost(const nsACString
& aSiteHost
,
80 OriginAttributes
* aOriginAttributes
);
82 // Clear all state within a given time range.
83 [[nodiscard
]] nsresult
ClearByTimeRange(PRTime aFrom
, PRTime aTo
);
85 // Clear all state for a given OriginAttributesPattern.
86 // Optional filtering for site host via aSiteHost.
87 [[nodiscard
]] nsresult
ClearByOriginAttributesPattern(
88 const OriginAttributesPattern
& aOriginAttributesPattern
,
89 const Maybe
<nsCString
>& aSiteHost
= Nothing());
92 [[nodiscard
]] nsresult
Clear();
95 [[nodiscard
]] nsresult
InitInternal();
97 ~BounceTrackingProtectionStorage() = default;
99 // Worker thread. This should be a valid thread after Init() returns and be
100 // destroyed when we finalize
101 nsCOMPtr
<nsISerialEventTarget
> mBackgroundThread
; // main thread only
103 // Database connections. Guaranteed to be non-null and working once
104 // initialized and not-yet finalized
105 RefPtr
<mozIStorageConnection
> mDatabaseConnection
; // Worker thread only
107 // Wait (non-blocking) until the service is fully initialized. We may be
108 // waiting for that async work started by Init().
109 [[nodiscard
]] nsresult
WaitForInitialization();
111 // Called to indicate to the async shutdown service that we are all wrapped
112 // up. This also spins down the worker thread, since it is called after all
113 // disk database connections are closed.
116 // Utility function to grab the correct barrier this service needs to shut
118 already_AddRefed
<nsIAsyncShutdownClient
> GetAsyncShutdownBarrier() const;
120 // Initialises the DB connection on the worker thread.
121 [[nodiscard
]] nsresult
CreateDatabaseConnection();
123 // Creates amd initialises the database table if needed. Worker thread only.
124 [[nodiscard
]] nsresult
EnsureTable();
126 // Temporary data structure used to import db data into memory.
128 OriginAttributes mOriginAttributes
;
130 EntryType mEntryType
;
134 // Imports state from the database on disk into memory.
135 [[nodiscard
]] nsresult
LoadMemoryStateFromDisk();
137 // Used to (thread-safely) track how many operations have been launched to the
138 // worker thread so that we can wait for it to hit zero before close the disk
139 // database connection
140 void IncrementPendingWrites();
141 void DecrementPendingWrites();
143 // Update or create database entry. Worker thread only.
144 [[nodiscard
]] static nsresult
UpsertData(
145 mozIStorageConnection
* aDatabaseConnection
,
146 const OriginAttributes
& aOriginAttributes
, const nsACString
& aSiteHost
,
147 EntryType aEntryType
, PRTime aTimeStamp
);
149 // Delete database entries. Worker thread only.
150 [[nodiscard
]] static nsresult
DeleteData(
151 mozIStorageConnection
* aDatabaseConnection
,
152 Maybe
<OriginAttributes
> aOriginAttributes
, const nsACString
& aSiteHost
);
154 // Delete all entries before a given time. Worker thread only.
155 // If aEntryType is passed only entries of that type will be deleted.
156 [[nodiscard
]] static nsresult
DeleteDataInTimeRange(
157 mozIStorageConnection
* aDatabaseConnection
,
158 Maybe
<OriginAttributes
> aOriginAttributes
, PRTime aFrom
,
160 Maybe
<BounceTrackingProtectionStorage::EntryType
> aEntryType
= Nothing
{});
162 // Delete all entries of a specific type.
163 // aOriginAttributes can be passed
164 [[nodiscard
]] nsresult
DeleteDataByType(
165 mozIStorageConnection
* aDatabaseConnection
,
166 const Maybe
<OriginAttributes
>& aOriginAttributes
,
167 BounceTrackingProtectionStorage::EntryType aEntryType
);
169 // Delete all entries matching the given OriginAttributesPattern. Worker
170 // thread only. May pass aSiteHost for additional filtering.
171 [[nodiscard
]] static nsresult
DeleteDataByOriginAttributesPattern(
172 mozIStorageConnection
* aDatabaseConnection
,
173 const OriginAttributesPattern
& aOriginAttributesPattern
,
174 const Maybe
<nsCString
>& aSiteHost
= Nothing());
176 // Clear all entries from the database.
177 [[nodiscard
]] static nsresult
ClearData(
178 mozIStorageConnection
* aDatabaseConnection
);
180 // Service state management. We protect these variables with a monitor. This
181 // monitor is also used to signal the completion of initialization and
182 // finalization performed in the worker thread.
185 FlippedOnce
<false> mInitialized
MOZ_GUARDED_BY(mMonitor
);
186 FlippedOnce
<false> mErrored
MOZ_GUARDED_BY(mMonitor
);
187 FlippedOnce
<false> mShuttingDown
MOZ_GUARDED_BY(mMonitor
);
188 uint32_t mPendingWrites
MOZ_GUARDED_BY(mMonitor
);
190 // The database file handle. We can only create this in the main thread and
191 // need it in the worker to perform blocking disk IO. So we put it on this,
192 // since we pass this to the worker anyway
193 nsCOMPtr
<nsIFile
> mDatabaseFile
;
195 // Map of origin attributes to global state object. This enables us to track
196 // bounce tracking state per OA, e.g. to separate private browsing from normal
198 StateGlobalMap mStateGlobal
{};
200 // Helpers used to sync updates to BounceTrackingStateGlobal with the
203 // Updates or inserts a DB entry keyed by OA + site host.
204 [[nodiscard
]] nsresult
UpdateDBEntry(
205 const OriginAttributes
& aOriginAttributes
, const nsACString
& aSiteHost
,
206 EntryType aEntryType
, PRTime aTimeStamp
);
208 // Deletes a DB entry keyed by OA + site host. If only aSiteHost is passed,
209 // all entries for that host will be deleted across OriginAttributes.
210 [[nodiscard
]] nsresult
DeleteDBEntries(OriginAttributes
* aOriginAttributes
,
211 const nsACString
& aSiteHost
);
213 // Delete all DB entries before a given time.
214 // If aEntryType is passed only entries of that type will be deleted.
215 [[nodiscard
]] nsresult
DeleteDBEntriesInTimeRange(
216 OriginAttributes
* aOriginAttributes
, PRTime aFrom
,
217 Maybe
<PRTime
> aTo
= Nothing
{}, Maybe
<EntryType
> aEntryType
= Nothing
{});
219 // Delete all DB entries matching the given type.
220 // If aOriginAttributes is passed it acts as an additional filter.
221 [[nodiscard
]] nsresult
DeleteDBEntriesByType(
222 OriginAttributes
* aOriginAttributes
,
223 BounceTrackingProtectionStorage::EntryType aEntryType
);
225 // Deletes all DB entries matching the given OriginAttributesPattern.
226 // Pass aSiteHost for additional filtering. By default all site hosts are
228 [[nodiscard
]] nsresult
DeleteDBEntriesByOriginAttributesPattern(
229 const OriginAttributesPattern
& aOriginAttributesPattern
,
230 const Maybe
<nsCString
>& aSiteHost
= Nothing());
233 // A SQL function to match DB entries by OriginAttributesPattern.
234 class OriginAttrsPatternMatchOASuffixSQLFunction final
235 : public mozIStorageFunction
{
237 NS_DECL_MOZISTORAGEFUNCTION
239 explicit OriginAttrsPatternMatchOASuffixSQLFunction(
240 OriginAttributesPattern
const& aPattern
)
241 : mPattern(aPattern
) {}
242 OriginAttrsPatternMatchOASuffixSQLFunction() = delete;
245 ~OriginAttrsPatternMatchOASuffixSQLFunction() = default;
247 OriginAttributesPattern mPattern
;
250 } // namespace mozilla
252 #endif // mozilla_BounceTrackingProtectionStorage_h__