1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/quota/QuotaManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,529 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_dom_quota_quotamanager_h__ 1.11 +#define mozilla_dom_quota_quotamanager_h__ 1.12 + 1.13 +#include "QuotaCommon.h" 1.14 + 1.15 +#include "nsIObserver.h" 1.16 +#include "nsIQuotaManager.h" 1.17 + 1.18 +#include "mozilla/dom/Nullable.h" 1.19 +#include "mozilla/Mutex.h" 1.20 + 1.21 +#include "nsClassHashtable.h" 1.22 +#include "nsRefPtrHashtable.h" 1.23 + 1.24 +#include "ArrayCluster.h" 1.25 +#include "Client.h" 1.26 +#include "PersistenceType.h" 1.27 +#include "StoragePrivilege.h" 1.28 + 1.29 +#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1" 1.30 + 1.31 +class nsIOfflineStorage; 1.32 +class nsIPrincipal; 1.33 +class nsIThread; 1.34 +class nsITimer; 1.35 +class nsIURI; 1.36 +class nsPIDOMWindow; 1.37 +class nsIRunnable; 1.38 + 1.39 +BEGIN_QUOTA_NAMESPACE 1.40 + 1.41 +class AcquireListener; 1.42 +class AsyncUsageRunnable; 1.43 +class CheckQuotaHelper; 1.44 +class CollectOriginsHelper; 1.45 +class FinalizeOriginEvictionRunnable; 1.46 +class GroupInfo; 1.47 +class GroupInfoPair; 1.48 +class OriginClearRunnable; 1.49 +class OriginInfo; 1.50 +class OriginOrPatternString; 1.51 +class QuotaObject; 1.52 +class ResetOrClearRunnable; 1.53 +struct SynchronizedOp; 1.54 + 1.55 +class QuotaManager MOZ_FINAL : public nsIQuotaManager, 1.56 + public nsIObserver 1.57 +{ 1.58 + friend class AsyncUsageRunnable; 1.59 + friend class CollectOriginsHelper; 1.60 + friend class FinalizeOriginEvictionRunnable; 1.61 + friend class GroupInfo; 1.62 + friend class OriginClearRunnable; 1.63 + friend class OriginInfo; 1.64 + friend class QuotaObject; 1.65 + friend class ResetOrClearRunnable; 1.66 + 1.67 + enum MozBrowserPatternFlag 1.68 + { 1.69 + MozBrowser = 0, 1.70 + NotMozBrowser, 1.71 + IgnoreMozBrowser 1.72 + }; 1.73 + 1.74 + typedef void 1.75 + (*WaitingOnStoragesCallback)(nsTArray<nsCOMPtr<nsIOfflineStorage> >&, void*); 1.76 + 1.77 +public: 1.78 + NS_DECL_ISUPPORTS 1.79 + NS_DECL_NSIQUOTAMANAGER 1.80 + NS_DECL_NSIOBSERVER 1.81 + 1.82 + // Returns a non-owning reference. 1.83 + static QuotaManager* 1.84 + GetOrCreate(); 1.85 + 1.86 + // Returns a non-owning reference. 1.87 + static QuotaManager* 1.88 + Get(); 1.89 + 1.90 + // Returns an owning reference! No one should call this but the factory. 1.91 + static QuotaManager* 1.92 + FactoryCreate(); 1.93 + 1.94 + // Returns true if we've begun the shutdown process. 1.95 + static bool IsShuttingDown(); 1.96 + 1.97 + void 1.98 + InitQuotaForOrigin(PersistenceType aPersistenceType, 1.99 + const nsACString& aGroup, 1.100 + const nsACString& aOrigin, 1.101 + uint64_t aLimitBytes, 1.102 + uint64_t aUsageBytes, 1.103 + int64_t aAccessTime); 1.104 + 1.105 + void 1.106 + DecreaseUsageForOrigin(PersistenceType aPersistenceType, 1.107 + const nsACString& aGroup, 1.108 + const nsACString& aOrigin, 1.109 + int64_t aSize); 1.110 + 1.111 + void 1.112 + UpdateOriginAccessTime(PersistenceType aPersistenceType, 1.113 + const nsACString& aGroup, 1.114 + const nsACString& aOrigin); 1.115 + 1.116 + void 1.117 + RemoveQuota(); 1.118 + 1.119 + void 1.120 + RemoveQuotaForPersistenceType(PersistenceType); 1.121 + 1.122 + void 1.123 + RemoveQuotaForOrigin(PersistenceType aPersistenceType, 1.124 + const nsACString& aGroup, 1.125 + const nsACString& aOrigin) 1.126 + { 1.127 + MutexAutoLock lock(mQuotaMutex); 1.128 + LockedRemoveQuotaForOrigin(aPersistenceType, aGroup, aOrigin); 1.129 + } 1.130 + 1.131 + void 1.132 + RemoveQuotaForPattern(PersistenceType aPersistenceType, 1.133 + const nsACString& aPattern); 1.134 + 1.135 + already_AddRefed<QuotaObject> 1.136 + GetQuotaObject(PersistenceType aPersistenceType, 1.137 + const nsACString& aGroup, 1.138 + const nsACString& aOrigin, 1.139 + nsIFile* aFile); 1.140 + 1.141 + already_AddRefed<QuotaObject> 1.142 + GetQuotaObject(PersistenceType aPersistenceType, 1.143 + const nsACString& aGroup, 1.144 + const nsACString& aOrigin, 1.145 + const nsAString& aPath); 1.146 + 1.147 + // Set the Window that the current thread is doing operations for. 1.148 + // The caller is responsible for ensuring that aWindow is held alive. 1.149 + static void 1.150 + SetCurrentWindow(nsPIDOMWindow* aWindow) 1.151 + { 1.152 + QuotaManager* quotaManager = Get(); 1.153 + NS_ASSERTION(quotaManager, "Must have a manager here!"); 1.154 + 1.155 + quotaManager->SetCurrentWindowInternal(aWindow); 1.156 + } 1.157 + 1.158 + static void 1.159 + CancelPromptsForWindow(nsPIDOMWindow* aWindow) 1.160 + { 1.161 + NS_ASSERTION(aWindow, "Passed null window!"); 1.162 + 1.163 + QuotaManager* quotaManager = Get(); 1.164 + NS_ASSERTION(quotaManager, "Must have a manager here!"); 1.165 + 1.166 + quotaManager->CancelPromptsForWindowInternal(aWindow); 1.167 + } 1.168 + 1.169 + // Called when a storage is created. 1.170 + bool 1.171 + RegisterStorage(nsIOfflineStorage* aStorage); 1.172 + 1.173 + // Called when a storage is being unlinked or destroyed. 1.174 + void 1.175 + UnregisterStorage(nsIOfflineStorage* aStorage); 1.176 + 1.177 + // Called when a storage has been closed. 1.178 + void 1.179 + OnStorageClosed(nsIOfflineStorage* aStorage); 1.180 + 1.181 + // Called when a window is being purged from the bfcache or the user leaves 1.182 + // a page which isn't going into the bfcache. Forces any live storage 1.183 + // objects to close themselves and aborts any running transactions. 1.184 + void 1.185 + AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow); 1.186 + 1.187 + // Used to check if there are running transactions in a given window. 1.188 + bool 1.189 + HasOpenTransactions(nsPIDOMWindow* aWindow); 1.190 + 1.191 + // Waits for storages to be cleared and for version change transactions to 1.192 + // complete before dispatching the given runnable. 1.193 + nsresult 1.194 + WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern, 1.195 + Nullable<PersistenceType> aPersistenceType, 1.196 + const nsACString& aId, nsIRunnable* aRunnable); 1.197 + 1.198 + // Acquire exclusive access to the storage given (waits for all others to 1.199 + // close). If storages need to close first, the callback will be invoked 1.200 + // with an array of said storages. 1.201 + nsresult 1.202 + AcquireExclusiveAccess(nsIOfflineStorage* aStorage, 1.203 + const nsACString& aOrigin, 1.204 + Nullable<PersistenceType> aPersistenceType, 1.205 + AcquireListener* aListener, 1.206 + WaitingOnStoragesCallback aCallback, 1.207 + void* aClosure) 1.208 + { 1.209 + NS_ASSERTION(aStorage, "Need a storage here!"); 1.210 + return AcquireExclusiveAccess(aOrigin, aPersistenceType, aStorage, 1.211 + aListener, aCallback, aClosure); 1.212 + } 1.213 + 1.214 + nsresult 1.215 + AcquireExclusiveAccess(const nsACString& aOrigin, 1.216 + Nullable<PersistenceType> aPersistenceType, 1.217 + AcquireListener* aListener, 1.218 + WaitingOnStoragesCallback aCallback, 1.219 + void* aClosure) 1.220 + { 1.221 + return AcquireExclusiveAccess(aOrigin, aPersistenceType, nullptr, 1.222 + aListener, aCallback, aClosure); 1.223 + } 1.224 + 1.225 + void 1.226 + AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, 1.227 + Nullable<PersistenceType> aPersistenceType, 1.228 + const nsACString& aId); 1.229 + 1.230 + bool 1.231 + IsClearOriginPending(const nsACString& aPattern, 1.232 + Nullable<PersistenceType> aPersistenceType) 1.233 + { 1.234 + return !!FindSynchronizedOp(aPattern, aPersistenceType, EmptyCString()); 1.235 + } 1.236 + 1.237 + nsresult 1.238 + GetDirectoryForOrigin(PersistenceType aPersistenceType, 1.239 + const nsACString& aASCIIOrigin, 1.240 + nsIFile** aDirectory) const; 1.241 + 1.242 + nsresult 1.243 + EnsureOriginIsInitialized(PersistenceType aPersistenceType, 1.244 + const nsACString& aGroup, 1.245 + const nsACString& aOrigin, 1.246 + bool aTrackQuota, 1.247 + nsIFile** aDirectory); 1.248 + 1.249 + void 1.250 + OriginClearCompleted(PersistenceType aPersistenceType, 1.251 + const OriginOrPatternString& aOriginOrPattern); 1.252 + 1.253 + void 1.254 + ResetOrClearCompleted(); 1.255 + 1.256 + void 1.257 + AssertCurrentThreadOwnsQuotaMutex() 1.258 + { 1.259 + mQuotaMutex.AssertCurrentThreadOwns(); 1.260 + } 1.261 + 1.262 + nsIThread* 1.263 + IOThread() 1.264 + { 1.265 + NS_ASSERTION(mIOThread, "This should never be null!"); 1.266 + return mIOThread; 1.267 + } 1.268 + 1.269 + already_AddRefed<Client> 1.270 + GetClient(Client::Type aClientType); 1.271 + 1.272 + const nsString& 1.273 + GetStoragePath(PersistenceType aPersistenceType) const 1.274 + { 1.275 + if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) { 1.276 + return mPersistentStoragePath; 1.277 + } 1.278 + 1.279 + NS_ASSERTION(aPersistenceType == PERSISTENCE_TYPE_TEMPORARY, "Huh?"); 1.280 + 1.281 + return mTemporaryStoragePath; 1.282 + } 1.283 + 1.284 + uint64_t 1.285 + GetGroupLimit() const; 1.286 + 1.287 + static uint32_t 1.288 + GetStorageQuotaMB(); 1.289 + 1.290 + static void 1.291 + GetStorageId(PersistenceType aPersistenceType, 1.292 + const nsACString& aOrigin, 1.293 + Client::Type aClientType, 1.294 + const nsAString& aName, 1.295 + nsACString& aDatabaseId); 1.296 + 1.297 + static nsresult 1.298 + GetInfoFromURI(nsIURI* aURI, 1.299 + uint32_t aAppId, 1.300 + bool aInMozBrowser, 1.301 + nsACString* aGroup, 1.302 + nsACString* aASCIIOrigin, 1.303 + StoragePrivilege* aPrivilege, 1.304 + PersistenceType* aDefaultPersistenceType); 1.305 + 1.306 + static nsresult 1.307 + GetInfoFromPrincipal(nsIPrincipal* aPrincipal, 1.308 + nsACString* aGroup, 1.309 + nsACString* aASCIIOrigin, 1.310 + StoragePrivilege* aPrivilege, 1.311 + PersistenceType* aDefaultPersistenceType); 1.312 + 1.313 + static nsresult 1.314 + GetInfoFromWindow(nsPIDOMWindow* aWindow, 1.315 + nsACString* aGroup, 1.316 + nsACString* aASCIIOrigin, 1.317 + StoragePrivilege* aPrivilege, 1.318 + PersistenceType* aDefaultPersistenceType); 1.319 + 1.320 + static void 1.321 + GetInfoForChrome(nsACString* aGroup, 1.322 + nsACString* aASCIIOrigin, 1.323 + StoragePrivilege* aPrivilege, 1.324 + PersistenceType* aDefaultPersistenceType); 1.325 + 1.326 + static void 1.327 + GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly, 1.328 + const nsACString& aOrigin, nsAutoCString& _retval) 1.329 + { 1.330 + return GetOriginPatternString(aAppId, 1.331 + aBrowserOnly ? MozBrowser : NotMozBrowser, 1.332 + aOrigin, _retval); 1.333 + } 1.334 + 1.335 + static void 1.336 + GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly, 1.337 + nsAutoCString& _retval) 1.338 + { 1.339 + return GetOriginPatternString(aAppId, 1.340 + aBrowserOnly ? MozBrowser : IgnoreMozBrowser, 1.341 + EmptyCString(), _retval); 1.342 + } 1.343 + 1.344 +private: 1.345 + QuotaManager(); 1.346 + 1.347 + virtual ~QuotaManager(); 1.348 + 1.349 + nsresult 1.350 + Init(); 1.351 + 1.352 + void 1.353 + SetCurrentWindowInternal(nsPIDOMWindow* aWindow); 1.354 + 1.355 + void 1.356 + CancelPromptsForWindowInternal(nsPIDOMWindow* aWindow); 1.357 + 1.358 + // Determine if the quota is lifted for the Window the current thread is 1.359 + // using. 1.360 + bool 1.361 + LockedQuotaIsLifted(); 1.362 + 1.363 + uint64_t 1.364 + LockedCollectOriginsForEviction(uint64_t aMinSizeToBeFreed, 1.365 + nsTArray<OriginInfo*>& aOriginInfos); 1.366 + 1.367 + void 1.368 + LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType, 1.369 + const nsACString& aGroup, 1.370 + const nsACString& aOrigin); 1.371 + 1.372 + nsresult 1.373 + AcquireExclusiveAccess(const nsACString& aOrigin, 1.374 + Nullable<PersistenceType> aPersistenceType, 1.375 + nsIOfflineStorage* aStorage, 1.376 + AcquireListener* aListener, 1.377 + WaitingOnStoragesCallback aCallback, 1.378 + void* aClosure); 1.379 + 1.380 + void 1.381 + AddSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, 1.382 + Nullable<PersistenceType> aPersistenceType); 1.383 + 1.384 + nsresult 1.385 + RunSynchronizedOp(nsIOfflineStorage* aStorage, 1.386 + SynchronizedOp* aOp); 1.387 + 1.388 + SynchronizedOp* 1.389 + FindSynchronizedOp(const nsACString& aPattern, 1.390 + Nullable<PersistenceType> aPersistenceType, 1.391 + const nsACString& aId); 1.392 + 1.393 + nsresult 1.394 + MaybeUpgradeIndexedDBDirectory(); 1.395 + 1.396 + nsresult 1.397 + InitializeOrigin(PersistenceType aPersistenceType, 1.398 + const nsACString& aGroup, 1.399 + const nsACString& aOrigin, 1.400 + bool aTrackQuota, 1.401 + int64_t aAccessTime, 1.402 + nsIFile* aDirectory); 1.403 + 1.404 + nsresult 1.405 + ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly); 1.406 + 1.407 + void 1.408 + CheckTemporaryStorageLimits(); 1.409 + 1.410 + // Collect inactive and the least recently used origins. 1.411 + uint64_t 1.412 + CollectOriginsForEviction(uint64_t aMinSizeToBeFreed, 1.413 + nsTArray<OriginInfo*>& aOriginInfos); 1.414 + 1.415 + void 1.416 + DeleteTemporaryFilesForOrigin(const nsACString& aOrigin); 1.417 + 1.418 + void 1.419 + FinalizeOriginEviction(nsTArray<nsCString>& aOrigins); 1.420 + 1.421 + void 1.422 + SaveOriginAccessTime(const nsACString& aOrigin, int64_t aTimestamp); 1.423 + 1.424 + void 1.425 + ReleaseIOThreadObjects() 1.426 + { 1.427 + AssertIsOnIOThread(); 1.428 + 1.429 + for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { 1.430 + mClients[index]->ReleaseIOThreadObjects(); 1.431 + } 1.432 + } 1.433 + 1.434 + static void 1.435 + GetOriginPatternString(uint32_t aAppId, 1.436 + MozBrowserPatternFlag aBrowserFlag, 1.437 + const nsACString& aOrigin, 1.438 + nsAutoCString& _retval); 1.439 + 1.440 + static PLDHashOperator 1.441 + RemoveQuotaForPersistenceTypeCallback(const nsACString& aKey, 1.442 + nsAutoPtr<GroupInfoPair>& aValue, 1.443 + void* aUserArg); 1.444 + 1.445 + static PLDHashOperator 1.446 + RemoveQuotaCallback(const nsACString& aKey, 1.447 + nsAutoPtr<GroupInfoPair>& aValue, 1.448 + void* aUserArg); 1.449 + 1.450 + static PLDHashOperator 1.451 + RemoveQuotaForPatternCallback(const nsACString& aKey, 1.452 + nsAutoPtr<GroupInfoPair>& aValue, 1.453 + void* aUserArg); 1.454 + 1.455 + static PLDHashOperator 1.456 + GetOriginsExceedingGroupLimit(const nsACString& aKey, 1.457 + GroupInfoPair* aValue, 1.458 + void* aUserArg); 1.459 + 1.460 + static PLDHashOperator 1.461 + GetAllTemporaryStorageOrigins(const nsACString& aKey, 1.462 + GroupInfoPair* aValue, 1.463 + void* aUserArg); 1.464 + 1.465 + static PLDHashOperator 1.466 + AddTemporaryStorageOrigins(const nsACString& aKey, 1.467 + ArrayCluster<nsIOfflineStorage*>* aValue, 1.468 + void* aUserArg); 1.469 + 1.470 + static PLDHashOperator 1.471 + GetInactiveTemporaryStorageOrigins(const nsACString& aKey, 1.472 + GroupInfoPair* aValue, 1.473 + void* aUserArg); 1.474 + 1.475 + // TLS storage index for the current thread's window. 1.476 + unsigned int mCurrentWindowIndex; 1.477 + 1.478 + mozilla::Mutex mQuotaMutex; 1.479 + 1.480 + nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs; 1.481 + 1.482 + // A map of Windows to the corresponding quota helper. 1.483 + nsRefPtrHashtable<nsPtrHashKey<nsPIDOMWindow>, 1.484 + CheckQuotaHelper> mCheckQuotaHelpers; 1.485 + 1.486 + // Maintains a list of live storages per origin. 1.487 + nsClassHashtable<nsCStringHashKey, 1.488 + ArrayCluster<nsIOfflineStorage*> > mLiveStorages; 1.489 + 1.490 + // Maintains a list of synchronized operatons that are in progress or queued. 1.491 + nsAutoTArray<nsAutoPtr<SynchronizedOp>, 5> mSynchronizedOps; 1.492 + 1.493 + // Thread on which IO is performed. 1.494 + nsCOMPtr<nsIThread> mIOThread; 1.495 + 1.496 + // A timer that gets activated at shutdown to ensure we close all storages. 1.497 + nsCOMPtr<nsITimer> mShutdownTimer; 1.498 + 1.499 + // A list of all successfully initialized origins. This list isn't protected 1.500 + // by any mutex but it is only ever touched on the IO thread. 1.501 + nsTArray<nsCString> mInitializedOrigins; 1.502 + 1.503 + nsAutoTArray<nsRefPtr<Client>, Client::TYPE_MAX> mClients; 1.504 + 1.505 + nsString mIndexedDBPath; 1.506 + nsString mPersistentStoragePath; 1.507 + nsString mTemporaryStoragePath; 1.508 + 1.509 + uint64_t mTemporaryStorageLimit; 1.510 + uint64_t mTemporaryStorageUsage; 1.511 + bool mTemporaryStorageInitialized; 1.512 + 1.513 + bool mStorageAreaInitialized; 1.514 +}; 1.515 + 1.516 +class AutoEnterWindow 1.517 +{ 1.518 +public: 1.519 + AutoEnterWindow(nsPIDOMWindow* aWindow) 1.520 + { 1.521 + QuotaManager::SetCurrentWindow(aWindow); 1.522 + } 1.523 + 1.524 + ~AutoEnterWindow() 1.525 + { 1.526 + QuotaManager::SetCurrentWindow(nullptr); 1.527 + } 1.528 +}; 1.529 + 1.530 +END_QUOTA_NAMESPACE 1.531 + 1.532 +#endif /* mozilla_dom_quota_quotamanager_h__ */