michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsPermissionManager_h__ michael@0: #define nsPermissionManager_h__ michael@0: michael@0: #include "nsIPermissionManager.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsWeakReference.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIFile.h" michael@0: #include "nsTHashtable.h" michael@0: #include "nsTArray.h" michael@0: #include "nsString.h" michael@0: #include "nsPermission.h" michael@0: #include "nsHashKeys.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMArray.h" michael@0: #include "nsDataHashtable.h" michael@0: michael@0: class nsIPermission; michael@0: class nsIIDNService; michael@0: class mozIStorageConnection; michael@0: class mozIStorageAsyncStatement; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class nsPermissionManager : public nsIPermissionManager, michael@0: public nsIObserver, michael@0: public nsSupportsWeakReference michael@0: { michael@0: public: michael@0: class PermissionEntry michael@0: { michael@0: public: michael@0: PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission, michael@0: uint32_t aExpireType, int64_t aExpireTime) michael@0: : mID(aID) michael@0: , mType(aType) michael@0: , mPermission(aPermission) michael@0: , mExpireType(aExpireType) michael@0: , mExpireTime(aExpireTime) michael@0: , mNonSessionPermission(aPermission) michael@0: , mNonSessionExpireType(aExpireType) michael@0: , mNonSessionExpireTime(aExpireTime) michael@0: {} michael@0: michael@0: int64_t mID; michael@0: uint32_t mType; michael@0: uint32_t mPermission; michael@0: uint32_t mExpireType; michael@0: int64_t mExpireTime; michael@0: uint32_t mNonSessionPermission; michael@0: uint32_t mNonSessionExpireType; michael@0: uint32_t mNonSessionExpireTime; michael@0: }; michael@0: michael@0: /** michael@0: * PermissionKey is the key used by PermissionHashKey hash table. michael@0: * michael@0: * NOTE: It could be implementing nsIHashable but there is no reason to worry michael@0: * with XPCOM interfaces while we don't need to. michael@0: */ michael@0: class PermissionKey michael@0: { michael@0: public: michael@0: PermissionKey(nsIPrincipal* aPrincipal); michael@0: PermissionKey(const nsACString& aHost, michael@0: uint32_t aAppId, michael@0: bool aIsInBrowserElement) michael@0: : mHost(aHost) michael@0: , mAppId(aAppId) michael@0: , mIsInBrowserElement(aIsInBrowserElement) michael@0: { michael@0: } michael@0: michael@0: bool operator==(const PermissionKey& aKey) const { michael@0: return mHost.Equals(aKey.mHost) && michael@0: mAppId == aKey.mAppId && michael@0: mIsInBrowserElement == aKey.mIsInBrowserElement; michael@0: } michael@0: michael@0: PLDHashNumber GetHashCode() const { michael@0: nsAutoCString str; michael@0: str.Assign(mHost); michael@0: str.AppendInt(mAppId); michael@0: str.AppendInt(static_cast(mIsInBrowserElement)); michael@0: michael@0: return mozilla::HashString(str); michael@0: } michael@0: michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey) michael@0: michael@0: nsCString mHost; michael@0: uint32_t mAppId; michael@0: bool mIsInBrowserElement; michael@0: michael@0: private: michael@0: // Default ctor shouldn't be used. michael@0: PermissionKey() MOZ_DELETE; michael@0: michael@0: // Dtor shouldn't be used outside of the class. michael@0: ~PermissionKey() {}; michael@0: }; michael@0: michael@0: class PermissionHashKey : public nsRefPtrHashKey michael@0: { michael@0: public: michael@0: PermissionHashKey(const PermissionKey* aPermissionKey) michael@0: : nsRefPtrHashKey(aPermissionKey) michael@0: {} michael@0: michael@0: PermissionHashKey(const PermissionHashKey& toCopy) michael@0: : nsRefPtrHashKey(toCopy) michael@0: , mPermissions(toCopy.mPermissions) michael@0: {} michael@0: michael@0: bool KeyEquals(const PermissionKey* aKey) const michael@0: { michael@0: return *aKey == *GetKey(); michael@0: } michael@0: michael@0: static PLDHashNumber HashKey(const PermissionKey* aKey) michael@0: { michael@0: return aKey->GetHashCode(); michael@0: } michael@0: michael@0: // Force the hashtable to use the copy constructor when shuffling entries michael@0: // around, otherwise the Auto part of our nsAutoTArray won't be happy! michael@0: enum { ALLOW_MEMMOVE = false }; michael@0: michael@0: inline nsTArray & GetPermissions() michael@0: { michael@0: return mPermissions; michael@0: } michael@0: michael@0: inline int32_t GetPermissionIndex(uint32_t aType) const michael@0: { michael@0: for (uint32_t i = 0; i < mPermissions.Length(); ++i) michael@0: if (mPermissions[i].mType == aType) michael@0: return i; michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: inline PermissionEntry GetPermission(uint32_t aType) const michael@0: { michael@0: for (uint32_t i = 0; i < mPermissions.Length(); ++i) michael@0: if (mPermissions[i].mType == aType) michael@0: return mPermissions[i]; michael@0: michael@0: // unknown permission... return relevant data michael@0: return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION, michael@0: nsIPermissionManager::EXPIRE_NEVER, 0); michael@0: } michael@0: michael@0: private: michael@0: nsAutoTArray mPermissions; michael@0: }; michael@0: michael@0: // nsISupports michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIPERMISSIONMANAGER michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: nsPermissionManager(); michael@0: virtual ~nsPermissionManager(); michael@0: static nsIPermissionManager* GetXPCOMSingleton(); michael@0: nsresult Init(); michael@0: michael@0: // enums for AddInternal() michael@0: enum OperationType { michael@0: eOperationNone, michael@0: eOperationAdding, michael@0: eOperationRemoving, michael@0: eOperationChanging michael@0: }; michael@0: michael@0: enum DBOperationType { michael@0: eNoDBOperation, michael@0: eWriteToDB michael@0: }; michael@0: michael@0: enum NotifyOperationType { michael@0: eDontNotify, michael@0: eNotify michael@0: }; michael@0: michael@0: nsresult AddInternal(nsIPrincipal* aPrincipal, michael@0: const nsAFlatCString &aType, michael@0: uint32_t aPermission, michael@0: int64_t aID, michael@0: uint32_t aExpireType, michael@0: int64_t aExpireTime, michael@0: NotifyOperationType aNotifyOperation, michael@0: DBOperationType aDBOperation); michael@0: michael@0: /** michael@0: * Initialize the "webapp-uninstall" observing. michael@0: * Will create a nsPermissionManager instance if needed. michael@0: * That way, we can prevent have nsPermissionManager created at startup just michael@0: * to be able to clear data when an application is uninstalled. michael@0: */ michael@0: static void AppClearDataObserverInit(); michael@0: michael@0: private: michael@0: int32_t GetTypeIndex(const char *aTypeString, michael@0: bool aAdd); michael@0: michael@0: PermissionHashKey* GetPermissionHashKey(const nsACString& aHost, michael@0: uint32_t aAppId, michael@0: bool aIsInBrowserElement, michael@0: uint32_t aType, michael@0: bool aExactHostMatch); michael@0: michael@0: nsresult CommonTestPermission(nsIPrincipal* aPrincipal, michael@0: const char *aType, michael@0: uint32_t *aPermission, michael@0: bool aExactHostMatch, michael@0: bool aIncludingSession); michael@0: michael@0: nsresult InitDB(bool aRemoveFile); michael@0: nsresult CreateTable(); michael@0: nsresult Import(); michael@0: nsresult Read(); michael@0: void NotifyObserversWithPermission(const nsACString &aHost, michael@0: uint32_t aAppId, michael@0: bool aIsInBrowserElement, michael@0: const nsCString &aType, michael@0: uint32_t aPermission, michael@0: uint32_t aExpireType, michael@0: int64_t aExpireTime, michael@0: const char16_t *aData); michael@0: void NotifyObservers(nsIPermission *aPermission, const char16_t *aData); michael@0: michael@0: // Finalize all statements, close the DB and null it. michael@0: // if aRebuildOnSuccess, reinitialize database michael@0: void CloseDB(bool aRebuildOnSuccess = false); michael@0: michael@0: nsresult RemoveAllInternal(bool aNotifyObservers); michael@0: nsresult RemoveAllFromMemory(); michael@0: nsresult NormalizeToACE(nsCString &aHost); michael@0: static void UpdateDB(OperationType aOp, michael@0: mozIStorageAsyncStatement* aStmt, michael@0: int64_t aID, michael@0: const nsACString& aHost, michael@0: const nsACString& aType, michael@0: uint32_t aPermission, michael@0: uint32_t aExpireType, michael@0: int64_t aExpireTime, michael@0: uint32_t aAppId, michael@0: bool aIsInBrowserElement); michael@0: michael@0: nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId); michael@0: michael@0: /** michael@0: * This struct has to be passed as an argument to GetPermissionsForApp. michael@0: * |appId| and |browserOnly| have to be defined. michael@0: * |permissions| will be filed with permissions that are related to the app. michael@0: * If |browserOnly| is true, only permissions related to a browserElement will michael@0: * be in |permissions|. michael@0: */ michael@0: struct GetPermissionsForAppStruct { michael@0: uint32_t appId; michael@0: bool browserOnly; michael@0: nsCOMArray permissions; michael@0: michael@0: GetPermissionsForAppStruct() MOZ_DELETE; michael@0: GetPermissionsForAppStruct(uint32_t aAppId, bool aBrowserOnly) michael@0: : appId(aAppId) michael@0: , browserOnly(aBrowserOnly) michael@0: {} michael@0: }; michael@0: michael@0: /** michael@0: * This method will return the list of all permissions that are related to a michael@0: * specific app. michael@0: * @param arg has to be an instance of GetPermissionsForAppStruct. michael@0: */ michael@0: static PLDHashOperator michael@0: GetPermissionsForApp(PermissionHashKey* entry, void* arg); michael@0: michael@0: /** michael@0: * This method restores an app's permissions when its session ends. michael@0: */ michael@0: static PLDHashOperator michael@0: RemoveExpiredPermissionsForAppEnumerator(PermissionHashKey* entry, michael@0: void* nonused); michael@0: michael@0: nsCOMPtr mObserverService; michael@0: nsCOMPtr mIDNService; michael@0: michael@0: nsCOMPtr mDBConn; michael@0: nsCOMPtr mStmtInsert; michael@0: nsCOMPtr mStmtDelete; michael@0: nsCOMPtr mStmtUpdate; michael@0: michael@0: nsTHashtable mPermissionTable; michael@0: // a unique, monotonically increasing id used to identify each database entry michael@0: int64_t mLargestID; michael@0: michael@0: // An array to store the strings identifying the different types. michael@0: nsTArray mTypeArray; michael@0: michael@0: // A list of struct for counting applications michael@0: struct ApplicationCounter { michael@0: uint32_t mAppId; michael@0: uint32_t mCounter; michael@0: }; michael@0: nsTArray mAppIdRefcounts; michael@0: michael@0: // Initially, |false|. Set to |true| once shutdown has started, to avoid michael@0: // reopening the database. michael@0: bool mIsShuttingDown; michael@0: michael@0: friend class DeleteFromMozHostListener; michael@0: friend class CloseDatabaseListener; michael@0: }; michael@0: michael@0: // {4F6B5E00-0C36-11d5-A535-0010A401EB10} michael@0: #define NS_PERMISSIONMANAGER_CID \ michael@0: { 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } michael@0: michael@0: #endif /* nsPermissionManager_h__ */