tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

QuotaManager.h (44784B)


      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/. */
      6 
      7 #ifndef mozilla_dom_quota_quotamanager_h__
      8 #define mozilla_dom_quota_quotamanager_h__
      9 
     10 #include <cstdint>
     11 #include <utility>
     12 
     13 #include "Client.h"
     14 #include "ErrorList.h"
     15 #include "mozilla/AlreadyAddRefed.h"
     16 #include "mozilla/Assertions.h"
     17 #include "mozilla/InitializedOnce.h"
     18 #include "mozilla/MozPromise.h"
     19 #include "mozilla/Mutex.h"
     20 #include "mozilla/RefPtr.h"
     21 #include "mozilla/Result.h"
     22 #include "mozilla/ThreadBound.h"
     23 #include "mozilla/dom/Nullable.h"
     24 #include "mozilla/dom/ipc/IdType.h"
     25 #include "mozilla/dom/quota/Assertions.h"
     26 #include "mozilla/dom/quota/BackgroundThreadObject.h"
     27 #include "mozilla/dom/quota/CommonMetadata.h"
     28 #include "mozilla/dom/quota/DirectoryLockCategory.h"
     29 #include "mozilla/dom/quota/ForwardDecls.h"
     30 #include "mozilla/dom/quota/HashKeys.h"
     31 #include "mozilla/dom/quota/InitializationTypes.h"
     32 #include "mozilla/dom/quota/NotifyUtils.h"
     33 #include "mozilla/dom/quota/OpenClientDirectoryInfo.h"
     34 #include "mozilla/dom/quota/OriginOperationCallbacks.h"
     35 #include "mozilla/dom/quota/PersistenceType.h"
     36 #include "nsCOMPtr.h"
     37 #include "nsClassHashtable.h"
     38 #include "nsDebug.h"
     39 #include "nsHashKeys.h"
     40 #include "nsISupports.h"
     41 #include "nsStringFwd.h"
     42 #include "nsTArray.h"
     43 #include "nsTHashMap.h"
     44 #include "nsTStringRepr.h"
     45 #include "nscore.h"
     46 #include "prenv.h"
     47 
     48 #define GTEST_CLASS(testFixture, testName) testFixture##_##testName##_Test
     49 
     50 class mozIStorageConnection;
     51 class nsIEventTarget;
     52 class nsIFile;
     53 class nsIRunnable;
     54 class nsIThread;
     55 class nsITimer;
     56 
     57 namespace mozilla {
     58 
     59 class OriginAttributes;
     60 class OriginAttributesPattern;
     61 
     62 namespace ipc {
     63 
     64 class PrincipalInfo;
     65 
     66 }  // namespace ipc
     67 
     68 }  // namespace mozilla
     69 
     70 namespace mozilla::dom::quota {
     71 
     72 class CanonicalQuotaObject;
     73 class ClearDataOp;
     74 class ClearRequestBase;
     75 class ClientStorageScope;
     76 class ClientUsageArray;
     77 class ClientDirectoryLock;
     78 class ClientDirectoryLockHandle;
     79 class DirectoryLockImpl;
     80 class GroupInfo;
     81 class GroupInfoPair;
     82 class NormalOriginOperationBase;
     83 class OriginDirectoryLock;
     84 class OriginInfo;
     85 class OriginScope;
     86 class QuotaObject;
     87 class SaveOriginAccessTimeOp;
     88 class UniversalDirectoryLock;
     89 
     90 namespace test {
     91 class GTEST_CLASS(TestQuotaManagerAndShutdownFixture,
     92                  ThumbnailPrivateIdentityTemporaryOriginCount);
     93 }
     94 
     95 class QuotaManager final : public BackgroundThreadObject {
     96  friend class CanonicalQuotaObject;
     97  friend class ClearDataOp;
     98  friend class ClearRequestBase;
     99  friend class ClearStorageOp;
    100  friend class ClientDirectoryLockHandle;
    101  friend class DirectoryLockImpl;
    102  friend class FinalizeOriginEvictionOp;
    103  friend class GroupInfo;
    104  friend class InitOp;
    105  friend class InitializePersistentOriginOp;
    106  friend class InitializePersistentStorageOp;
    107  friend class InitializeTemporaryGroupOp;
    108  friend class InitializeTemporaryOriginOp;
    109  friend class InitTemporaryStorageOp;
    110  friend class ListCachedOriginsOp;
    111  friend class OriginInfo;
    112  friend class PersistOp;
    113  friend class SaveOriginAccessTimeOp;
    114  friend class ShutdownStorageOp;
    115  friend class test::GTEST_CLASS(TestQuotaManagerAndShutdownFixture,
    116                                 ThumbnailPrivateIdentityTemporaryOriginCount);
    117  friend class UniversalDirectoryLock;
    118 
    119  friend Result<PrincipalMetadata, nsresult> GetInfoFromValidatedPrincipalInfo(
    120      QuotaManager& aQuotaManager,
    121      const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
    122 
    123  using PrincipalInfo = mozilla::ipc::PrincipalInfo;
    124 
    125  class Observer;
    126 
    127 public:
    128  using ClientDirectoryLockHandlePromise =
    129      MozPromise<ClientDirectoryLockHandle, nsresult, true>;
    130 
    131  QuotaManager(const nsAString& aBasePath, const nsAString& aStorageName);
    132 
    133  NS_INLINE_DECL_REFCOUNTING(QuotaManager)
    134 
    135  static nsresult Initialize();
    136 
    137  static bool IsRunningXPCShellTests() {
    138    static bool kRunningXPCShellTests =
    139        !!PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR");
    140    return kRunningXPCShellTests;
    141  }
    142 
    143  static bool IsRunningGTests() {
    144    static bool kRunningGTests = !!PR_GetEnv("MOZ_RUN_GTEST");
    145    return kRunningGTests;
    146  }
    147 
    148  static const char kReplaceChars[];
    149  static const char16_t kReplaceChars16[];
    150 
    151  static Result<MovingNotNull<RefPtr<QuotaManager>>, nsresult> GetOrCreate();
    152 
    153  static Result<Ok, nsresult> EnsureCreated();
    154 
    155  // Returns a non-owning reference.
    156  static QuotaManager* Get();
    157 
    158  // Use only in gtests!
    159  static nsIObserver* GetObserver();
    160 
    161  /**
    162   * Ensures that all pending normal origin operations and their follow-up
    163   * events are processed and completed.
    164   *
    165   * This is useful in cases where operations are scheduled asynchronously
    166   * without a way to explicitly await their completion, and must be finalized
    167   * before continuing with further checks or logic.
    168   *
    169   * This method asserts that gtests are currently running and must not be used
    170   * outside of gtest code.
    171   */
    172  static void ProcessPendingNormalOriginOperations();
    173 
    174  // Returns true if we've begun the shutdown process.
    175  static bool IsShuttingDown();
    176 
    177  static void ShutdownInstance();
    178 
    179  // Use only in gtests!
    180  static void Reset();
    181 
    182  static bool IsOSMetadata(const nsAString& aFileName);
    183 
    184  static bool IsDotFile(const nsAString& aFileName);
    185 
    186  void RegisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp);
    187 
    188  void UnregisterNormalOriginOp(NormalOriginOperationBase& aNormalOriginOp);
    189 
    190  bool IsPersistentOriginInitializedInternal(const nsACString& aOrigin) const {
    191    AssertIsOnIOThread();
    192 
    193    return mInitializedOriginsInternal.Contains(aOrigin);
    194  }
    195 
    196  bool IsTemporaryStorageInitializedInternal() const {
    197    AssertIsOnIOThread();
    198 
    199    return mTemporaryStorageInitializedInternal;
    200  }
    201 
    202  /**
    203   * For initialization of an origin where the directory either exists or it
    204   * does not. The directory exists case is used by InitializeOrigin once it
    205   * has tallied origin usage by calling each of the QuotaClient InitOrigin
    206   * methods. It's also used by LoadQuota when quota information is available
    207   * from the cache. EnsureTemporaryStorageIsInitializedInternal calls this
    208   * either if the directory exists or it does not depending on requirements
    209   * of a particular quota client. The special case when origin directory is
    210   * not created during origin initialization is currently utilized only by
    211   * LSNG.
    212   */
    213  void InitQuotaForOrigin(const FullOriginMetadata& aFullOriginMetadata,
    214                          bool aDirectoryExists = true);
    215 
    216  // XXX clients can use QuotaObject instead of calling this method directly.
    217  void DecreaseUsageForClient(const ClientMetadata& aClientMetadata,
    218                              int64_t aSize);
    219 
    220  void ResetUsageForClient(const ClientMetadata& aClientMetadata);
    221 
    222  UsageInfo GetUsageForClient(PersistenceType aPersistenceType,
    223                              const OriginMetadata& aOriginMetadata,
    224                              Client::Type aClientType);
    225 
    226  void UpdateOriginAccessTime(const OriginMetadata& aOriginMetadata,
    227                              int64_t aTimestamp);
    228 
    229  void UpdateOriginMaintenanceDate(const OriginMetadata& aOriginMetadata,
    230                                   int32_t aMaintenanceDate);
    231 
    232  void UpdateOriginAccessed(const OriginMetadata& aOriginMetadata);
    233 
    234  void RemoveQuota();
    235 
    236  void RemoveQuotaForRepository(PersistenceType aPersistenceType) {
    237    MutexAutoLock lock(mQuotaMutex);
    238    LockedRemoveQuotaForRepository(aPersistenceType);
    239  }
    240 
    241  void RemoveQuotaForOrigin(PersistenceType aPersistenceType,
    242                            const OriginMetadata& aOriginMetadata) {
    243    MutexAutoLock lock(mQuotaMutex);
    244    LockedRemoveQuotaForOrigin(aOriginMetadata);
    245  }
    246 
    247  nsresult LoadQuota();
    248 
    249  void UnloadQuota();
    250 
    251  void RemoveOriginFromCache(const OriginMetadata& aOriginMetadata);
    252 
    253  already_AddRefed<QuotaObject> GetQuotaObject(
    254      PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
    255      Client::Type aClientType, nsIFile* aFile, int64_t aFileSize = -1,
    256      int64_t* aFileSizeOut = nullptr);
    257 
    258  already_AddRefed<QuotaObject> GetQuotaObject(
    259      PersistenceType aPersistenceType, const OriginMetadata& aOriginMetadata,
    260      Client::Type aClientType, const nsAString& aPath, int64_t aFileSize = -1,
    261      int64_t* aFileSizeOut = nullptr);
    262 
    263  already_AddRefed<QuotaObject> GetQuotaObject(const int64_t aDirectoryLockId,
    264                                               const nsAString& aPath);
    265 
    266  Nullable<bool> OriginPersisted(const OriginMetadata& aOriginMetadata);
    267 
    268  void PersistOrigin(const OriginMetadata& aOriginMetadata);
    269 
    270  template <typename F>
    271  auto WithOriginInfo(const OriginMetadata& aOriginMetadata, F aFunction)
    272      -> std::invoke_result_t<F, const RefPtr<OriginInfo>&>;
    273 
    274  using DirectoryLockIdTableArray =
    275      AutoTArray<Client::DirectoryLockIdTable, Client::TYPE_MAX>;
    276  void AbortOperationsForLocks(const DirectoryLockIdTableArray& aLockIds);
    277 
    278  // Called when a process is being shot down. Aborts any running operations
    279  // for the given process.
    280  void AbortOperationsForProcess(ContentParentId aContentParentId);
    281 
    282  Result<nsCOMPtr<nsIFile>, nsresult> GetOriginDirectory(
    283      const OriginMetadata& aOriginMetadata) const;
    284 
    285  Result<bool, nsresult> DoesOriginDirectoryExist(
    286      const OriginMetadata& aOriginMetadata) const;
    287 
    288  Result<nsCOMPtr<nsIFile>, nsresult> GetOrCreateTemporaryOriginDirectory(
    289      const OriginMetadata& aOriginMetadata);
    290 
    291  Result<Ok, nsresult> EnsureTemporaryOriginDirectoryCreated(
    292      const OriginMetadata& aOriginMetadata);
    293 
    294  static nsresult CreateDirectoryMetadata2(
    295      nsIFile& aDirectory, const FullOriginMetadata& aFullOriginMetadata);
    296 
    297  nsresult RestoreDirectoryMetadata2(nsIFile* aDirectory);
    298 
    299  // XXX Remove aPersistenceType argument once the persistence type is stored
    300  // in the metadata file.
    301  Result<FullOriginMetadata, nsresult> LoadFullOriginMetadata(
    302      nsIFile* aDirectory, PersistenceType aPersistenceType);
    303 
    304  Result<FullOriginMetadata, nsresult> LoadFullOriginMetadataWithRestore(
    305      nsIFile* aDirectory);
    306 
    307  Result<std::pair<FullOriginMetadata, bool /* restore status */>, nsresult>
    308  LoadFullOriginMetadataWithRestoreAndStatus(nsIFile* aDirectory);
    309 
    310  Result<OriginMetadata, nsresult> GetOriginMetadata(nsIFile* aDirectory);
    311 
    312  Result<Ok, nsresult> RemoveOriginDirectory(nsIFile& aDirectory);
    313 
    314  Result<bool, nsresult> DoesClientDirectoryExist(
    315      const ClientMetadata& aClientMetadata) const;
    316 
    317  RefPtr<UniversalDirectoryLockPromise> OpenStorageDirectory(
    318      const PersistenceScope& aPersistenceScope,
    319      const OriginScope& aOriginScope,
    320      const ClientStorageScope& aClientStorageScope, bool aExclusive,
    321      bool aInitializeOrigins = false,
    322      DirectoryLockCategory aCategory = DirectoryLockCategory::None,
    323      Maybe<RefPtr<UniversalDirectoryLock>&> aPendingDirectoryLockOut =
    324          Nothing());
    325 
    326  // This is the main entry point into the QuotaManager API.
    327  // Any storage API implementation (quota client) that participates in
    328  // centralized quota and storage handling should call this method to obtain
    329  // a directory lock, ensuring the client’s files are protected from deletion
    330  // while in use.
    331  //
    332  // After a lock is acquired, the client is notified by resolving the returned
    333  // promise. If the lock couldn't be acquired, the promise is rejected.
    334  //
    335  // The returned lock is encapsulated in ClientDirectoryLockHandle, which
    336  // manages ownership and automatically drops the lock when destroyed. Clients
    337  // should retain ownership of the handle for as long as the lock is needed.
    338  //
    339  // The lock may still be invalidated by a clear operation, so consumers
    340  // should check its validity and release it as soon as it is no longer
    341  // required.
    342  //
    343  // Internally, QuotaManager may perform various initialization steps before
    344  // resolving the promise. This can include storage, temporary storage, group
    345  // and origin initialization.
    346  //
    347  // Optionally, an output parameter (aPendingDirectoryLockOut) can be provided
    348  // to receive a reference to the ClientDirectoryLock before wrapping it in
    349  // ClientDirectoryLockHandle. This allows tracking pending locks separately.
    350  RefPtr<ClientDirectoryLockHandlePromise> OpenClientDirectory(
    351      const ClientMetadata& aClientMetadata, bool aInitializeOrigins = true,
    352      bool aCreateIfNonExistent = true,
    353      Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut = Nothing());
    354 
    355  RefPtr<ClientDirectoryLockHandlePromise> OpenClientDirectoryImpl(
    356      const ClientMetadata& aClientMetadata, bool aInitializeOrigins,
    357      bool aCreateIfNonExistent,
    358      Maybe<RefPtr<ClientDirectoryLock>&> aPendingDirectoryLockOut);
    359 
    360  RefPtr<ClientDirectoryLock> CreateDirectoryLock(
    361      const ClientMetadata& aClientMetadata, bool aExclusive);
    362 
    363  // XXX RemoveMe once bug 1170279 gets fixed.
    364  RefPtr<UniversalDirectoryLock> CreateDirectoryLockInternal(
    365      const PersistenceScope& aPersistenceScope,
    366      const OriginScope& aOriginScope,
    367      const ClientStorageScope& aClientStorageScope, bool aExclusive,
    368      DirectoryLockCategory aCategory = DirectoryLockCategory::None);
    369 
    370  // Collect inactive and the least recently used origins.
    371  uint64_t CollectOriginsForEviction(
    372      uint64_t aMinSizeToBeFreed,
    373      nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
    374 
    375  /**
    376   * Helper method to invoke the provided predicate on all "pending" OriginInfo
    377   * instances. These are origins for which the origin directory has not yet
    378   * been created but for which quota is already being tracked. This happens,
    379   * for example, for the LocalStorage client where an origin that previously
    380   * was not using LocalStorage can start issuing writes which it buffers until
    381   * eventually flushing them. We defer creating the origin directory for as
    382   * long as possible in that case, so the directory won't exist. Logic that
    383   * would otherwise only consult the filesystem also needs to use this method.
    384   */
    385  template <typename P>
    386  void CollectPendingOriginsForListing(P aPredicate);
    387 
    388  bool IsPendingOrigin(const OriginMetadata& aOriginMetadata) const;
    389 
    390  RefPtr<BoolPromise> InitializeStorage();
    391 
    392  RefPtr<BoolPromise> InitializeStorage(
    393      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    394 
    395  RefPtr<BoolPromise> StorageInitialized();
    396 
    397  bool IsStorageInitialized() const {
    398    AssertIsOnOwningThread();
    399 
    400    return mStorageInitialized;
    401  }
    402 
    403  bool IsStorageInitializedInternal() const {
    404    AssertIsOnIOThread();
    405    return static_cast<bool>(mStorageConnection);
    406  }
    407 
    408  void AssertStorageIsInitializedInternal() const
    409 #ifdef DEBUG
    410      ;
    411 #else
    412  {
    413  }
    414 #endif
    415 
    416  RefPtr<BoolPromise> TemporaryStorageInitialized();
    417 
    418 private:
    419  nsresult EnsureStorageIsInitializedInternal();
    420 
    421 public:
    422  RefPtr<BoolPromise> InitializePersistentStorage();
    423 
    424  RefPtr<BoolPromise> InitializePersistentStorage(
    425      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    426 
    427  RefPtr<BoolPromise> PersistentStorageInitialized();
    428 
    429  bool IsPersistentStorageInitialized() const {
    430    AssertIsOnOwningThread();
    431 
    432    return mPersistentStorageInitialized;
    433  }
    434 
    435  bool IsPersistentStorageInitializedInternal() const {
    436    AssertIsOnIOThread();
    437 
    438    return mPersistentStorageInitializedInternal;
    439  }
    440 
    441 private:
    442  nsresult EnsurePersistentStorageIsInitializedInternal();
    443 
    444 public:
    445  RefPtr<BoolPromise> InitializeTemporaryGroup(
    446      const PrincipalMetadata& aPrincipalMetadata);
    447 
    448  RefPtr<BoolPromise> InitializeTemporaryGroup(
    449      const PrincipalMetadata& aPrincipalMetadata,
    450      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    451 
    452  RefPtr<BoolPromise> TemporaryGroupInitialized(
    453      const PrincipalMetadata& aPrincipalMetadata);
    454 
    455  bool IsTemporaryGroupInitialized(const PrincipalMetadata& aPrincipalMetadata);
    456 
    457  bool IsTemporaryGroupInitializedInternal(
    458      const PrincipalMetadata& aPrincipalMetadata) const;
    459 
    460 private:
    461  Result<Ok, nsresult> EnsureTemporaryGroupIsInitializedInternal(
    462      const PrincipalMetadata& aPrincipalMetadata);
    463 
    464 public:
    465  RefPtr<BoolPromise> InitializePersistentOrigin(
    466      const OriginMetadata& aOriginMetadata);
    467 
    468  RefPtr<BoolPromise> InitializePersistentOrigin(
    469      const OriginMetadata& aOriginMetadata,
    470      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    471 
    472  RefPtr<BoolPromise> PersistentOriginInitialized(
    473      const OriginMetadata& aOriginMetadata);
    474 
    475  bool IsPersistentOriginInitialized(const OriginMetadata& aOriginMetadata);
    476 
    477  bool IsPersistentOriginInitializedInternal(
    478      const OriginMetadata& aOriginMetadata) const;
    479 
    480 private:
    481  // Returns a pair of an nsIFile object referring to the directory, and a bool
    482  // indicating whether the directory was newly created.
    483  Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
    484  EnsurePersistentOriginIsInitializedInternal(
    485      const OriginMetadata& aOriginMetadata);
    486 
    487 public:
    488  RefPtr<BoolPromise> InitializeTemporaryOrigin(
    489      const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent);
    490 
    491  RefPtr<BoolPromise> InitializeTemporaryOrigin(
    492      const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent,
    493      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    494 
    495  RefPtr<BoolPromise> TemporaryOriginInitialized(
    496      const OriginMetadata& aOriginMetadata);
    497 
    498  bool IsTemporaryOriginInitialized(const OriginMetadata& aOriginMetadata);
    499 
    500  bool IsTemporaryOriginInitializedInternal(
    501      const OriginMetadata& aOriginMetadata) const;
    502 
    503 private:
    504  // Returns a pair of an nsIFile object referring to the directory, and a bool
    505  // indicating whether the directory was newly created.
    506  Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
    507  EnsureTemporaryOriginIsInitializedInternal(
    508      const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent);
    509 
    510 public:
    511  RefPtr<BoolPromise> InitializePersistentClient(
    512      const ClientMetadata& aClientMetadata);
    513 
    514  RefPtr<BoolPromise> InitializePersistentClient(
    515      const ClientMetadata& aClientMetadata,
    516      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    517 
    518  bool IsPersistentClientInitialized(const ClientMetadata& aClientMetadata);
    519 
    520  // Returns a pair of an nsIFile object referring to the directory, and a bool
    521  // indicating whether the directory was newly created.
    522  Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
    523  EnsurePersistentClientIsInitialized(const ClientMetadata& aClientMetadata);
    524 
    525  RefPtr<BoolPromise> InitializeTemporaryClient(
    526      const ClientMetadata& aClientMetadata, bool aCreateIfNonExistent);
    527 
    528  RefPtr<BoolPromise> InitializeTemporaryClient(
    529      const ClientMetadata& aClientMetadata, bool aCreateIfNonExistent,
    530      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    531 
    532  bool IsTemporaryClientInitialized(const ClientMetadata& aClientMetadata);
    533 
    534  // Returns a pair of an nsIFile object referring to the directory, and a bool
    535  // indicating whether the directory was newly created.
    536  Result<std::pair<nsCOMPtr<nsIFile>, bool>, nsresult>
    537  EnsureTemporaryClientIsInitialized(const ClientMetadata& aClientMetadata,
    538                                     bool aCreateIfNonExistent);
    539 
    540  RefPtr<BoolPromise> InitializeTemporaryStorage();
    541 
    542  RefPtr<BoolPromise> InitializeTemporaryStorage(
    543      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    544 
    545  bool IsTemporaryStorageInitialized() const {
    546    AssertIsOnOwningThread();
    547 
    548    return mTemporaryStorageInitialized;
    549  }
    550 
    551 private:
    552  nsresult InitializeTemporaryStorageInternal();
    553 
    554  nsresult EnsureTemporaryStorageIsInitializedInternal();
    555 
    556 public:
    557  RefPtr<BoolPromise> InitializeAllTemporaryOrigins();
    558 
    559  RefPtr<BoolPromise> SaveOriginAccessTime(
    560      const OriginMetadata& aOriginMetadata);
    561 
    562  RefPtr<BoolPromise> SaveOriginAccessTime(
    563      const OriginMetadata& aOriginMetadata,
    564      RefPtr<UniversalDirectoryLock> aDirectoryLock);
    565 
    566  RefPtr<OriginUsageMetadataArrayPromise> GetUsage(
    567      bool aGetAll, RefPtr<BoolPromise> aOnCancelPromise = nullptr);
    568 
    569  RefPtr<UsageInfoPromise> GetOriginUsage(
    570      const PrincipalInfo& aPrincipalInfo,
    571      RefPtr<BoolPromise> aOnCancelPromise = nullptr);
    572 
    573  RefPtr<UInt64Promise> GetCachedOriginUsage(
    574      const PrincipalInfo& aPrincipalInfo);
    575 
    576  RefPtr<CStringArrayPromise> ListOrigins();
    577 
    578  RefPtr<CStringArrayPromise> ListCachedOrigins();
    579 
    580  RefPtr<BoolPromise> ClearStoragesForOrigin(
    581      const Maybe<PersistenceType>& aPersistenceType,
    582      const PrincipalInfo& aPrincipalInfo);
    583 
    584  RefPtr<BoolPromise> ClearStoragesForClient(
    585      Maybe<PersistenceType> aPersistenceType,
    586      const PrincipalInfo& aPrincipalInfo, Client::Type aClientType);
    587 
    588  RefPtr<BoolPromise> ClearStoragesForOriginPrefix(
    589      const Maybe<PersistenceType>& aPersistenceType,
    590      const PrincipalInfo& aPrincipalInfo);
    591 
    592  RefPtr<BoolPromise> ClearStoragesForOriginAttributesPattern(
    593      const OriginAttributesPattern& aPattern);
    594 
    595  RefPtr<BoolPromise> ClearPrivateRepository();
    596 
    597  RefPtr<BoolPromise> ClearStorage();
    598 
    599  RefPtr<BoolPromise> ShutdownStoragesForOrigin(
    600      Maybe<PersistenceType> aPersistenceType,
    601      const PrincipalInfo& aPrincipalInfo);
    602 
    603  RefPtr<BoolPromise> ShutdownStoragesForClient(
    604      Maybe<PersistenceType> aPersistenceType,
    605      const PrincipalInfo& aPrincipalInfo, Client::Type aClientType);
    606 
    607  RefPtr<BoolPromise> ShutdownStorage(
    608      Maybe<OriginOperationCallbackOptions> aCallbackOptions = Nothing(),
    609      Maybe<OriginOperationCallbacks&> aCallbacks = Nothing());
    610 
    611  void ShutdownStorageInternal();
    612 
    613  // Returns a bool indicating whether the directory was newly created.
    614  Result<bool, nsresult> EnsureOriginDirectory(nsIFile& aDirectory);
    615 
    616  nsresult AboutToClearOrigins(const PersistenceScope& aPersistenceScope,
    617                               const OriginScope& aOriginScope,
    618                               const ClientStorageScope& aClientStorageScope);
    619 
    620  void OriginClearCompleted(const OriginMetadata& aOriginMetadata,
    621                            const ClientStorageScope& aClientStorageScope);
    622 
    623  void RepositoryClearCompleted(PersistenceType aPersistenceType);
    624 
    625  void StartIdleMaintenance() {
    626    AssertIsOnOwningThread();
    627 
    628    for (const auto& client : *mClients) {
    629      client->StartIdleMaintenance();
    630    }
    631 
    632    NotifyMaintenanceStarted(*this);
    633  }
    634 
    635  void StopIdleMaintenance() {
    636    AssertIsOnOwningThread();
    637 
    638    for (const auto& client : *mClients) {
    639      client->StopIdleMaintenance();
    640    }
    641  }
    642 
    643  void AssertCurrentThreadOwnsQuotaMutex() {
    644    mQuotaMutex.AssertCurrentThreadOwns();
    645  }
    646 
    647  void AssertNotCurrentThreadOwnsQuotaMutex() {
    648    mQuotaMutex.AssertNotCurrentThreadOwns();
    649  }
    650 
    651  nsIThread* IOThread() { return mIOThread->get(); }
    652 
    653  Client* GetClient(Client::Type aClientType);
    654 
    655  const AutoTArray<Client::Type, Client::TYPE_MAX>& AllClientTypes();
    656 
    657  const nsString& GetBasePath() const { return mBasePath; }
    658 
    659  const nsString& GetStorageName() const { return mStorageName; }
    660 
    661  const nsString& GetStoragePath() const { return *mStoragePath; }
    662 
    663  const nsString& GetStoragePath(PersistenceType aPersistenceType) const {
    664    if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
    665      return *mPermanentStoragePath;
    666    }
    667 
    668    if (aPersistenceType == PERSISTENCE_TYPE_TEMPORARY) {
    669      return *mTemporaryStoragePath;
    670    }
    671 
    672    if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) {
    673      return *mDefaultStoragePath;
    674    }
    675 
    676    MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_PRIVATE);
    677 
    678    return *mPrivateStoragePath;
    679  }
    680 
    681  bool IsThumbnailPrivateIdentityIdKnown() const;
    682 
    683  uint32_t GetThumbnailPrivateIdentityId() const;
    684 
    685  void SetThumbnailPrivateIdentityId(uint32_t aThumbnailPrivateIdentityId);
    686 
    687  uint64_t GetGroupLimit() const;
    688  static uint64_t GetGroupLimitForLimit(uint64_t aLimit);
    689 
    690  Maybe<OriginStateMetadata> GetOriginStateMetadata(
    691      const OriginMetadata& aOriginMetadata);
    692 
    693  std::pair<uint64_t, uint64_t> GetUsageAndLimitForEstimate(
    694      const OriginMetadata& aOriginMetadata);
    695 
    696  uint64_t GetOriginUsage(const PrincipalMetadata& aPrincipalMetadata);
    697 
    698  Maybe<FullOriginMetadata> GetFullOriginMetadata(
    699      const OriginMetadata& aOriginMetadata);
    700 
    701  /**
    702   * Retrieves the total number of directory iterations performed.
    703   *
    704   * @return The total count of directory iterations, which is currently
    705   *         incremented only during clearing operations.
    706   */
    707  uint64_t TotalDirectoryIterations() const;
    708 
    709  /**
    710   * Retrieves the number of metadata updates performed by SaveOriginAccessTime
    711   * operation, as tracked on the background thread. This count is incremented
    712   * after the operation has fully completed.
    713   */
    714  uint64_t SaveOriginAccessTimeCount() const;
    715 
    716  /**
    717   * Retrieves the number of metadata updates performed by SaveOriginAccessTime
    718   * operation, as tracked internally on the I/O thread. This count is
    719   * incremented when the actual metadata file update occurs.
    720   */
    721  uint64_t SaveOriginAccessTimeCountInternal() const;
    722 
    723  // Record a quota client shutdown step, if shutting down.
    724  // Assumes that the QuotaManager singleton is alive.
    725  static void MaybeRecordQuotaClientShutdownStep(
    726      const Client::Type aClientType, const nsACString& aStepDescription);
    727 
    728  // Record a quota client shutdown step, if shutting down.
    729  // Checks if the QuotaManager singleton is alive.
    730  static void SafeMaybeRecordQuotaClientShutdownStep(
    731      Client::Type aClientType, const nsACString& aStepDescription);
    732 
    733  // Record a quota manager shutdown step, use only if shutdown is active.
    734  void RecordQuotaManagerShutdownStep(const nsACString& aStepDescription);
    735 
    736  // Record a quota manager shutdown step, if shutting down.
    737  void MaybeRecordQuotaManagerShutdownStep(const nsACString& aStepDescription);
    738 
    739  template <typename F>
    740  void MaybeRecordQuotaManagerShutdownStepWith(F&& aFunc);
    741 
    742  static void GetStorageId(PersistenceType aPersistenceType,
    743                           const nsACString& aOrigin, Client::Type aClientType,
    744                           nsACString& aDatabaseId);
    745 
    746  static bool IsOriginInternal(const nsACString& aOrigin);
    747 
    748  static bool AreOriginsEqualOnDisk(const nsACString& aOrigin1,
    749                                    const nsACString& aOrigin2);
    750 
    751  // XXX This method currently expects the original origin string (not yet
    752  // sanitized).
    753  static Result<PrincipalInfo, nsresult> ParseOrigin(const nsACString& aOrigin);
    754 
    755  static void InvalidateQuotaCache();
    756 
    757 private:
    758  virtual ~QuotaManager();
    759 
    760  nsresult Init();
    761 
    762  void Shutdown();
    763 
    764  void RegisterDirectoryLock(DirectoryLockImpl& aLock);
    765 
    766  void UnregisterDirectoryLock(DirectoryLockImpl& aLock);
    767 
    768  void AddPendingDirectoryLock(DirectoryLockImpl& aLock);
    769 
    770  void RemovePendingDirectoryLock(DirectoryLockImpl& aLock);
    771 
    772  uint64_t LockedCollectOriginsForEviction(
    773      uint64_t aMinSizeToBeFreed,
    774      nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
    775 
    776  void LockedRemoveQuotaForRepository(PersistenceType aPersistenceType);
    777 
    778  void LockedRemoveQuotaForOrigin(const OriginMetadata& aOriginMetadata);
    779 
    780  bool LockedHasGroupInfoPair(const nsACString& aGroup) const;
    781 
    782  already_AddRefed<GroupInfo> LockedGetOrCreateGroupInfo(
    783      PersistenceType aPersistenceType, const nsACString& aSuffix,
    784      const nsACString& aGroup);
    785 
    786  already_AddRefed<OriginInfo> LockedGetOriginInfo(
    787      PersistenceType aPersistenceType,
    788      const OriginMetadata& aOriginMetadata) const;
    789 
    790  nsresult UpgradeFromIndexedDBDirectoryToPersistentStorageDirectory(
    791      nsIFile* aIndexedDBDir);
    792 
    793  nsresult UpgradeFromPersistentStorageDirectoryToDefaultStorageDirectory(
    794      nsIFile* aPersistentStorageDir);
    795 
    796  nsresult MaybeUpgradeToDefaultStorageDirectory(nsIFile& aStorageFile);
    797 
    798  template <typename Helper>
    799  nsresult UpgradeStorage(const int32_t aOldVersion, const int32_t aNewVersion,
    800                          mozIStorageConnection* aConnection);
    801 
    802  nsresult UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
    803 
    804  nsresult UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection);
    805 
    806  nsresult UpgradeStorageFrom2_0To2_1(mozIStorageConnection* aConnection);
    807 
    808  nsresult UpgradeStorageFrom2_1To2_2(mozIStorageConnection* aConnection);
    809 
    810  nsresult UpgradeStorageFrom2_2To2_3(mozIStorageConnection* aConnection);
    811 
    812  nsresult MaybeCreateOrUpgradeStorage(mozIStorageConnection& aConnection);
    813 
    814  OkOrErr MaybeRemoveLocalStorageArchiveTmpFile();
    815 
    816  nsresult MaybeRemoveLocalStorageDataAndArchive(nsIFile& aLsArchiveFile);
    817 
    818  nsresult MaybeRemoveLocalStorageDirectories();
    819 
    820  Result<Ok, nsresult> CopyLocalStorageArchiveFromWebAppsStore(
    821      nsIFile& aLsArchiveFile) const;
    822 
    823  Result<nsCOMPtr<mozIStorageConnection>, nsresult>
    824  CreateLocalStorageArchiveConnection(nsIFile& aLsArchiveFile) const;
    825 
    826  Result<nsCOMPtr<mozIStorageConnection>, nsresult>
    827  RecopyLocalStorageArchiveFromWebAppsStore(nsIFile& aLsArchiveFile);
    828 
    829  Result<nsCOMPtr<mozIStorageConnection>, nsresult>
    830  DowngradeLocalStorageArchive(nsIFile& aLsArchiveFile);
    831 
    832  Result<nsCOMPtr<mozIStorageConnection>, nsresult>
    833  UpgradeLocalStorageArchiveFromLessThan4To4(nsIFile& aLsArchiveFile);
    834 
    835  /*
    836  nsresult UpgradeLocalStorageArchiveFrom4To5();
    837  */
    838 
    839  Result<Ok, nsresult> MaybeCreateOrUpgradeLocalStorageArchive(
    840      nsIFile& aLsArchiveFile);
    841 
    842  Result<Ok, nsresult> CreateEmptyLocalStorageArchive(
    843      nsIFile& aLsArchiveFile) const;
    844 
    845  template <typename OriginFunc>
    846  nsresult InitializeRepository(PersistenceType aPersistenceType,
    847                                OriginFunc&& aOriginFunc);
    848 
    849  nsresult InitializeOrigin(nsIFile* aDirectory,
    850                            const FullOriginMetadata& aFullOriginMetadata,
    851                            bool aForGroup = false);
    852 
    853  using OriginInfosFlatTraversable =
    854      nsTArray<NotNull<RefPtr<const OriginInfo>>>;
    855 
    856  using OriginInfosNestedTraversable =
    857      nsTArray<nsTArray<NotNull<RefPtr<const OriginInfo>>>>;
    858 
    859  OriginInfosNestedTraversable GetOriginInfosExceedingGroupLimit() const;
    860 
    861  OriginInfosNestedTraversable GetOriginInfosExceedingGlobalLimit() const;
    862 
    863  // Returns origins with zero usage. If aCutoffAccessTime is provided, origins
    864  // whose last access time is newer than the cutoff are excluded.
    865  //
    866  // The cutoff time is expressed as an int64_t value in microseconds since the
    867  // Unix epoch (1970-01-01 00:00:00 UTC), matching the format returned by
    868  // PR_Now(). This is the same time unit used throughout Quota Manager for
    869  // access and modification timestamps.
    870  //
    871  // Typically callers compute it as:
    872  //     const int64_t cutoff = PR_Now() - (N * PR_USEC_PER_SEC);
    873  // where N is the desired age threshold in seconds (for example, one week).
    874  OriginInfosNestedTraversable GetOriginInfosWithZeroUsage(
    875      const Maybe<int64_t>& aCutoffAccessTime = Nothing()) const;
    876 
    877  /**
    878   * Clears the given set of origins.
    879   *
    880   * @param aDoomedOriginInfos
    881   *   Origins to be cleared.
    882   * @param aChecker
    883   *   A callable invoked for each origin before clearing. Typically used to
    884   *   enforce or assert invariants at the call site.
    885   * @param aMaxOriginsToClear
    886   *   Optional cap on the number of origins cleared in a single run. If
    887   *   Nothing(), all doomed origins are cleared.
    888   */
    889  template <typename Checker>
    890  void ClearOrigins(const OriginInfosNestedTraversable& aDoomedOriginInfos,
    891                    Checker&& aChecker,
    892                    const Maybe<size_t>& aMaxOriginsToClear = Nothing());
    893 
    894  void CleanupTemporaryStorage();
    895 
    896  void RecordTemporaryStorageMetrics();
    897 
    898  void DeleteOriginDirectory(const OriginMetadata& aOriginMetadata);
    899 
    900  void FinalizeOriginEviction(nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks);
    901 
    902  Result<Ok, nsresult> ArchiveOrigins(
    903      const nsTArray<FullOriginMetadata>& aFullOriginMetadatas);
    904 
    905  void ReleaseIOThreadObjects() {
    906    AssertIsOnIOThread();
    907 
    908    for (Client::Type type : AllClientTypes()) {
    909      (*mClients)[type]->ReleaseIOThreadObjects();
    910    }
    911  }
    912 
    913  void AddTemporaryOrigin(const FullOriginMetadata& aFullOriginMetadata);
    914 
    915  void RemoveTemporaryOrigin(const OriginMetadata& aOriginMetadata);
    916 
    917  void RemoveTemporaryOrigins(PersistenceType aPersistenceType);
    918 
    919  void RemoveTemporaryOrigins();
    920 
    921  /**
    922   * Retrieves the count of thumbnail private identity temporary origins.
    923   *
    924   * This method returns the current count of temporary origins associated with
    925   * thumbnail private identity contexts. It requires that the thumbnail
    926   * private identity id is known.
    927   *
    928   * @return The count of thumbnail private identity temporary origins.
    929   *
    930   * @note The thumbnail private identity id must be known before calling this
    931   *   method. If the id is not known, it will cause a debug assertion failure
    932   *   due to the `MOZ_ASSERT`.
    933   */
    934  uint32_t ThumbnailPrivateIdentityTemporaryOriginCount() const;
    935 
    936  PrincipalMetadataArray GetAllTemporaryGroups() const;
    937 
    938  OriginMetadataArray GetAllTemporaryOrigins() const;
    939 
    940  void NoteInitializedOrigin(PersistenceType aPersistenceType,
    941                             const nsACString& aOrigin);
    942 
    943  void NoteUninitializedOrigins(
    944      const OriginMetadataArray& aOriginMetadataArray);
    945 
    946  void NoteUninitializedRepository(PersistenceType aPersistenceType);
    947 
    948  bool IsOriginInitialized(PersistenceType aPersistenceType,
    949                           const nsACString& aOrigin) const;
    950 
    951  void NoteInitializedClient(PersistenceType aPersistenceType,
    952                             const nsACString& aOrigin,
    953                             Client::Type aClientType);
    954 
    955  void NoteUninitializedClients(
    956      const ClientMetadataArray& aClientMetadataArray);
    957 
    958  void NoteUninitializedClients(
    959      const OriginMetadataArray& aOriginMetadataArray);
    960 
    961  void NoteUninitializedClients(PersistenceType aPersistenceType);
    962 
    963  bool IsClientInitialized(PersistenceType aPersistenceType,
    964                           const nsACString& aOrigin,
    965                           Client::Type aClientType) const;
    966 
    967  bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
    968 
    969  Result<nsCString, nsresult> EnsureStorageOriginFromOrigin(
    970      const nsACString& aOrigin);
    971 
    972  Result<nsCString, nsresult> GetOriginFromStorageOrigin(
    973      const nsACString& aStorageOrigin);
    974 
    975  int64_t GenerateDirectoryLockId();
    976 
    977  /**
    978   * Registers a ClientDirectoryLockHandle for the given origin.
    979   *
    980   * Tracks the handle in internal bookkeeping. If this is the first handle
    981   * registered for the origin, the caller-provided update callback is invoked.
    982   *
    983   * The update callback can be used to perform first-time setup, such as
    984   * updating the origin’s access time.
    985   */
    986  template <typename UpdateCallback>
    987  void RegisterClientDirectoryLockHandle(const OriginMetadata& aOriginMetadata,
    988                                         UpdateCallback&& aUpdateCallback);
    989 
    990  /**
    991   * Invokes the given callback with the active OpenClientDirectoryInfo entry
    992   * for the specified origin.
    993   *
    994   * This method is typically used after the first handle has been registered
    995   * via RegisterClientDirectoryLockHandle. It provides easy access to the
    996   * associated OpenClientDirectoryInfo for reading and/or updating its data.
    997   *
    998   * Currently, it is primarily used in the final step of OpenClientDirectory
    999   * to retrieve the first-access promise returned by SaveOriginAccessTime,
   1000   * which is stored during the first handle registration. The returned promise
   1001   * is then used to ensure that client access is blocked until the origin
   1002   * access time update is complete.
   1003   */
   1004  template <typename Callback>
   1005  auto WithOpenClientDirectoryInfo(const OriginMetadata& aOriginMetadata,
   1006                                   Callback&& aCallback)
   1007      -> std::invoke_result_t<Callback, OpenClientDirectoryInfo&>;
   1008 
   1009  /**
   1010   * Unregisters a ClientDirectoryLockHandle for the given origin.
   1011   *
   1012   * Decreases the active handle count and removes the internal tracking entry
   1013   * if this was the last handle (in some shutdown cases, the entry may no
   1014   * longer exist; this is currently tolerated, see comment in implementation).
   1015   * If the handle being unregistered was the last one for the origin, the
   1016   * caller-provided update callback is invoked.
   1017   *
   1018   * The update callback can be used to perform final cleanup, such as updating
   1019   * the origin’s access time.
   1020   */
   1021  template <typename UpdateCallback>
   1022  void UnregisterClientDirectoryLockHandle(
   1023      const OriginMetadata& aOriginMetadata, UpdateCallback&& aUpdateCallback);
   1024 
   1025  /**
   1026   * This wrapper is used by ClientDirectoryLockHandle to notify the
   1027   * QuotaManager when a non-inert (i.e., owning) handle is being destroyed.
   1028   *
   1029   * This extra abstraction (ClientDirectoryLockHandle could call
   1030   * UnregisterClientDirectoryLockHandle directly) enables future changes to
   1031   * the registration methods, such as templating them. Without this wrapper,
   1032   * such changes would require exposing their implementation in
   1033   * QuotaManagerImpl.h, which would allow access from another translation unit.
   1034   */
   1035  void ClientDirectoryLockHandleDestroy(ClientDirectoryLockHandle& aHandle);
   1036 
   1037  bool ShutdownStarted() const;
   1038 
   1039  void RecordShutdownStep(Maybe<Client::Type> aClientType,
   1040                          const nsACString& aStepDescription);
   1041 
   1042  template <typename Func>
   1043  auto ExecuteInitialization(Initialization aInitialization, Func&& aFunc)
   1044      -> std::invoke_result_t<Func, const FirstInitializationAttempt<
   1045                                        Initialization, StringGenerator>&>;
   1046 
   1047  template <typename Func>
   1048  auto ExecuteInitialization(Initialization aInitialization,
   1049                             const nsACString& aContext, Func&& aFunc)
   1050      -> std::invoke_result_t<Func, const FirstInitializationAttempt<
   1051                                        Initialization, StringGenerator>&>;
   1052 
   1053  template <typename Func>
   1054  auto ExecuteGroupInitialization(const nsACString& aGroup,
   1055                                  const GroupInitialization aInitialization,
   1056                                  const nsACString& aContext, Func&& aFunc)
   1057      -> std::invoke_result_t<Func, const FirstInitializationAttempt<
   1058                                        Initialization, StringGenerator>&>;
   1059 
   1060  template <typename Func>
   1061  auto ExecuteOriginInitialization(const nsACString& aOrigin,
   1062                                   const OriginInitialization aInitialization,
   1063                                   const nsACString& aContext, Func&& aFunc)
   1064      -> std::invoke_result_t<Func, const FirstInitializationAttempt<
   1065                                        Initialization, StringGenerator>&>;
   1066 
   1067  /**
   1068   * Increments the counter tracking the total number of directory iterations.
   1069   *
   1070   * @note This is currently called only during clearing operations to update
   1071   *       the mTotalDirectoryIterations member.
   1072   */
   1073  void IncreaseTotalDirectoryIterations();
   1074 
   1075  /**
   1076   * Increments the counter tracking SaveOriginAccessTime metadata updates,
   1077   * recorded on the background thread after the operation has completed.
   1078   */
   1079  void IncreaseSaveOriginAccessTimeCount();
   1080 
   1081  /**
   1082   * Increments the counter tracking SaveOriginAccessTime metadata updates,
   1083   * recorded internally on the I/O thread when the metadata file is updated.
   1084   */
   1085  void IncreaseSaveOriginAccessTimeCountInternal();
   1086 
   1087  template <typename Collect, typename Pred>
   1088  static OriginInfosFlatTraversable CollectLRUOriginInfosUntil(
   1089      Collect&& aCollect, Pred&& aPred);
   1090 
   1091  // Thread on which IO is performed.
   1092  LazyInitializedOnceNotNull<const nsCOMPtr<nsIThread>> mIOThread;
   1093 
   1094  nsCOMPtr<mozIStorageConnection> mStorageConnection;
   1095 
   1096  EnumeratedArray<Client::Type, nsCString, size_t(Client::TYPE_MAX)>
   1097      mShutdownSteps;
   1098  LazyInitializedOnce<const TimeStamp> mShutdownStartedAt;
   1099 
   1100  // Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex.
   1101  nsCString mQuotaManagerShutdownSteps;
   1102 
   1103  mutable mozilla::Mutex mQuotaMutex MOZ_UNANNOTATED;
   1104 
   1105  nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
   1106 
   1107  // Maintains a list of directory locks that are queued.
   1108  nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks;
   1109 
   1110  // Maintains a list of directory locks that are acquired or queued. It can be
   1111  // accessed on the owning (PBackground) thread only.
   1112  nsTArray<NotNull<DirectoryLockImpl*>> mDirectoryLocks;
   1113 
   1114  // Maintains a list of directory locks that are exclusive. This is a subset
   1115  // of mDirectoryLocks and is used to optimize lock acquisition by allowing
   1116  // shared locks to skip unnecessary comparisons. It is accessed only on the
   1117  // owning (PBackground) thread.
   1118  nsTArray<NotNull<DirectoryLockImpl*>> mExclusiveDirectoryLocks;
   1119 
   1120  // Only modifed on the owning thread, but read on multiple threads. Therefore
   1121  // all modifications (including those on the owning thread) and all reads off
   1122  // the owning thread must be protected by mQuotaMutex. In other words, only
   1123  // reads on the owning thread don't have to be protected by mQuotaMutex.
   1124  nsTHashMap<nsUint64HashKey, NotNull<DirectoryLockImpl*>>
   1125      mDirectoryLockIdTable;
   1126 
   1127  // Things touched on the owning (PBackground) thread only.
   1128  struct BackgroundThreadAccessible {
   1129    PrincipalMetadataArray mUninitializedGroups;
   1130    nsTHashSet<nsCString> mInitializedGroups;
   1131 
   1132    // Tracks active origin directories for updating origin access time.
   1133    nsTHashMap<nsCStringHashKey, OpenClientDirectoryInfo>
   1134        mOpenClientDirectoryInfos;
   1135 
   1136    // Tracks how many times SaveOriginAccessTime resulted in updating metadata.
   1137    uint64_t mSaveOriginAccessTimeCount = 0;
   1138  };
   1139  ThreadBound<BackgroundThreadAccessible> mBackgroundThreadAccessible;
   1140 
   1141  using BoolArray = AutoTArray<bool, PERSISTENCE_TYPE_INVALID>;
   1142  nsTHashMap<nsCStringHashKeyWithDisabledMemmove, BoolArray>
   1143      mInitializedOrigins;
   1144 
   1145  using BitSetArray =
   1146      AutoTArray<BitSet<Client::TYPE_MAX>, PERSISTENCE_TYPE_INVALID>;
   1147  nsTHashMap<nsCStringHashKeyWithDisabledMemmove, BitSetArray>
   1148      mInitializedClients;
   1149 
   1150  // Things touched on the IO thread only.
   1151  struct IOThreadAccessible {
   1152    nsTHashMap<nsCStringHashKey, nsTArray<FullOriginMetadata>>
   1153        mAllTemporaryOrigins;
   1154    Maybe<uint32_t> mThumbnailPrivateIdentityId;
   1155    // Tracks the total number of directory iterations.
   1156    // Note: This is currently incremented only during clearing operations.
   1157    uint64_t mTotalDirectoryIterations = 0;
   1158    // Tracks how many times SaveOriginAccessTime resulted in updating metadata.
   1159    uint64_t mSaveOriginAccessTimeCount = 0;
   1160    // Tracks the count of thumbnail private identity temporary origins.
   1161    uint32_t mThumbnailPrivateIdentityTemporaryOriginCount = 0;
   1162  };
   1163  ThreadBound<IOThreadAccessible> mIOThreadAccessible;
   1164 
   1165  // A list of all successfully initialized persistent origins. This list isn't
   1166  // protected by any mutex but it is only ever touched on the IO thread.
   1167  nsTArray<nsCString> mInitializedOriginsInternal;
   1168 
   1169  // A hash table that is used to cache origin parser results for given
   1170  // sanitized origin strings. This hash table isn't protected by any mutex but
   1171  // it is only ever touched on the IO thread.
   1172  nsTHashMap<nsCStringHashKey, bool> mValidOrigins;
   1173 
   1174  // These maps are protected by mQuotaMutex.
   1175  nsTHashMap<nsCStringHashKey, nsCString> mOriginToStorageOriginMap;
   1176  nsTHashMap<nsCStringHashKey, nsCString> mStorageOriginToOriginMap;
   1177 
   1178  // This array is populated at initialization time and then never modified, so
   1179  // it can be iterated on any thread.
   1180  LazyInitializedOnce<const AutoTArray<RefPtr<Client>, Client::TYPE_MAX>>
   1181      mClients;
   1182 
   1183  using ClientTypesArray = AutoTArray<Client::Type, Client::TYPE_MAX>;
   1184  LazyInitializedOnce<const ClientTypesArray> mAllClientTypes;
   1185  LazyInitializedOnce<const ClientTypesArray> mAllClientTypesExceptLS;
   1186 
   1187  // This object isn't protected by any mutex but it is only ever touched on
   1188  // the IO thread.
   1189  InitializationInfo mInitializationInfo;
   1190 
   1191  const nsString mBasePath;
   1192  const nsString mStorageName;
   1193  LazyInitializedOnce<const nsString> mIndexedDBPath;
   1194  LazyInitializedOnce<const nsString> mStoragePath;
   1195  LazyInitializedOnce<const nsString> mStorageArchivesPath;
   1196  LazyInitializedOnce<const nsString> mPermanentStoragePath;
   1197  LazyInitializedOnce<const nsString> mTemporaryStoragePath;
   1198  LazyInitializedOnce<const nsString> mDefaultStoragePath;
   1199  LazyInitializedOnce<const nsString> mPrivateStoragePath;
   1200  LazyInitializedOnce<const nsString> mToBeRemovedStoragePath;
   1201 
   1202  MozPromiseHolder<BoolPromise> mInitializeAllTemporaryOriginsPromiseHolder;
   1203 
   1204  uint64_t mTemporaryStorageLimit;
   1205  uint64_t mTemporaryStorageUsage;
   1206  int64_t mNextDirectoryLockId;
   1207  bool mStorageInitialized;
   1208  bool mPersistentStorageInitialized;
   1209  bool mPersistentStorageInitializedInternal;
   1210  bool mTemporaryStorageInitialized;
   1211  bool mTemporaryStorageInitializedInternal;
   1212  bool mInitializingAllTemporaryOrigins;
   1213  bool mAllTemporaryOriginsInitialized;
   1214  bool mCacheUsable;
   1215 };
   1216 
   1217 }  // namespace mozilla::dom::quota
   1218 
   1219 #endif /* mozilla_dom_quota_quotamanager_h__ */