/src/mozilla-central/toolkit/components/url-classifier/nsUrlClassifierDBService.h
Line | Count | Source (jump to first uncovered line) |
1 | | //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-/ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #ifndef nsUrlClassifierDBService_h_ |
7 | | #define nsUrlClassifierDBService_h_ |
8 | | |
9 | | #include <nsISupportsUtils.h> |
10 | | |
11 | | #include "nsID.h" |
12 | | #include "nsInterfaceHashtable.h" |
13 | | #include "nsIObserver.h" |
14 | | #include "nsUrlClassifierPrefixSet.h" |
15 | | #include "nsIUrlClassifierHashCompleter.h" |
16 | | #include "nsIUrlListManager.h" |
17 | | #include "nsIUrlClassifierDBService.h" |
18 | | #include "nsIUrlClassifierInfo.h" |
19 | | #include "nsIURIClassifier.h" |
20 | | #include "nsToolkitCompsCID.h" |
21 | | #include "nsICryptoHMAC.h" |
22 | | #include "mozilla/Attributes.h" |
23 | | #include "mozilla/Mutex.h" |
24 | | #include "mozilla/TimeStamp.h" |
25 | | |
26 | | #include "Entries.h" |
27 | | #include "LookupCache.h" |
28 | | #include "HashStore.h" |
29 | | |
30 | | // GCC < 6.1 workaround, see bug 1329593 |
31 | | #if defined(XP_WIN) && defined(__MINGW32__) |
32 | | #define GCC_MANGLING_WORKAROUND __stdcall |
33 | | #else |
34 | | #define GCC_MANGLING_WORKAROUND |
35 | | #endif |
36 | | |
37 | | // The hash length for a domain key. |
38 | | #define DOMAIN_LENGTH 4 |
39 | | |
40 | | // The hash length of a partial hash entry. |
41 | | #define PARTIAL_LENGTH 4 |
42 | | |
43 | | // The hash length of a complete hash entry. |
44 | | #define COMPLETE_LENGTH 32 |
45 | | |
46 | | // Prefs for implementing nsIURIClassifier to block page loads |
47 | 0 | #define CHECK_MALWARE_PREF "browser.safebrowsing.malware.enabled" |
48 | 0 | #define CHECK_MALWARE_DEFAULT false |
49 | | |
50 | 0 | #define CHECK_PHISHING_PREF "browser.safebrowsing.phishing.enabled" |
51 | 0 | #define CHECK_PHISHING_DEFAULT false |
52 | | |
53 | 0 | #define CHECK_BLOCKED_PREF "browser.safebrowsing.blockedURIs.enabled" |
54 | 0 | #define CHECK_BLOCKED_DEFAULT false |
55 | | |
56 | | // Comma-separated lists |
57 | 0 | #define MALWARE_TABLE_PREF "urlclassifier.malwareTable" |
58 | 0 | #define PHISH_TABLE_PREF "urlclassifier.phishTable" |
59 | 0 | #define TRACKING_TABLE_PREF "urlclassifier.trackingTable" |
60 | 0 | #define TRACKING_TABLE_TEST_ENTRIES_PREF "urlclassifier.trackingTable.testEntries" |
61 | 0 | #define TRACKING_WHITELIST_TABLE_PREF "urlclassifier.trackingWhitelistTable" |
62 | 0 | #define TRACKING_WHITELIST_TABLE_TEST_ENTRIES_PREF "urlclassifier.trackingWhitelistTable.testEntries" |
63 | 0 | #define BLOCKED_TABLE_PREF "urlclassifier.blockedTable" |
64 | 0 | #define DOWNLOAD_BLOCK_TABLE_PREF "urlclassifier.downloadBlockTable" |
65 | 0 | #define DOWNLOAD_ALLOW_TABLE_PREF "urlclassifier.downloadAllowTable" |
66 | 0 | #define DISALLOW_COMPLETION_TABLE_PREF "urlclassifier.disallow_completions" |
67 | 0 | #define PASSWORD_ALLOW_TABLE_PREF "urlclassifier.passwordAllowTable" |
68 | | |
69 | | using namespace mozilla::safebrowsing; |
70 | | |
71 | | class nsUrlClassifierDBServiceWorker; |
72 | | class nsIThread; |
73 | | class nsIURI; |
74 | | class UrlClassifierDBServiceWorkerProxy; |
75 | | namespace mozilla { |
76 | | namespace safebrowsing { |
77 | | class Classifier; |
78 | | class ProtocolParser; |
79 | | |
80 | | nsresult |
81 | | TablesToResponse(const nsACString& tables); |
82 | | |
83 | | } // namespace safebrowsing |
84 | | } // namespace mozilla |
85 | | |
86 | | // This is a proxy class that just creates a background thread and delegates |
87 | | // calls to the background thread. |
88 | | class nsUrlClassifierDBService final : public nsIUrlClassifierDBService, |
89 | | public nsIURIClassifier, |
90 | | public nsIUrlClassifierInfo, |
91 | | public nsIObserver |
92 | | { |
93 | | public: |
94 | | // This is thread safe. It throws an exception if the thread is busy. |
95 | | nsUrlClassifierDBService(); |
96 | | |
97 | | nsresult Init(); |
98 | | |
99 | | static nsUrlClassifierDBService* GetInstance(nsresult *result); |
100 | | |
101 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_URLCLASSIFIERDBSERVICE_CID) |
102 | | |
103 | | NS_DECL_THREADSAFE_ISUPPORTS |
104 | | NS_DECL_NSIURLCLASSIFIERDBSERVICE |
105 | | NS_DECL_NSIURICLASSIFIER |
106 | | NS_DECL_NSIURLCLASSIFIERINFO |
107 | | NS_DECL_NSIOBSERVER |
108 | | |
109 | | bool CanComplete(const nsACString &tableName); |
110 | | bool GetCompleter(const nsACString& tableName, |
111 | | nsIUrlClassifierHashCompleter** completer); |
112 | | nsresult CacheCompletions(const mozilla::safebrowsing::ConstCacheResultArray& results); |
113 | | |
114 | | static nsIThread* BackgroundThread(); |
115 | | |
116 | | static bool ShutdownHasStarted(); |
117 | | |
118 | | private: |
119 | | |
120 | | const nsTArray<nsCString> kObservedPrefs = { |
121 | | NS_LITERAL_CSTRING(CHECK_MALWARE_PREF), |
122 | | NS_LITERAL_CSTRING(CHECK_PHISHING_PREF), |
123 | | NS_LITERAL_CSTRING(CHECK_BLOCKED_PREF), |
124 | | NS_LITERAL_CSTRING(MALWARE_TABLE_PREF), |
125 | | NS_LITERAL_CSTRING(PHISH_TABLE_PREF), |
126 | | NS_LITERAL_CSTRING(TRACKING_TABLE_PREF), |
127 | | NS_LITERAL_CSTRING(TRACKING_TABLE_TEST_ENTRIES_PREF), |
128 | | NS_LITERAL_CSTRING(TRACKING_WHITELIST_TABLE_PREF), |
129 | | NS_LITERAL_CSTRING(TRACKING_WHITELIST_TABLE_TEST_ENTRIES_PREF), |
130 | | NS_LITERAL_CSTRING(BLOCKED_TABLE_PREF), |
131 | | NS_LITERAL_CSTRING(DOWNLOAD_BLOCK_TABLE_PREF), |
132 | | NS_LITERAL_CSTRING(DOWNLOAD_ALLOW_TABLE_PREF), |
133 | | NS_LITERAL_CSTRING(DISALLOW_COMPLETION_TABLE_PREF) |
134 | | }; |
135 | | |
136 | | // No subclassing |
137 | | ~nsUrlClassifierDBService(); |
138 | | |
139 | | // Disallow copy constructor |
140 | | nsUrlClassifierDBService(nsUrlClassifierDBService&); |
141 | | |
142 | | nsresult LookupURI(nsIPrincipal* aPrincipal, |
143 | | const nsACString& tables, |
144 | | const nsTArray<nsCString>& extraTablesByPrefs, |
145 | | const nsTArray<nsCString>& extraEntriesByPrefs, |
146 | | nsIUrlClassifierCallback* c, |
147 | | bool forceCheck, bool *didCheck); |
148 | | |
149 | | // Post an event to worker thread to release objects when receive 'quit-application' |
150 | | nsresult PreShutdown(); |
151 | | |
152 | | // Close db connection and join the background thread if it exists. |
153 | | nsresult Shutdown(); |
154 | | |
155 | | nsresult ReadTablesFromPrefs(); |
156 | | |
157 | | RefPtr<nsUrlClassifierDBServiceWorker> mWorker; |
158 | | RefPtr<UrlClassifierDBServiceWorkerProxy> mWorkerProxy; |
159 | | |
160 | | nsInterfaceHashtable<nsCStringHashKey, nsIUrlClassifierHashCompleter> mCompleters; |
161 | | |
162 | | // TRUE if the nsURIClassifier implementation should check for malware |
163 | | // uris on document loads. |
164 | | bool mCheckMalware; |
165 | | |
166 | | // TRUE if the nsURIClassifier implementation should check for phishing |
167 | | // uris on document loads. |
168 | | bool mCheckPhishing; |
169 | | |
170 | | // TRUE if the nsURIClassifier implementation should check for blocked |
171 | | // uris on document loads. |
172 | | bool mCheckBlockedURIs; |
173 | | |
174 | | // TRUE if a BeginUpdate() has been called without an accompanying |
175 | | // CancelUpdate()/FinishUpdate(). This is used to prevent competing |
176 | | // updates, not to determine whether an update is still being |
177 | | // processed. |
178 | | bool mInUpdate; |
179 | | |
180 | | // The list of tables that can use the default hash completer object. |
181 | | nsTArray<nsCString> mGethashTables; |
182 | | |
183 | | // The list of tables that should never be hash completed. |
184 | | nsTArray<nsCString> mDisallowCompletionsTables; |
185 | | |
186 | | // Comma-separated list of tables to use in lookups. |
187 | | nsCString mTrackingProtectionTables; |
188 | | nsCString mBaseTables; |
189 | | |
190 | | // Comma-separated hosts set by prefs to use in lookups. |
191 | | nsCString mTrackingProtectionWhitelistExtraEntriesByPrefs; |
192 | | nsCString mTrackingProtectionBlacklistExtraEntriesByPrefs; |
193 | | |
194 | | // Thread that we do the updates on. |
195 | | static nsIThread* gDbBackgroundThread; |
196 | | }; |
197 | | |
198 | | class nsUrlClassifierDBServiceWorker final : public nsIUrlClassifierDBService |
199 | | { |
200 | | public: |
201 | | nsUrlClassifierDBServiceWorker(); |
202 | | |
203 | | NS_DECL_THREADSAFE_ISUPPORTS |
204 | | NS_DECL_NSIURLCLASSIFIERDBSERVICE |
205 | | |
206 | | nsresult Init(uint32_t aGethashNoise, |
207 | | nsCOMPtr<nsIFile> aCacheDir, |
208 | | nsUrlClassifierDBService* aDBService); |
209 | | |
210 | | // Queue a lookup for the worker to perform, called in the main thread. |
211 | | // tables is a comma-separated list of tables to query |
212 | | nsresult QueueLookup(const nsACString& lookupKey, |
213 | | const nsACString& tables, |
214 | | nsIUrlClassifierLookupCallback* callback); |
215 | | |
216 | | // Handle any queued-up lookups. We call this function during long-running |
217 | | // update operations to prevent lookups from blocking for too long. |
218 | | nsresult HandlePendingLookups(); |
219 | | |
220 | | // Perform a blocking classifier lookup for a given url. Can be called on |
221 | | // either the main thread or the worker thread. |
222 | | nsresult DoLocalLookup(const nsACString& spec, |
223 | | const nsACString& tables, |
224 | | LookupResultArray& results); |
225 | | |
226 | | // Open the DB connection |
227 | | nsresult GCC_MANGLING_WORKAROUND OpenDb(); |
228 | | |
229 | | // Provide a way to forcibly close the db connection. |
230 | | nsresult GCC_MANGLING_WORKAROUND CloseDb(); |
231 | | |
232 | | nsresult GCC_MANGLING_WORKAROUND PreShutdown(); |
233 | | |
234 | | nsresult CacheCompletions(const ConstCacheResultArray& aEntries); |
235 | | |
236 | | // Used to probe the state of the worker thread. When the update begins, |
237 | | // mUpdateObserver will be set. When the update finished, mUpdateObserver |
238 | | // will be nulled out in NotifyUpdateObserver. |
239 | 0 | bool IsBusyUpdating() const { return !!mUpdateObserver; } |
240 | | |
241 | | // Check the DB ready state of the worker thread |
242 | 0 | bool IsDBOpened() const { return !!mClassifier; } |
243 | | |
244 | | // Delegate Classifier to disable async update. If there is an |
245 | | // ongoing update on the update thread, we will be blocked until |
246 | | // the background update is done and callback is fired. |
247 | | // Should be called on the worker thread. |
248 | | void FlushAndDisableAsyncUpdate(); |
249 | | |
250 | | // A synchronous call to get cache information for the given table. |
251 | | // This is only used by about:url-classifier now. |
252 | | nsresult GetCacheInfo(const nsACString& aTable, |
253 | | nsIUrlClassifierCacheInfo** aCache); |
254 | | private: |
255 | | // No subclassing |
256 | | ~nsUrlClassifierDBServiceWorker(); |
257 | | |
258 | | // Disallow copy constructor |
259 | | nsUrlClassifierDBServiceWorker(nsUrlClassifierDBServiceWorker&); |
260 | | |
261 | | nsresult NotifyUpdateObserver(nsresult aUpdateStatus); |
262 | | |
263 | | // Reset the in-progress update stream |
264 | | void ResetStream(); |
265 | | |
266 | | // Reset the in-progress update |
267 | | void ResetUpdate(); |
268 | | |
269 | | // Perform a classifier lookup for a given url. |
270 | | nsresult DoLookup(const nsACString& spec, |
271 | | const nsACString& tables, |
272 | | nsIUrlClassifierLookupCallback* c); |
273 | | |
274 | | nsresult AddNoise(const Prefix aPrefix, |
275 | | const nsCString tableName, |
276 | | uint32_t aCount, |
277 | | LookupResultArray& results); |
278 | | |
279 | | nsresult CacheResultToTableUpdate(RefPtr<const CacheResult> aCacheResult, |
280 | | RefPtr<TableUpdate> aUpdate); |
281 | | |
282 | | bool IsSameAsLastResults(const ConstCacheResultArray& aResult) const; |
283 | | |
284 | | RefPtr<mozilla::safebrowsing::Classifier> mClassifier; |
285 | | // The class that actually parses the update chunks. |
286 | | mozilla::UniquePtr<ProtocolParser> mProtocolParser; |
287 | | |
288 | | // Directory where to store the SB databases. |
289 | | nsCOMPtr<nsIFile> mCacheDir; |
290 | | |
291 | | RefPtr<nsUrlClassifierDBService> mDBService; |
292 | | |
293 | | TableUpdateArray mTableUpdates; |
294 | | |
295 | | uint32_t mUpdateWaitSec; |
296 | | |
297 | | // Stores the last results that triggered a table update. |
298 | | ConstCacheResultArray mLastResults; |
299 | | |
300 | | nsresult mUpdateStatus; |
301 | | nsTArray<nsCString> mUpdateTables; |
302 | | |
303 | | nsCOMPtr<nsIUrlClassifierUpdateObserver> mUpdateObserver; |
304 | | bool mInStream; |
305 | | |
306 | | // The number of noise entries to add to the set of lookup results. |
307 | | uint32_t mGethashNoise; |
308 | | |
309 | | // Pending lookups are stored in a queue for processing. The queue |
310 | | // is protected by mPendingLookupLock. |
311 | | mozilla::Mutex mPendingLookupLock; |
312 | | |
313 | | class PendingLookup { |
314 | | public: |
315 | | mozilla::TimeStamp mStartTime; |
316 | | nsCString mKey; |
317 | | nsCString mTables; |
318 | | nsCOMPtr<nsIUrlClassifierLookupCallback> mCallback; |
319 | | }; |
320 | | |
321 | | // list of pending lookups |
322 | | nsTArray<PendingLookup> mPendingLookups; |
323 | | |
324 | | #ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES |
325 | | // The raw update response for debugging. |
326 | | nsCString mRawTableUpdates; |
327 | | #endif |
328 | | }; |
329 | | |
330 | | NS_DEFINE_STATIC_IID_ACCESSOR(nsUrlClassifierDBService, NS_URLCLASSIFIERDBSERVICE_CID) |
331 | | |
332 | | #endif // nsUrlClassifierDBService_h_ |