|
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 nsPermissionManager_h__ |
|
7 #define nsPermissionManager_h__ |
|
8 |
|
9 #include "nsIPermissionManager.h" |
|
10 #include "nsIObserver.h" |
|
11 #include "nsIObserverService.h" |
|
12 #include "nsWeakReference.h" |
|
13 #include "nsCOMPtr.h" |
|
14 #include "nsIFile.h" |
|
15 #include "nsTHashtable.h" |
|
16 #include "nsTArray.h" |
|
17 #include "nsString.h" |
|
18 #include "nsPermission.h" |
|
19 #include "nsHashKeys.h" |
|
20 #include "nsAutoPtr.h" |
|
21 #include "nsCOMArray.h" |
|
22 #include "nsDataHashtable.h" |
|
23 |
|
24 class nsIPermission; |
|
25 class nsIIDNService; |
|
26 class mozIStorageConnection; |
|
27 class mozIStorageAsyncStatement; |
|
28 |
|
29 //////////////////////////////////////////////////////////////////////////////// |
|
30 |
|
31 class nsPermissionManager : public nsIPermissionManager, |
|
32 public nsIObserver, |
|
33 public nsSupportsWeakReference |
|
34 { |
|
35 public: |
|
36 class PermissionEntry |
|
37 { |
|
38 public: |
|
39 PermissionEntry(int64_t aID, uint32_t aType, uint32_t aPermission, |
|
40 uint32_t aExpireType, int64_t aExpireTime) |
|
41 : mID(aID) |
|
42 , mType(aType) |
|
43 , mPermission(aPermission) |
|
44 , mExpireType(aExpireType) |
|
45 , mExpireTime(aExpireTime) |
|
46 , mNonSessionPermission(aPermission) |
|
47 , mNonSessionExpireType(aExpireType) |
|
48 , mNonSessionExpireTime(aExpireTime) |
|
49 {} |
|
50 |
|
51 int64_t mID; |
|
52 uint32_t mType; |
|
53 uint32_t mPermission; |
|
54 uint32_t mExpireType; |
|
55 int64_t mExpireTime; |
|
56 uint32_t mNonSessionPermission; |
|
57 uint32_t mNonSessionExpireType; |
|
58 uint32_t mNonSessionExpireTime; |
|
59 }; |
|
60 |
|
61 /** |
|
62 * PermissionKey is the key used by PermissionHashKey hash table. |
|
63 * |
|
64 * NOTE: It could be implementing nsIHashable but there is no reason to worry |
|
65 * with XPCOM interfaces while we don't need to. |
|
66 */ |
|
67 class PermissionKey |
|
68 { |
|
69 public: |
|
70 PermissionKey(nsIPrincipal* aPrincipal); |
|
71 PermissionKey(const nsACString& aHost, |
|
72 uint32_t aAppId, |
|
73 bool aIsInBrowserElement) |
|
74 : mHost(aHost) |
|
75 , mAppId(aAppId) |
|
76 , mIsInBrowserElement(aIsInBrowserElement) |
|
77 { |
|
78 } |
|
79 |
|
80 bool operator==(const PermissionKey& aKey) const { |
|
81 return mHost.Equals(aKey.mHost) && |
|
82 mAppId == aKey.mAppId && |
|
83 mIsInBrowserElement == aKey.mIsInBrowserElement; |
|
84 } |
|
85 |
|
86 PLDHashNumber GetHashCode() const { |
|
87 nsAutoCString str; |
|
88 str.Assign(mHost); |
|
89 str.AppendInt(mAppId); |
|
90 str.AppendInt(static_cast<int32_t>(mIsInBrowserElement)); |
|
91 |
|
92 return mozilla::HashString(str); |
|
93 } |
|
94 |
|
95 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey) |
|
96 |
|
97 nsCString mHost; |
|
98 uint32_t mAppId; |
|
99 bool mIsInBrowserElement; |
|
100 |
|
101 private: |
|
102 // Default ctor shouldn't be used. |
|
103 PermissionKey() MOZ_DELETE; |
|
104 |
|
105 // Dtor shouldn't be used outside of the class. |
|
106 ~PermissionKey() {}; |
|
107 }; |
|
108 |
|
109 class PermissionHashKey : public nsRefPtrHashKey<PermissionKey> |
|
110 { |
|
111 public: |
|
112 PermissionHashKey(const PermissionKey* aPermissionKey) |
|
113 : nsRefPtrHashKey<PermissionKey>(aPermissionKey) |
|
114 {} |
|
115 |
|
116 PermissionHashKey(const PermissionHashKey& toCopy) |
|
117 : nsRefPtrHashKey<PermissionKey>(toCopy) |
|
118 , mPermissions(toCopy.mPermissions) |
|
119 {} |
|
120 |
|
121 bool KeyEquals(const PermissionKey* aKey) const |
|
122 { |
|
123 return *aKey == *GetKey(); |
|
124 } |
|
125 |
|
126 static PLDHashNumber HashKey(const PermissionKey* aKey) |
|
127 { |
|
128 return aKey->GetHashCode(); |
|
129 } |
|
130 |
|
131 // Force the hashtable to use the copy constructor when shuffling entries |
|
132 // around, otherwise the Auto part of our nsAutoTArray won't be happy! |
|
133 enum { ALLOW_MEMMOVE = false }; |
|
134 |
|
135 inline nsTArray<PermissionEntry> & GetPermissions() |
|
136 { |
|
137 return mPermissions; |
|
138 } |
|
139 |
|
140 inline int32_t GetPermissionIndex(uint32_t aType) const |
|
141 { |
|
142 for (uint32_t i = 0; i < mPermissions.Length(); ++i) |
|
143 if (mPermissions[i].mType == aType) |
|
144 return i; |
|
145 |
|
146 return -1; |
|
147 } |
|
148 |
|
149 inline PermissionEntry GetPermission(uint32_t aType) const |
|
150 { |
|
151 for (uint32_t i = 0; i < mPermissions.Length(); ++i) |
|
152 if (mPermissions[i].mType == aType) |
|
153 return mPermissions[i]; |
|
154 |
|
155 // unknown permission... return relevant data |
|
156 return PermissionEntry(-1, aType, nsIPermissionManager::UNKNOWN_ACTION, |
|
157 nsIPermissionManager::EXPIRE_NEVER, 0); |
|
158 } |
|
159 |
|
160 private: |
|
161 nsAutoTArray<PermissionEntry, 1> mPermissions; |
|
162 }; |
|
163 |
|
164 // nsISupports |
|
165 NS_DECL_ISUPPORTS |
|
166 NS_DECL_NSIPERMISSIONMANAGER |
|
167 NS_DECL_NSIOBSERVER |
|
168 |
|
169 nsPermissionManager(); |
|
170 virtual ~nsPermissionManager(); |
|
171 static nsIPermissionManager* GetXPCOMSingleton(); |
|
172 nsresult Init(); |
|
173 |
|
174 // enums for AddInternal() |
|
175 enum OperationType { |
|
176 eOperationNone, |
|
177 eOperationAdding, |
|
178 eOperationRemoving, |
|
179 eOperationChanging |
|
180 }; |
|
181 |
|
182 enum DBOperationType { |
|
183 eNoDBOperation, |
|
184 eWriteToDB |
|
185 }; |
|
186 |
|
187 enum NotifyOperationType { |
|
188 eDontNotify, |
|
189 eNotify |
|
190 }; |
|
191 |
|
192 nsresult AddInternal(nsIPrincipal* aPrincipal, |
|
193 const nsAFlatCString &aType, |
|
194 uint32_t aPermission, |
|
195 int64_t aID, |
|
196 uint32_t aExpireType, |
|
197 int64_t aExpireTime, |
|
198 NotifyOperationType aNotifyOperation, |
|
199 DBOperationType aDBOperation); |
|
200 |
|
201 /** |
|
202 * Initialize the "webapp-uninstall" observing. |
|
203 * Will create a nsPermissionManager instance if needed. |
|
204 * That way, we can prevent have nsPermissionManager created at startup just |
|
205 * to be able to clear data when an application is uninstalled. |
|
206 */ |
|
207 static void AppClearDataObserverInit(); |
|
208 |
|
209 private: |
|
210 int32_t GetTypeIndex(const char *aTypeString, |
|
211 bool aAdd); |
|
212 |
|
213 PermissionHashKey* GetPermissionHashKey(const nsACString& aHost, |
|
214 uint32_t aAppId, |
|
215 bool aIsInBrowserElement, |
|
216 uint32_t aType, |
|
217 bool aExactHostMatch); |
|
218 |
|
219 nsresult CommonTestPermission(nsIPrincipal* aPrincipal, |
|
220 const char *aType, |
|
221 uint32_t *aPermission, |
|
222 bool aExactHostMatch, |
|
223 bool aIncludingSession); |
|
224 |
|
225 nsresult InitDB(bool aRemoveFile); |
|
226 nsresult CreateTable(); |
|
227 nsresult Import(); |
|
228 nsresult Read(); |
|
229 void NotifyObserversWithPermission(const nsACString &aHost, |
|
230 uint32_t aAppId, |
|
231 bool aIsInBrowserElement, |
|
232 const nsCString &aType, |
|
233 uint32_t aPermission, |
|
234 uint32_t aExpireType, |
|
235 int64_t aExpireTime, |
|
236 const char16_t *aData); |
|
237 void NotifyObservers(nsIPermission *aPermission, const char16_t *aData); |
|
238 |
|
239 // Finalize all statements, close the DB and null it. |
|
240 // if aRebuildOnSuccess, reinitialize database |
|
241 void CloseDB(bool aRebuildOnSuccess = false); |
|
242 |
|
243 nsresult RemoveAllInternal(bool aNotifyObservers); |
|
244 nsresult RemoveAllFromMemory(); |
|
245 nsresult NormalizeToACE(nsCString &aHost); |
|
246 static void UpdateDB(OperationType aOp, |
|
247 mozIStorageAsyncStatement* aStmt, |
|
248 int64_t aID, |
|
249 const nsACString& aHost, |
|
250 const nsACString& aType, |
|
251 uint32_t aPermission, |
|
252 uint32_t aExpireType, |
|
253 int64_t aExpireTime, |
|
254 uint32_t aAppId, |
|
255 bool aIsInBrowserElement); |
|
256 |
|
257 nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId); |
|
258 |
|
259 /** |
|
260 * This struct has to be passed as an argument to GetPermissionsForApp. |
|
261 * |appId| and |browserOnly| have to be defined. |
|
262 * |permissions| will be filed with permissions that are related to the app. |
|
263 * If |browserOnly| is true, only permissions related to a browserElement will |
|
264 * be in |permissions|. |
|
265 */ |
|
266 struct GetPermissionsForAppStruct { |
|
267 uint32_t appId; |
|
268 bool browserOnly; |
|
269 nsCOMArray<nsIPermission> permissions; |
|
270 |
|
271 GetPermissionsForAppStruct() MOZ_DELETE; |
|
272 GetPermissionsForAppStruct(uint32_t aAppId, bool aBrowserOnly) |
|
273 : appId(aAppId) |
|
274 , browserOnly(aBrowserOnly) |
|
275 {} |
|
276 }; |
|
277 |
|
278 /** |
|
279 * This method will return the list of all permissions that are related to a |
|
280 * specific app. |
|
281 * @param arg has to be an instance of GetPermissionsForAppStruct. |
|
282 */ |
|
283 static PLDHashOperator |
|
284 GetPermissionsForApp(PermissionHashKey* entry, void* arg); |
|
285 |
|
286 /** |
|
287 * This method restores an app's permissions when its session ends. |
|
288 */ |
|
289 static PLDHashOperator |
|
290 RemoveExpiredPermissionsForAppEnumerator(PermissionHashKey* entry, |
|
291 void* nonused); |
|
292 |
|
293 nsCOMPtr<nsIObserverService> mObserverService; |
|
294 nsCOMPtr<nsIIDNService> mIDNService; |
|
295 |
|
296 nsCOMPtr<mozIStorageConnection> mDBConn; |
|
297 nsCOMPtr<mozIStorageAsyncStatement> mStmtInsert; |
|
298 nsCOMPtr<mozIStorageAsyncStatement> mStmtDelete; |
|
299 nsCOMPtr<mozIStorageAsyncStatement> mStmtUpdate; |
|
300 |
|
301 nsTHashtable<PermissionHashKey> mPermissionTable; |
|
302 // a unique, monotonically increasing id used to identify each database entry |
|
303 int64_t mLargestID; |
|
304 |
|
305 // An array to store the strings identifying the different types. |
|
306 nsTArray<nsCString> mTypeArray; |
|
307 |
|
308 // A list of struct for counting applications |
|
309 struct ApplicationCounter { |
|
310 uint32_t mAppId; |
|
311 uint32_t mCounter; |
|
312 }; |
|
313 nsTArray<ApplicationCounter> mAppIdRefcounts; |
|
314 |
|
315 // Initially, |false|. Set to |true| once shutdown has started, to avoid |
|
316 // reopening the database. |
|
317 bool mIsShuttingDown; |
|
318 |
|
319 friend class DeleteFromMozHostListener; |
|
320 friend class CloseDatabaseListener; |
|
321 }; |
|
322 |
|
323 // {4F6B5E00-0C36-11d5-A535-0010A401EB10} |
|
324 #define NS_PERMISSIONMANAGER_CID \ |
|
325 { 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } |
|
326 |
|
327 #endif /* nsPermissionManager_h__ */ |