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/. */
7 #ifndef nsPermissionManager_h__
8 #define nsPermissionManager_h__
10 #include "nsIPermissionManager.h"
11 #include "nsIObserver.h"
12 #include "nsWeakReference.h"
14 #include "nsIInputStream.h"
15 #include "nsTHashtable.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"
28 class OriginAttributesPattern
;
32 class mozIStorageConnection
;
33 class mozIStorageAsyncStatement
;
35 ////////////////////////////////////////////////////////////////////////////////
37 class nsPermissionManager final
: public nsIPermissionManager
,
39 public nsSupportsWeakReference
45 PermissionEntry(int64_t aID
, uint32_t aType
, uint32_t aPermission
,
46 uint32_t aExpireType
, int64_t aExpireTime
,
47 int64_t aModificationTime
)
50 , mPermission(aPermission
)
51 , mExpireType(aExpireType
)
52 , mExpireTime(aExpireTime
)
53 , mModificationTime(aModificationTime
)
54 , mNonSessionPermission(aPermission
)
55 , mNonSessionExpireType(aExpireType
)
56 , mNonSessionExpireTime(aExpireTime
)
64 int64_t mModificationTime
;
65 uint32_t mNonSessionPermission
;
66 uint32_t mNonSessionExpireType
;
67 uint32_t mNonSessionExpireTime
;
71 * PermissionKey is the key used by PermissionHashKey hash table.
73 * NOTE: It could be implementing nsIHashable but there is no reason to worry
74 * with XPCOM interfaces while we don't need to.
79 static PermissionKey
* CreateFromPrincipal(nsIPrincipal
* aPrincipal
,
81 static PermissionKey
* CreateFromURI(nsIURI
* aURI
,
84 explicit PermissionKey(const nsACString
& aOrigin
)
89 bool operator==(const PermissionKey
& aKey
) const {
90 return mOrigin
.Equals(aKey
.mOrigin
);
93 PLDHashNumber
GetHashCode() const {
94 return mozilla::HashString(mOrigin
);
97 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey
)
102 // Default ctor shouldn't be used.
103 PermissionKey() = delete;
105 // Dtor shouldn't be used outside of the class.
109 class PermissionHashKey
: public nsRefPtrHashKey
<PermissionKey
>
112 explicit PermissionHashKey(const PermissionKey
* aPermissionKey
)
113 : nsRefPtrHashKey
<PermissionKey
>(aPermissionKey
)
116 PermissionHashKey(PermissionHashKey
&& toCopy
)
117 : nsRefPtrHashKey
<PermissionKey
>(std::move(toCopy
))
118 , mPermissions(std::move(toCopy
.mPermissions
))
121 bool KeyEquals(const PermissionKey
* aKey
) const
123 return *aKey
== *GetKey();
126 static PLDHashNumber
HashKey(const PermissionKey
* aKey
)
128 return aKey
->GetHashCode();
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 };
135 inline nsTArray
<PermissionEntry
> & GetPermissions()
140 inline int32_t GetPermissionIndex(uint32_t aType
) const
142 for (uint32_t i
= 0; i
< mPermissions
.Length(); ++i
)
143 if (mPermissions
[i
].mType
== aType
)
149 inline PermissionEntry
GetPermission(uint32_t aType
) const
151 for (uint32_t i
= 0; i
< mPermissions
.Length(); ++i
)
152 if (mPermissions
[i
].mType
== aType
)
153 return mPermissions
[i
];
155 // unknown permission... return relevant data
156 return PermissionEntry(-1, aType
, nsIPermissionManager::UNKNOWN_ACTION
,
157 nsIPermissionManager::EXPIRE_NEVER
, 0, 0);
161 AutoTArray
<PermissionEntry
, 1> mPermissions
;
166 NS_DECL_NSIPERMISSIONMANAGER
169 nsPermissionManager();
170 static already_AddRefed
<nsIPermissionManager
> GetXPCOMSingleton();
173 // enums for AddInternal()
179 eOperationReplacingDefault
182 enum DBOperationType
{
187 enum NotifyOperationType
{
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;
197 nsresult
AddInternal(nsIPrincipal
* aPrincipal
,
198 const nsCString
& aType
,
199 uint32_t aPermission
,
201 uint32_t aExpireType
,
203 int64_t aModificationTime
,
204 NotifyOperationType aNotifyOperation
,
205 DBOperationType aDBOperation
,
206 const bool aIgnoreSessionPermissions
= false);
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.
214 static void ClearOriginDataObserverInit();
217 RemovePermissionsWithAttributes(mozilla::OriginAttributesPattern
& aAttrs
);
220 * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
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.
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.
231 static void GetKeyForPrincipal(nsIPrincipal
* aPrincipal
, nsACString
& aPermissionKey
);
234 * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
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.
241 * If this method is passed a nonsensical origin string it may produce a
242 * nonsensical permission key result.
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.
247 static void GetKeyForOrigin(const nsACString
& aOrigin
, nsACString
& aPermissionKey
);
250 * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
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
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.
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.
266 static void GetKeyForPermission(nsIPrincipal
* aPrincipal
,
268 nsACString
& aPermissionKey
);
271 * See `nsIPermissionManager::GetPermissionsWithKey` for more info on
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.
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.
283 * @param aPrincipal The Principal which the key is to be extracted from.
285 static nsTArray
<nsCString
> GetAllKeysForPrincipal(nsIPrincipal
* aPrincipal
);
287 // From ContentChild.
288 nsresult
RemoveAllFromIPC();
291 virtual ~nsPermissionManager();
293 int32_t GetTypeIndex(const char *aTypeString
,
296 PermissionHashKey
* GetPermissionHashKey(nsIPrincipal
* aPrincipal
,
298 bool aExactHostMatch
);
299 PermissionHashKey
* GetPermissionHashKey(nsIURI
* aURI
,
301 bool aExactHostMatch
);
303 nsresult
CommonTestPermission(nsIPrincipal
* aPrincipal
,
305 uint32_t * aPermission
,
306 bool aExactHostMatch
,
307 bool aIncludingSession
)
309 return CommonTestPermissionInternal(aPrincipal
, nullptr, aType
,
310 aPermission
, aExactHostMatch
,
313 nsresult
CommonTestPermission(nsIURI
* aURI
,
315 uint32_t * aPermission
,
316 bool aExactHostMatch
,
317 bool aIncludingSession
)
319 return CommonTestPermissionInternal(nullptr, aURI
, aType
, aPermission
,
320 aExactHostMatch
, aIncludingSession
);
322 // Only one of aPrincipal or aURI is allowed to be passed in.
323 nsresult
CommonTestPermissionInternal(nsIPrincipal
* aPrincipal
,
326 uint32_t * aPermission
,
327 bool aExactHostMatch
,
328 bool aIncludingSession
);
330 nsresult
OpenDatabase(nsIFile
* permissionsFile
);
331 nsresult
InitDB(bool aRemoveFile
);
332 nsresult
CreateTable();
334 nsresult
ImportDefaults();
335 nsresult
_DoImport(nsIInputStream
*inputStream
, mozIStorageConnection
*aConn
);
337 void NotifyObserversWithPermission(nsIPrincipal
* aPrincipal
,
338 const nsCString
&aType
,
339 uint32_t aPermission
,
340 uint32_t aExpireType
,
342 const char16_t
*aData
);
343 void NotifyObservers(nsIPermission
*aPermission
, const char16_t
*aData
);
345 // Finalize all statements, close the DB and null it.
346 // if aRebuildOnSuccess, reinitialize database
347 void CloseDB(bool aRebuildOnSuccess
= false);
349 nsresult
RemoveAllInternal(bool aNotifyObservers
);
350 nsresult
RemoveAllFromMemory();
351 static void UpdateDB(OperationType aOp
,
352 mozIStorageAsyncStatement
* aStmt
,
354 const nsACString
& aOrigin
,
355 const nsACString
& aType
,
356 uint32_t aPermission
,
357 uint32_t aExpireType
,
359 int64_t aModificationTime
);
362 * This method removes all permissions modified after the specified time.
365 RemoveAllModifiedSince(int64_t aModificationTime
);
369 RemovePermissionEntries(T aCondition
);
372 * Returns false if this permission manager wouldn't have the permission
373 * requested available.
375 * If aType is nullptr, checks that the permission manager would have all
376 * permissions available for the given principal.
378 bool PermissionAvailable(nsIPrincipal
* aPrincipal
, const char* aType
);
380 nsRefPtrHashtable
<nsCStringHashKey
, mozilla::GenericPromise::Private
> mPermissionKeyPromiseMap
;
382 nsCOMPtr
<mozIStorageConnection
> mDBConn
;
383 nsCOMPtr
<mozIStorageAsyncStatement
> mStmtInsert
;
384 nsCOMPtr
<mozIStorageAsyncStatement
> mStmtDelete
;
385 nsCOMPtr
<mozIStorageAsyncStatement
> mStmtUpdate
;
389 nsTHashtable
<PermissionHashKey
> mPermissionTable
;
390 // a unique, monotonically increasing id used to identify each database entry
393 // An array to store the strings identifying the different types.
394 nsTArray
<nsCString
> mTypeArray
;
396 // Initially, |false|. Set to |true| once shutdown has started, to avoid
397 // reopening the database.
398 bool mIsShuttingDown
;
400 nsCOMPtr
<nsIPrefBranch
> mDefaultPrefBranch
;
402 friend class DeleteFromMozHostListener
;
403 friend class CloseDatabaseListener
;
406 // {4F6B5E00-0C36-11d5-A535-0010A401EB10}
407 #define NS_PERMISSIONMANAGER_CID \
408 { 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } }
410 #endif /* nsPermissionManager_h__ */