Bug 1874684 - Part 6: Limit day length calculations to safe integers. r=mgaudet
[gecko.git] / dom / quota / QuotaManager.h
blob25c069810d31a826bc416b6f26cda48c2064b962
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 <cstdint>
11 #include <utility>
12 #include "Client.h"
13 #include "ErrorList.h"
14 #include "mozilla/AlreadyAddRefed.h"
15 #include "mozilla/Assertions.h"
16 #include "mozilla/InitializedOnce.h"
17 #include "mozilla/MozPromise.h"
18 #include "mozilla/Mutex.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/Result.h"
21 #include "mozilla/dom/Nullable.h"
22 #include "mozilla/dom/ipc/IdType.h"
23 #include "mozilla/dom/quota/Assertions.h"
24 #include "mozilla/dom/quota/CommonMetadata.h"
25 #include "mozilla/dom/quota/DirectoryLockCategory.h"
26 #include "mozilla/dom/quota/ForwardDecls.h"
27 #include "mozilla/dom/quota/InitializationTypes.h"
28 #include "mozilla/dom/quota/PersistenceType.h"
29 #include "mozilla/dom/quota/QuotaCommon.h"
30 #include "nsCOMPtr.h"
31 #include "nsClassHashtable.h"
32 #include "nsTHashMap.h"
33 #include "nsDebug.h"
34 #include "nsHashKeys.h"
35 #include "nsISupports.h"
36 #include "nsStringFwd.h"
37 #include "nsTArray.h"
38 #include "nsTStringRepr.h"
39 #include "nscore.h"
40 #include "prenv.h"
42 #define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1"
44 class mozIStorageConnection;
45 class nsIEventTarget;
46 class nsIFile;
47 class nsIPrincipal;
48 class nsIRunnable;
49 class nsIThread;
50 class nsITimer;
51 class nsPIDOMWindowOuter;
53 namespace mozilla {
55 class OriginAttributes;
56 class OriginAttributesPattern;
58 namespace ipc {
60 class PrincipalInfo;
62 } // namespace ipc
64 } // namespace mozilla
66 namespace mozilla::dom::quota {
68 class CanonicalQuotaObject;
69 class ClientUsageArray;
70 class ClientDirectoryLock;
71 class DirectoryLockImpl;
72 class GroupInfo;
73 class GroupInfoPair;
74 class NormalOriginOperationBase;
75 class OriginDirectoryLock;
76 class OriginInfo;
77 class OriginScope;
78 class QuotaObject;
79 class UniversalDirectoryLock;
81 class QuotaManager final : public BackgroundThreadObject {
82 friend class CanonicalQuotaObject;
83 friend class ClearStorageOp;
84 friend class DirectoryLockImpl;
85 friend class GroupInfo;
86 friend class InitOp;
87 friend class OriginInfo;
88 friend class ShutdownStorageOp;
90 using PrincipalInfo = mozilla::ipc::PrincipalInfo;
91 using DirectoryLockTable =
92 nsClassHashtable<nsCStringHashKey, nsTArray<NotNull<DirectoryLockImpl*>>>;
94 class Observer;
96 public:
97 QuotaManager(const nsAString& aBasePath, const nsAString& aStorageName);
99 NS_INLINE_DECL_REFCOUNTING(QuotaManager)
101 static nsresult Initialize();
103 static bool IsRunningXPCShellTests() {
104 static bool kRunningXPCShellTests =
105 !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
106 return kRunningXPCShellTests;
109 static bool IsRunningGTests() {
110 static bool kRunningGTests = !!PR_GetEnv("MOZ_RUN_GTEST");
111 return kRunningGTests;
114 static const char kReplaceChars[];
115 static const char16_t kReplaceChars16[];
117 static Result<MovingNotNull<RefPtr<QuotaManager>>, nsresult> GetOrCreate();
119 static Result<Ok, nsresult> EnsureCreated();
121 // Returns a non-owning reference.
122 static QuotaManager* Get();
124 // Use only in gtests!
125 static nsIObserver* GetObserver();
127 // Returns true if we've begun the shutdown process.
128 static bool IsShuttingDown();
130 static void ShutdownInstance();
132 // Use only in gtests!
133 static void Reset();
135 static bool IsOSMetadata(const nsAString& aFileName);
137 static bool IsDotFile(const nsAString& aFileName);
139 void RegisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp);
141 void UnregisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp);
143 bool IsOriginInitialized(const nsACString& aOrigin) const {
144 AssertIsOnIOThread();
146 return mInitializedOrigins.Contains(aOrigin);
149 bool IsTemporaryStorageInitializedInternal() const {
150 AssertIsOnIOThread();
152 return mTemporaryStorageInitializedInternal;
156 * For initialization of an origin where the directory already exists. This is
157 * used by EnsureTemporaryStorageIsInitializedInternal/InitializeRepository
158 * once it has tallied origin usage by calling each of the QuotaClient
159 * InitOrigin methods.
161 void InitQuotaForOrigin(const FullOriginMetadata& aFullOriginMetadata,
162 const ClientUsageArray& aClientUsages,
163 uint64_t aUsageBytes);
166 * For use in special-cases like LSNG where we need to be able to know that
167 * there is no data stored for an origin. LSNG knows that there is 0 usage for
168 * its storage of an origin and wants to make sure there is a QuotaObject
169 * tracking this. This method will create a non-persisted, 0-usage,
170 * mDirectoryExists=false OriginInfo if there isn't already an OriginInfo. If
171 * an OriginInfo already exists, it will be left as-is, because that implies a
172 * different client has usages for the origin (and there's no need to add
173 * LSNG's 0 usage to the QuotaObject).
175 void EnsureQuotaForOrigin(const OriginMetadata& aOriginMetadata);
178 * For use when creating an origin directory. It's possible that origin usage
179 * is already being tracked due to a call to EnsureQuotaForOrigin, and in that
180 * case we need to update the existing OriginInfo rather than create a new
181 * one.
183 * @return last access time of the origin.
185 int64_t NoteOriginDirectoryCreated(const OriginMetadata& aOriginMetadata,
186 bool aPersisted);
188 // XXX clients can use QuotaObject instead of calling this method directly.
189 void DecreaseUsageForClient(const ClientMetadata& aClientMetadata,
190 int64_t aSize);
192 void ResetUsageForClient(const ClientMetadata& aClientMetadata);
194 UsageInfo GetUsageForClient(PersistenceType aPersistenceType,
195 const OriginMetadata& aOriginMetadata,
196 Client::Type aClientType);
198 void UpdateOriginAccessTime(PersistenceType aPersistenceType,
199 const OriginMetadata& aOriginMetadata);
201 void RemoveQuota();
203 void RemoveQuotaForRepository(PersistenceType aPersistenceType) {
204 MutexAutoLock lock(mQuotaMutex);
205 LockedRemoveQuotaForRepository(aPersistenceType);
208 void RemoveQuotaForOrigin(PersistenceType aPersistenceType,
209 const OriginMetadata& aOriginMetadata) {
210 MutexAutoLock lock(mQuotaMutex);
211 LockedRemoveQuotaForOrigin(aOriginMetadata);
214 nsresult LoadQuota();
216 void UnloadQuota();
218 already_AddRefed<QuotaObject> GetQuotaObject(
219 PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
220 Client::Type aClientType, nsIFile* aFile, int64_t aFileSize = -1,
221 int64_t* aFileSizeOut = nullptr);
223 already_AddRefed<QuotaObject> GetQuotaObject(
224 PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
225 Client::Type aClientType, const nsAString& aPath, int64_t aFileSize = -1,
226 int64_t* aFileSizeOut = nullptr);
228 already_AddRefed<QuotaObject> GetQuotaObject(const int64_t aDirectoryLockId,
229 const nsAString& aPath);
231 Nullable<bool> OriginPersisted(const OriginMetadata& aOriginMetadata);
233 void PersistOrigin(const OriginMetadata& aOriginMetadata);
235 using DirectoryLockIdTableArray =
236 AutoTArray<Client::DirectoryLockIdTable, Client::TYPE_MAX>;
237 void AbortOperationsForLocks(const DirectoryLockIdTableArray& aLockIds);
239 // Called when a process is being shot down. Aborts any running operations
240 // for the given process.
241 void AbortOperationsForProcess(ContentParentId aContentParentId);
243 Result<nsCOMPtr<nsIFile>, nsresult> GetOriginDirectory(
244 const OriginMetadata& aOriginMetadata) const;
246 Result<bool, nsresult> DoesOriginDirectoryExist(
247 const OriginMetadata& aOriginMetadata) const;
249 static nsresult CreateDirectoryMetadata(
250 nsIFile& aDirectory, int64_t aTimestamp,
251 const OriginMetadata& aOriginMetadata);
253 static nsresult CreateDirectoryMetadata2(
254 nsIFile& aDirectory, int64_t aTimestamp, bool aPersisted,
255 const OriginMetadata& aOriginMetadata);
257 nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory);
259 // XXX Remove aPersistenceType argument once the persistence type is stored
260 // in the metadata file.
261 Result<FullOriginMetadata, nsresult> LoadFullOriginMetadata(
262 nsIFile* aDirectory, PersistenceType aPersistenceType);
264 Result<FullOriginMetadata, nsresult> LoadFullOriginMetadataWithRestore(
265 nsIFile* aDirectory);
267 Result<OriginMetadata, nsresult> GetOriginMetadata(nsIFile* aDirectory);
269 Result<Ok, nsresult> RemoveOriginDirectory(nsIFile& aDirectory);
271 Result<bool, nsresult> DoesClientDirectoryExist(
272 const ClientMetadata& aClientMetadata) const;
274 RefPtr<UniversalDirectoryLockPromise> OpenStorageDirectory(
275 const Nullable<PersistenceType>& aPersistenceType,
276 const OriginScope& aOriginScope,
277 const Nullable<Client::Type>& aClientType, bool aExclusive,
278 DirectoryLockCategory aCategory = DirectoryLockCategory::None,
279 Maybe<RefPtr<UniversalDirectoryLock>&> aPendingDirectoryLockOut =
280 Nothing());
282 // This is the main entry point into the QuotaManager API.
283 // Any storage API implementation (quota client) that participates in
284 // centralized quota and storage handling should call this method to get
285 // a directory lock which will protect client's files from being deleted
286 // while they are still in use.
287 // After a lock is acquired, client is notified by resolving the returned
288 // promise. If the lock couldn't be acquired, client is notified by rejecting
289 // the returned promise.
290 // A lock is a reference counted object and at the time the returned promise
291 // is resolved, there are no longer other strong references except the one
292 // held by the resolve value itself. So it's up to client to add a new
293 // reference in order to keep the lock alive.
294 // Unlocking is simply done by dropping all references to the lock object.
295 // In other words, protection which the lock represents dies with the lock
296 // object itself (Note that it's now possible to release directory locks
297 // sooner by calling newly added Drop method).
298 RefPtr<ClientDirectoryLockPromise> OpenClientDirectory(
299 const ClientMetadata& aClientMetadata,
300 Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut = Nothing());
302 RefPtr<ClientDirectoryLock> CreateDirectoryLock(
303 const ClientMetadata& aClientMetadata, bool aExclusive);
305 // XXX RemoveMe once bug 1170279 gets fixed.
306 RefPtr<UniversalDirectoryLock> CreateDirectoryLockInternal(
307 const Nullable<PersistenceType>& aPersistenceType,
308 const OriginScope& aOriginScope,
309 const Nullable<Client::Type>& aClientType, bool aExclusive,
310 DirectoryLockCategory aCategory = DirectoryLockCategory::None);
312 // Collect inactive and the least recently used origins.
313 uint64_t CollectOriginsForEviction(
314 uint64_t aMinSizeToBeFreed,
315 nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
318 * Helper method to invoke the provided predicate on all "pending" OriginInfo
319 * instances. These are origins for which the origin directory has not yet
320 * been created but for which quota is already being tracked. This happens,
321 * for example, for the LocalStorage client where an origin that previously
322 * was not using LocalStorage can start issuing writes which it buffers until
323 * eventually flushing them. We defer creating the origin directory for as
324 * long as possible in that case, so the directory won't exist. Logic that
325 * would otherwise only consult the filesystem also needs to use this method.
327 template <typename P>
328 void CollectPendingOriginsForListing(P aPredicate);
330 RefPtr<BoolPromise> InitializeStorage();
332 RefPtr<BoolPromise> InitializeStorage(
333 RefPtr<UniversalDirectoryLock> aDirectoryLock);
335 RefPtr<BoolPromise> StorageInitialized();
337 bool IsStorageInitialized() const {
338 AssertIsOnOwningThread();
340 return mStorageInitialized;
343 bool IsStorageInitializedInternal() const {
344 AssertIsOnIOThread();
345 return static_cast<bool>(mStorageConnection);
348 void AssertStorageIsInitializedInternal() const
349 #ifdef DEBUG
351 #else
354 #endif
356 RefPtr<BoolPromise> TemporaryStorageInitialized();
358 private:
359 nsresult EnsureStorageIsInitializedInternal();
361 public:
362 // Returns a pair of an nsIFile object referring to the directory, and a bool
363 // indicating whether the directory was newly created.
364 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
365 EnsurePersistentOriginIsInitialized(const OriginMetadata& aOriginMetadata);
367 bool IsTemporaryOriginInitialized(
368 const OriginMetadata& aOriginMetadata) const;
370 // Returns a pair of an nsIFile object referring to the directory, and a bool
371 // indicating whether the directory was newly created.
372 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
373 EnsureTemporaryOriginIsInitialized(PersistenceType aPersistenceType,
374 const OriginMetadata& aOriginMetadata);
376 RefPtr<BoolPromise> InitializePersistentClient(
377 const PrincipalInfo& aPrincipalInfo, Client::Type aClientType);
379 // Returns a pair of an nsIFile object referring to the directory, and a bool
380 // indicating whether the directory was newly created.
381 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
382 EnsurePersistentClientIsInitialized(const ClientMetadata& aClientMetadata);
384 RefPtr<BoolPromise> InitializeTemporaryClient(
385 PersistenceType aPersistenceType, const PrincipalInfo& aPrincipalInfo,
386 Client::Type aClientType);
388 // Returns a pair of an nsIFile object referring to the directory, and a bool
389 // indicating whether the directory was newly created.
390 Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
391 EnsureTemporaryClientIsInitialized(const ClientMetadata& aClientMetadata);
393 RefPtr<BoolPromise> InitializeTemporaryStorage();
395 RefPtr<BoolPromise> InitializeTemporaryStorage(
396 RefPtr<UniversalDirectoryLock> aDirectoryLock);
398 bool IsTemporaryStorageInitialized() const {
399 AssertIsOnOwningThread();
401 return mTemporaryStorageInitialized;
404 nsresult EnsureTemporaryStorageIsInitializedInternal();
406 RefPtr<BoolPromise> ClearStoragesForOrigin(
407 const Maybe<PersistenceType>& aPersistenceType,
408 const PrincipalInfo& aPrincipalInfo,
409 const Maybe<Client::Type>& aClientType);
411 RefPtr<BoolPromise> ClearStoragesForOriginPrefix(
412 const Maybe<PersistenceType>& aPersistenceType,
413 const PrincipalInfo& aPrincipalInfo);
415 RefPtr<BoolPromise> ClearStoragesForOriginAttributesPattern(
416 const OriginAttributesPattern& aPattern);
418 RefPtr<BoolPromise> ClearPrivateRepository();
420 RefPtr<BoolPromise> ClearStorage();
422 RefPtr<BoolPromise> ShutdownStorage();
424 void ShutdownStorageInternal();
426 // Returns a bool indicating whether the directory was newly created.
427 Result<bool, nsresult> EnsureOriginDirectory(nsIFile& aDirectory);
429 nsresult AboutToClearOrigins(
430 const Nullable<PersistenceType>& aPersistenceType,
431 const OriginScope& aOriginScope,
432 const Nullable<Client::Type>& aClientType);
434 void OriginClearCompleted(PersistenceType aPersistenceType,
435 const nsACString& aOrigin,
436 const Nullable<Client::Type>& aClientType);
438 void RepositoryClearCompleted(PersistenceType aPersistenceType);
440 void StartIdleMaintenance() {
441 AssertIsOnOwningThread();
443 for (const auto& client : *mClients) {
444 client->StartIdleMaintenance();
448 void StopIdleMaintenance() {
449 AssertIsOnOwningThread();
451 for (const auto& client : *mClients) {
452 client->StopIdleMaintenance();
456 void AssertCurrentThreadOwnsQuotaMutex() {
457 mQuotaMutex.AssertCurrentThreadOwns();
460 nsIThread* IOThread() { return mIOThread->get(); }
462 Client* GetClient(Client::Type aClientType);
464 const AutoTArray<Client::Type, Client::TYPE_MAX>& AllClientTypes();
466 const nsString& GetBasePath() const { return mBasePath; }
468 const nsString& GetStorageName() const { return mStorageName; }
470 const nsString& GetStoragePath() const { return *mStoragePath; }
472 const nsString& GetStoragePath(PersistenceType aPersistenceType) const {
473 if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
474 return *mPermanentStoragePath;
477 if (aPersistenceType == PERSISTENCE_TYPE_TEMPORARY) {
478 return *mTemporaryStoragePath;
481 if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) {
482 return *mDefaultStoragePath;
485 MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_PRIVATE);
487 return *mPrivateStoragePath;
490 uint64_t GetGroupLimit() const;
492 std::pair<uint64_t, uint64_t> GetUsageAndLimitForEstimate(
493 const OriginMetadata& aOriginMetadata);
495 uint64_t GetOriginUsage(const PrincipalMetadata& aPrincipalMetadata);
497 Maybe<FullOriginMetadata> GetFullOriginMetadata(
498 const OriginMetadata& aOriginMetadata);
500 void NotifyStoragePressure(uint64_t aUsage);
502 // Record a quota client shutdown step, if shutting down.
503 // Assumes that the QuotaManager singleton is alive.
504 static void MaybeRecordQuotaClientShutdownStep(
505 const Client::Type aClientType, const nsACString& aStepDescription);
507 // Record a quota client shutdown step, if shutting down.
508 // Checks if the QuotaManager singleton is alive.
509 static void SafeMaybeRecordQuotaClientShutdownStep(
510 Client::Type aClientType, const nsACString& aStepDescription);
512 // Record a quota manager shutdown step, use only if shutdown is active.
513 void RecordQuotaManagerShutdownStep(const nsACString& aStepDescription);
515 // Record a quota manager shutdown step, if shutting down.
516 void MaybeRecordQuotaManagerShutdownStep(const nsACString& aStepDescription);
518 template <typename F>
519 void MaybeRecordQuotaManagerShutdownStepWith(F&& aFunc);
521 static void GetStorageId(PersistenceType aPersistenceType,
522 const nsACString& aOrigin, Client::Type aClientType,
523 nsACString& aDatabaseId);
525 static bool IsPrincipalInfoValid(const PrincipalInfo& aPrincipalInfo);
527 Result<PrincipalMetadata, nsresult> GetInfoFromValidatedPrincipalInfo(
528 const PrincipalInfo& aPrincipalInfo);
530 static nsAutoCString GetOriginFromValidatedPrincipalInfo(
531 const PrincipalInfo& aPrincipalInfo);
533 static Result<PrincipalMetadata, nsresult> GetInfoFromPrincipal(
534 nsIPrincipal* aPrincipal);
536 static Result<PrincipalMetadata, nsresult> GetInfoFromWindow(
537 nsPIDOMWindowOuter* aWindow);
539 static Result<nsAutoCString, nsresult> GetOriginFromPrincipal(
540 nsIPrincipal* aPrincipal);
542 static Result<nsAutoCString, nsresult> GetOriginFromWindow(
543 nsPIDOMWindowOuter* aWindow);
545 static nsLiteralCString GetOriginForChrome();
547 static PrincipalMetadata GetInfoForChrome();
549 static bool IsOriginInternal(const nsACString& aOrigin);
551 static bool AreOriginsEqualOnDisk(const nsACString& aOrigin1,
552 const nsACString& aOrigin2);
554 // XXX This method currently expects the original origin string (not yet
555 // sanitized).
556 static Result<PrincipalInfo, nsresult> ParseOrigin(const nsACString& aOrigin);
558 static void InvalidateQuotaCache();
560 private:
561 virtual ~QuotaManager();
563 nsresult Init();
565 void Shutdown();
567 void RegisterDirectoryLock(DirectoryLockImpl& aLock);
569 void UnregisterDirectoryLock(DirectoryLockImpl& aLock);
571 void AddPendingDirectoryLock(DirectoryLockImpl& aLock);
573 void RemovePendingDirectoryLock(DirectoryLockImpl& aLock);
575 uint64_t LockedCollectOriginsForEviction(
576 uint64_t aMinSizeToBeFreed,
577 nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
579 void LockedRemoveQuotaForRepository(PersistenceType aPersistenceType);
581 void LockedRemoveQuotaForOrigin(const OriginMetadata& aOriginMetadata);
583 already_AddRefed<GroupInfo> LockedGetOrCreateGroupInfo(
584 PersistenceType aPersistenceType, const nsACString& aSuffix,
585 const nsACString& aGroup);
587 already_AddRefed<OriginInfo> LockedGetOriginInfo(
588 PersistenceType aPersistenceType,
589 const OriginMetadata& aOriginMetadata) const;
591 nsresult UpgradeFromIndexedDBDirectoryToPersistentStorageDirectory(
592 nsIFile* aIndexedDBDir);
594 nsresult UpgradeFromPersistentStorageDirectoryToDefaultStorageDirectory(
595 nsIFile* aPersistentStorageDir);
597 nsresult MaybeUpgradeToDefaultStorageDirectory(nsIFile& aStorageFile);
599 template <typename Helper>
600 nsresult UpgradeStorage(const int32_t aOldVersion, const int32_t aNewVersion,
601 mozIStorageConnection* aConnection);
603 nsresult UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
605 nsresult UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection);
607 nsresult UpgradeStorageFrom2_0To2_1(mozIStorageConnection* aConnection);
609 nsresult UpgradeStorageFrom2_1To2_2(mozIStorageConnection* aConnection);
611 nsresult UpgradeStorageFrom2_2To2_3(mozIStorageConnection* aConnection);
613 nsresult MaybeCreateOrUpgradeStorage(mozIStorageConnection& aConnection);
615 OkOrErr MaybeRemoveLocalStorageArchiveTmpFile();
617 nsresult MaybeRemoveLocalStorageDataAndArchive(nsIFile& aLsArchiveFile);
619 nsresult MaybeRemoveLocalStorageDirectories();
621 Result<Ok, nsresult> CopyLocalStorageArchiveFromWebAppsStore(
622 nsIFile& aLsArchiveFile) const;
624 Result<nsCOMPtr<mozIStorageConnection>, nsresult>
625 CreateLocalStorageArchiveConnection(nsIFile& aLsArchiveFile) const;
627 Result<nsCOMPtr<mozIStorageConnection>, nsresult>
628 RecopyLocalStorageArchiveFromWebAppsStore(nsIFile& aLsArchiveFile);
630 Result<nsCOMPtr<mozIStorageConnection>, nsresult>
631 DowngradeLocalStorageArchive(nsIFile& aLsArchiveFile);
633 Result<nsCOMPtr<mozIStorageConnection>, nsresult>
634 UpgradeLocalStorageArchiveFromLessThan4To4(nsIFile& aLsArchiveFile);
637 nsresult UpgradeLocalStorageArchiveFrom4To5();
640 Result<Ok, nsresult> MaybeCreateOrUpgradeLocalStorageArchive(
641 nsIFile& aLsArchiveFile);
643 Result<Ok, nsresult> CreateEmptyLocalStorageArchive(
644 nsIFile& aLsArchiveFile) const;
646 template <typename OriginFunc>
647 nsresult InitializeRepository(PersistenceType aPersistenceType,
648 OriginFunc&& aOriginFunc);
650 nsresult InitializeOrigin(PersistenceType aPersistenceType,
651 const OriginMetadata& aOriginMetadata,
652 int64_t aAccessTime, bool aPersisted,
653 nsIFile* aDirectory);
655 using OriginInfosFlatTraversable =
656 nsTArray<NotNull<RefPtr<const OriginInfo>>>;
658 using OriginInfosNestedTraversable =
659 nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>;
661 OriginInfosNestedTraversable GetOriginInfosExceedingGroupLimit() const;
663 OriginInfosNestedTraversable GetOriginInfosExceedingGlobalLimit() const;
665 void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos);
667 void CleanupTemporaryStorage();
669 void DeleteOriginDirectory(const OriginMetadata& aOriginMetadata);
671 void FinalizeOriginEviction(nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks);
673 Result<Ok, nsresult> ArchiveOrigins(
674 const nsTArray<FullOriginMetadata>& aFullOriginMetadatas);
676 void ReleaseIOThreadObjects() {
677 AssertIsOnIOThread();
679 for (Client::Type type : AllClientTypes()) {
680 (*mClients)[type]->ReleaseIOThreadObjects();
684 DirectoryLockTable& GetDirectoryLockTable(PersistenceType aPersistenceType);
686 void ClearDirectoryLockTables();
688 bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
690 Result<nsCString, nsresult> EnsureStorageOriginFromOrigin(
691 const nsACString& aOrigin);
693 Result<nsCString, nsresult> GetOriginFromStorageOrigin(
694 const nsACString& aStorageOrigin);
696 int64_t GenerateDirectoryLockId();
698 bool ShutdownStarted() const;
700 void RecordShutdownStep(Maybe<Client::Type> aClientType,
701 const nsACString& aStepDescription);
703 template <typename Func>
704 auto ExecuteInitialization(Initialization aInitialization, Func&& aFunc)
705 -> std::invoke_result_t<Func, const FirstInitializationAttempt<
706 Initialization, StringGenerator>&>;
708 template <typename Func>
709 auto ExecuteInitialization(Initialization aInitialization,
710 const nsACString& aContext, Func&& aFunc)
711 -> std::invoke_result_t<Func, const FirstInitializationAttempt<
712 Initialization, StringGenerator>&>;
714 template <typename Func>
715 auto ExecuteOriginInitialization(const nsACString& aOrigin,
716 const OriginInitialization aInitialization,
717 const nsACString& aContext, Func&& aFunc)
718 -> std::invoke_result_t<Func, const FirstInitializationAttempt<
719 Initialization, StringGenerator>&>;
721 template <typename Iterator>
722 static void MaybeInsertNonPersistedOriginInfos(
723 Iterator aDest, const RefPtr<GroupInfo>& aTemporaryGroupInfo,
724 const RefPtr<GroupInfo>& aDefaultGroupInfo,
725 const RefPtr<GroupInfo>& aPrivateGroupInfo);
727 template <typename Collect, typename Pred>
728 static OriginInfosFlatTraversable CollectLRUOriginInfosUntil(
729 Collect&& aCollect, Pred&& aPred);
731 // Thread on which IO is performed.
732 LazyInitializedOnceNotNull<const nsCOMPtr<nsIThread>> mIOThread;
734 nsCOMPtr<mozIStorageConnection> mStorageConnection;
736 EnumeratedArray<Client::Type, nsCString, size_t(Client::TYPE_MAX)>
737 mShutdownSteps;
738 LazyInitializedOnce<const TimeStamp> mShutdownStartedAt;
740 // Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex.
741 nsCString mQuotaManagerShutdownSteps;
743 mutable mozilla::Mutex mQuotaMutex MOZ_UNANNOTATED;
745 nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
747 // Maintains a list of directory locks that are queued.
748 nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks;
750 // Maintains a list of directory locks that are acquired or queued. It can be
751 // accessed on the owning (PBackground) thread only.
752 nsTArray<NotNull<DirectoryLockImpl*>> mDirectoryLocks;
754 // Only modifed on the owning thread, but read on multiple threads. Therefore
755 // all modifications (including those on the owning thread) and all reads off
756 // the owning thread must be protected by mQuotaMutex. In other words, only
757 // reads on the owning thread don't have to be protected by mQuotaMutex.
758 nsTHashMap<nsUint64HashKey, NotNull<DirectoryLockImpl*>>
759 mDirectoryLockIdTable;
761 // Directory lock tables that are used to update origin access time.
762 DirectoryLockTable mTemporaryDirectoryLockTable;
763 DirectoryLockTable mDefaultDirectoryLockTable;
764 DirectoryLockTable mPrivateDirectoryLockTable;
766 // A list of all successfully initialized persistent origins. This list isn't
767 // protected by any mutex but it is only ever touched on the IO thread.
768 nsTArray<nsCString> mInitializedOrigins;
770 // A hash table that is used to cache origin parser results for given
771 // sanitized origin strings. This hash table isn't protected by any mutex but
772 // it is only ever touched on the IO thread.
773 nsTHashMap<nsCStringHashKey, bool> mValidOrigins;
775 // These maps are protected by mQuotaMutex.
776 nsTHashMap<nsCStringHashKey, nsCString> mOriginToStorageOriginMap;
777 nsTHashMap<nsCStringHashKey, nsCString> mStorageOriginToOriginMap;
779 // This array is populated at initialization time and then never modified, so
780 // it can be iterated on any thread.
781 LazyInitializedOnce<const AutoTArray<RefPtr<Client>, Client::TYPE_MAX>>
782 mClients;
784 using ClientTypesArray = AutoTArray<Client::Type, Client::TYPE_MAX>;
785 LazyInitializedOnce<const ClientTypesArray> mAllClientTypes;
786 LazyInitializedOnce<const ClientTypesArray> mAllClientTypesExceptLS;
788 // This object isn't protected by any mutex but it is only ever touched on
789 // the IO thread.
790 InitializationInfo mInitializationInfo;
792 const nsString mBasePath;
793 const nsString mStorageName;
794 LazyInitializedOnce<const nsString> mIndexedDBPath;
795 LazyInitializedOnce<const nsString> mStoragePath;
796 LazyInitializedOnce<const nsString> mStorageArchivesPath;
797 LazyInitializedOnce<const nsString> mPermanentStoragePath;
798 LazyInitializedOnce<const nsString> mTemporaryStoragePath;
799 LazyInitializedOnce<const nsString> mDefaultStoragePath;
800 LazyInitializedOnce<const nsString> mPrivateStoragePath;
801 LazyInitializedOnce<const nsString> mToBeRemovedStoragePath;
803 uint64_t mTemporaryStorageLimit;
804 uint64_t mTemporaryStorageUsage;
805 int64_t mNextDirectoryLockId;
806 uint64_t mShutdownStorageOpCount;
807 bool mStorageInitialized;
808 bool mTemporaryStorageInitialized;
809 bool mTemporaryStorageInitializedInternal;
810 bool mCacheUsable;
813 } // namespace mozilla::dom::quota
815 #endif /* mozilla_dom_quota_quotamanager_h__ */