/src/mozilla-central/extensions/cookie/nsPermissionManager.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsPermissionManager_h__ |
8 | | #define nsPermissionManager_h__ |
9 | | |
10 | | #include "nsIPermissionManager.h" |
11 | | #include "nsIObserver.h" |
12 | | #include "nsWeakReference.h" |
13 | | #include "nsCOMPtr.h" |
14 | | #include "nsIInputStream.h" |
15 | | #include "nsTHashtable.h" |
16 | | #include "nsTArray.h" |
17 | | #include "nsString.h" |
18 | | #include "nsPermission.h" |
19 | | #include "nsIPrefBranch.h" |
20 | | #include "nsHashKeys.h" |
21 | | #include "nsCOMArray.h" |
22 | | #include "nsDataHashtable.h" |
23 | | #include "nsIRunnable.h" |
24 | | #include "nsRefPtrHashtable.h" |
25 | | #include "mozilla/MozPromise.h" |
26 | | |
27 | | namespace mozilla { |
28 | | class OriginAttributesPattern; |
29 | | } |
30 | | |
31 | | class nsIPermission; |
32 | | class mozIStorageConnection; |
33 | | class mozIStorageAsyncStatement; |
34 | | |
35 | | //////////////////////////////////////////////////////////////////////////////// |
36 | | |
37 | | class nsPermissionManager final : public nsIPermissionManager, |
38 | | public nsIObserver, |
39 | | public nsSupportsWeakReference |
40 | | { |
41 | | public: |
42 | | class PermissionEntry |
43 | | { |
44 | | public: |
45 | | PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission, |
46 | | uint32_t aExpireType, int64_t aExpireTime, |
47 | | int64_t aModificationTime) |
48 | | : mID(aID) |
49 | | , mType(aType) |
50 | | , mPermission(aPermission) |
51 | | , mExpireType(aExpireType) |
52 | | , mExpireTime(aExpireTime) |
53 | | , mModificationTime(aModificationTime) |
54 | | , mNonSessionPermission(aPermission) |
55 | | , mNonSessionExpireType(aExpireType) |
56 | | , mNonSessionExpireTime(aExpireTime) |
57 | 0 | {} |
58 | | |
59 | | int64_t mID; |
60 | | uint32_t mType; |
61 | | uint32_t mPermission; |
62 | | uint32_t mExpireType; |
63 | | int64_t mExpireTime; |
64 | | int64_t mModificationTime; |
65 | | uint32_t mNonSessionPermission; |
66 | | uint32_t mNonSessionExpireType; |
67 | | uint32_t mNonSessionExpireTime; |
68 | | }; |
69 | | |
70 | | /** |
71 | | * PermissionKey is the key used by PermissionHashKey hash table. |
72 | | * |
73 | | * NOTE: It could be implementing nsIHashable but there is no reason to worry |
74 | | * with XPCOM interfaces while we don't need to. |
75 | | */ |
76 | | class PermissionKey |
77 | | { |
78 | | public: |
79 | | static PermissionKey* CreateFromPrincipal(nsIPrincipal* aPrincipal, |
80 | | nsresult& aResult); |
81 | | static PermissionKey* CreateFromURI(nsIURI* aURI, |
82 | | nsresult& aResult); |
83 | | |
84 | | explicit PermissionKey(const nsACString& aOrigin) |
85 | | : mOrigin(aOrigin) |
86 | 0 | { |
87 | 0 | } |
88 | | |
89 | 0 | bool operator==(const PermissionKey& aKey) const { |
90 | 0 | return mOrigin.Equals(aKey.mOrigin); |
91 | 0 | } |
92 | | |
93 | 0 | PLDHashNumber GetHashCode() const { |
94 | 0 | return mozilla::HashString(mOrigin); |
95 | 0 | } |
96 | | |
97 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey) |
98 | | |
99 | | nsCString mOrigin; |
100 | | |
101 | | private: |
102 | | // Default ctor shouldn't be used. |
103 | | PermissionKey() = delete; |
104 | | |
105 | | // Dtor shouldn't be used outside of the class. |
106 | 0 | ~PermissionKey() {}; |
107 | | }; |
108 | | |
109 | | class PermissionHashKey : public nsRefPtrHashKey<PermissionKey> |
110 | | { |
111 | | public: |
112 | | explicit PermissionHashKey(const PermissionKey* aPermissionKey) |
113 | | : nsRefPtrHashKey<PermissionKey>(aPermissionKey) |
114 | 0 | {} |
115 | | |
116 | | PermissionHashKey(PermissionHashKey&& toCopy) |
117 | | : nsRefPtrHashKey<PermissionKey>(std::move(toCopy)) |
118 | | , mPermissions(std::move(toCopy.mPermissions)) |
119 | 0 | {} |
120 | | |
121 | | bool KeyEquals(const PermissionKey* aKey) const |
122 | 0 | { |
123 | 0 | return *aKey == *GetKey(); |
124 | 0 | } |
125 | | |
126 | | static PLDHashNumber HashKey(const PermissionKey* aKey) |
127 | 0 | { |
128 | 0 | return aKey->GetHashCode(); |
129 | 0 | } |
130 | | |
131 | | // Force the hashtable to use the copy constructor when shuffling entries |
132 | | // around, otherwise the Auto part of our AutoTArray won't be happy! |
133 | | enum { ALLOW_MEMMOVE = false }; |
134 | | |
135 | | inline nsTArray<PermissionEntry> & GetPermissions() |
136 | 0 | { |
137 | 0 | return mPermissions; |
138 | 0 | } |
139 | | |
140 | | inline int32_t GetPermissionIndex(uint32_t aType) const |
141 | 0 | { |
142 | 0 | for (uint32_t i = 0; i < mPermissions.Length(); ++i) |
143 | 0 | if (mPermissions[i].mType == aType) |
144 | 0 | return i; |
145 | 0 |
|
146 | 0 | return -1; |
147 | 0 | } |
148 | | |
149 | | inline PermissionEntry GetPermission(uint32_t aType) const |
150 | 0 | { |
151 | 0 | for (uint32_t i = 0; i < mPermissions.Length(); ++i) |
152 | 0 | if (mPermissions[i].mType == aType) |
153 | 0 | return mPermissions[i]; |
154 | 0 |
|
155 | 0 | // unknown permission... return relevant data |
156 | 0 | return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION, |
157 | 0 | nsIPermissionManager::EXPIRE_NEVER, 0, 0); |
158 | 0 | } |
159 | | |
160 | | private: |
161 | | AutoTArray<PermissionEntry, 1> mPermissions; |
162 | | }; |
163 | | |
164 | | // nsISupports |
165 | | NS_DECL_ISUPPORTS |
166 | | NS_DECL_NSIPERMISSIONMANAGER |
167 | | NS_DECL_NSIOBSERVER |
168 | | |
169 | | nsPermissionManager(); |
170 | | static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton(); |
171 | | nsresult Init(); |
172 | | |
173 | | // enums for AddInternal() |
174 | | enum OperationType { |
175 | | eOperationNone, |
176 | | eOperationAdding, |
177 | | eOperationRemoving, |
178 | | eOperationChanging, |
179 | | eOperationReplacingDefault |
180 | | }; |
181 | | |
182 | | enum DBOperationType { |
183 | | eNoDBOperation, |
184 | | eWriteToDB |
185 | | }; |
186 | | |
187 | | enum NotifyOperationType { |
188 | | eDontNotify, |
189 | | eNotify |
190 | | }; |
191 | | |
192 | | // A special value for a permission ID that indicates the ID was loaded as |
193 | | // a default value. These will never be written to the database, but may |
194 | | // be overridden with an explicit permission (including UNKNOWN_ACTION) |
195 | | static const int64_t cIDPermissionIsDefault = -1; |
196 | | |
197 | | nsresult AddInternal(nsIPrincipal* aPrincipal, |
198 | | const nsCString& aType, |
199 | | uint32_t aPermission, |
200 | | int64_t aID, |
201 | | uint32_t aExpireType, |
202 | | int64_t aExpireTime, |
203 | | int64_t aModificationTime, |
204 | | NotifyOperationType aNotifyOperation, |
205 | | DBOperationType aDBOperation, |
206 | | const bool aIgnoreSessionPermissions = false); |
207 | | |
208 | | /** |
209 | | * Initialize the "clear-origin-attributes-data" observing. |
210 | | * Will create a nsPermissionManager instance if needed. |
211 | | * That way, we can prevent have nsPermissionManager created at startup just |
212 | | * to be able to clear data when an application is uninstalled. |
213 | | */ |
214 | | static void ClearOriginDataObserverInit(); |
215 | | |
216 | | nsresult |
217 | | RemovePermissionsWithAttributes(mozilla::OriginAttributesPattern& aAttrs); |
218 | | |
219 | | /** |
220 | | * See `nsIPermissionManager::GetPermissionsWithKey` for more info on |
221 | | * permission keys. |
222 | | * |
223 | | * Get the permission key corresponding to the given Principal. This method is |
224 | | * intentionally infallible, as we want to provide an permission key to every |
225 | | * principal. Principals which don't have meaningful URIs with http://, |
226 | | * https://, or ftp:// schemes are given the default "" Permission Key. |
227 | | * |
228 | | * @param aPrincipal The Principal which the key is to be extracted from. |
229 | | * @param aPermissionKey A string which will be filled with the permission key. |
230 | | */ |
231 | | static void GetKeyForPrincipal(nsIPrincipal* aPrincipal, nsACString& aPermissionKey); |
232 | | |
233 | | /** |
234 | | * See `nsIPermissionManager::GetPermissionsWithKey` for more info on |
235 | | * permission keys. |
236 | | * |
237 | | * Get the permission key corresponding to the given Origin. This method is |
238 | | * like GetKeyForPrincipal, except that it avoids creating a nsIPrincipal |
239 | | * object when you already have access to an origin string. |
240 | | * |
241 | | * If this method is passed a nonsensical origin string it may produce a |
242 | | * nonsensical permission key result. |
243 | | * |
244 | | * @param aOrigin The origin which the key is to be extracted from. |
245 | | * @param aPermissionKey A string which will be filled with the permission key. |
246 | | */ |
247 | | static void GetKeyForOrigin(const nsACString& aOrigin, nsACString& aPermissionKey); |
248 | | |
249 | | /** |
250 | | * See `nsIPermissionManager::GetPermissionsWithKey` for more info on |
251 | | * permission keys. |
252 | | * |
253 | | * Get the permission key corresponding to the given Principal and type. This |
254 | | * method is intentionally infallible, as we want to provide an permission key |
255 | | * to every principal. Principals which don't have meaningful URIs with |
256 | | * http://, https://, or ftp:// schemes are given the default "" Permission |
257 | | * Key. |
258 | | * |
259 | | * This method is different from GetKeyForPrincipal in that it also takes |
260 | | * permissions which must be sent down before loading a document into account. |
261 | | * |
262 | | * @param aPrincipal The Principal which the key is to be extracted from. |
263 | | * @param aType The type of the permission to get the key for. |
264 | | * @param aPermissionKey A string which will be filled with the permission key. |
265 | | */ |
266 | | static void GetKeyForPermission(nsIPrincipal* aPrincipal, |
267 | | const char* aType, |
268 | | nsACString& aPermissionKey); |
269 | | |
270 | | /** |
271 | | * See `nsIPermissionManager::GetPermissionsWithKey` for more info on |
272 | | * permission keys. |
273 | | * |
274 | | * Get all permissions keys which could correspond to the given principal. |
275 | | * This method, like GetKeyForPrincipal, is infallible and should always |
276 | | * produce at least one key. |
277 | | * |
278 | | * Unlike GetKeyForPrincipal, this method also gets the keys for base domains |
279 | | * of the given principal. All keys returned by this method must be available |
280 | | * in the content process for a given URL to successfully have its permissions |
281 | | * checked in the `aExactHostMatch = false` situation. |
282 | | * |
283 | | * @param aPrincipal The Principal which the key is to be extracted from. |
284 | | */ |
285 | | static nsTArray<nsCString> GetAllKeysForPrincipal(nsIPrincipal* aPrincipal); |
286 | | |
287 | | // From ContentChild. |
288 | | nsresult RemoveAllFromIPC(); |
289 | | |
290 | | private: |
291 | | virtual ~nsPermissionManager(); |
292 | | |
293 | | int32_t GetTypeIndex(const char *aTypeString, |
294 | | bool aAdd); |
295 | | |
296 | | PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal, |
297 | | uint32_t aType, |
298 | | bool aExactHostMatch); |
299 | | PermissionHashKey* GetPermissionHashKey(nsIURI* aURI, |
300 | | uint32_t aType, |
301 | | bool aExactHostMatch); |
302 | | |
303 | | nsresult CommonTestPermission(nsIPrincipal* aPrincipal, |
304 | | const char * aType, |
305 | | uint32_t * aPermission, |
306 | | bool aExactHostMatch, |
307 | | bool aIncludingSession) |
308 | 0 | { |
309 | 0 | return CommonTestPermissionInternal(aPrincipal, nullptr, aType, |
310 | 0 | aPermission, aExactHostMatch, |
311 | 0 | aIncludingSession); |
312 | 0 | } |
313 | | nsresult CommonTestPermission(nsIURI * aURI, |
314 | | const char* aType, |
315 | | uint32_t * aPermission, |
316 | | bool aExactHostMatch, |
317 | | bool aIncludingSession) |
318 | 0 | { |
319 | 0 | return CommonTestPermissionInternal(nullptr, aURI, aType, aPermission, |
320 | 0 | aExactHostMatch, aIncludingSession); |
321 | 0 | } |
322 | | // Only one of aPrincipal or aURI is allowed to be passed in. |
323 | | nsresult CommonTestPermissionInternal(nsIPrincipal* aPrincipal, |
324 | | nsIURI * aURI, |
325 | | const char * aType, |
326 | | uint32_t * aPermission, |
327 | | bool aExactHostMatch, |
328 | | bool aIncludingSession); |
329 | | |
330 | | nsresult OpenDatabase(nsIFile* permissionsFile); |
331 | | nsresult InitDB(bool aRemoveFile); |
332 | | nsresult CreateTable(); |
333 | | nsresult Import(); |
334 | | nsresult ImportDefaults(); |
335 | | nsresult _DoImport(nsIInputStream *inputStream, mozIStorageConnection *aConn); |
336 | | nsresult Read(); |
337 | | void NotifyObserversWithPermission(nsIPrincipal* aPrincipal, |
338 | | const nsCString &aType, |
339 | | uint32_t aPermission, |
340 | | uint32_t aExpireType, |
341 | | int64_t aExpireTime, |
342 | | const char16_t *aData); |
343 | | void NotifyObservers(nsIPermission *aPermission, const char16_t *aData); |
344 | | |
345 | | // Finalize all statements, close the DB and null it. |
346 | | // if aRebuildOnSuccess, reinitialize database |
347 | | void CloseDB(bool aRebuildOnSuccess = false); |
348 | | |
349 | | nsresult RemoveAllInternal(bool aNotifyObservers); |
350 | | nsresult RemoveAllFromMemory(); |
351 | | static void UpdateDB(OperationType aOp, |
352 | | mozIStorageAsyncStatement* aStmt, |
353 | | int64_t aID, |
354 | | const nsACString& aOrigin, |
355 | | const nsACString& aType, |
356 | | uint32_t aPermission, |
357 | | uint32_t aExpireType, |
358 | | int64_t aExpireTime, |
359 | | int64_t aModificationTime); |
360 | | |
361 | | /** |
362 | | * This method removes all permissions modified after the specified time. |
363 | | */ |
364 | | nsresult |
365 | | RemoveAllModifiedSince(int64_t aModificationTime); |
366 | | |
367 | | template<class T> |
368 | | nsresult |
369 | | RemovePermissionEntries(T aCondition); |
370 | | |
371 | | /** |
372 | | * Returns false if this permission manager wouldn't have the permission |
373 | | * requested available. |
374 | | * |
375 | | * If aType is nullptr, checks that the permission manager would have all |
376 | | * permissions available for the given principal. |
377 | | */ |
378 | | bool PermissionAvailable(nsIPrincipal* aPrincipal, const char* aType); |
379 | | |
380 | | nsRefPtrHashtable<nsCStringHashKey, mozilla::GenericPromise::Private> mPermissionKeyPromiseMap; |
381 | | |
382 | | nsCOMPtr<mozIStorageConnection> mDBConn; |
383 | | nsCOMPtr<mozIStorageAsyncStatement> mStmtInsert; |
384 | | nsCOMPtr<mozIStorageAsyncStatement> mStmtDelete; |
385 | | nsCOMPtr<mozIStorageAsyncStatement> mStmtUpdate; |
386 | | |
387 | | bool mMemoryOnlyDB; |
388 | | |
389 | | nsTHashtable<PermissionHashKey> mPermissionTable; |
390 | | // a unique, monotonically increasing id used to identify each database entry |
391 | | int64_t mLargestID; |
392 | | |
393 | | // An array to store the strings identifying the different types. |
394 | | nsTArray<nsCString> mTypeArray; |
395 | | |
396 | | // Initially, |false|. Set to |true| once shutdown has started, to avoid |
397 | | // reopening the database. |
398 | | bool mIsShuttingDown; |
399 | | |
400 | | nsCOMPtr<nsIPrefBranch> mDefaultPrefBranch; |
401 | | |
402 | | friend class DeleteFromMozHostListener; |
403 | | friend class CloseDatabaseListener; |
404 | | }; |
405 | | |
406 | | // {4F6B5E00-0C36-11d5-A535-0010A401EB10} |
407 | | #define NS_PERMISSIONMANAGER_CID \ |
408 | | { 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } |
409 | | |
410 | | #endif /* nsPermissionManager_h__ */ |