Bug 1526591 - Remove devtools.inspector.shapesHighlighter.enabled pref. r=rcaliman
[gecko.git] / dom / quota / QuotaManager.h
blobfb763544862312c25f3dc357483618590f700c99
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_quota_quotamanager_h__
8 #define mozilla_dom_quota_quotamanager_h__
10 #include "QuotaCommon.h"
12 #include "mozilla/dom/Nullable.h"
13 #include "mozilla/dom/ipc/IdType.h"
14 #include "mozilla/Mutex.h"
16 #include "nsClassHashtable.h"
17 #include "nsRefPtrHashtable.h"
19 #include "Client.h"
20 #include "PersistenceType.h"
22 #include "prenv.h"
24 #define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
26 class mozIStorageConnection;
27 class nsIEventTarget;
28 class nsIPrincipal;
29 class nsIThread;
30 class nsITimer;
31 class nsIURI;
32 class nsPIDOMWindowOuter;
33 class nsIRunnable;
35 namespace mozilla {
37 class OriginAttributes;
39 } // namespace mozilla
41 BEGIN_QUOTA_NAMESPACE
43 class DirectoryLockImpl;
44 class GroupInfo;
45 class GroupInfoPair;
46 class OriginInfo;
47 class OriginScope;
48 class QuotaObject;
50 class NS_NO_VTABLE RefCountedObject {
51 public:
52 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
55 class DirectoryLock : public RefCountedObject {
56 friend class DirectoryLockImpl;
58 private:
59 DirectoryLock() {}
61 ~DirectoryLock() {}
64 class NS_NO_VTABLE OpenDirectoryListener : public RefCountedObject {
65 public:
66 virtual void DirectoryLockAcquired(DirectoryLock* aLock) = 0;
68 virtual void DirectoryLockFailed() = 0;
70 protected:
71 virtual ~OpenDirectoryListener() {}
74 struct OriginParams {
75 OriginParams(PersistenceType aPersistenceType, const nsACString& aOrigin)
76 : mOrigin(aOrigin), mPersistenceType(aPersistenceType) {}
78 nsCString mOrigin;
79 PersistenceType mPersistenceType;
82 class QuotaManager final : public BackgroundThreadObject {
83 friend class DirectoryLockImpl;
84 friend class GroupInfo;
85 friend class OriginInfo;
86 friend class QuotaObject;
88 typedef nsClassHashtable<nsCStringHashKey, nsTArray<DirectoryLockImpl*>>
89 DirectoryLockTable;
91 public:
92 class CreateRunnable;
94 private:
95 class ShutdownRunnable;
96 class ShutdownObserver;
98 public:
99 NS_INLINE_DECL_REFCOUNTING(QuotaManager)
101 static bool IsRunningXPCShellTests() {
102 static bool kRunningXPCShellTests =
103 !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
104 return kRunningXPCShellTests;
107 static bool IsRunningGTests() {
108 static bool kRunningGTests = !!PR_GetEnv("MOZ_RUN_GTEST");
109 return kRunningGTests;
112 static const char kReplaceChars[];
114 static void GetOrCreate(nsIRunnable* aCallback,
115 nsIEventTarget* aMainEventTarget = nullptr);
117 // Returns a non-owning reference.
118 static QuotaManager* Get();
120 // Returns true if we've begun the shutdown process.
121 static bool IsShuttingDown();
123 static bool IsOSMetadata(const nsAString& aFileName);
125 static bool IsDotFile(const nsAString& aFileName);
127 bool IsOriginInitialized(const nsACString& aOrigin) const {
128 AssertIsOnIOThread();
130 return mInitializedOrigins.Contains(aOrigin);
133 bool IsTemporaryStorageInitialized() const {
134 AssertIsOnIOThread();
136 return mTemporaryStorageInitialized;
139 void InitQuotaForOrigin(PersistenceType aPersistenceType,
140 const nsACString& aGroup, const nsACString& aOrigin,
141 uint64_t aUsageBytes, int64_t aAccessTime,
142 bool aPersisted);
144 void DecreaseUsageForOrigin(PersistenceType aPersistenceType,
145 const nsACString& aGroup,
146 const nsACString& aOrigin, int64_t aSize);
148 void UpdateOriginAccessTime(PersistenceType aPersistenceType,
149 const nsACString& aGroup,
150 const nsACString& aOrigin);
152 void RemoveQuota();
154 void RemoveQuotaForOrigin(PersistenceType aPersistenceType,
155 const nsACString& aGroup,
156 const nsACString& aOrigin) {
157 MutexAutoLock lock(mQuotaMutex);
158 LockedRemoveQuotaForOrigin(aPersistenceType, aGroup, aOrigin);
161 already_AddRefed<QuotaObject> GetQuotaObject(PersistenceType aPersistenceType,
162 const nsACString& aGroup,
163 const nsACString& aOrigin,
164 nsIFile* aFile,
165 int64_t aFileSize = -1,
166 int64_t* aFileSizeOut = nullptr);
168 already_AddRefed<QuotaObject> GetQuotaObject(PersistenceType aPersistenceType,
169 const nsACString& aGroup,
170 const nsACString& aOrigin,
171 const nsAString& aPath,
172 int64_t aFileSize = -1,
173 int64_t* aFileSizeOut = nullptr);
175 Nullable<bool> OriginPersisted(const nsACString& aGroup,
176 const nsACString& aOrigin);
178 void PersistOrigin(const nsACString& aGroup, const nsACString& aOrigin);
180 // Called when a process is being shot down. Aborts any running operations
181 // for the given process.
182 void AbortOperationsForProcess(ContentParentId aContentParentId);
184 nsresult GetDirectoryForOrigin(PersistenceType aPersistenceType,
185 const nsACString& aASCIIOrigin,
186 nsIFile** aDirectory) const;
188 nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory, bool aPersistent);
190 nsresult GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp,
191 bool* aPersisted, nsACString& aSuffix,
192 nsACString& aGroup, nsACString& aOrigin);
194 nsresult GetDirectoryMetadata2WithRestore(
195 nsIFile* aDirectory, bool aPersistent, int64_t* aTimestamp,
196 bool* aPersisted, nsACString& aSuffix, nsACString& aGroup,
197 nsACString& aOrigin, const bool aTelemetry = false);
199 nsresult GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp,
200 bool* aPersisted);
202 nsresult GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
203 bool aPersistent,
204 int64_t* aTimestamp,
205 bool* aPersisted);
207 // This is the main entry point into the QuotaManager API.
208 // Any storage API implementation (quota client) that participates in
209 // centralized quota and storage handling should call this method to get
210 // a directory lock which will protect client's files from being deleted
211 // while they are still in use.
212 // After a lock is acquired, client is notified via the open listener's
213 // method DirectoryLockAcquired. If the lock couldn't be acquired, client
214 // gets DirectoryLockFailed notification.
215 // A lock is a reference counted object and at the time DirectoryLockAcquired
216 // is called, quota manager holds just one strong reference to it which is
217 // then immediatelly cleared by quota manager. So it's up to client to add
218 // a new reference in order to keep the lock alive.
219 // Unlocking is simply done by dropping all references to the lock object.
220 // In other words, protection which the lock represents dies with the lock
221 // object itself.
222 void OpenDirectory(PersistenceType aPersistenceType, const nsACString& aGroup,
223 const nsACString& aOrigin, Client::Type aClientType,
224 bool aExclusive, OpenDirectoryListener* aOpenListener);
226 // XXX RemoveMe once bug 1170279 gets fixed.
227 void OpenDirectoryInternal(const Nullable<PersistenceType>& aPersistenceType,
228 const OriginScope& aOriginScope,
229 const Nullable<Client::Type>& aClientType,
230 bool aExclusive,
231 OpenDirectoryListener* aOpenListener);
233 // Collect inactive and the least recently used origins.
234 uint64_t CollectOriginsForEviction(
235 uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
237 void AssertStorageIsInitialized() const
238 #ifdef DEBUG
240 #else
243 #endif
245 nsresult EnsureStorageIsInitialized();
247 nsresult EnsureOriginIsInitialized(PersistenceType aPersistenceType,
248 const nsACString& aSuffix,
249 const nsACString& aGroup,
250 const nsACString& aOrigin,
251 bool aCreateIfNotExists,
252 nsIFile** aDirectory);
254 nsresult EnsureOriginIsInitializedInternal(
255 PersistenceType aPersistenceType, const nsACString& aSuffix,
256 const nsACString& aGroup, const nsACString& aOrigin,
257 bool aCreateIfNotExists, nsIFile** aDirectory, bool* aCreated);
259 nsresult EnsureTemporaryStorageIsInitialized();
261 nsresult EnsureOriginDirectory(nsIFile* aDirectory, bool aCreateIfNotExists,
262 bool* aCreated);
264 nsresult AboutToClearOrigins(
265 const Nullable<PersistenceType>& aPersistenceType,
266 const OriginScope& aOriginScope,
267 const Nullable<Client::Type>& aClientType);
269 void OriginClearCompleted(PersistenceType aPersistenceType,
270 const nsACString& aOrigin,
271 const Nullable<Client::Type>& aClientType);
273 void ResetOrClearCompleted();
275 void StartIdleMaintenance() {
276 AssertIsOnOwningThread();
278 for (auto& client : mClients) {
279 client->StartIdleMaintenance();
283 void StopIdleMaintenance() {
284 AssertIsOnOwningThread();
286 for (auto& client : mClients) {
287 client->StopIdleMaintenance();
291 void AssertCurrentThreadOwnsQuotaMutex() {
292 mQuotaMutex.AssertCurrentThreadOwns();
295 nsIThread* IOThread() {
296 NS_ASSERTION(mIOThread, "This should never be null!");
297 return mIOThread;
300 Client* GetClient(Client::Type aClientType);
302 const nsString& GetBasePath() const { return mBasePath; }
304 const nsString& GetStoragePath() const { return mStoragePath; }
306 const nsString& GetStoragePath(PersistenceType aPersistenceType) const {
307 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
308 return mPermanentStoragePath;
311 if (aPersistenceType == PERSISTENCE_TYPE_TEMPORARY) {
312 return mTemporaryStoragePath;
315 MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_DEFAULT);
317 return mDefaultStoragePath;
320 uint64_t GetGroupLimit() const;
322 void GetGroupUsageAndLimit(const nsACString& aGroup, UsageInfo* aUsageInfo);
324 void NotifyStoragePressure(uint64_t aUsage);
326 static void GetStorageId(PersistenceType aPersistenceType,
327 const nsACString& aOrigin, Client::Type aClientType,
328 nsACString& aDatabaseId);
330 static nsresult GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
331 nsACString* aSuffix, nsACString* aGroup,
332 nsACString* aOrigin);
334 static nsresult GetInfoFromWindow(nsPIDOMWindowOuter* aWindow,
335 nsACString* aSuffix, nsACString* aGroup,
336 nsACString* aOrigin);
338 static void GetInfoForChrome(nsACString* aSuffix, nsACString* aGroup,
339 nsACString* aOrigin);
341 static bool IsOriginInternal(const nsACString& aOrigin);
343 static void ChromeOrigin(nsACString& aOrigin);
345 static bool AreOriginsEqualOnDisk(nsACString& aOrigin1, nsACString& aOrigin2);
347 static bool ParseOrigin(const nsACString& aOrigin, nsCString& aSpec,
348 OriginAttributes* aAttrs);
350 private:
351 QuotaManager();
353 virtual ~QuotaManager();
355 nsresult Init(const nsAString& aBaseDirPath);
357 void Shutdown();
359 already_AddRefed<DirectoryLockImpl> CreateDirectoryLock(
360 const Nullable<PersistenceType>& aPersistenceType,
361 const nsACString& aGroup, const OriginScope& aOriginScope,
362 const Nullable<Client::Type>& aClientType, bool aExclusive,
363 bool aInternal, OpenDirectoryListener* aOpenListener);
365 already_AddRefed<DirectoryLockImpl> CreateDirectoryLockForEviction(
366 PersistenceType aPersistenceType, const nsACString& aGroup,
367 const nsACString& aOrigin);
369 void RegisterDirectoryLock(DirectoryLockImpl* aLock);
371 void UnregisterDirectoryLock(DirectoryLockImpl* aLock);
373 void RemovePendingDirectoryLock(DirectoryLockImpl* aLock);
375 uint64_t LockedCollectOriginsForEviction(
376 uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
378 void LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
379 const nsACString& aGroup,
380 const nsACString& aOrigin);
382 already_AddRefed<OriginInfo> LockedGetOriginInfo(
383 PersistenceType aPersistenceType, const nsACString& aGroup,
384 const nsACString& aOrigin);
386 nsresult MaybeUpgradeIndexedDBDirectory();
388 nsresult MaybeUpgradePersistentStorageDirectory();
390 nsresult MaybeRemoveOldDirectories();
392 template <typename Helper>
393 nsresult UpgradeStorage(const int32_t aOldVersion, const int32_t aNewVersion,
394 mozIStorageConnection* aConnection);
396 nsresult UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
398 nsresult UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection);
400 nsresult UpgradeStorageFrom2_0To2_1(mozIStorageConnection* aConnection);
402 nsresult MaybeRemoveLocalStorageData();
404 nsresult MaybeRemoveLocalStorageDirectories();
406 nsresult MaybeCreateLocalStorageArchive();
408 nsresult InitializeRepository(PersistenceType aPersistenceType);
410 nsresult InitializeOrigin(PersistenceType aPersistenceType,
411 const nsACString& aGroup, const nsACString& aOrigin,
412 int64_t aAccessTime, bool aPersisted,
413 nsIFile* aDirectory);
415 void CheckTemporaryStorageLimits();
417 void DeleteFilesForOrigin(PersistenceType aPersistenceType,
418 const nsACString& aOrigin);
420 void FinalizeOriginEviction(nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
422 void ReleaseIOThreadObjects() {
423 AssertIsOnIOThread();
425 for (uint32_t index = 0; index < uint32_t(Client::TypeMax()); index++) {
426 mClients[index]->ReleaseIOThreadObjects();
430 DirectoryLockTable& GetDirectoryLockTable(PersistenceType aPersistenceType);
432 bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
434 static void ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
436 mozilla::Mutex mQuotaMutex;
438 nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
440 // Maintains a list of directory locks that are queued.
441 nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks;
443 // Maintains a list of directory locks that are acquired or queued.
444 nsTArray<DirectoryLockImpl*> mDirectoryLocks;
446 // Directory lock tables that are used to update origin access time.
447 DirectoryLockTable mTemporaryDirectoryLockTable;
448 DirectoryLockTable mDefaultDirectoryLockTable;
450 // Thread on which IO is performed.
451 nsCOMPtr<nsIThread> mIOThread;
453 // A timer that gets activated at shutdown to ensure we close all storages.
454 nsCOMPtr<nsITimer> mShutdownTimer;
456 // A list of all successfully initialized persistent origins. This list isn't
457 // protected by any mutex but it is only ever touched on the IO thread.
458 nsTArray<nsCString> mInitializedOrigins;
460 // A hash table that is used to cache origin parser results for given
461 // sanitized origin strings. This hash table isn't protected by any mutex but
462 // it is only ever touched on the IO thread.
463 nsDataHashtable<nsCStringHashKey, bool> mValidOrigins;
465 // This array is populated at initialization time and then never modified, so
466 // it can be iterated on any thread.
467 AutoTArray<RefPtr<Client>, Client::TYPE_MAX> mClients;
469 nsString mBasePath;
470 nsString mIndexedDBPath;
471 nsString mStoragePath;
472 nsString mPermanentStoragePath;
473 nsString mTemporaryStoragePath;
474 nsString mDefaultStoragePath;
476 uint64_t mTemporaryStorageLimit;
477 uint64_t mTemporaryStorageUsage;
478 bool mTemporaryStorageInitialized;
480 bool mStorageInitialized;
483 END_QUOTA_NAMESPACE
485 #endif /* mozilla_dom_quota_quotamanager_h__ */