|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=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 file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef mozilla_dom_quota_quotamanager_h__ |
|
8 #define mozilla_dom_quota_quotamanager_h__ |
|
9 |
|
10 #include "QuotaCommon.h" |
|
11 |
|
12 #include "nsIObserver.h" |
|
13 #include "nsIQuotaManager.h" |
|
14 |
|
15 #include "mozilla/dom/Nullable.h" |
|
16 #include "mozilla/Mutex.h" |
|
17 |
|
18 #include "nsClassHashtable.h" |
|
19 #include "nsRefPtrHashtable.h" |
|
20 |
|
21 #include "ArrayCluster.h" |
|
22 #include "Client.h" |
|
23 #include "PersistenceType.h" |
|
24 #include "StoragePrivilege.h" |
|
25 |
|
26 #define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1" |
|
27 |
|
28 class nsIOfflineStorage; |
|
29 class nsIPrincipal; |
|
30 class nsIThread; |
|
31 class nsITimer; |
|
32 class nsIURI; |
|
33 class nsPIDOMWindow; |
|
34 class nsIRunnable; |
|
35 |
|
36 BEGIN_QUOTA_NAMESPACE |
|
37 |
|
38 class AcquireListener; |
|
39 class AsyncUsageRunnable; |
|
40 class CheckQuotaHelper; |
|
41 class CollectOriginsHelper; |
|
42 class FinalizeOriginEvictionRunnable; |
|
43 class GroupInfo; |
|
44 class GroupInfoPair; |
|
45 class OriginClearRunnable; |
|
46 class OriginInfo; |
|
47 class OriginOrPatternString; |
|
48 class QuotaObject; |
|
49 class ResetOrClearRunnable; |
|
50 struct SynchronizedOp; |
|
51 |
|
52 class QuotaManager MOZ_FINAL : public nsIQuotaManager, |
|
53 public nsIObserver |
|
54 { |
|
55 friend class AsyncUsageRunnable; |
|
56 friend class CollectOriginsHelper; |
|
57 friend class FinalizeOriginEvictionRunnable; |
|
58 friend class GroupInfo; |
|
59 friend class OriginClearRunnable; |
|
60 friend class OriginInfo; |
|
61 friend class QuotaObject; |
|
62 friend class ResetOrClearRunnable; |
|
63 |
|
64 enum MozBrowserPatternFlag |
|
65 { |
|
66 MozBrowser = 0, |
|
67 NotMozBrowser, |
|
68 IgnoreMozBrowser |
|
69 }; |
|
70 |
|
71 typedef void |
|
72 (*WaitingOnStoragesCallback)(nsTArray<nsCOMPtr<nsIOfflineStorage> >&, void*); |
|
73 |
|
74 public: |
|
75 NS_DECL_ISUPPORTS |
|
76 NS_DECL_NSIQUOTAMANAGER |
|
77 NS_DECL_NSIOBSERVER |
|
78 |
|
79 // Returns a non-owning reference. |
|
80 static QuotaManager* |
|
81 GetOrCreate(); |
|
82 |
|
83 // Returns a non-owning reference. |
|
84 static QuotaManager* |
|
85 Get(); |
|
86 |
|
87 // Returns an owning reference! No one should call this but the factory. |
|
88 static QuotaManager* |
|
89 FactoryCreate(); |
|
90 |
|
91 // Returns true if we've begun the shutdown process. |
|
92 static bool IsShuttingDown(); |
|
93 |
|
94 void |
|
95 InitQuotaForOrigin(PersistenceType aPersistenceType, |
|
96 const nsACString& aGroup, |
|
97 const nsACString& aOrigin, |
|
98 uint64_t aLimitBytes, |
|
99 uint64_t aUsageBytes, |
|
100 int64_t aAccessTime); |
|
101 |
|
102 void |
|
103 DecreaseUsageForOrigin(PersistenceType aPersistenceType, |
|
104 const nsACString& aGroup, |
|
105 const nsACString& aOrigin, |
|
106 int64_t aSize); |
|
107 |
|
108 void |
|
109 UpdateOriginAccessTime(PersistenceType aPersistenceType, |
|
110 const nsACString& aGroup, |
|
111 const nsACString& aOrigin); |
|
112 |
|
113 void |
|
114 RemoveQuota(); |
|
115 |
|
116 void |
|
117 RemoveQuotaForPersistenceType(PersistenceType); |
|
118 |
|
119 void |
|
120 RemoveQuotaForOrigin(PersistenceType aPersistenceType, |
|
121 const nsACString& aGroup, |
|
122 const nsACString& aOrigin) |
|
123 { |
|
124 MutexAutoLock lock(mQuotaMutex); |
|
125 LockedRemoveQuotaForOrigin(aPersistenceType, aGroup, aOrigin); |
|
126 } |
|
127 |
|
128 void |
|
129 RemoveQuotaForPattern(PersistenceType aPersistenceType, |
|
130 const nsACString& aPattern); |
|
131 |
|
132 already_AddRefed<QuotaObject> |
|
133 GetQuotaObject(PersistenceType aPersistenceType, |
|
134 const nsACString& aGroup, |
|
135 const nsACString& aOrigin, |
|
136 nsIFile* aFile); |
|
137 |
|
138 already_AddRefed<QuotaObject> |
|
139 GetQuotaObject(PersistenceType aPersistenceType, |
|
140 const nsACString& aGroup, |
|
141 const nsACString& aOrigin, |
|
142 const nsAString& aPath); |
|
143 |
|
144 // Set the Window that the current thread is doing operations for. |
|
145 // The caller is responsible for ensuring that aWindow is held alive. |
|
146 static void |
|
147 SetCurrentWindow(nsPIDOMWindow* aWindow) |
|
148 { |
|
149 QuotaManager* quotaManager = Get(); |
|
150 NS_ASSERTION(quotaManager, "Must have a manager here!"); |
|
151 |
|
152 quotaManager->SetCurrentWindowInternal(aWindow); |
|
153 } |
|
154 |
|
155 static void |
|
156 CancelPromptsForWindow(nsPIDOMWindow* aWindow) |
|
157 { |
|
158 NS_ASSERTION(aWindow, "Passed null window!"); |
|
159 |
|
160 QuotaManager* quotaManager = Get(); |
|
161 NS_ASSERTION(quotaManager, "Must have a manager here!"); |
|
162 |
|
163 quotaManager->CancelPromptsForWindowInternal(aWindow); |
|
164 } |
|
165 |
|
166 // Called when a storage is created. |
|
167 bool |
|
168 RegisterStorage(nsIOfflineStorage* aStorage); |
|
169 |
|
170 // Called when a storage is being unlinked or destroyed. |
|
171 void |
|
172 UnregisterStorage(nsIOfflineStorage* aStorage); |
|
173 |
|
174 // Called when a storage has been closed. |
|
175 void |
|
176 OnStorageClosed(nsIOfflineStorage* aStorage); |
|
177 |
|
178 // Called when a window is being purged from the bfcache or the user leaves |
|
179 // a page which isn't going into the bfcache. Forces any live storage |
|
180 // objects to close themselves and aborts any running transactions. |
|
181 void |
|
182 AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow); |
|
183 |
|
184 // Used to check if there are running transactions in a given window. |
|
185 bool |
|
186 HasOpenTransactions(nsPIDOMWindow* aWindow); |
|
187 |
|
188 // Waits for storages to be cleared and for version change transactions to |
|
189 // complete before dispatching the given runnable. |
|
190 nsresult |
|
191 WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern, |
|
192 Nullable<PersistenceType> aPersistenceType, |
|
193 const nsACString& aId, nsIRunnable* aRunnable); |
|
194 |
|
195 // Acquire exclusive access to the storage given (waits for all others to |
|
196 // close). If storages need to close first, the callback will be invoked |
|
197 // with an array of said storages. |
|
198 nsresult |
|
199 AcquireExclusiveAccess(nsIOfflineStorage* aStorage, |
|
200 const nsACString& aOrigin, |
|
201 Nullable<PersistenceType> aPersistenceType, |
|
202 AcquireListener* aListener, |
|
203 WaitingOnStoragesCallback aCallback, |
|
204 void* aClosure) |
|
205 { |
|
206 NS_ASSERTION(aStorage, "Need a storage here!"); |
|
207 return AcquireExclusiveAccess(aOrigin, aPersistenceType, aStorage, |
|
208 aListener, aCallback, aClosure); |
|
209 } |
|
210 |
|
211 nsresult |
|
212 AcquireExclusiveAccess(const nsACString& aOrigin, |
|
213 Nullable<PersistenceType> aPersistenceType, |
|
214 AcquireListener* aListener, |
|
215 WaitingOnStoragesCallback aCallback, |
|
216 void* aClosure) |
|
217 { |
|
218 return AcquireExclusiveAccess(aOrigin, aPersistenceType, nullptr, |
|
219 aListener, aCallback, aClosure); |
|
220 } |
|
221 |
|
222 void |
|
223 AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, |
|
224 Nullable<PersistenceType> aPersistenceType, |
|
225 const nsACString& aId); |
|
226 |
|
227 bool |
|
228 IsClearOriginPending(const nsACString& aPattern, |
|
229 Nullable<PersistenceType> aPersistenceType) |
|
230 { |
|
231 return !!FindSynchronizedOp(aPattern, aPersistenceType, EmptyCString()); |
|
232 } |
|
233 |
|
234 nsresult |
|
235 GetDirectoryForOrigin(PersistenceType aPersistenceType, |
|
236 const nsACString& aASCIIOrigin, |
|
237 nsIFile** aDirectory) const; |
|
238 |
|
239 nsresult |
|
240 EnsureOriginIsInitialized(PersistenceType aPersistenceType, |
|
241 const nsACString& aGroup, |
|
242 const nsACString& aOrigin, |
|
243 bool aTrackQuota, |
|
244 nsIFile** aDirectory); |
|
245 |
|
246 void |
|
247 OriginClearCompleted(PersistenceType aPersistenceType, |
|
248 const OriginOrPatternString& aOriginOrPattern); |
|
249 |
|
250 void |
|
251 ResetOrClearCompleted(); |
|
252 |
|
253 void |
|
254 AssertCurrentThreadOwnsQuotaMutex() |
|
255 { |
|
256 mQuotaMutex.AssertCurrentThreadOwns(); |
|
257 } |
|
258 |
|
259 nsIThread* |
|
260 IOThread() |
|
261 { |
|
262 NS_ASSERTION(mIOThread, "This should never be null!"); |
|
263 return mIOThread; |
|
264 } |
|
265 |
|
266 already_AddRefed<Client> |
|
267 GetClient(Client::Type aClientType); |
|
268 |
|
269 const nsString& |
|
270 GetStoragePath(PersistenceType aPersistenceType) const |
|
271 { |
|
272 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) { |
|
273 return mPersistentStoragePath; |
|
274 } |
|
275 |
|
276 NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?"); |
|
277 |
|
278 return mTemporaryStoragePath; |
|
279 } |
|
280 |
|
281 uint64_t |
|
282 GetGroupLimit() const; |
|
283 |
|
284 static uint32_t |
|
285 GetStorageQuotaMB(); |
|
286 |
|
287 static void |
|
288 GetStorageId(PersistenceType aPersistenceType, |
|
289 const nsACString& aOrigin, |
|
290 Client::Type aClientType, |
|
291 const nsAString& aName, |
|
292 nsACString& aDatabaseId); |
|
293 |
|
294 static nsresult |
|
295 GetInfoFromURI(nsIURI* aURI, |
|
296 uint32_t aAppId, |
|
297 bool aInMozBrowser, |
|
298 nsACString* aGroup, |
|
299 nsACString* aASCIIOrigin, |
|
300 StoragePrivilege* aPrivilege, |
|
301 PersistenceType* aDefaultPersistenceType); |
|
302 |
|
303 static nsresult |
|
304 GetInfoFromPrincipal(nsIPrincipal* aPrincipal, |
|
305 nsACString* aGroup, |
|
306 nsACString* aASCIIOrigin, |
|
307 StoragePrivilege* aPrivilege, |
|
308 PersistenceType* aDefaultPersistenceType); |
|
309 |
|
310 static nsresult |
|
311 GetInfoFromWindow(nsPIDOMWindow* aWindow, |
|
312 nsACString* aGroup, |
|
313 nsACString* aASCIIOrigin, |
|
314 StoragePrivilege* aPrivilege, |
|
315 PersistenceType* aDefaultPersistenceType); |
|
316 |
|
317 static void |
|
318 GetInfoForChrome(nsACString* aGroup, |
|
319 nsACString* aASCIIOrigin, |
|
320 StoragePrivilege* aPrivilege, |
|
321 PersistenceType* aDefaultPersistenceType); |
|
322 |
|
323 static void |
|
324 GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly, |
|
325 const nsACString& aOrigin, nsAutoCString& _retval) |
|
326 { |
|
327 return GetOriginPatternString(aAppId, |
|
328 aBrowserOnly ? MozBrowser : NotMozBrowser, |
|
329 aOrigin, _retval); |
|
330 } |
|
331 |
|
332 static void |
|
333 GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly, |
|
334 nsAutoCString& _retval) |
|
335 { |
|
336 return GetOriginPatternString(aAppId, |
|
337 aBrowserOnly ? MozBrowser : IgnoreMozBrowser, |
|
338 EmptyCString(), _retval); |
|
339 } |
|
340 |
|
341 private: |
|
342 QuotaManager(); |
|
343 |
|
344 virtual ~QuotaManager(); |
|
345 |
|
346 nsresult |
|
347 Init(); |
|
348 |
|
349 void |
|
350 SetCurrentWindowInternal(nsPIDOMWindow* aWindow); |
|
351 |
|
352 void |
|
353 CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow); |
|
354 |
|
355 // Determine if the quota is lifted for the Window the current thread is |
|
356 // using. |
|
357 bool |
|
358 LockedQuotaIsLifted(); |
|
359 |
|
360 uint64_t |
|
361 LockedCollectOriginsForEviction(uint64_t aMinSizeToBeFreed, |
|
362 nsTArray<OriginInfo*>& aOriginInfos); |
|
363 |
|
364 void |
|
365 LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType, |
|
366 const nsACString& aGroup, |
|
367 const nsACString& aOrigin); |
|
368 |
|
369 nsresult |
|
370 AcquireExclusiveAccess(const nsACString& aOrigin, |
|
371 Nullable<PersistenceType> aPersistenceType, |
|
372 nsIOfflineStorage* aStorage, |
|
373 AcquireListener* aListener, |
|
374 WaitingOnStoragesCallback aCallback, |
|
375 void* aClosure); |
|
376 |
|
377 void |
|
378 AddSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, |
|
379 Nullable<PersistenceType> aPersistenceType); |
|
380 |
|
381 nsresult |
|
382 RunSynchronizedOp(nsIOfflineStorage* aStorage, |
|
383 SynchronizedOp* aOp); |
|
384 |
|
385 SynchronizedOp* |
|
386 FindSynchronizedOp(const nsACString& aPattern, |
|
387 Nullable<PersistenceType> aPersistenceType, |
|
388 const nsACString& aId); |
|
389 |
|
390 nsresult |
|
391 MaybeUpgradeIndexedDBDirectory(); |
|
392 |
|
393 nsresult |
|
394 InitializeOrigin(PersistenceType aPersistenceType, |
|
395 const nsACString& aGroup, |
|
396 const nsACString& aOrigin, |
|
397 bool aTrackQuota, |
|
398 int64_t aAccessTime, |
|
399 nsIFile* aDirectory); |
|
400 |
|
401 nsresult |
|
402 ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly); |
|
403 |
|
404 void |
|
405 CheckTemporaryStorageLimits(); |
|
406 |
|
407 // Collect inactive and the least recently used origins. |
|
408 uint64_t |
|
409 CollectOriginsForEviction(uint64_t aMinSizeToBeFreed, |
|
410 nsTArray<OriginInfo*>& aOriginInfos); |
|
411 |
|
412 void |
|
413 DeleteTemporaryFilesForOrigin(const nsACString& aOrigin); |
|
414 |
|
415 void |
|
416 FinalizeOriginEviction(nsTArray<nsCString>& aOrigins); |
|
417 |
|
418 void |
|
419 SaveOriginAccessTime(const nsACString& aOrigin, int64_t aTimestamp); |
|
420 |
|
421 void |
|
422 ReleaseIOThreadObjects() |
|
423 { |
|
424 AssertIsOnIOThread(); |
|
425 |
|
426 for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { |
|
427 mClients[index]->ReleaseIOThreadObjects(); |
|
428 } |
|
429 } |
|
430 |
|
431 static void |
|
432 GetOriginPatternString(uint32_t aAppId, |
|
433 MozBrowserPatternFlag aBrowserFlag, |
|
434 const nsACString& aOrigin, |
|
435 nsAutoCString& _retval); |
|
436 |
|
437 static PLDHashOperator |
|
438 RemoveQuotaForPersistenceTypeCallback(const nsACString& aKey, |
|
439 nsAutoPtr<GroupInfoPair>& aValue, |
|
440 void* aUserArg); |
|
441 |
|
442 static PLDHashOperator |
|
443 RemoveQuotaCallback(const nsACString& aKey, |
|
444 nsAutoPtr<GroupInfoPair>& aValue, |
|
445 void* aUserArg); |
|
446 |
|
447 static PLDHashOperator |
|
448 RemoveQuotaForPatternCallback(const nsACString& aKey, |
|
449 nsAutoPtr<GroupInfoPair>& aValue, |
|
450 void* aUserArg); |
|
451 |
|
452 static PLDHashOperator |
|
453 GetOriginsExceedingGroupLimit(const nsACString& aKey, |
|
454 GroupInfoPair* aValue, |
|
455 void* aUserArg); |
|
456 |
|
457 static PLDHashOperator |
|
458 GetAllTemporaryStorageOrigins(const nsACString& aKey, |
|
459 GroupInfoPair* aValue, |
|
460 void* aUserArg); |
|
461 |
|
462 static PLDHashOperator |
|
463 AddTemporaryStorageOrigins(const nsACString& aKey, |
|
464 ArrayCluster<nsIOfflineStorage*>* aValue, |
|
465 void* aUserArg); |
|
466 |
|
467 static PLDHashOperator |
|
468 GetInactiveTemporaryStorageOrigins(const nsACString& aKey, |
|
469 GroupInfoPair* aValue, |
|
470 void* aUserArg); |
|
471 |
|
472 // TLS storage index for the current thread's window. |
|
473 unsigned int mCurrentWindowIndex; |
|
474 |
|
475 mozilla::Mutex mQuotaMutex; |
|
476 |
|
477 nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs; |
|
478 |
|
479 // A map of Windows to the corresponding quota helper. |
|
480 nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>, |
|
481 CheckQuotaHelper> mCheckQuotaHelpers; |
|
482 |
|
483 // Maintains a list of live storages per origin. |
|
484 nsClassHashtable<nsCStringHashKey, |
|
485 ArrayCluster<nsIOfflineStorage*> > mLiveStorages; |
|
486 |
|
487 // Maintains a list of synchronized operatons that are in progress or queued. |
|
488 nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps; |
|
489 |
|
490 // Thread on which IO is performed. |
|
491 nsCOMPtr<nsIThread> mIOThread; |
|
492 |
|
493 // A timer that gets activated at shutdown to ensure we close all storages. |
|
494 nsCOMPtr<nsITimer> mShutdownTimer; |
|
495 |
|
496 // A list of all successfully initialized origins. This list isn't protected |
|
497 // by any mutex but it is only ever touched on the IO thread. |
|
498 nsTArray<nsCString> mInitializedOrigins; |
|
499 |
|
500 nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients; |
|
501 |
|
502 nsString mIndexedDBPath; |
|
503 nsString mPersistentStoragePath; |
|
504 nsString mTemporaryStoragePath; |
|
505 |
|
506 uint64_t mTemporaryStorageLimit; |
|
507 uint64_t mTemporaryStorageUsage; |
|
508 bool mTemporaryStorageInitialized; |
|
509 |
|
510 bool mStorageAreaInitialized; |
|
511 }; |
|
512 |
|
513 class AutoEnterWindow |
|
514 { |
|
515 public: |
|
516 AutoEnterWindow(nsPIDOMWindow* aWindow) |
|
517 { |
|
518 QuotaManager::SetCurrentWindow(aWindow); |
|
519 } |
|
520 |
|
521 ~AutoEnterWindow() |
|
522 { |
|
523 QuotaManager::SetCurrentWindow(nullptr); |
|
524 } |
|
525 }; |
|
526 |
|
527 END_QUOTA_NAMESPACE |
|
528 |
|
529 #endif /* mozilla_dom_quota_quotamanager_h__ */ |