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