Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/quota/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 119 kB image not shown  

Quelle  OriginOperations.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "OriginOperations.h"

#include <algorithm>
#include <cstdint>
#include <utility>

#include "ErrorList.h"
#include "FileUtils.h"
#include "GroupInfo.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/quota/CommonMetadata.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/Constants.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DirectoryLockInlines.h"
#include "mozilla/dom/quota/OriginDirectoryLock.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/quota/PQuota.h"
#include "mozilla/dom/quota/PQuotaRequest.h"
#include "mozilla/dom/quota/PQuotaUsageRequest.h"
#include "mozilla/dom/quota/OriginScope.h"
#include "mozilla/dom/quota/PersistenceScope.h"
#include "mozilla/dom/quota/QuotaCommon.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/QuotaManagerImpl.h"
#include "mozilla/dom/quota/ResultExtensions.h"
#include "mozilla/dom/quota/StreamUtils.h"
#include "mozilla/dom/quota/UniversalDirectoryLock.h"
#include "mozilla/dom/quota/UsageInfo.h"
#include "mozilla/fallible.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "NormalOriginOperationBase.h"
#include "nsCOMPtr.h"
#include "nsTHashMap.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsHashKeys.h"
#include "nsIBinaryOutputStream.h"
#include "nsIFile.h"
#include "nsIObjectOutputStream.h"
#include "nsIOutputStream.h"
#include "nsLiteralString.h"
#include "nsPrintfCString.h"
#include "nsString.h"
#include "nsTArray.h"
#include "OriginInfo.h"
#include "OriginOperationBase.h"
#include "OriginParser.h"
#include "QuotaRequestBase.h"
#include "ResolvableNormalOriginOp.h"
#include "prthread.h"
#include "prtime.h"

namespace mozilla::dom::quota {

using namespace mozilla::ipc;

template <class Base>
class OpenStorageDirectoryHelper : public Base {
 protected:
  OpenStorageDirectoryHelper(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                             const char* aName)
      : Base(std::move(aQuotaManager), aName) {}

  RefPtr<BoolPromise> OpenStorageDirectory(
      const PersistenceScope& aPersistenceScope,
      const OriginScope& aOriginScope,
      const Nullable<Client::Type>& aClientType, bool aExclusive,
      bool aInitializeOrigins = false,
      DirectoryLockCategory aCategory = DirectoryLockCategory::None);

  RefPtr<UniversalDirectoryLock> mDirectoryLock;
};

class FinalizeOriginEvictionOp : public OriginOperationBase {
  nsTArray<RefPtr<OriginDirectoryLock>> mLocks;

 public:
  FinalizeOriginEvictionOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                           nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks)
      : OriginOperationBase(std::move(aQuotaManager),
                            "dom::quota::FinalizeOriginEvictionOp"),
        mLocks(std::move(aLocks)) {
    AssertIsOnOwningThread();
  }

  NS_INLINE_DECL_REFCOUNTING(FinalizeOriginEvictionOp, override)

 private:
  ~FinalizeOriginEvictionOp() = default;

  virtual RefPtr<BoolPromise> Open() override;

  virtual nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  virtual void UnblockOpen() override;
};

class SaveOriginAccessTimeOp
    : public OpenStorageDirectoryHelper<NormalOriginOperationBase> {
  const OriginMetadata mOriginMetadata;
  int64_t mTimestamp;

 public:
  SaveOriginAccessTimeOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                         const OriginMetadata& aOriginMetadata,
                         int64_t aTimestamp)
      : OpenStorageDirectoryHelper(std::move(aQuotaManager),
                                   "dom::quota::SaveOriginAccessTimeOp"),
        mOriginMetadata(aOriginMetadata),
        mTimestamp(aTimestamp) {
    AssertIsOnOwningThread();
  }

  NS_INLINE_DECL_REFCOUNTING(SaveOriginAccessTimeOp, override)

 private:
  ~SaveOriginAccessTimeOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  virtual nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  virtual void SendResults() override;

  void CloseDirectory() override;
};

class ClearPrivateRepositoryOp
    : public OpenStorageDirectoryHelper<ResolvableNormalOriginOp<bool>> {
 public:
  explicit ClearPrivateRepositoryOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
      : OpenStorageDirectoryHelper(std::move(aQuotaManager),
                                   "dom::quota::ClearPrivateRepositoryOp") {
    AssertIsOnOwningThread();
  }

 private:
  ~ClearPrivateRepositoryOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override { return true; }

  void CloseDirectory() override;
};

class ShutdownStorageOp : public ResolvableNormalOriginOp<bool> {
  RefPtr<UniversalDirectoryLock> mDirectoryLock;

 public:
  explicit ShutdownStorageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
      : ResolvableNormalOriginOp(std::move(aQuotaManager),
                                 "dom::quota::ShutdownStorageOp") {
    AssertIsOnOwningThread();
  }

 private:
  ~ShutdownStorageOp() = default;

#ifdef DEBUG
  nsresult DirectoryOpen() override;
#endif

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override { return true; }

  void CloseDirectory() override;
};

class CancelableHelper {
 protected:
  virtual const Atomic<bool>& GetIsCanceledFlag() = 0;
};

// A mix-in class to simplify operations that need to process every origin in
// one or more repositories. Sub-classes should call TraverseRepository in their
// DoDirectoryWork and implement a ProcessOrigin method for their per-origin
// logic.
class TraverseRepositoryHelper : public CancelableHelper {
 public:
  TraverseRepositoryHelper() = default;

 protected:
  virtual ~TraverseRepositoryHelper() = default;

  // If ProcessOrigin returns an error, TraverseRepository will immediately
  // terminate and return the received error code to its caller.
  nsresult TraverseRepository(QuotaManager& aQuotaManager,
                              PersistenceType aPersistenceType);

 private:
  virtual nsresult ProcessOrigin(QuotaManager& aQuotaManager,
                                 nsIFile& aOriginDir, const bool aPersistent,
                                 const PersistenceType aPersistenceType) = 0;
};

class OriginUsageHelper : public CancelableHelper {
 protected:
  mozilla::Result<UsageInfo, nsresult> GetUsageForOrigin(
      QuotaManager& aQuotaManager, PersistenceType aPersistenceType,
      const OriginMetadata& aOriginMetadata);

 private:
  mozilla::Result<UsageInfo, nsresult> GetUsageForOriginEntries(
      QuotaManager& aQuotaManager, PersistenceType aPersistenceType,
      const OriginMetadata& aOriginMetadata, nsIFile& aDirectory,
      bool aInitialized);
};

class GetUsageOp final
    : public OpenStorageDirectoryHelper<
          ResolvableNormalOriginOp<OriginUsageMetadataArray, true>>,
      public TraverseRepositoryHelper,
      public OriginUsageHelper {
  OriginUsageMetadataArray mOriginUsages;
  nsTHashMap<nsCStringHashKey, uint32_t> mOriginUsagesIndex;

  bool mGetAll;

 public:
  GetUsageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager, bool aGetAll);

 private:
  ~GetUsageOp() = default;

  void ProcessOriginInternal(QuotaManager* aQuotaManager,
                             const PersistenceType aPersistenceType,
                             const nsACString& aOrigin,
                             const int64_t aTimestamp, const bool aPersisted,
                             const uint64_t aUsage);

  RefPtr<BoolPromise> OpenDirectory() override;

  const Atomic<bool>& GetIsCanceledFlag() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  nsresult ProcessOrigin(QuotaManager& aQuotaManager, nsIFile& aOriginDir,
                         const bool aPersistent,
                         const PersistenceType aPersistenceType) override;

  OriginUsageMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class GetOriginUsageOp final
    : public OpenStorageDirectoryHelper<ResolvableNormalOriginOp<UsageInfo>>,
      public OriginUsageHelper {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  UsageInfo mUsageInfo;

 public:
  GetOriginUsageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                   const PrincipalInfo& aPrincipalInfo);

 private:
  ~GetOriginUsageOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  virtual nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  const Atomic<bool>& GetIsCanceledFlag() override;

  UsageInfo UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class StorageNameOp final : public QuotaRequestBase {
  nsString mName;

 public:
  explicit StorageNameOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager);

 private:
  ~StorageNameOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  void GetResponse(RequestResponse& aResponse) override;

  void CloseDirectory() override;
};

class InitializedRequestBase : public ResolvableNormalOriginOp<bool> {
 protected:
  bool mInitialized;

  InitializedRequestBase(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                         const char* aName);

 private:
  RefPtr<BoolPromise> OpenDirectory() override;

  void CloseDirectory() override;
};

class StorageInitializedOp final : public InitializedRequestBase {
 public:
  explicit StorageInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
      : InitializedRequestBase(std::move(aQuotaManager),
                               "dom::quota::StorageInitializedOp") {}

 private:
  ~StorageInitializedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class PersistentStorageInitializedOp final : public InitializedRequestBase {
 public:
  explicit PersistentStorageInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
      : InitializedRequestBase(std::move(aQuotaManager),
                               "dom::quota::PersistentStorageInitializedOp") {}

 private:
  ~PersistentStorageInitializedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class TemporaryStorageInitializedOp final : public InitializedRequestBase {
 public:
  explicit TemporaryStorageInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
      : InitializedRequestBase(std::move(aQuotaManager),
                               "dom::quota::TemporaryStorageInitializedOp") {}

 private:
  ~TemporaryStorageInitializedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class TemporaryGroupInitializedOp final
    : public ResolvableNormalOriginOp<bool> {
  const PrincipalMetadata mPrincipalMetadata;
  bool mInitialized;

 public:
  explicit TemporaryGroupInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const PrincipalMetadata& aPrincipalMetadata);

 private:
  ~TemporaryGroupInitializedOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class InitializedOriginRequestBase : public ResolvableNormalOriginOp<bool> {
 protected:
  const PrincipalMetadata mPrincipalMetadata;
  bool mInitialized;

  InitializedOriginRequestBase(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager, const char* aName,
      const PrincipalMetadata& aPrincipalMetadata);

 private:
  RefPtr<BoolPromise> OpenDirectory() override;

  void CloseDirectory() override;
};

class PersistentOriginInitializedOp final
    : public InitializedOriginRequestBase {
 public:
  explicit PersistentOriginInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const OriginMetadata& aOriginMetadata);

 private:
  ~PersistentOriginInitializedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class TemporaryOriginInitializedOp final : public InitializedOriginRequestBase {
  const PersistenceType mPersistenceType;

 public:
  explicit TemporaryOriginInitializedOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const OriginMetadata& aOriginMetadata);

 private:
  ~TemporaryOriginInitializedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class InitOp final : public ResolvableNormalOriginOp<bool> {
  RefPtr<UniversalDirectoryLock> mDirectoryLock;

 public:
  InitOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
         RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class InitializePersistentStorageOp final
    : public ResolvableNormalOriginOp<bool> {
  RefPtr<UniversalDirectoryLock> mDirectoryLock;

 public:
  InitializePersistentStorageOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitializePersistentStorageOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class InitTemporaryStorageOp final
    : public ResolvableNormalOriginOp<MaybePrincipalMetadataArray, true> {
  MaybePrincipalMetadataArray mAllTemporaryGroups;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;

 public:
  InitTemporaryStorageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                         RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitTemporaryStorageOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  MaybePrincipalMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class InitializeTemporaryGroupOp final : public ResolvableNormalOriginOp<bool> {
  const PrincipalMetadata mPrincipalMetadata;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;

 public:
  InitializeTemporaryGroupOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                             const PrincipalMetadata& aPrincipalMetadata,
                             RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitializeTemporaryGroupOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class InitializeOriginRequestBase : public ResolvableNormalOriginOp<bool> {
 protected:
  const PrincipalMetadata mPrincipalMetadata;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;
  bool mCreated;

  InitializeOriginRequestBase(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                              const char* aName,
                              const PrincipalMetadata& aPrincipalMetadata,
                              RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  RefPtr<BoolPromise> OpenDirectory() override;

  void CloseDirectory() override;
};

class InitializePersistentOriginOp final : public InitializeOriginRequestBase {
 public:
  InitializePersistentOriginOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const OriginMetadata& aOriginMetadata,
      RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitializePersistentOriginOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class InitializeTemporaryOriginOp final : public InitializeOriginRequestBase {
  const PersistenceType mPersistenceType;
  const bool mCreateIfNonExistent;

 public:
  InitializeTemporaryOriginOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                              const OriginMetadata& aOriginMetadata,
                              bool aCreateIfNonExistent,
                              RefPtr<UniversalDirectoryLock> aDirectoryLock);

 private:
  ~InitializeTemporaryOriginOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class InitializeClientBase : public ResolvableNormalOriginOp<bool> {
 protected:
  const PrincipalInfo mPrincipalInfo;
  ClientMetadata mClientMetadata;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;
  const PersistenceType mPersistenceType;
  const Client::Type mClientType;
  bool mCreated;

  InitializeClientBase(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                       const char* aName, PersistenceType aPersistenceType,
                       const PrincipalInfo& aPrincipalInfo,
                       Client::Type aClientType);

  nsresult DoInit(QuotaManager& aQuotaManager) override;

 private:
  RefPtr<BoolPromise> OpenDirectory() override;

  void CloseDirectory() override;
};

class InitializePersistentClientOp : public InitializeClientBase {
 public:
  InitializePersistentClientOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const PrincipalInfo& aPrincipalInfo, Client::Type aClientType);

 private:
  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class InitializeTemporaryClientOp : public InitializeClientBase {
 public:
  InitializeTemporaryClientOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                              PersistenceType aPersistenceType,
                              const PrincipalInfo& aPrincipalInfo,
                              Client::Type aClientType);

 private:
  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;
};

class GetFullOriginMetadataOp
    : public OpenStorageDirectoryHelper<QuotaRequestBase> {
  const GetFullOriginMetadataParams mParams;
  // XXX Consider wrapping with LazyInitializedOnce
  OriginMetadata mOriginMetadata;
  Maybe<FullOriginMetadata> mMaybeFullOriginMetadata;

 public:
  GetFullOriginMetadataOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                          const GetFullOriginMetadataParams& aParams);

 private:
  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  void GetResponse(RequestResponse& aResponse) override;

  void CloseDirectory() override;
};

class GetCachedOriginUsageOp
    : public OpenStorageDirectoryHelper<ResolvableNormalOriginOp<uint64_t>> {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  uint64_t mUsage;

 public:
  GetCachedOriginUsageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                         const PrincipalInfo& aPrincipalInfo);

 private:
  ~GetCachedOriginUsageOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  uint64_t UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ListCachedOriginsOp final
    : public OpenStorageDirectoryHelper<
          ResolvableNormalOriginOp<CStringArray, /* IsExclusive */ true>> {
  nsTArray<nsCString> mOrigins;

 public:
  explicit ListCachedOriginsOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager);

 private:
  ~ListCachedOriginsOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  CStringArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ClearStorageOp final
    : public OpenStorageDirectoryHelper<ResolvableNormalOriginOp<bool>> {
 public:
  explicit ClearStorageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager);

 private:
  ~ClearStorageOp() = default;

  void DeleteFiles(QuotaManager& aQuotaManager);

  void DeleteStorageFile(QuotaManager& aQuotaManager);

  RefPtr<BoolPromise> OpenDirectory() override;

  virtual nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ClearRequestBase
    : public OpenStorageDirectoryHelper<
          ResolvableNormalOriginOp<OriginMetadataArray, true>> {
  Atomic<uint64_t> mIterations;

 protected:
  OriginMetadataArray mOriginMetadataArray;

  ClearRequestBase(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                   const char* aName)
      : OpenStorageDirectoryHelper(std::move(aQuotaManager), aName),
        mIterations(0) {
    AssertIsOnOwningThread();
  }

  void DeleteFiles(QuotaManager& aQuotaManager,
                   const OriginMetadata& aOriginMetadata);

  void DeleteFiles(QuotaManager& aQuotaManager,
                   PersistenceType aPersistenceType,
                   const OriginScope& aOriginScope);

 private:
  template <typename FileCollector>
  void DeleteFilesInternal(QuotaManager& aQuotaManager,
                           PersistenceType aPersistenceType,
                           const OriginScope& aOriginScope,
                           const FileCollector& aFileCollector);

  void DoStringify(nsACString& aData) override {
    aData.Append("ClearRequestBase "_ns +
                 //
                 kStringifyStartInstance +
                 //
                 "Iterations:"_ns +
                 IntToCString(static_cast<uint64_t>(mIterations)) +
                 //
                 kStringifyEndInstance);
  }
};

class ClearOriginOp final : public ClearRequestBase {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  const PersistenceScope mPersistenceScope;

 public:
  ClearOriginOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                const mozilla::Maybe<PersistenceType>& aPersistenceType,
                const PrincipalInfo& aPrincipalInfo);

 private:
  ~ClearOriginOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  OriginMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ClearClientOp final
    : public OpenStorageDirectoryHelper<ResolvableNormalOriginOp<bool>> {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  const PersistenceScope mPersistenceScope;
  const Client::Type mClientType;

 public:
  ClearClientOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                mozilla::Maybe<PersistenceType> aPersistenceType,
                const PrincipalInfo& aPrincipalInfo,
                const Client::Type aClientType);

 private:
  ~ClearClientOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  void DeleteFiles(const ClientMetadata& aClientMetadata);

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ClearStoragesForOriginPrefixOp final
    : public OpenStorageDirectoryHelper<ClearRequestBase> {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  const PersistenceScope mPersistenceScope;

 public:
  ClearStoragesForOriginPrefixOp(
      MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
      const Maybe<PersistenceType>& aPersistenceType,
      const PrincipalInfo& aPrincipalInfo);

 private:
  ~ClearStoragesForOriginPrefixOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  OriginMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ClearDataOp final : public ClearRequestBase {
  const OriginAttributesPattern mPattern;

 public:
  ClearDataOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
              const OriginAttributesPattern& aPattern);

 private:
  ~ClearDataOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  OriginMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ShutdownOriginOp final
    : public ResolvableNormalOriginOp<OriginMetadataArray, true> {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  OriginMetadataArray mOriginMetadataArray;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;
  const PersistenceScope mPersistenceScope;

 public:
  ShutdownOriginOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                   mozilla::Maybe<PersistenceType> aPersistenceType,
                   const PrincipalInfo& aPrincipalInfo);

 private:
  ~ShutdownOriginOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  void CollectOriginMetadata(const OriginMetadata& aOriginMetadata);

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  OriginMetadataArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class ShutdownClientOp final : public ResolvableNormalOriginOp<bool> {
  const PrincipalInfo mPrincipalInfo;
  PrincipalMetadata mPrincipalMetadata;
  RefPtr<UniversalDirectoryLock> mDirectoryLock;
  const PersistenceScope mPersistenceScope;
  const Client::Type mClientType;

 public:
  ShutdownClientOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                   mozilla::Maybe<PersistenceType> aPersistenceType,
                   const PrincipalInfo& aPrincipalInfo,
                   const Client::Type aClientType);

 private:
  ~ShutdownClientOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  bool UnwrapResolveValue() override;

  void CloseDirectory() override;
};

class PersistRequestBase : public OpenStorageDirectoryHelper<QuotaRequestBase> {
  const PrincipalInfo mPrincipalInfo;

 protected:
  PrincipalMetadata mPrincipalMetadata;

 protected:
  PersistRequestBase(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                     const PrincipalInfo& aPrincipalInfo);

  nsresult DoInit(QuotaManager& aQuotaManager) override;

 private:
  RefPtr<BoolPromise> OpenDirectory() override;

  void CloseDirectory() override;
};

class PersistedOp final : public PersistRequestBase {
  bool mPersisted;

 public:
  PersistedOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
              const RequestParams& aParams);

 private:
  ~PersistedOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  void GetResponse(RequestResponse& aResponse) override;
};

class PersistOp final : public PersistRequestBase {
 public:
  PersistOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
            const RequestParams& aParams);

 private:
  ~PersistOp() = default;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  void GetResponse(RequestResponse& aResponse) override;
};

class EstimateOp final : public OpenStorageDirectoryHelper<QuotaRequestBase> {
  const EstimateParams mParams;
  OriginMetadata mOriginMetadata;
  std::pair<uint64_t, uint64_t> mUsageAndLimit;

 public:
  EstimateOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
             const EstimateParams& aParams);

 private:
  ~EstimateOp() = default;

  nsresult DoInit(QuotaManager& aQuotaManager) override;

  RefPtr<BoolPromise> OpenDirectory() override;

  virtual nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  void GetResponse(RequestResponse& aResponse) override;

  void CloseDirectory() override;
};

class ListOriginsOp final
    : public OpenStorageDirectoryHelper<
          ResolvableNormalOriginOp<CStringArray, /* IsExclusive */ true>>,
      public TraverseRepositoryHelper {
  // XXX Bug 1521541 will make each origin has it's own state.
  nsTArray<nsCString> mOrigins;

 public:
  explicit ListOriginsOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager);

 private:
  ~ListOriginsOp() = default;

  RefPtr<BoolPromise> OpenDirectory() override;

  nsresult DoDirectoryWork(QuotaManager& aQuotaManager) override;

  const Atomic<bool>& GetIsCanceledFlag() override;

  nsresult ProcessOrigin(QuotaManager& aQuotaManager, nsIFile& aOriginDir,
                         const bool aPersistent,
                         const PersistenceType aPersistenceType) override;

  CStringArray UnwrapResolveValue() override;

  void CloseDirectory() override;
};

RefPtr<OriginOperationBase> CreateFinalizeOriginEvictionOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks) {
  return MakeRefPtr<FinalizeOriginEvictionOp>(std::move(aQuotaManager),
                                              std::move(aLocks));
}

RefPtr<NormalOriginOperationBase> CreateSaveOriginAccessTimeOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata, int64_t aTimestamp) {
  return MakeRefPtr<SaveOriginAccessTimeOp>(std::move(aQuotaManager),
                                            aOriginMetadata, aTimestamp);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateClearPrivateRepositoryOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<ClearPrivateRepositoryOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateShutdownStorageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<ShutdownStorageOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<OriginUsageMetadataArray, true>>
CreateGetUsageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                 bool aGetAll) {
  return MakeRefPtr<GetUsageOp>(std::move(aQuotaManager), aGetAll);
}

RefPtr<ResolvableNormalOriginOp<UsageInfo>> CreateGetOriginUsageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
  return MakeRefPtr<GetOriginUsageOp>(std::move(aQuotaManager), aPrincipalInfo);
}

RefPtr<QuotaRequestBase> CreateStorageNameOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<StorageNameOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateStorageInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<StorageInitializedOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreatePersistentStorageInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<PersistentStorageInitializedOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateTemporaryStorageInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<TemporaryStorageInitializedOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateTemporaryGroupInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const PrincipalMetadata& aPrincipalMetadata) {
  return MakeRefPtr<TemporaryGroupInitializedOp>(std::move(aQuotaManager),
                                                 aPrincipalMetadata);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreatePersistentOriginInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata) {
  return MakeRefPtr<PersistentOriginInitializedOp>(std::move(aQuotaManager),
                                                   aOriginMetadata);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateTemporaryOriginInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata) {
  return MakeRefPtr<TemporaryOriginInitializedOp>(std::move(aQuotaManager),
                                                  aOriginMetadata);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitOp>(std::move(aQuotaManager),
                            std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializePersistentStorageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitializePersistentStorageOp>(std::move(aQuotaManager),
                                                   std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<MaybePrincipalMetadataArray, true>>
CreateInitTemporaryStorageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                             RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitTemporaryStorageOp>(std::move(aQuotaManager),
                                            std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializeTemporaryGroupOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const PrincipalMetadata& aPrincipalMetadata,
    RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitializeTemporaryGroupOp>(
      std::move(aQuotaManager), aPrincipalMetadata, std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializePersistentOriginOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata,
    RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitializePersistentOriginOp>(
      std::move(aQuotaManager), aOriginMetadata, std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializeTemporaryOriginOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata, bool aCreateIfNonExistent,
    RefPtr<UniversalDirectoryLock> aDirectoryLock) {
  return MakeRefPtr<InitializeTemporaryOriginOp>(
      std::move(aQuotaManager), aOriginMetadata, aCreateIfNonExistent,
      std::move(aDirectoryLock));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializePersistentClientOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
    const Client::Type aClientType) {
  return MakeRefPtr<InitializePersistentClientOp>(std::move(aQuotaManager),
                                                  aPrincipalInfo, aClientType);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateInitializeTemporaryClientOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const PersistenceType aPersistenceType, const PrincipalInfo& aPrincipalInfo,
    const Client::Type aClientType) {
  return MakeRefPtr<InitializeTemporaryClientOp>(
      std::move(aQuotaManager), aPersistenceType, aPrincipalInfo, aClientType);
}

RefPtr<QuotaRequestBase> CreateGetFullOriginMetadataOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const GetFullOriginMetadataParams& aParams) {
  return MakeRefPtr<GetFullOriginMetadataOp>(std::move(aQuotaManager), aParams);
}

RefPtr<ResolvableNormalOriginOp<uint64_t>> CreateGetCachedOriginUsageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
  return MakeRefPtr<GetCachedOriginUsageOp>(std::move(aQuotaManager),
                                            aPrincipalInfo);
}

RefPtr<ResolvableNormalOriginOp<CStringArray, true>> CreateListCachedOriginsOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<ListCachedOriginsOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateClearStorageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<ClearStorageOp>(std::move(aQuotaManager));
}

RefPtr<ResolvableNormalOriginOp<OriginMetadataArray, true>> CreateClearOriginOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const Maybe<PersistenceType>& aPersistenceType,
    const PrincipalInfo& aPrincipalInfo) {
  return MakeRefPtr<ClearOriginOp>(std::move(aQuotaManager), aPersistenceType,
                                   aPrincipalInfo);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateClearClientOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    Maybe<PersistenceType> aPersistenceType,
    const PrincipalInfo& aPrincipalInfo, Client::Type aClientType) {
  return MakeRefPtr<ClearClientOp>(std::move(aQuotaManager), aPersistenceType,
                                   aPrincipalInfo, aClientType);
}

RefPtr<ResolvableNormalOriginOp<OriginMetadataArray, true>>
CreateClearStoragesForOriginPrefixOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const Maybe<PersistenceType>& aPersistenceType,
    const PrincipalInfo& aPrincipalInfo) {
  return MakeRefPtr<ClearStoragesForOriginPrefixOp>(
      std::move(aQuotaManager), aPersistenceType, aPrincipalInfo);
}

RefPtr<ResolvableNormalOriginOp<OriginMetadataArray, true>> CreateClearDataOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginAttributesPattern& aPattern) {
  return MakeRefPtr<ClearDataOp>(std::move(aQuotaManager), aPattern);
}

RefPtr<ResolvableNormalOriginOp<OriginMetadataArray, true>>
CreateShutdownOriginOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                       Maybe<PersistenceType> aPersistenceType,
                       const mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
  return MakeRefPtr<ShutdownOriginOp>(std::move(aQuotaManager),
                                      aPersistenceType, aPrincipalInfo);
}

RefPtr<ResolvableNormalOriginOp<bool>> CreateShutdownClientOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    Maybe<PersistenceType> aPersistenceType,
    const PrincipalInfo& aPrincipalInfo, Client::Type aClientType) {
  return MakeRefPtr<ShutdownClientOp>(
      std::move(aQuotaManager), aPersistenceType, aPrincipalInfo, aClientType);
}

RefPtr<QuotaRequestBase> CreatePersistedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const RequestParams& aParams) {
  return MakeRefPtr<PersistedOp>(std::move(aQuotaManager), aParams);
}

RefPtr<QuotaRequestBase> CreatePersistOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const RequestParams& aParams) {
  return MakeRefPtr<PersistOp>(std::move(aQuotaManager), aParams);
}

RefPtr<QuotaRequestBase> CreateEstimateOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const EstimateParams& aParams) {
  return MakeRefPtr<EstimateOp>(std::move(aQuotaManager), aParams);
}

RefPtr<ResolvableNormalOriginOp<CStringArray, /* IsExclusive */ true>>
CreateListOriginsOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager) {
  return MakeRefPtr<ListOriginsOp>(std::move(aQuotaManager));
}

template <class Base>
RefPtr<BoolPromise> OpenStorageDirectoryHelper<Base>::OpenStorageDirectory(
    const PersistenceScope& aPersistenceScope, const OriginScope& aOriginScope,
    const Nullable<Client::Type>& aClientType, bool aExclusive,
    bool aInitializeOrigins, const DirectoryLockCategory aCategory) {
  return Base::mQuotaManager
      ->OpenStorageDirectory(aPersistenceScope, aOriginScope, aClientType,
                             aExclusive, aInitializeOrigins, aCategory)
      ->Then(GetCurrentSerialEventTarget(), __func__,
             [self = RefPtr(this)](
                 UniversalDirectoryLockPromise::ResolveOrRejectValue&& aValue) {
               if (aValue.IsReject()) {
                 return BoolPromise::CreateAndReject(aValue.RejectValue(),
                                                     __func__);
               }

               self->mDirectoryLock = std::move(aValue.ResolveValue());

               return BoolPromise::CreateAndResolve(true, __func__);
             });
}

RefPtr<BoolPromise> FinalizeOriginEvictionOp::Open() {
  AssertIsOnOwningThread();
  MOZ_ASSERT(!mLocks.IsEmpty());

  return BoolPromise::CreateAndResolve(true, __func__);
}

nsresult FinalizeOriginEvictionOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("FinalizeOriginEvictionOp::DoDirectoryWork", OTHER);

  for (const auto& lock : mLocks) {
    aQuotaManager.OriginClearCompleted(lock->OriginMetadata(),
                                       Nullable<Client::Type>());
  }

  return NS_OK;
}

void FinalizeOriginEvictionOp::UnblockOpen() {
  AssertIsOnOwningThread();

  nsTArray<OriginMetadata> origins;

  std::transform(mLocks.cbegin(), mLocks.cend(), MakeBackInserter(origins),
                 [](const auto& lock) { return lock->OriginMetadata(); });

  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(NS_NewRunnableFunction(
      "dom::quota::FinalizeOriginEvictionOp::UnblockOpen",
      [quotaManager = mQuotaManager, origins = std::move(origins)]() {
        quotaManager->NoteUninitializedOrigins(origins);
      })));

  for (const auto& lock : mLocks) {
    lock->Drop();
  }
  mLocks.Clear();
}

RefPtr<BoolPromise> SaveOriginAccessTimeOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return OpenStorageDirectory(
      PersistenceScope::CreateFromValue(mOriginMetadata.mPersistenceType),
      OriginScope::FromOrigin(mOriginMetadata), Nullable<Client::Type>(),
      /* aExclusive */ false);
}

nsresult SaveOriginAccessTimeOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();
  aQuotaManager.AssertStorageIsInitializedInternal();

  AUTO_PROFILER_LABEL("SaveOriginAccessTimeOp::DoDirectoryWork", OTHER);

  QM_TRY(MOZ_TO_RESULT(!QuotaManager::IsShuttingDown()), NS_ERROR_ABORT);

  QM_TRY_INSPECT(const auto& file,
                 aQuotaManager.GetOriginDirectory(mOriginMetadata));

  // The origin directory might not exist
  // anymore, because it was deleted by a clear operation.
  QM_TRY_INSPECT(const bool& exists, MOZ_TO_RESULT_INVOKE_MEMBER(file, Exists));

  if (exists) {
    QM_TRY(MOZ_TO_RESULT(file->Append(nsLiteralString(METADATA_V2_FILE_NAME))));

    QM_TRY_INSPECT(const auto& stream,
                   GetBinaryOutputStream(*file, FileFlag::Update));
    MOZ_ASSERT(stream);

    QM_TRY(MOZ_TO_RESULT(stream->Write64(mTimestamp)));
  }

  return NS_OK;
}

void SaveOriginAccessTimeOp::SendResults() {}

void SaveOriginAccessTimeOp::CloseDirectory() {
  AssertIsOnOwningThread();

  SafeDropDirectoryLock(mDirectoryLock);
}

RefPtr<BoolPromise> ClearPrivateRepositoryOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return OpenStorageDirectory(
      PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PRIVATE),
      OriginScope::FromNull(), Nullable<Client::Type>(),
      /* aExclusive */ true, /* aInitializeOrigins */ false,
      DirectoryLockCategory::UninitOrigins);
}

nsresult ClearPrivateRepositoryOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();
  aQuotaManager.AssertStorageIsInitializedInternal();

  AUTO_PROFILER_LABEL("ClearPrivateRepositoryOp::DoDirectoryWork", OTHER);

  QM_TRY_INSPECT(
      const auto& directory,
      QM_NewLocalFile(aQuotaManager.GetStoragePath(PERSISTENCE_TYPE_PRIVATE)));

  nsresult rv = directory->Remove(true);
  if (rv != NS_ERROR_FILE_NOT_FOUND && NS_FAILED(rv)) {
    // This should never fail if we've closed all storage connections
    // correctly...
    MOZ_ASSERT(false"Failed to remove directory!");
  }

  aQuotaManager.RemoveQuotaForRepository(PERSISTENCE_TYPE_PRIVATE);

  aQuotaManager.RepositoryClearCompleted(PERSISTENCE_TYPE_PRIVATE);

  return NS_OK;
}

void ClearPrivateRepositoryOp::CloseDirectory() {
  AssertIsOnOwningThread();

  SafeDropDirectoryLock(mDirectoryLock);
}

RefPtr<BoolPromise> ShutdownStorageOp::OpenDirectory() {
  AssertIsOnOwningThread();

  // Clear directory lock tables (which also saves origin access time) before
  // acquiring the exclusive lock below. Otherwise, saving of origin access
  // time would be scheduled after storage shutdown and that would initialize
  // storage again in the end.
  mQuotaManager->ClearDirectoryLockTables();

  mDirectoryLock = mQuotaManager->CreateDirectoryLockInternal(
      PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
      Nullable<Client::Type>(),
      /* aExclusive */ true, DirectoryLockCategory::UninitStorage);

  return mDirectoryLock->Acquire();
}

#ifdef DEBUG
nsresult ShutdownStorageOp::DirectoryOpen() {
  AssertIsOnBackgroundThread();
  MOZ_ASSERT(mDirectoryLock);
  mDirectoryLock->AssertIsAcquiredExclusively();

  return NormalOriginOperationBase::DirectoryOpen();
}
#endif

nsresult ShutdownStorageOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("ShutdownStorageOp::DoDirectoryWork", OTHER);

  aQuotaManager.MaybeRecordQuotaManagerShutdownStep(
      "ShutdownStorageOp::DoDirectoryWork -> ShutdownStorageInternal."_ns);

  aQuotaManager.ShutdownStorageInternal();

  return NS_OK;
}

void ShutdownStorageOp::CloseDirectory() {
  AssertIsOnOwningThread();

  DropDirectoryLockIfNotDropped(mDirectoryLock);
}

nsresult TraverseRepositoryHelper::TraverseRepository(
    QuotaManager& aQuotaManager, PersistenceType aPersistenceType) {
  AssertIsOnIOThread();

  QM_TRY_INSPECT(
      const auto& directory,
      QM_NewLocalFile(aQuotaManager.GetStoragePath(aPersistenceType)));

  QM_TRY_INSPECT(const bool& exists,
                 MOZ_TO_RESULT_INVOKE_MEMBER(directory, Exists));

  if (!exists) {
    return NS_OK;
  }

  QM_TRY(CollectEachFileAtomicCancelable(
      *directory, GetIsCanceledFlag(),
      [this, aPersistenceType, &aQuotaManager,
       persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT](
          const nsCOMPtr<nsIFile>& originDir) -> Result<Ok, nsresult> {
        QM_TRY_INSPECT(const auto& dirEntryKind, GetDirEntryKind(*originDir));

        switch (dirEntryKind) {
          case nsIFileKind::ExistsAsDirectory:
            QM_TRY(MOZ_TO_RESULT(ProcessOrigin(aQuotaManager, *originDir,
                                               persistent, aPersistenceType)));
            break;

          case nsIFileKind::ExistsAsFile: {
            QM_TRY_INSPECT(const auto& leafName,
                           MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
                               nsAutoString, originDir, GetLeafName));

            // Unknown files during getting usages are allowed. Just warn if we
            // find them.
            if (!IsOSMetadata(leafName)) {
              UNKNOWN_FILE_WARNING(leafName);
            }

            break;
          }

          case nsIFileKind::DoesNotExist:
            // Ignore files that got removed externally while iterating.
            break;
        }

        return Ok{};
      }));

  return NS_OK;
}

Result<UsageInfo, nsresult> OriginUsageHelper::GetUsageForOrigin(
    QuotaManager& aQuotaManager, PersistenceType aPersistenceType,
    const OriginMetadata& aOriginMetadata) {
  AssertIsOnIOThread();
  MOZ_ASSERT(aOriginMetadata.mPersistenceType == aPersistenceType);

  QM_TRY_INSPECT(const auto& directory,
                 aQuotaManager.GetOriginDirectory(aOriginMetadata));

  QM_TRY_INSPECT(const bool& exists,
                 MOZ_TO_RESULT_INVOKE_MEMBER(directory, Exists));

  if (!exists || GetIsCanceledFlag()) {
    return UsageInfo();
  }

  // If the directory exists then enumerate all the files inside, adding up
  // the sizes to get the final usage statistic.
  bool initialized;

  if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
    initialized = aQuotaManager.IsPersistentOriginInitializedInternal(
        aOriginMetadata.mOrigin);
  } else {
    initialized = aQuotaManager.IsTemporaryStorageInitializedInternal();
  }

  return GetUsageForOriginEntries(aQuotaManager, aPersistenceType,
                                  aOriginMetadata, *directory, initialized);
}

Result<UsageInfo, nsresult> OriginUsageHelper::GetUsageForOriginEntries(
    QuotaManager& aQuotaManager, PersistenceType aPersistenceType,
    const OriginMetadata& aOriginMetadata, nsIFile& aDirectory,
    const bool aInitialized) {
  AssertIsOnIOThread();

  QM_TRY_RETURN((ReduceEachFileAtomicCancelable(
      aDirectory, GetIsCanceledFlag(), UsageInfo{},
      [&](UsageInfo oldUsageInfo, const nsCOMPtr<nsIFile>& file)
          -> mozilla::Result<UsageInfo, nsresult> {
        QM_TRY_INSPECT(
            const auto& leafName,
            MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString, file, GetLeafName));

        QM_TRY_INSPECT(const auto& dirEntryKind, GetDirEntryKind(*file));

        switch (dirEntryKind) {
          case nsIFileKind::ExistsAsDirectory: {
            Client::Type clientType;
            const bool ok =
                Client::TypeFromText(leafName, clientType, fallible);
            if (!ok) {
              // Unknown directories during getting usage for an origin (even
              // for an uninitialized origin) are now allowed. Just warn if we
              // find them.
              UNKNOWN_FILE_WARNING(leafName);
              break;
            }

            Client* const client = aQuotaManager.GetClient(clientType);
            MOZ_ASSERT(client);

            QM_TRY_INSPECT(const auto& usageInfo,
                           aInitialized ? client->GetUsageForOrigin(
                                              aPersistenceType, aOriginMetadata,
                                              GetIsCanceledFlag())
                                        : client->InitOrigin(
                                              aPersistenceType, aOriginMetadata,
                                              GetIsCanceledFlag()));
            return oldUsageInfo + usageInfo;
          }

          case nsIFileKind::ExistsAsFile:
            // We are maintaining existing behavior for unknown files here (just
            // continuing).
            // This can possibly be used by developers to add temporary backups
            // into origin directories without losing get usage functionality.
            if (IsTempMetadata(leafName)) {
              if (!aInitialized) {
                QM_TRY(MOZ_TO_RESULT(file->Remove(/* recursive */ false)));
              }

              break;
            }

            if (IsOriginMetadata(leafName) || IsOSMetadata(leafName) ||
                IsDotFile(leafName)) {
              break;
            }

            // Unknown files during getting usage for an origin (even for an
            // uninitialized origin) are now allowed. Just warn if we find them.
            UNKNOWN_FILE_WARNING(leafName);
            break;

          case nsIFileKind::DoesNotExist:
            // Ignore files that got removed externally while iterating.
            break;
        }

        return oldUsageInfo;
      })));
}

GetUsageOp::GetUsageOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
                       bool aGetAll)
    : OpenStorageDirectoryHelper(std::move(aQuotaManager),
                                 "dom::quota::GetUsageOp"),
      mGetAll(aGetAll) {
  AssertIsOnOwningThread();
}

void GetUsageOp::ProcessOriginInternal(QuotaManager* aQuotaManager,
                                       const PersistenceType aPersistenceType,
                                       const nsACString& aOrigin,
                                       const int64_t aTimestamp,
                                       const bool aPersisted,
                                       const uint64_t aUsage) {
  if (!mGetAll && aQuotaManager->IsOriginInternal(aOrigin)) {
    return;
  }

  // We can't store pointers to OriginUsage objects in the hashtable
  // since AppendElement() reallocates its internal array buffer as number
  // of elements grows.
  const auto& originUsage =
      mOriginUsagesIndex.WithEntryHandle(aOrigin, [&](auto&& entry) {
        if (entry) {
          return WrapNotNullUnchecked(&mOriginUsages[entry.Data()]);
        }

        entry.Insert(mOriginUsages.Length());

        OriginUsageMetadata metadata;
        metadata.mOrigin = aOrigin;
        metadata.mPersistenceType = PERSISTENCE_TYPE_DEFAULT;
        metadata.mPersisted = false;
        metadata.mLastAccessTime = 0;
        metadata.mUsage = 0;

        return mOriginUsages.EmplaceBack(std::move(metadata));
      });

  if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) {
    originUsage->mPersisted = aPersisted;
  }

  originUsage->mUsage = originUsage->mUsage + aUsage;

  originUsage->mLastAccessTime =
      std::max<int64_t>(originUsage->mLastAccessTime, aTimestamp);
}

const Atomic<bool>& GetUsageOp::GetIsCanceledFlag() {
  AssertIsOnIOThread();

  return Canceled();
}

// XXX Remove aPersistent
// XXX Remove aPersistenceType once GetUsageForOrigin uses the persistence
// type from OriginMetadata
nsresult GetUsageOp::ProcessOrigin(QuotaManager& aQuotaManager,
                                   nsIFile& aOriginDir, const bool aPersistent,
                                   const PersistenceType aPersistenceType) {
  AssertIsOnIOThread();

  QM_TRY_UNWRAP(auto maybeMetadata,
                QM_OR_ELSE_WARN_IF(
                    // Expression
                    aQuotaManager.LoadFullOriginMetadataWithRestore(&aOriginDir)
                        .map([](auto metadata) -> Maybe<FullOriginMetadata> {
                          return Some(std::move(metadata));
                        }),
                    // Predicate.
                    IsSpecificError<NS_ERROR_MALFORMED_URI>,
                    // Fallback.
                    ErrToDefaultOk<Maybe<FullOriginMetadata>>));

  if (!maybeMetadata) {
    // Unknown directories during getting usage are allowed. Just warn if we
    // find them.
    QM_TRY_INSPECT(const auto& leafName,
                   MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoString, aOriginDir,
                                                     GetLeafName));

    UNKNOWN_FILE_WARNING(leafName);
    return NS_OK;
  }

  auto metadata = maybeMetadata.extract();

  QM_TRY_INSPECT(const auto& usageInfo,
                 GetUsageForOrigin(aQuotaManager, aPersistenceType, metadata));

  ProcessOriginInternal(&aQuotaManager, aPersistenceType, metadata.mOrigin,
                        metadata.mLastAccessTime, metadata.mPersisted,
                        usageInfo.TotalUsage().valueOr(0));

  return NS_OK;
}

RefPtr<BoolPromise> GetUsageOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
                              OriginScope::FromNull(), Nullable<Client::Type>(),
                              /* aExclusive */ false);
}

nsresult GetUsageOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();
  aQuotaManager.AssertStorageIsInitializedInternal();

  AUTO_PROFILER_LABEL("GetUsageOp::DoDirectoryWork", OTHER);

  nsresult rv;

  for (const PersistenceType type : kAllPersistenceTypes) {
    rv = TraverseRepository(aQuotaManager, type);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  // TraverseRepository above only consulted the filesystem. We also need to
  // consider origins which may have pending quota usage, such as buffered
  // LocalStorage writes for an origin which didn't previously have any
  // LocalStorage data.

  aQuotaManager.CollectPendingOriginsForListing(
      [this, &aQuotaManager](const auto& originInfo) {
        ProcessOriginInternal(
            &aQuotaManager, originInfo->GetGroupInfo()->GetPersistenceType(),
            originInfo->Origin(), originInfo->LockedAccessTime(),
            originInfo->LockedPersisted(), originInfo->LockedUsage());
      });

  return NS_OK;
}

OriginUsageMetadataArray GetUsageOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return std::move(mOriginUsages);
}

void GetUsageOp::CloseDirectory() {
  AssertIsOnOwningThread();

  SafeDropDirectoryLock(mDirectoryLock);
}

GetOriginUsageOp::GetOriginUsageOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const PrincipalInfo& aPrincipalInfo)
    : OpenStorageDirectoryHelper(std::move(aQuotaManager),
                                 "dom::quota::GetOriginUsageOp"),
      mPrincipalInfo(aPrincipalInfo) {
  AssertIsOnOwningThread();
}

nsresult GetOriginUsageOp::DoInit(QuotaManager& aQuotaManager) {
  AssertIsOnOwningThread();

  QM_TRY_UNWRAP(mPrincipalMetadata, GetInfoFromValidatedPrincipalInfo(
                                        aQuotaManager, mPrincipalInfo));

  mPrincipalMetadata.AssertInvariants();

  return NS_OK;
}

RefPtr<BoolPromise> GetOriginUsageOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return OpenStorageDirectory(PersistenceScope::CreateFromNull(),
                              OriginScope::FromOrigin(mPrincipalMetadata),
                              Nullable<Client::Type>(),
                              /* aExclusive */ false);
}

const Atomic<bool>& GetOriginUsageOp::GetIsCanceledFlag() {
  AssertIsOnIOThread();

  return Canceled();
}

nsresult GetOriginUsageOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();
  aQuotaManager.AssertStorageIsInitializedInternal();
  MOZ_ASSERT(mUsageInfo.TotalUsage().isNothing());

  AUTO_PROFILER_LABEL("GetOriginUsageOp::DoDirectoryWork", OTHER);

  // Add all the persistent/temporary/default/private storage files we care
  // about.
  for (const PersistenceType type : kAllPersistenceTypes) {
    const OriginMetadata originMetadata = {mPrincipalMetadata, type};

    auto usageInfoOrErr =
        GetUsageForOrigin(aQuotaManager, type, originMetadata);
    if (NS_WARN_IF(usageInfoOrErr.isErr())) {
      return usageInfoOrErr.unwrapErr();
    }

    mUsageInfo += usageInfoOrErr.unwrap();
  }

  return NS_OK;
}

UsageInfo GetOriginUsageOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mUsageInfo;
}

void GetOriginUsageOp::CloseDirectory() {
  AssertIsOnOwningThread();

  SafeDropDirectoryLock(mDirectoryLock);
}

StorageNameOp::StorageNameOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager)
    : QuotaRequestBase(std::move(aQuotaManager), "dom::quota::StorageNameOp") {
  AssertIsOnOwningThread();
}

RefPtr<BoolPromise> StorageNameOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return BoolPromise::CreateAndResolve(true, __func__);
}

nsresult StorageNameOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("StorageNameOp::DoDirectoryWork", OTHER);

  mName = aQuotaManager.GetStorageName();

  return NS_OK;
}

void StorageNameOp::GetResponse(RequestResponse& aResponse) {
  AssertIsOnOwningThread();

  StorageNameResponse storageNameResponse;

  storageNameResponse.name() = mName;

  aResponse = storageNameResponse;
}

void StorageNameOp::CloseDirectory() { AssertIsOnOwningThread(); }

InitializedRequestBase::InitializedRequestBase(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager, const char* aName)
    : ResolvableNormalOriginOp(std::move(aQuotaManager), aName),
      mInitialized(false) {
  AssertIsOnOwningThread();
}

RefPtr<BoolPromise> InitializedRequestBase::OpenDirectory() {
  AssertIsOnOwningThread();

  return BoolPromise::CreateAndResolve(true, __func__);
}

void InitializedRequestBase::CloseDirectory() { AssertIsOnOwningThread(); }

nsresult StorageInitializedOp::DoDirectoryWork(QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("StorageInitializedOp::DoDirectoryWork", OTHER);

  mInitialized = aQuotaManager.IsStorageInitializedInternal();

  return NS_OK;
}

bool StorageInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

nsresult PersistentStorageInitializedOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("PersistentStorageInitializedOp::DoDirectoryWork", OTHER);

  mInitialized = aQuotaManager.IsPersistentStorageInitializedInternal();

  return NS_OK;
}

bool PersistentStorageInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

nsresult TemporaryStorageInitializedOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("TemporaryStorageInitializedOp::DoDirectoryWork", OTHER);

  mInitialized = aQuotaManager.IsTemporaryStorageInitializedInternal();

  return NS_OK;
}

bool TemporaryStorageInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

TemporaryGroupInitializedOp::TemporaryGroupInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const PrincipalMetadata& aPrincipalMetadata)
    : ResolvableNormalOriginOp(std::move(aQuotaManager),
                               "dom::quota::TemporaryGroupInitializedOp"),
      mPrincipalMetadata(aPrincipalMetadata),
      mInitialized(false) {
  AssertIsOnOwningThread();
}

RefPtr<BoolPromise> TemporaryGroupInitializedOp::OpenDirectory() {
  AssertIsOnOwningThread();

  return BoolPromise::CreateAndResolve(true, __func__);
}

nsresult TemporaryGroupInitializedOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("TemporaryGroupInitializedOp::DoDirectoryWork", OTHER);

  mInitialized =
      aQuotaManager.IsTemporaryGroupInitializedInternal(mPrincipalMetadata);

  return NS_OK;
}

bool TemporaryGroupInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

void TemporaryGroupInitializedOp::CloseDirectory() { AssertIsOnOwningThread(); }

InitializedOriginRequestBase::InitializedOriginRequestBase(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager, const char* aName,
    const PrincipalMetadata& aPrincipalMetadata)
    : ResolvableNormalOriginOp(std::move(aQuotaManager), aName),
      mPrincipalMetadata(aPrincipalMetadata),
      mInitialized(false) {
  AssertIsOnOwningThread();
}

RefPtr<BoolPromise> InitializedOriginRequestBase::OpenDirectory() {
  AssertIsOnOwningThread();

  return BoolPromise::CreateAndResolve(true, __func__);
}

void InitializedOriginRequestBase::CloseDirectory() {
  AssertIsOnOwningThread();
}

PersistentOriginInitializedOp::PersistentOriginInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata)
    : InitializedOriginRequestBase(std::move(aQuotaManager),
                                   "dom::quota::PersistentOriginInitializedOp",
                                   aOriginMetadata) {
  AssertIsOnOwningThread();
  MOZ_ASSERT(aOriginMetadata.mPersistenceType == PERSISTENCE_TYPE_PERSISTENT);
}

nsresult PersistentOriginInitializedOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("PersistentOriginInitializedOp::DoDirectoryWork", OTHER);

  mInitialized = aQuotaManager.IsPersistentOriginInitializedInternal(
      OriginMetadata{mPrincipalMetadata, PERSISTENCE_TYPE_PERSISTENT});

  return NS_OK;
}

bool PersistentOriginInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

TemporaryOriginInitializedOp::TemporaryOriginInitializedOp(
    MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
    const OriginMetadata& aOriginMetadata)
    : InitializedOriginRequestBase(std::move(aQuotaManager),
                                   "dom::quota::TemporaryOriginInitializedOp",
                                   aOriginMetadata),
      mPersistenceType(aOriginMetadata.mPersistenceType) {
  AssertIsOnOwningThread();
  MOZ_ASSERT(aOriginMetadata.mPersistenceType != PERSISTENCE_TYPE_PERSISTENT);
}

nsresult TemporaryOriginInitializedOp::DoDirectoryWork(
    QuotaManager& aQuotaManager) {
  AssertIsOnIOThread();

  AUTO_PROFILER_LABEL("TemporaryOriginInitializedOp::DoDirectoryWork", OTHER);

  mInitialized = aQuotaManager.IsTemporaryOriginInitializedInternal(
      OriginMetadata{mPrincipalMetadata, mPersistenceType});

  return NS_OK;
}

bool TemporaryOriginInitializedOp::UnwrapResolveValue() {
  AssertIsOnOwningThread();

  return mInitialized;
}

InitOp::InitOp(MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
               RefPtr<UniversalDirectoryLock> aDirectoryLock)
    : ResolvableNormalOriginOp(std::move(aQuotaManager), "dom::quota::InitOp"),
      mDirectoryLock(std::move(aDirectoryLock)) {
  AssertIsOnOwningThread();
  MOZ_ASSERT(mDirectoryLock);
}

RefPtr<BoolPromise> InitOp::OpenDirectory() {
  AssertIsOnOwningThread();
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.19 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.