tor-browser

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

TestQuotaManager.cpp (145216B)


      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 #include "QuotaManagerDependencyFixture.h"
      8 #include "QuotaManagerTestHelpers.h"
      9 #include "gtest/gtest.h"
     10 #include "mozilla/BasePrincipal.h"
     11 #include "mozilla/dom/quota/ClientDirectoryLock.h"
     12 #include "mozilla/dom/quota/ClientDirectoryLockHandle.h"
     13 #include "mozilla/dom/quota/DirectoryLock.h"
     14 #include "mozilla/dom/quota/DirectoryLockInlines.h"
     15 #include "mozilla/dom/quota/OriginScope.h"
     16 #include "mozilla/dom/quota/PersistenceScope.h"
     17 #include "mozilla/dom/quota/QuotaManager.h"
     18 #include "mozilla/dom/quota/ResultExtensions.h"
     19 #include "mozilla/dom/quota/UniversalDirectoryLock.h"
     20 #include "mozilla/gtest/MozAssertions.h"
     21 #include "mozilla/ipc/PBackgroundSharedTypes.h"
     22 #include "nsFmtString.h"
     23 #include "prtime.h"
     24 
     25 namespace mozilla::dom::quota::test {
     26 
     27 class TestQuotaManager : public QuotaManagerDependencyFixture {
     28 public:
     29  static void SetUpTestCase() { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
     30 
     31  static void TearDownTestCase() { ASSERT_NO_FATAL_FAILURE(ShutdownFixture()); }
     32 
     33  void TearDown() override {
     34    ASSERT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetTestOriginMetadata()));
     35  }
     36 };
     37 
     38 class TestQuotaManagerAndClearStorage : public TestQuotaManager {
     39 public:
     40  void TearDown() override { ASSERT_NO_FATAL_FAILURE(ClearStorage()); }
     41 };
     42 
     43 using BoolPairTestParams = std::pair<bool, bool>;
     44 
     45 class TestQuotaManagerAndClearStorageWithBoolPair
     46    : public TestQuotaManagerAndClearStorage,
     47      public testing::WithParamInterface<BoolPairTestParams> {};
     48 
     49 class TestQuotaManagerAndShutdownFixture
     50    : public QuotaManagerDependencyFixture {
     51 public:
     52  void SetUp() override { ASSERT_NO_FATAL_FAILURE(InitializeFixture()); }
     53 
     54  void TearDown() override { ASSERT_NO_FATAL_FAILURE(ShutdownFixture()); }
     55 };
     56 
     57 TEST_F(TestQuotaManager, GetThumbnailPrivateIdentityId) {
     58  PerformOnIOThread([]() {
     59    QuotaManager* quotaManager = QuotaManager::Get();
     60    ASSERT_TRUE(quotaManager);
     61 
     62    const bool known = quotaManager->IsThumbnailPrivateIdentityIdKnown();
     63    ASSERT_TRUE(known);
     64 
     65    const uint32_t id = quotaManager->GetThumbnailPrivateIdentityId();
     66    ASSERT_GT(id, 4u);
     67  });
     68 }
     69 
     70 // Test OpenStorageDirectory when an opening of the storage directory is
     71 // already ongoing and storage shutdown is scheduled after that.
     72 TEST_F(TestQuotaManager, OpenStorageDirectory_OngoingWithScheduledShutdown) {
     73  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
     74 
     75  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
     76 
     77  PerformOnBackgroundThread([]() {
     78    QuotaManager* quotaManager = QuotaManager::Get();
     79    ASSERT_TRUE(quotaManager);
     80 
     81    RefPtr<UniversalDirectoryLock> directoryLock;
     82 
     83    nsTArray<RefPtr<BoolPromise>> promises;
     84 
     85    promises.AppendElement(
     86        quotaManager
     87            ->OpenStorageDirectory(
     88                PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
     89                OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
     90                /* aExclusive */ false)
     91            ->Then(GetCurrentSerialEventTarget(), __func__,
     92                   [&directoryLock](
     93                       UniversalDirectoryLockPromise::ResolveOrRejectValue&&
     94                           aValue) {
     95                     if (aValue.IsReject()) {
     96                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
     97                                                           __func__);
     98                     }
     99 
    100                     [&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
    101 
    102                     directoryLock = std::move(aValue.ResolveValue());
    103 
    104                     return BoolPromise::CreateAndResolve(true, __func__);
    105                   })
    106            ->Then(quotaManager->IOThread(), __func__,
    107                   [](const BoolPromise::ResolveOrRejectValue& aValue) {
    108                     if (aValue.IsReject()) {
    109                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    110                                                           __func__);
    111                     }
    112 
    113                     []() {
    114                       QuotaManager* quotaManager = QuotaManager::Get();
    115                       ASSERT_TRUE(quotaManager);
    116 
    117                       ASSERT_TRUE(
    118                           quotaManager->IsStorageInitializedInternal());
    119                     }();
    120 
    121                     return BoolPromise::CreateAndResolve(true, __func__);
    122                   })
    123            ->Then(GetCurrentSerialEventTarget(), __func__,
    124                   [&directoryLock](
    125                       const BoolPromise::ResolveOrRejectValue& aValue) {
    126                     DropDirectoryLock(directoryLock);
    127 
    128                     if (aValue.IsReject()) {
    129                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    130                                                           __func__);
    131                     }
    132 
    133                     return BoolPromise::CreateAndResolve(true, __func__);
    134                   }));
    135    promises.AppendElement(quotaManager->ShutdownStorage());
    136    promises.AppendElement(
    137        quotaManager
    138            ->OpenStorageDirectory(
    139                PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    140                OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    141                /* aExclusive */ false)
    142            ->Then(GetCurrentSerialEventTarget(), __func__,
    143                   [](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
    144                          aValue) {
    145                     if (aValue.IsReject()) {
    146                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    147                                                           __func__);
    148                     }
    149 
    150                     RefPtr<UniversalDirectoryLock> directoryLock =
    151                         std::move(aValue.ResolveValue());
    152                     DropDirectoryLock(directoryLock);
    153 
    154                     return BoolPromise::CreateAndResolve(true, __func__);
    155                   }));
    156 
    157    {
    158      auto value =
    159          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
    160      ASSERT_TRUE(value.IsResolve());
    161 
    162      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    163    }
    164  });
    165 
    166  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    167 
    168  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    169 }
    170 
    171 // Test OpenStorageDirectory when an opening of the storage directory is
    172 // already ongoing and an exclusive directory lock is requested after that.
    173 TEST_F(TestQuotaManager,
    174       OpenStorageDirectory_OngoingWithExclusiveDirectoryLock) {
    175  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    176 
    177  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    178 
    179  PerformOnBackgroundThread([]() {
    180    QuotaManager* quotaManager = QuotaManager::Get();
    181    ASSERT_TRUE(quotaManager);
    182 
    183    RefPtr<UniversalDirectoryLock> directoryLock =
    184        quotaManager->CreateDirectoryLockInternal(
    185            PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
    186            ClientStorageScope::CreateFromNull(),
    187            /* aExclusive */ true);
    188 
    189    nsTArray<RefPtr<BoolPromise>> promises;
    190 
    191    promises.AppendElement(
    192        quotaManager
    193            ->OpenStorageDirectory(
    194                PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    195                OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    196                /* aExclusive */ false)
    197            ->Then(GetCurrentSerialEventTarget(), __func__,
    198                   [&directoryLock](
    199                       UniversalDirectoryLockPromise::ResolveOrRejectValue&&
    200                           aValue) {
    201                     DropDirectoryLock(directoryLock);
    202 
    203                     if (aValue.IsReject()) {
    204                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    205                                                           __func__);
    206                     }
    207 
    208                     RefPtr<UniversalDirectoryLock> directoryLock =
    209                         std::move(aValue.ResolveValue());
    210                     DropDirectoryLock(directoryLock);
    211 
    212                     return BoolPromise::CreateAndResolve(true, __func__);
    213                   }));
    214    promises.AppendElement(directoryLock->Acquire());
    215    promises.AppendElement(
    216        quotaManager
    217            ->OpenStorageDirectory(
    218                PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    219                OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    220                /* aExclusive */ false)
    221            ->Then(GetCurrentSerialEventTarget(), __func__,
    222                   [](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
    223                          aValue) {
    224                     if (aValue.IsReject()) {
    225                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    226                                                           __func__);
    227                     }
    228 
    229                     RefPtr<UniversalDirectoryLock> directoryLock =
    230                         std::move(aValue.ResolveValue());
    231                     DropDirectoryLock(directoryLock);
    232 
    233                     return BoolPromise::CreateAndResolve(true, __func__);
    234                   }));
    235 
    236    {
    237      auto value =
    238          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
    239      ASSERT_TRUE(value.IsResolve());
    240 
    241      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    242    }
    243  });
    244 
    245  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    246 
    247  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    248 }
    249 
    250 // Test OpenStorageDirectory when an opening of the storage directory already
    251 // finished.
    252 TEST_F(TestQuotaManager, OpenStorageDirectory_Finished) {
    253  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    254 
    255  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    256 
    257  PerformOnBackgroundThread([]() {
    258    QuotaManager* quotaManager = QuotaManager::Get();
    259    ASSERT_TRUE(quotaManager);
    260 
    261    {
    262      auto value = Await(quotaManager->OpenStorageDirectory(
    263          PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    264          OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    265          /* aExclusive */ false));
    266      ASSERT_TRUE(value.IsResolve());
    267 
    268      RefPtr<UniversalDirectoryLock> directoryLock =
    269          std::move(value.ResolveValue());
    270      DropDirectoryLock(directoryLock);
    271 
    272      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    273    }
    274 
    275    {
    276      auto value = Await(quotaManager->OpenStorageDirectory(
    277          PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    278          OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    279          /* aExclusive */ false));
    280      ASSERT_TRUE(value.IsResolve());
    281 
    282      RefPtr<UniversalDirectoryLock> directoryLock =
    283          std::move(value.ResolveValue());
    284      DropDirectoryLock(directoryLock);
    285 
    286      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    287    }
    288  });
    289 
    290  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    291 
    292  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    293 }
    294 
    295 // Test OpenStorageDirectory when an opening of the storage directory already
    296 // finished but storage shutdown has just been scheduled.
    297 TEST_F(TestQuotaManager, OpenStorageDirectory_FinishedWithScheduledShutdown) {
    298  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    299 
    300  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    301 
    302  PerformOnBackgroundThread([]() {
    303    QuotaManager* quotaManager = QuotaManager::Get();
    304    ASSERT_TRUE(quotaManager);
    305 
    306    {
    307      auto value = Await(quotaManager->OpenStorageDirectory(
    308          PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    309          OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    310          /* aExclusive */ false));
    311      ASSERT_TRUE(value.IsResolve());
    312 
    313      RefPtr<UniversalDirectoryLock> directoryLock =
    314          std::move(value.ResolveValue());
    315      DropDirectoryLock(directoryLock);
    316 
    317      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    318    }
    319 
    320    nsTArray<RefPtr<BoolPromise>> promises;
    321 
    322    promises.AppendElement(quotaManager->ShutdownStorage());
    323    promises.AppendElement(
    324        quotaManager
    325            ->OpenStorageDirectory(
    326                PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    327                OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    328                /* aExclusive */ false)
    329            ->Then(GetCurrentSerialEventTarget(), __func__,
    330                   [](UniversalDirectoryLockPromise::ResolveOrRejectValue&&
    331                          aValue) {
    332                     if (aValue.IsReject()) {
    333                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    334                                                           __func__);
    335                     }
    336 
    337                     RefPtr<UniversalDirectoryLock> directoryLock =
    338                         std::move(aValue.ResolveValue());
    339                     DropDirectoryLock(directoryLock);
    340 
    341                     return BoolPromise::CreateAndResolve(true, __func__);
    342                   }));
    343 
    344    {
    345      auto value =
    346          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
    347      ASSERT_TRUE(value.IsResolve());
    348 
    349      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    350    }
    351  });
    352 
    353  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    354 
    355  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    356 }
    357 
    358 // Test OpenStorageDirectory when an opening of the storage directory already
    359 // finished and an exclusive client directory lock for a non-overlapping
    360 // origin is acquired in between.
    361 TEST_F(TestQuotaManager,
    362       OpenStorageDirectory_FinishedWithExclusiveClientDirectoryLock) {
    363  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    364 
    365  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    366 
    367  PerformOnBackgroundThread([]() {
    368    QuotaManager* quotaManager = QuotaManager::Get();
    369    ASSERT_TRUE(quotaManager);
    370 
    371    {
    372      auto value = Await(quotaManager->OpenStorageDirectory(
    373          PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    374          OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    375          /* aExclusive */ false));
    376      ASSERT_TRUE(value.IsResolve());
    377 
    378      RefPtr<UniversalDirectoryLock> directoryLock =
    379          std::move(value.ResolveValue());
    380      DropDirectoryLock(directoryLock);
    381 
    382      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    383    }
    384 
    385    RefPtr<ClientDirectoryLock> directoryLock =
    386        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
    387                                          /* aExclusive */ true);
    388 
    389    {
    390      auto value = Await(directoryLock->Acquire());
    391      ASSERT_TRUE(value.IsResolve());
    392    }
    393 
    394    {
    395      auto value = Await(quotaManager->OpenStorageDirectory(
    396          PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
    397          OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
    398          /* aExclusive */ false));
    399      ASSERT_TRUE(value.IsResolve());
    400 
    401      RefPtr<UniversalDirectoryLock> directoryLock =
    402          std::move(value.ResolveValue());
    403      DropDirectoryLock(directoryLock);
    404 
    405      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    406    }
    407 
    408    DropDirectoryLock(directoryLock);
    409  });
    410 
    411  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    412 
    413  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    414 }
    415 
    416 // Test simple OpenClientDirectory behavior and verify that origin access time
    417 // updates are triggered as expected.
    418 TEST_F(TestQuotaManager, OpenClientDirectory_Simple) {
    419  auto testOriginMetadata = GetTestOriginMetadata();
    420 
    421  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    422 
    423  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    424 
    425  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
    426  const auto saveOriginAccessTimeCountInternalBefore =
    427      SaveOriginAccessTimeCountInternal();
    428 
    429  // Can't check origin state metadata since storage is not yet initialized.
    430 
    431  auto directoryMetadataHeaderBefore =
    432      LoadDirectoryMetadataHeader(testOriginMetadata);
    433  ASSERT_FALSE(directoryMetadataHeaderBefore);
    434 
    435  PerformOnBackgroundThread([]() {
    436    QuotaManager* quotaManager = QuotaManager::Get();
    437    ASSERT_TRUE(quotaManager);
    438 
    439    {
    440      auto value =
    441          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
    442      ASSERT_TRUE(value.IsResolve());
    443 
    444      ClientDirectoryLockHandle directoryLockHandle =
    445          std::move(value.ResolveValue());
    446 
    447      {
    448        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    449      }
    450 
    451      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    452    }
    453  });
    454 
    455  ProcessPendingNormalOriginOperations();
    456 
    457  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
    458  const auto saveOriginAccessTimeCountInternalAfter =
    459      SaveOriginAccessTimeCountInternal();
    460 
    461  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
    462            2u);
    463  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
    464                saveOriginAccessTimeCountInternalBefore,
    465            2u);
    466 
    467  auto originStateMetadataAfter = GetOriginStateMetadata(testOriginMetadata);
    468  ASSERT_TRUE(originStateMetadataAfter);
    469  ASSERT_TRUE(originStateMetadataAfter->mAccessed);
    470 
    471  auto directoryMetadataHeaderAfter =
    472      LoadDirectoryMetadataHeader(testOriginMetadata);
    473  ASSERT_TRUE(directoryMetadataHeaderAfter);
    474  ASSERT_TRUE(directoryMetadataHeaderAfter->mAccessed);
    475 
    476  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    477 
    478  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    479 }
    480 
    481 // Test simple OpenClientDirectory behavior when the origin directory exists,
    482 // and verify that access time updates are triggered on first and last access.
    483 TEST_F(TestQuotaManager, OpenClientDirectory_Simple_OriginDirectoryExists) {
    484  auto testOriginMetadata = GetTestOriginMetadata();
    485 
    486  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    487 
    488  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    489 
    490  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
    491  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
    492  ASSERT_NO_FATAL_FAILURE(
    493      InitializeTemporaryOrigin(GetTestOriginMetadata(),
    494                                /* aCreateIfNonExistent */ true));
    495 
    496  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
    497  const auto saveOriginAccessTimeCountInternalBefore =
    498      SaveOriginAccessTimeCountInternal();
    499 
    500  auto originStateMetadataBefore = GetOriginStateMetadata(testOriginMetadata);
    501  ASSERT_TRUE(originStateMetadataBefore);
    502  ASSERT_FALSE(originStateMetadataBefore->mAccessed);
    503 
    504  auto directoryMetadataHeaderBefore =
    505      LoadDirectoryMetadataHeader(testOriginMetadata);
    506  ASSERT_TRUE(directoryMetadataHeaderBefore);
    507  ASSERT_FALSE(directoryMetadataHeaderBefore->mAccessed);
    508 
    509  PerformOnBackgroundThread([]() {
    510    QuotaManager* quotaManager = QuotaManager::Get();
    511    ASSERT_TRUE(quotaManager);
    512 
    513    {
    514      auto value =
    515          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
    516      ASSERT_TRUE(value.IsResolve());
    517 
    518      ClientDirectoryLockHandle directoryLockHandle =
    519          std::move(value.ResolveValue());
    520 
    521      {
    522        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    523      }
    524 
    525      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    526    }
    527  });
    528 
    529  ProcessPendingNormalOriginOperations();
    530 
    531  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
    532  const auto saveOriginAccessTimeCountInternalAfter =
    533      SaveOriginAccessTimeCountInternal();
    534 
    535  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
    536            2u);
    537  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
    538                saveOriginAccessTimeCountInternalBefore,
    539            2u);
    540 
    541  auto originStateMetadataAfter = GetOriginStateMetadata(testOriginMetadata);
    542  ASSERT_TRUE(originStateMetadataAfter);
    543  ASSERT_TRUE(originStateMetadataAfter->mAccessed);
    544 
    545  auto directoryMetadataHeaderAfter =
    546      LoadDirectoryMetadataHeader(testOriginMetadata);
    547  ASSERT_TRUE(directoryMetadataHeaderAfter);
    548  ASSERT_TRUE(directoryMetadataHeaderAfter->mAccessed);
    549 
    550  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    551 
    552  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    553 }
    554 
    555 // Test OpenClientDirectory when the origin directory doesn't exist, and verify
    556 // that no access time update occurs. The directory should not be created
    557 // solely for updating access time.
    558 TEST_F(TestQuotaManager,
    559       OpenClientDirectory_Simple_NonExistingOriginDirectory) {
    560  auto testOriginMetadata = GetTestOriginMetadata();
    561 
    562  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    563 
    564  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    565 
    566  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
    567  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
    568  ASSERT_NO_FATAL_FAILURE(
    569      InitializeTemporaryOrigin(GetTestOriginMetadata(),
    570                                /* aCreateIfNonExistent */ false));
    571 
    572  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
    573  const auto saveOriginAccessTimeCountInternalBefore =
    574      SaveOriginAccessTimeCountInternal();
    575 
    576  auto originStateMetadataBefore = GetOriginStateMetadata(testOriginMetadata);
    577  ASSERT_TRUE(originStateMetadataBefore);
    578  ASSERT_FALSE(originStateMetadataBefore->mAccessed);
    579 
    580  auto directoryMetadataHeaderBefore =
    581      LoadDirectoryMetadataHeader(testOriginMetadata);
    582  ASSERT_FALSE(directoryMetadataHeaderBefore);
    583 
    584  PerformOnBackgroundThread([]() {
    585    QuotaManager* quotaManager = QuotaManager::Get();
    586    ASSERT_TRUE(quotaManager);
    587 
    588    {
    589      auto value = Await(quotaManager->OpenClientDirectory(
    590          GetTestClientMetadata(),
    591          /* aInitializeOrigin */ true, /* aCreateIfNonExistent */ false));
    592      ASSERT_TRUE(value.IsResolve());
    593 
    594      ClientDirectoryLockHandle directoryLockHandle =
    595          std::move(value.ResolveValue());
    596 
    597      {
    598        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    599      }
    600 
    601      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    602    }
    603  });
    604 
    605  ProcessPendingNormalOriginOperations();
    606 
    607  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
    608  const auto saveOriginAccessTimeCountInternalAfter =
    609      SaveOriginAccessTimeCountInternal();
    610 
    611  // This is expected to be 0, the origin directory should not be created
    612  // solely to update access time when, for example, LSNG explicitly requests
    613  // that it not be created if it doesn't exist. The access time will be saved
    614  // later.
    615  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
    616            0u);
    617  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
    618                saveOriginAccessTimeCountInternalBefore,
    619            0u);
    620 
    621  auto originStateMetadataAfter = GetOriginStateMetadata(testOriginMetadata);
    622  ASSERT_TRUE(originStateMetadataAfter);
    623  ASSERT_TRUE(originStateMetadataAfter->mAccessed);
    624 
    625  auto directoryMetadataHeaderAfter =
    626      LoadDirectoryMetadataHeader(testOriginMetadata);
    627  ASSERT_FALSE(directoryMetadataHeaderAfter);
    628 
    629  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    630 
    631  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    632 }
    633 
    634 // Test OpenClientDirectory when a clear operation is scheduled before
    635 // releasing the directory lock. Verifies that access time updates still occur,
    636 // even with the scheduled clear operation.
    637 TEST_F(TestQuotaManager,
    638       OpenClientDirectory_SimpleWithScheduledClearing_OriginDirectoryExists) {
    639  auto testOriginMetadata = GetTestOriginMetadata();
    640 
    641  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    642 
    643  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    644 
    645  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
    646  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
    647  ASSERT_NO_FATAL_FAILURE(
    648      InitializeTemporaryOrigin(testOriginMetadata,
    649                                /* aCreateIfNonExistent */ true));
    650 
    651  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
    652  const auto saveOriginAccessTimeCountInternalBefore =
    653      SaveOriginAccessTimeCountInternal();
    654 
    655  auto originStateMetadataBefore = GetOriginStateMetadata(testOriginMetadata);
    656  ASSERT_TRUE(originStateMetadataBefore);
    657  ASSERT_FALSE(originStateMetadataBefore->mAccessed);
    658 
    659  auto directoryMetadataHeaderBefore =
    660      LoadDirectoryMetadataHeader(testOriginMetadata);
    661  ASSERT_TRUE(directoryMetadataHeaderBefore);
    662  ASSERT_FALSE(directoryMetadataHeaderBefore->mAccessed);
    663 
    664  PerformOnBackgroundThread([testOriginMetadata]() {
    665    QuotaManager* quotaManager = QuotaManager::Get();
    666    ASSERT_TRUE(quotaManager);
    667 
    668    {
    669      auto value =
    670          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
    671      ASSERT_TRUE(value.IsResolve());
    672 
    673      ClientDirectoryLockHandle directoryLockHandle =
    674          std::move(value.ResolveValue());
    675 
    676      nsCOMPtr<nsIPrincipal> principal =
    677          BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
    678      QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
    679 
    680      mozilla::ipc::PrincipalInfo principalInfo;
    681      QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
    682             QM_TEST_FAIL);
    683 
    684      // This can't be awaited here, it would cause a hang, on the other hand,
    685      // it must be scheduled before the handle is moved below.
    686      quotaManager->ClearStoragesForOrigin(
    687          /* aPersistenceType */ Nothing(), principalInfo);
    688 
    689      {
    690        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    691      }
    692 
    693      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    694    }
    695  });
    696 
    697  ProcessPendingNormalOriginOperations();
    698 
    699  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
    700  const auto saveOriginAccessTimeCountInternalAfter =
    701      SaveOriginAccessTimeCountInternal();
    702 
    703  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
    704            2u);
    705  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
    706                saveOriginAccessTimeCountInternalBefore,
    707            2u);
    708 
    709  auto originStateMetadataAfter = GetOriginStateMetadata(testOriginMetadata);
    710  ASSERT_FALSE(originStateMetadataAfter);
    711 
    712  auto directoryMetadataHeaderAfter =
    713      LoadDirectoryMetadataHeader(testOriginMetadata);
    714  ASSERT_FALSE(directoryMetadataHeaderAfter);
    715 
    716  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    717 
    718  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    719 }
    720 
    721 // Test OpenClientDirectory when a client directory opening is already ongoing
    722 // and the origin directory exists. Verifies that each opening completes only
    723 // after the origin access time update triggered by first access has finished,
    724 // and that access time is updated only on first and last access as expected.
    725 TEST_F(TestQuotaManager, OpenClientDirectory_Ongoing_OriginDirectoryExists) {
    726  auto testOriginMetadata = GetTestOriginMetadata();
    727 
    728  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    729 
    730  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    731 
    732  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
    733  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
    734  ASSERT_NO_FATAL_FAILURE(
    735      InitializeTemporaryOrigin(GetTestOriginMetadata(),
    736                                /* aCreateIfNonExistent */ true));
    737 
    738  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
    739  const auto saveOriginAccessTimeCountInternalBefore =
    740      SaveOriginAccessTimeCountInternal();
    741 
    742  auto originStateMetadataBefore = GetOriginStateMetadata(testOriginMetadata);
    743  ASSERT_TRUE(originStateMetadataBefore);
    744  ASSERT_FALSE(originStateMetadataBefore->mAccessed);
    745 
    746  auto directoryMetadataHeaderBefore =
    747      LoadDirectoryMetadataHeader(testOriginMetadata);
    748  ASSERT_TRUE(directoryMetadataHeaderBefore);
    749  ASSERT_FALSE(directoryMetadataHeaderBefore->mAccessed);
    750 
    751  PerformOnBackgroundThread([saveOriginAccessTimeCountBefore,
    752                             saveOriginAccessTimeCountInternalBefore]() {
    753    auto testClientMetadata = GetTestClientMetadata();
    754 
    755    QuotaManager* quotaManager = QuotaManager::Get();
    756    ASSERT_TRUE(quotaManager);
    757 
    758    ClientDirectoryLockHandle directoryLockHandle;
    759    ClientDirectoryLockHandle directoryLockHandle2;
    760 
    761    nsTArray<RefPtr<BoolPromise>> promises;
    762 
    763    promises.AppendElement(
    764        quotaManager->OpenClientDirectory(testClientMetadata)
    765            ->Then(GetCurrentSerialEventTarget(), __func__,
    766                   [saveOriginAccessTimeCountBefore, &directoryLockHandle](
    767                       QuotaManager::ClientDirectoryLockHandlePromise::
    768                           ResolveOrRejectValue&& aValue) {
    769                     if (aValue.IsReject()) {
    770                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    771                                                           __func__);
    772                     }
    773 
    774                     QuotaManager* quotaManager = QuotaManager::Get();
    775                     MOZ_RELEASE_ASSERT(quotaManager);
    776 
    777                     const auto saveOriginAccessTimeCountNow =
    778                         quotaManager->SaveOriginAccessTimeCount();
    779 
    780                     EXPECT_EQ(saveOriginAccessTimeCountNow -
    781                                   saveOriginAccessTimeCountBefore,
    782                               1u);
    783 
    784                     directoryLockHandle = std::move(aValue.ResolveValue());
    785 
    786                     return BoolPromise::CreateAndResolve(true, __func__);
    787                   })
    788            ->Then(quotaManager->IOThread(), __func__,
    789                   [saveOriginAccessTimeCountInternalBefore](
    790                       const BoolPromise::ResolveOrRejectValue& aValue) {
    791                     if (aValue.IsReject()) {
    792                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    793                                                           __func__);
    794                     }
    795 
    796                     QuotaManager* quotaManager = QuotaManager::Get();
    797                     MOZ_RELEASE_ASSERT(quotaManager);
    798 
    799                     const auto saveOriginAccessTimeCountInternalNow =
    800                         quotaManager->SaveOriginAccessTimeCountInternal();
    801 
    802                     EXPECT_EQ(saveOriginAccessTimeCountInternalNow -
    803                                   saveOriginAccessTimeCountInternalBefore,
    804                               1u);
    805 
    806                     return BoolPromise::CreateAndResolve(true, __func__);
    807                   }));
    808    promises.AppendElement(
    809        quotaManager->OpenClientDirectory(testClientMetadata)
    810            ->Then(GetCurrentSerialEventTarget(), __func__,
    811                   [saveOriginAccessTimeCountBefore, &directoryLockHandle2](
    812                       QuotaManager::ClientDirectoryLockHandlePromise::
    813                           ResolveOrRejectValue&& aValue) {
    814                     if (aValue.IsReject()) {
    815                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    816                                                           __func__);
    817                     }
    818 
    819                     QuotaManager* quotaManager = QuotaManager::Get();
    820                     MOZ_RELEASE_ASSERT(quotaManager);
    821 
    822                     const auto saveOriginAccessTimeCountNow =
    823                         quotaManager->SaveOriginAccessTimeCount();
    824 
    825                     EXPECT_EQ(saveOriginAccessTimeCountNow -
    826                                   saveOriginAccessTimeCountBefore,
    827                               1u);
    828 
    829                     directoryLockHandle2 = std::move(aValue.ResolveValue());
    830 
    831                     return BoolPromise::CreateAndResolve(true, __func__);
    832                   })
    833            ->Then(quotaManager->IOThread(), __func__,
    834                   [saveOriginAccessTimeCountInternalBefore](
    835                       const BoolPromise::ResolveOrRejectValue& aValue) {
    836                     if (aValue.IsReject()) {
    837                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    838                                                           __func__);
    839                     }
    840 
    841                     QuotaManager* quotaManager = QuotaManager::Get();
    842                     MOZ_RELEASE_ASSERT(quotaManager);
    843 
    844                     const auto saveOriginAccessTimeCountInternalNow =
    845                         quotaManager->SaveOriginAccessTimeCountInternal();
    846 
    847                     EXPECT_EQ(saveOriginAccessTimeCountInternalNow -
    848                                   saveOriginAccessTimeCountInternalBefore,
    849                               1u);
    850 
    851                     return BoolPromise::CreateAndResolve(true, __func__);
    852                   }));
    853 
    854    {
    855      auto value =
    856          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
    857      ASSERT_TRUE(value.IsResolve());
    858 
    859      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    860    }
    861 
    862    {
    863      auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
    864    }
    865 
    866    {
    867      auto destroyingDirectoryLockHandle2 = std::move(directoryLockHandle2);
    868    }
    869  });
    870 
    871  ProcessPendingNormalOriginOperations();
    872 
    873  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
    874  const auto saveOriginAccessTimeCountInternalAfter =
    875      SaveOriginAccessTimeCountInternal();
    876 
    877  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
    878            2u);
    879  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
    880                saveOriginAccessTimeCountInternalBefore,
    881            2u);
    882 
    883  auto originStateMetadataAfter = GetOriginStateMetadata(testOriginMetadata);
    884  ASSERT_TRUE(originStateMetadataAfter);
    885  ASSERT_TRUE(originStateMetadataAfter->mAccessed);
    886 
    887  auto directoryMetadataHeaderAfter =
    888      LoadDirectoryMetadataHeader(testOriginMetadata);
    889  ASSERT_TRUE(directoryMetadataHeaderAfter);
    890  ASSERT_TRUE(directoryMetadataHeaderAfter->mAccessed);
    891 
    892  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    893 
    894  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    895 }
    896 
    897 // Test OpenClientDirctory when an opening of a client directory is already
    898 // ongoing and storage shutdown is scheduled after that.
    899 TEST_F(TestQuotaManager, OpenClientDirectory_OngoingWithScheduledShutdown) {
    900  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    901 
    902  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
    903 
    904  PerformOnBackgroundThread([]() {
    905    QuotaManager* quotaManager = QuotaManager::Get();
    906    ASSERT_TRUE(quotaManager);
    907 
    908    ClientDirectoryLockHandle directoryLockHandle;
    909 
    910    nsTArray<RefPtr<BoolPromise>> promises;
    911 
    912    promises.AppendElement(
    913        quotaManager->OpenClientDirectory(GetTestClientMetadata())
    914            ->Then(GetCurrentSerialEventTarget(), __func__,
    915                   [&directoryLockHandle](
    916                       QuotaManager::ClientDirectoryLockHandlePromise::
    917                           ResolveOrRejectValue&& aValue) {
    918                     if (aValue.IsReject()) {
    919                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    920                                                           __func__);
    921                     }
    922 
    923                     [&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
    924 
    925                     directoryLockHandle = std::move(aValue.ResolveValue());
    926 
    927                     return BoolPromise::CreateAndResolve(true, __func__);
    928                   })
    929            ->Then(quotaManager->IOThread(), __func__,
    930                   [](const BoolPromise::ResolveOrRejectValue& aValue) {
    931                     if (aValue.IsReject()) {
    932                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    933                                                           __func__);
    934                     }
    935 
    936                     []() {
    937                       QuotaManager* quotaManager = QuotaManager::Get();
    938                       ASSERT_TRUE(quotaManager);
    939 
    940                       ASSERT_TRUE(
    941                           quotaManager->IsStorageInitializedInternal());
    942                     }();
    943 
    944                     return BoolPromise::CreateAndResolve(true, __func__);
    945                   })
    946            ->Then(GetCurrentSerialEventTarget(), __func__,
    947                   [&directoryLockHandle](
    948                       const BoolPromise::ResolveOrRejectValue& aValue) {
    949                     {
    950                       auto destroyingDirectoryLockHandle =
    951                           std::move(directoryLockHandle);
    952                     }
    953 
    954                     if (aValue.IsReject()) {
    955                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    956                                                           __func__);
    957                     }
    958 
    959                     return BoolPromise::CreateAndResolve(true, __func__);
    960                   }));
    961    promises.AppendElement(quotaManager->ShutdownStorage());
    962    promises.AppendElement(
    963        quotaManager->OpenClientDirectory(GetTestClientMetadata())
    964            ->Then(GetCurrentSerialEventTarget(), __func__,
    965                   [](QuotaManager::ClientDirectoryLockHandlePromise::
    966                          ResolveOrRejectValue&& aValue) {
    967                     if (aValue.IsReject()) {
    968                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
    969                                                           __func__);
    970                     }
    971 
    972                     ClientDirectoryLockHandle directoryLockHandle =
    973                         std::move(aValue.ResolveValue());
    974 
    975                     {
    976                       auto destroyingDirectoryLockHandle =
    977                           std::move(directoryLockHandle);
    978                     }
    979 
    980                     return BoolPromise::CreateAndResolve(true, __func__);
    981                   }));
    982 
    983    {
    984      auto value =
    985          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
    986      ASSERT_TRUE(value.IsResolve());
    987 
    988      ASSERT_TRUE(quotaManager->IsStorageInitialized());
    989    }
    990  });
    991 
    992  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
    993 
    994  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
    995 }
    996 
    997 // Test OpenClientDirectory when an opening of a client directory is already
    998 // ongoing and an exclusive directory lock is requested after that.
    999 TEST_F(TestQuotaManager,
   1000       OpenClientDirectory_OngoingWithExclusiveDirectoryLock) {
   1001  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1002 
   1003  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1004 
   1005  PerformOnBackgroundThread([]() {
   1006    QuotaManager* quotaManager = QuotaManager::Get();
   1007    ASSERT_TRUE(quotaManager);
   1008 
   1009    RefPtr<UniversalDirectoryLock> directoryLock =
   1010        quotaManager->CreateDirectoryLockInternal(
   1011            PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
   1012            ClientStorageScope::CreateFromNull(),
   1013            /* aExclusive */ true);
   1014 
   1015    nsTArray<RefPtr<BoolPromise>> promises;
   1016 
   1017    promises.AppendElement(
   1018        quotaManager->OpenClientDirectory(GetTestClientMetadata())
   1019            ->Then(GetCurrentSerialEventTarget(), __func__,
   1020                   [&directoryLock](
   1021                       QuotaManager::ClientDirectoryLockHandlePromise::
   1022                           ResolveOrRejectValue&& aValue) {
   1023                     DropDirectoryLock(directoryLock);
   1024 
   1025                     if (aValue.IsReject()) {
   1026                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1027                                                           __func__);
   1028                     }
   1029 
   1030                     ClientDirectoryLockHandle directoryLockHandle =
   1031                         std::move(aValue.ResolveValue());
   1032 
   1033                     {
   1034                       auto destroyingDirectoryLockHandle =
   1035                           std::move(directoryLockHandle);
   1036                     }
   1037 
   1038                     return BoolPromise::CreateAndResolve(true, __func__);
   1039                   }));
   1040    promises.AppendElement(directoryLock->Acquire());
   1041    promises.AppendElement(
   1042        quotaManager->OpenClientDirectory(GetTestClientMetadata())
   1043            ->Then(GetCurrentSerialEventTarget(), __func__,
   1044                   [](QuotaManager::ClientDirectoryLockHandlePromise::
   1045                          ResolveOrRejectValue&& aValue) {
   1046                     if (aValue.IsReject()) {
   1047                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1048                                                           __func__);
   1049                     }
   1050 
   1051                     ClientDirectoryLockHandle directoryLockHandle =
   1052                         std::move(aValue.ResolveValue());
   1053 
   1054                     {
   1055                       auto destroyingDirectoryLockHandle =
   1056                           std::move(directoryLockHandle);
   1057                     }
   1058 
   1059                     return BoolPromise::CreateAndResolve(true, __func__);
   1060                   }));
   1061 
   1062    {
   1063      auto value =
   1064          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1065      ASSERT_TRUE(value.IsResolve());
   1066 
   1067      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1068    }
   1069  });
   1070 
   1071  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1072 
   1073  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1074 }
   1075 
   1076 // Test OpenClientDirectory when an opening of a client directory already
   1077 // finished.
   1078 TEST_F(TestQuotaManager, OpenClientDirectory_Finished) {
   1079  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1080 
   1081  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1082 
   1083  PerformOnBackgroundThread([]() {
   1084    QuotaManager* quotaManager = QuotaManager::Get();
   1085    ASSERT_TRUE(quotaManager);
   1086 
   1087    {
   1088      auto value =
   1089          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
   1090      ASSERT_TRUE(value.IsResolve());
   1091 
   1092      ClientDirectoryLockHandle directoryLockHandle =
   1093          std::move(value.ResolveValue());
   1094 
   1095      {
   1096        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
   1097      }
   1098 
   1099      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1100    }
   1101 
   1102    {
   1103      auto value =
   1104          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
   1105      ASSERT_TRUE(value.IsResolve());
   1106 
   1107      ClientDirectoryLockHandle directoryLockHandle =
   1108          std::move(value.ResolveValue());
   1109 
   1110      {
   1111        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
   1112      }
   1113 
   1114      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1115    }
   1116  });
   1117 
   1118  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1119 
   1120  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1121 }
   1122 
   1123 // Test OpenClientDirectory when an opening of a client directory already
   1124 // finished but storage shutdown has just been scheduled.
   1125 TEST_F(TestQuotaManager, OpenClientDirectory_FinishedWithScheduledShutdown) {
   1126  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1127 
   1128  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1129 
   1130  PerformOnBackgroundThread([]() {
   1131    QuotaManager* quotaManager = QuotaManager::Get();
   1132    ASSERT_TRUE(quotaManager);
   1133 
   1134    {
   1135      auto value =
   1136          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
   1137      ASSERT_TRUE(value.IsResolve());
   1138 
   1139      ClientDirectoryLockHandle directoryLockHandle =
   1140          std::move(value.ResolveValue());
   1141 
   1142      {
   1143        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
   1144      }
   1145 
   1146      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1147    }
   1148 
   1149    nsTArray<RefPtr<BoolPromise>> promises;
   1150 
   1151    promises.AppendElement(quotaManager->ShutdownStorage());
   1152    promises.AppendElement(
   1153        quotaManager->OpenClientDirectory(GetTestClientMetadata())
   1154            ->Then(GetCurrentSerialEventTarget(), __func__,
   1155                   [](QuotaManager::ClientDirectoryLockHandlePromise::
   1156                          ResolveOrRejectValue&& aValue) {
   1157                     if (aValue.IsReject()) {
   1158                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1159                                                           __func__);
   1160                     }
   1161 
   1162                     ClientDirectoryLockHandle directoryLockHandle =
   1163                         std::move(aValue.ResolveValue());
   1164 
   1165                     {
   1166                       auto destroyingDirectoryLockHandle =
   1167                           std::move(directoryLockHandle);
   1168                     }
   1169 
   1170                     return BoolPromise::CreateAndResolve(true, __func__);
   1171                   }));
   1172 
   1173    {
   1174      auto value =
   1175          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1176      ASSERT_TRUE(value.IsResolve());
   1177 
   1178      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1179    }
   1180  });
   1181 
   1182  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1183 
   1184  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1185 }
   1186 
   1187 // Test OpenClientDirectory when an opening of a client directory already
   1188 // finished with an exclusive client directory lock for a different origin is
   1189 // acquired in between.
   1190 TEST_F(TestQuotaManager,
   1191       OpenClientDirectory_FinishedWithOtherExclusiveClientDirectoryLock) {
   1192  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1193 
   1194  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1195 
   1196  PerformOnBackgroundThread([]() {
   1197    QuotaManager* quotaManager = QuotaManager::Get();
   1198    ASSERT_TRUE(quotaManager);
   1199 
   1200    {
   1201      auto value =
   1202          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
   1203      ASSERT_TRUE(value.IsResolve());
   1204 
   1205      ClientDirectoryLockHandle directoryLockHandle =
   1206          std::move(value.ResolveValue());
   1207 
   1208      {
   1209        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
   1210      }
   1211 
   1212      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1213    }
   1214 
   1215    RefPtr<ClientDirectoryLock> directoryLock =
   1216        quotaManager->CreateDirectoryLock(GetOtherTestClientMetadata(),
   1217                                          /* aExclusive */ true);
   1218 
   1219    {
   1220      auto value = Await(directoryLock->Acquire());
   1221      ASSERT_TRUE(value.IsResolve());
   1222    }
   1223 
   1224    {
   1225      auto value =
   1226          Await(quotaManager->OpenClientDirectory(GetTestClientMetadata()));
   1227      ASSERT_TRUE(value.IsResolve());
   1228 
   1229      ClientDirectoryLockHandle directoryLockHandle =
   1230          std::move(value.ResolveValue());
   1231 
   1232      {
   1233        auto destroyingDirectoryLockHandle = std::move(directoryLockHandle);
   1234      }
   1235 
   1236      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1237    }
   1238 
   1239    DropDirectoryLock(directoryLock);
   1240  });
   1241 
   1242  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1243 
   1244  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1245 }
   1246 
   1247 TEST_F(TestQuotaManager, OpenClientDirectory_InitializeOrigin) {
   1248  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1249 
   1250  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1251 
   1252  PerformOnBackgroundThread([]() {
   1253    QuotaManager* quotaManager = QuotaManager::Get();
   1254    ASSERT_TRUE(quotaManager);
   1255 
   1256    ClientDirectoryLockHandle directoryLockHandle;
   1257 
   1258    RefPtr<BoolPromise> promise =
   1259        quotaManager
   1260            ->OpenClientDirectory(GetTestClientMetadata(),
   1261                                  /* aInitializeOrigin */ true)
   1262            ->Then(GetCurrentSerialEventTarget(), __func__,
   1263                   [&directoryLockHandle](
   1264                       QuotaManager::ClientDirectoryLockHandlePromise::
   1265                           ResolveOrRejectValue&& aValue) {
   1266                     if (aValue.IsReject()) {
   1267                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1268                                                           __func__);
   1269                     }
   1270 
   1271                     [&aValue]() { ASSERT_TRUE(aValue.ResolveValue()); }();
   1272 
   1273                     directoryLockHandle = std::move(aValue.ResolveValue());
   1274 
   1275                     return BoolPromise::CreateAndResolve(true, __func__);
   1276                   })
   1277            ->Then(quotaManager->IOThread(), __func__,
   1278                   [](const BoolPromise::ResolveOrRejectValue& aValue) {
   1279                     if (aValue.IsReject()) {
   1280                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1281                                                           __func__);
   1282                     }
   1283 
   1284                     []() {
   1285                       QuotaManager* quotaManager = QuotaManager::Get();
   1286                       ASSERT_TRUE(quotaManager);
   1287 
   1288                       ASSERT_TRUE(
   1289                           quotaManager->IsTemporaryOriginInitializedInternal(
   1290                               GetTestOriginMetadata()));
   1291                     }();
   1292 
   1293                     return BoolPromise::CreateAndResolve(true, __func__);
   1294                   })
   1295            ->Then(GetCurrentSerialEventTarget(), __func__,
   1296                   [&directoryLockHandle](
   1297                       const BoolPromise::ResolveOrRejectValue& aValue) {
   1298                     {
   1299                       auto destroyingDirectoryLockHandle =
   1300                           std::move(directoryLockHandle);
   1301                     }
   1302 
   1303                     if (aValue.IsReject()) {
   1304                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   1305                                                           __func__);
   1306                     }
   1307 
   1308                     return BoolPromise::CreateAndResolve(true, __func__);
   1309                   });
   1310 
   1311    {
   1312      auto value = Await(promise);
   1313      ASSERT_TRUE(value.IsResolve());
   1314      ASSERT_TRUE(value.ResolveValue());
   1315    }
   1316  });
   1317  ASSERT_NO_FATAL_FAILURE(
   1318      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   1319 
   1320  ASSERT_NO_FATAL_FAILURE(ClearStoragesForOrigin(GetTestOriginMetadata()));
   1321 
   1322  PerformOnBackgroundThread([]() {
   1323    QuotaManager* quotaManager = QuotaManager::Get();
   1324    ASSERT_TRUE(quotaManager);
   1325 
   1326    ClientDirectoryLockHandle directoryLockHandle;
   1327 
   1328    RefPtr<QuotaManager::ClientDirectoryLockHandlePromise> promise =
   1329        quotaManager->OpenClientDirectory(GetTestClientMetadata(),
   1330                                          /* aInitializeOrigin */ false);
   1331 
   1332    {
   1333      auto value = Await(promise);
   1334      ASSERT_TRUE(value.IsReject());
   1335      ASSERT_EQ(value.RejectValue(),
   1336                NS_ERROR_DOM_QM_CLIENT_INIT_ORIGIN_UNINITIALIZED);
   1337    }
   1338  });
   1339  ASSERT_NO_FATAL_FAILURE(
   1340      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   1341 
   1342  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1343 
   1344  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1345 }
   1346 
   1347 // Test simple InitializeStorage.
   1348 TEST_F(TestQuotaManager, InitializeStorage_Simple) {
   1349  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1350 
   1351  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1352 
   1353  PerformOnBackgroundThread([]() {
   1354    QuotaManager* quotaManager = QuotaManager::Get();
   1355    ASSERT_TRUE(quotaManager);
   1356 
   1357    {
   1358      auto value = Await(quotaManager->InitializeStorage());
   1359      ASSERT_TRUE(value.IsResolve());
   1360 
   1361      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1362    }
   1363  });
   1364 
   1365  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1366 
   1367  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1368 }
   1369 
   1370 // Test InitializeStorage when a storage initialization is already ongoing.
   1371 TEST_F(TestQuotaManager, InitializeStorage_Ongoing) {
   1372  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1373 
   1374  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1375 
   1376  PerformOnBackgroundThread([]() {
   1377    QuotaManager* quotaManager = QuotaManager::Get();
   1378    ASSERT_TRUE(quotaManager);
   1379 
   1380    nsTArray<RefPtr<BoolPromise>> promises;
   1381 
   1382    promises.AppendElement(quotaManager->InitializeStorage());
   1383    promises.AppendElement(quotaManager->InitializeStorage());
   1384 
   1385    {
   1386      auto value =
   1387          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1388      ASSERT_TRUE(value.IsResolve());
   1389 
   1390      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1391    }
   1392  });
   1393 
   1394  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1395 
   1396  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1397 }
   1398 
   1399 // Test InitializeStorage when a storage initialization is already ongoing and
   1400 // storage shutdown is scheduled after that.
   1401 TEST_F(TestQuotaManager, InitializeStorage_OngoingWithScheduledShutdown) {
   1402  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1403 
   1404  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1405 
   1406  PerformOnBackgroundThread([]() {
   1407    QuotaManager* quotaManager = QuotaManager::Get();
   1408    ASSERT_TRUE(quotaManager);
   1409 
   1410    nsTArray<RefPtr<BoolPromise>> promises;
   1411 
   1412    promises.AppendElement(quotaManager->InitializeStorage());
   1413    promises.AppendElement(quotaManager->ShutdownStorage());
   1414    promises.AppendElement(quotaManager->InitializeStorage());
   1415 
   1416    {
   1417      auto value =
   1418          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1419      ASSERT_TRUE(value.IsResolve());
   1420 
   1421      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1422    }
   1423  });
   1424 
   1425  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1426 
   1427  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1428 }
   1429 
   1430 // Test InitializeStorage when a storage initialization is already ongoing and
   1431 // storage shutdown is scheduled after that. The tested InitializeStorage call
   1432 // is delayed to the point when storage shutdown is about to finish.
   1433 TEST_F(TestQuotaManager,
   1434       InitializeStorage_OngoingWithScheduledShutdown_Delayed) {
   1435  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1436 
   1437  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1438 
   1439  PerformOnBackgroundThread([]() {
   1440    QuotaManager* quotaManager = QuotaManager::Get();
   1441    ASSERT_TRUE(quotaManager);
   1442 
   1443    nsTArray<RefPtr<BoolPromise>> promises;
   1444 
   1445    promises.AppendElement(quotaManager->InitializeStorage());
   1446 
   1447    OriginOperationCallbackOptions callbackOptions;
   1448    callbackOptions.mWantWillFinishSync = true;
   1449 
   1450    OriginOperationCallbacks callbacks;
   1451    promises.AppendElement(quotaManager->ShutdownStorage(Some(callbackOptions),
   1452                                                         SomeRef(callbacks)));
   1453 
   1454    promises.AppendElement(callbacks.mWillFinishSyncPromise.ref()->Then(
   1455        GetCurrentSerialEventTarget(), __func__,
   1456        [quotaManager = RefPtr(quotaManager)](
   1457            const ExclusiveBoolPromise::ResolveOrRejectValue& aValue) {
   1458          return InvokeAsync(
   1459              GetCurrentSerialEventTarget(), __func__,
   1460              [quotaManager]() { return quotaManager->InitializeStorage(); });
   1461        }));
   1462 
   1463    {
   1464      auto value =
   1465          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1466      ASSERT_TRUE(value.IsResolve());
   1467 
   1468      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1469    }
   1470  });
   1471 
   1472  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1473 
   1474  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1475 }
   1476 
   1477 // Test InitializeStorage when a storage initialization is already ongoing and
   1478 // an exclusive directory lock is requested after that.
   1479 TEST_F(TestQuotaManager, InitializeStorage_OngoingWithExclusiveDirectoryLock) {
   1480  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1481 
   1482  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1483 
   1484  PerformOnBackgroundThread([]() {
   1485    QuotaManager* quotaManager = QuotaManager::Get();
   1486    ASSERT_TRUE(quotaManager);
   1487 
   1488    RefPtr<UniversalDirectoryLock> directoryLock =
   1489        quotaManager->CreateDirectoryLockInternal(
   1490            PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
   1491            ClientStorageScope::CreateFromNull(),
   1492            /* aExclusive */ true);
   1493 
   1494    nsTArray<RefPtr<BoolPromise>> promises;
   1495 
   1496    promises.AppendElement(quotaManager->InitializeStorage()->Then(
   1497        GetCurrentSerialEventTarget(), __func__,
   1498        [&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
   1499          // The exclusive directory lock must be released when the first
   1500          // storage initialization is finished, otherwise it would endlessly
   1501          // block the second storage initialization.
   1502          DropDirectoryLock(directoryLock);
   1503 
   1504          if (aValue.IsReject()) {
   1505            return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
   1506          }
   1507 
   1508          return BoolPromise::CreateAndResolve(true, __func__);
   1509        }));
   1510    promises.AppendElement(directoryLock->Acquire());
   1511    promises.AppendElement(quotaManager->InitializeStorage());
   1512 
   1513    {
   1514      auto value =
   1515          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1516      ASSERT_TRUE(value.IsResolve());
   1517 
   1518      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1519    }
   1520  });
   1521 
   1522  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1523 
   1524  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1525 }
   1526 
   1527 // Test InitializeStorage when a storage initialization is already ongoing and
   1528 // shared client directory locks are requested after that.
   1529 // The shared client directory locks don't have to be released in this case.
   1530 TEST_F(TestQuotaManager, InitializeStorage_OngoingWithClientDirectoryLocks) {
   1531  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1532 
   1533  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1534 
   1535  PerformOnBackgroundThread([]() {
   1536    QuotaManager* quotaManager = QuotaManager::Get();
   1537    ASSERT_TRUE(quotaManager);
   1538 
   1539    RefPtr<ClientDirectoryLock> directoryLock =
   1540        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1541                                          /* aExclusive */ false);
   1542 
   1543    RefPtr<ClientDirectoryLock> directoryLock2 =
   1544        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1545                                          /* aExclusive */ false);
   1546 
   1547    nsTArray<RefPtr<BoolPromise>> promises;
   1548 
   1549    promises.AppendElement(quotaManager->InitializeStorage());
   1550    promises.AppendElement(directoryLock->Acquire());
   1551    promises.AppendElement(quotaManager->InitializeStorage());
   1552    promises.AppendElement(directoryLock2->Acquire());
   1553 
   1554    {
   1555      auto value =
   1556          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1557      ASSERT_TRUE(value.IsResolve());
   1558 
   1559      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1560    }
   1561 
   1562    DropDirectoryLock(directoryLock);
   1563    DropDirectoryLock(directoryLock2);
   1564  });
   1565 
   1566  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1567 
   1568  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1569 }
   1570 
   1571 // Test InitializeStorage when a storage initialization is already ongoing and
   1572 // shared client directory locks are requested after that with storage shutdown
   1573 // scheduled in between.
   1574 TEST_F(TestQuotaManager,
   1575       InitializeStorage_OngoingWithClientDirectoryLocksAndScheduledShutdown) {
   1576  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1577 
   1578  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1579 
   1580  PerformOnBackgroundThread([]() {
   1581    QuotaManager* quotaManager = QuotaManager::Get();
   1582    ASSERT_TRUE(quotaManager);
   1583 
   1584    RefPtr<ClientDirectoryLock> directoryLock =
   1585        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1586                                          /* aExclusive */ false);
   1587 
   1588    directoryLock->OnInvalidate(
   1589        [&directoryLock]() { DropDirectoryLock(directoryLock); });
   1590 
   1591    RefPtr<ClientDirectoryLock> directoryLock2 =
   1592        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1593                                          /* aExclusive */ false);
   1594 
   1595    nsTArray<RefPtr<BoolPromise>> promises;
   1596 
   1597    promises.AppendElement(quotaManager->InitializeStorage());
   1598    promises.AppendElement(directoryLock->Acquire());
   1599    promises.AppendElement(quotaManager->ShutdownStorage());
   1600    promises.AppendElement(quotaManager->InitializeStorage());
   1601    promises.AppendElement(directoryLock2->Acquire());
   1602 
   1603    {
   1604      auto value =
   1605          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1606      ASSERT_TRUE(value.IsResolve());
   1607 
   1608      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1609    }
   1610 
   1611    DropDirectoryLock(directoryLock2);
   1612  });
   1613 
   1614  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1615 
   1616  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1617 }
   1618 
   1619 // Test InitializeStorage when a storage initialization already finished.
   1620 TEST_F(TestQuotaManager, InitializeStorage_Finished) {
   1621  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1622 
   1623  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1624 
   1625  PerformOnBackgroundThread([]() {
   1626    QuotaManager* quotaManager = QuotaManager::Get();
   1627    ASSERT_TRUE(quotaManager);
   1628 
   1629    {
   1630      auto value = Await(quotaManager->InitializeStorage());
   1631      ASSERT_TRUE(value.IsResolve());
   1632 
   1633      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1634    }
   1635 
   1636    {
   1637      auto value = Await(quotaManager->InitializeStorage());
   1638      ASSERT_TRUE(value.IsResolve());
   1639 
   1640      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1641    }
   1642  });
   1643 
   1644  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1645 
   1646  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1647 }
   1648 
   1649 // Test InitializeStorage when a storage initialization already finished but
   1650 // storage shutdown has just been scheduled.
   1651 TEST_F(TestQuotaManager, InitializeStorage_FinishedWithScheduledShutdown) {
   1652  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1653 
   1654  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1655 
   1656  PerformOnBackgroundThread([]() {
   1657    QuotaManager* quotaManager = QuotaManager::Get();
   1658    ASSERT_TRUE(quotaManager);
   1659 
   1660    {
   1661      auto value = Await(quotaManager->InitializeStorage());
   1662      ASSERT_TRUE(value.IsResolve());
   1663 
   1664      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1665    }
   1666 
   1667    nsTArray<RefPtr<BoolPromise>> promises;
   1668 
   1669    promises.AppendElement(quotaManager->ShutdownStorage());
   1670    promises.AppendElement(quotaManager->InitializeStorage());
   1671 
   1672    {
   1673      auto value =
   1674          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1675      ASSERT_TRUE(value.IsResolve());
   1676 
   1677      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1678    }
   1679  });
   1680 
   1681  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1682 
   1683  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1684 }
   1685 
   1686 // Test InitializeStorage when a storage initialization already finished and
   1687 // shared client directory locks are requested immediately after requesting
   1688 // storage initialization.
   1689 TEST_F(TestQuotaManager, InitializeStorage_FinishedWithClientDirectoryLocks) {
   1690  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1691 
   1692  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1693 
   1694  PerformOnBackgroundThread([]() {
   1695    QuotaManager* quotaManager = QuotaManager::Get();
   1696    ASSERT_TRUE(quotaManager);
   1697 
   1698    RefPtr<ClientDirectoryLock> directoryLock =
   1699        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1700                                          /* aExclusive */ false);
   1701 
   1702    nsTArray<RefPtr<BoolPromise>> promises;
   1703 
   1704    promises.AppendElement(quotaManager->InitializeStorage());
   1705    promises.AppendElement(directoryLock->Acquire());
   1706 
   1707    {
   1708      auto value =
   1709          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1710      ASSERT_TRUE(value.IsResolve());
   1711 
   1712      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1713    }
   1714 
   1715    RefPtr<ClientDirectoryLock> directoryLock2 =
   1716        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1717                                          /* aExclusive */ false);
   1718 
   1719    promises.Clear();
   1720 
   1721    promises.AppendElement(quotaManager->InitializeStorage());
   1722    promises.AppendElement(directoryLock2->Acquire());
   1723 
   1724    {
   1725      auto value =
   1726          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1727      ASSERT_TRUE(value.IsResolve());
   1728 
   1729      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1730    }
   1731 
   1732    DropDirectoryLock(directoryLock);
   1733    DropDirectoryLock(directoryLock2);
   1734  });
   1735 
   1736  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1737 
   1738  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1739 }
   1740 
   1741 // Test InitializeStorage when a storage initialization already finished and
   1742 // shared client directory locks are requested immediatelly after requesting
   1743 // storage initialization with storage shutdown performed in between.
   1744 // The shared client directory lock is released when it gets invalidated by
   1745 // storage shutdown which then unblocks the shutdown.
   1746 TEST_F(TestQuotaManager,
   1747       InitializeStorage_FinishedWithClientDirectoryLocksAndScheduledShutdown) {
   1748  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1749 
   1750  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1751 
   1752  PerformOnBackgroundThread([]() {
   1753    QuotaManager* quotaManager = QuotaManager::Get();
   1754    ASSERT_TRUE(quotaManager);
   1755 
   1756    RefPtr<ClientDirectoryLock> directoryLock =
   1757        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1758                                          /* aExclusive */ false);
   1759 
   1760    directoryLock->OnInvalidate(
   1761        [&directoryLock]() { DropDirectoryLock(directoryLock); });
   1762 
   1763    nsTArray<RefPtr<BoolPromise>> promises;
   1764 
   1765    promises.AppendElement(quotaManager->InitializeStorage());
   1766    promises.AppendElement(directoryLock->Acquire());
   1767 
   1768    {
   1769      auto value =
   1770          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1771      ASSERT_TRUE(value.IsResolve());
   1772 
   1773      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1774    }
   1775 
   1776    {
   1777      auto value = Await(quotaManager->ShutdownStorage());
   1778      ASSERT_TRUE(value.IsResolve());
   1779 
   1780      ASSERT_FALSE(quotaManager->IsStorageInitialized());
   1781    }
   1782 
   1783    RefPtr<ClientDirectoryLock> directoryLock2 =
   1784        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   1785                                          /* aExclusive */ false);
   1786 
   1787    promises.Clear();
   1788 
   1789    promises.AppendElement(quotaManager->InitializeStorage());
   1790    promises.AppendElement(directoryLock2->Acquire());
   1791 
   1792    {
   1793      auto value =
   1794          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1795      ASSERT_TRUE(value.IsResolve());
   1796 
   1797      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1798    }
   1799 
   1800    DropDirectoryLock(directoryLock2);
   1801  });
   1802 
   1803  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1804 
   1805  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1806 }
   1807 
   1808 TEST_F(TestQuotaManager,
   1809       InitializePersistentStorage_OtherExclusiveDirectoryLockAcquired) {
   1810  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1811 
   1812  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1813 
   1814  PerformOnBackgroundThread([]() {
   1815    QuotaManager* quotaManager = QuotaManager::Get();
   1816    ASSERT_TRUE(quotaManager);
   1817 
   1818    {
   1819      auto value = Await(quotaManager->InitializeStorage());
   1820      ASSERT_TRUE(value.IsResolve());
   1821 
   1822      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1823    }
   1824 
   1825    RefPtr<UniversalDirectoryLock> directoryLock =
   1826        quotaManager->CreateDirectoryLockInternal(
   1827            PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY,
   1828                                            PERSISTENCE_TYPE_DEFAULT),
   1829            OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
   1830            /* aExclusive */ true);
   1831 
   1832    {
   1833      auto value = Await(directoryLock->Acquire());
   1834      ASSERT_TRUE(value.IsResolve());
   1835    }
   1836 
   1837    {
   1838      auto value = Await(quotaManager->InitializePersistentStorage());
   1839      ASSERT_TRUE(value.IsResolve());
   1840 
   1841      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1842    }
   1843 
   1844    DropDirectoryLock(directoryLock);
   1845  });
   1846 
   1847  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1848 
   1849  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1850 }
   1851 
   1852 // Test InitializePersistentStorage when a persistent storage initialization is
   1853 // already ongoing and an exclusive directory lock is requested after that.
   1854 TEST_F(TestQuotaManager,
   1855       InitializePersistentStorage_OngoingWithExclusiveDirectoryLock) {
   1856  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1857 
   1858  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1859 
   1860  PerformOnBackgroundThread([]() {
   1861    QuotaManager* quotaManager = QuotaManager::Get();
   1862    ASSERT_TRUE(quotaManager);
   1863 
   1864    RefPtr<UniversalDirectoryLock> directoryLock =
   1865        quotaManager->CreateDirectoryLockInternal(
   1866            PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
   1867            ClientStorageScope::CreateFromNull(),
   1868            /* aExclusive */ true);
   1869 
   1870    nsTArray<RefPtr<BoolPromise>> promises;
   1871 
   1872    promises.AppendElement(quotaManager->InitializeStorage());
   1873    promises.AppendElement(quotaManager->InitializePersistentStorage()->Then(
   1874        GetCurrentSerialEventTarget(), __func__,
   1875        [&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
   1876          // The exclusive directory lock must be released when the first
   1877          // Persistent storage initialization is finished, otherwise it would
   1878          // endlessly block the second persistent storage initialization.
   1879          DropDirectoryLock(directoryLock);
   1880 
   1881          if (aValue.IsReject()) {
   1882            return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
   1883          }
   1884 
   1885          return BoolPromise::CreateAndResolve(true, __func__);
   1886        }));
   1887    promises.AppendElement(directoryLock->Acquire());
   1888    promises.AppendElement(quotaManager->InitializeStorage());
   1889    promises.AppendElement(quotaManager->InitializePersistentStorage());
   1890 
   1891    {
   1892      auto value =
   1893          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1894      ASSERT_TRUE(value.IsResolve());
   1895 
   1896      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1897      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1898    }
   1899  });
   1900 
   1901  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1902 
   1903  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1904 }
   1905 
   1906 // Test InitializePersistentStorage when a persistent storage initialization
   1907 // already finished.
   1908 TEST_F(TestQuotaManager, InitializePersistentStorage_Finished) {
   1909  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1910 
   1911  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1912 
   1913  PerformOnBackgroundThread([]() {
   1914    nsTArray<RefPtr<BoolPromise>> promises;
   1915 
   1916    QuotaManager* quotaManager = QuotaManager::Get();
   1917    ASSERT_TRUE(quotaManager);
   1918 
   1919    promises.AppendElement(quotaManager->InitializeStorage());
   1920    promises.AppendElement(quotaManager->InitializePersistentStorage());
   1921 
   1922    {
   1923      auto value =
   1924          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1925      ASSERT_TRUE(value.IsResolve());
   1926 
   1927      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1928      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1929    }
   1930 
   1931    promises.Clear();
   1932 
   1933    promises.AppendElement(quotaManager->InitializeStorage());
   1934    promises.AppendElement(quotaManager->InitializePersistentStorage());
   1935 
   1936    {
   1937      auto value =
   1938          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1939      ASSERT_TRUE(value.IsResolve());
   1940 
   1941      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1942      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1943    }
   1944  });
   1945 
   1946  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1947 
   1948  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1949 }
   1950 
   1951 TEST_F(TestQuotaManager,
   1952       InitializePersistentStorage_FinishedWithScheduledShutdown) {
   1953  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1954 
   1955  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   1956 
   1957  PerformOnBackgroundThread([]() {
   1958    nsTArray<RefPtr<BoolPromise>> promises;
   1959 
   1960    QuotaManager* quotaManager = QuotaManager::Get();
   1961    ASSERT_TRUE(quotaManager);
   1962 
   1963    promises.AppendElement(quotaManager->InitializeStorage());
   1964    promises.AppendElement(quotaManager->InitializePersistentStorage());
   1965 
   1966    {
   1967      auto value =
   1968          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1969      ASSERT_TRUE(value.IsResolve());
   1970 
   1971      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1972      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1973    }
   1974 
   1975    promises.Clear();
   1976 
   1977    promises.AppendElement(quotaManager->ShutdownStorage());
   1978    promises.AppendElement(quotaManager->InitializeStorage());
   1979    promises.AppendElement(quotaManager->InitializePersistentStorage());
   1980 
   1981    {
   1982      auto value =
   1983          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   1984      ASSERT_TRUE(value.IsResolve());
   1985 
   1986      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   1987      ASSERT_TRUE(quotaManager->IsPersistentStorageInitialized());
   1988    }
   1989  });
   1990 
   1991  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   1992 
   1993  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1994 }
   1995 
   1996 TEST_F(TestQuotaManager,
   1997       InitializeTemporaryStorage_OtherExclusiveDirectoryLockAcquired) {
   1998  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   1999 
   2000  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2001 
   2002  PerformOnBackgroundThread([]() {
   2003    QuotaManager* quotaManager = QuotaManager::Get();
   2004    ASSERT_TRUE(quotaManager);
   2005 
   2006    {
   2007      auto value = Await(quotaManager->InitializeStorage());
   2008      ASSERT_TRUE(value.IsResolve());
   2009 
   2010      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2011    }
   2012 
   2013    RefPtr<UniversalDirectoryLock> directoryLock =
   2014        quotaManager->CreateDirectoryLockInternal(
   2015            PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
   2016            OriginScope::FromNull(), ClientStorageScope::CreateFromNull(),
   2017            /* aExclusive */ true);
   2018 
   2019    {
   2020      auto value = Await(directoryLock->Acquire());
   2021      ASSERT_TRUE(value.IsResolve());
   2022    }
   2023 
   2024    {
   2025      auto value = Await(quotaManager->InitializeTemporaryStorage());
   2026      ASSERT_TRUE(value.IsResolve());
   2027 
   2028      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2029    }
   2030 
   2031    DropDirectoryLock(directoryLock);
   2032  });
   2033 
   2034  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2035 
   2036  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2037 }
   2038 
   2039 // Test InitializeTemporaryStorage when a temporary storage initialization is
   2040 // already ongoing and an exclusive directory lock is requested after that.
   2041 TEST_F(TestQuotaManager,
   2042       InitializeTemporaryStorage_OngoingWithExclusiveDirectoryLock) {
   2043  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2044 
   2045  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2046 
   2047  PerformOnBackgroundThread([]() {
   2048    QuotaManager* quotaManager = QuotaManager::Get();
   2049    ASSERT_TRUE(quotaManager);
   2050 
   2051    RefPtr<UniversalDirectoryLock> directoryLock =
   2052        quotaManager->CreateDirectoryLockInternal(
   2053            PersistenceScope::CreateFromNull(), OriginScope::FromNull(),
   2054            ClientStorageScope::CreateFromNull(),
   2055            /* aExclusive */ true);
   2056 
   2057    nsTArray<RefPtr<BoolPromise>> promises;
   2058 
   2059    promises.AppendElement(quotaManager->InitializeStorage());
   2060    promises.AppendElement(quotaManager->InitializeTemporaryStorage()->Then(
   2061        GetCurrentSerialEventTarget(), __func__,
   2062        [&directoryLock](const BoolPromise::ResolveOrRejectValue& aValue) {
   2063          // The exclusive directory lock must be dropped when the first
   2064          // temporary storage initialization is finished, otherwise it would
   2065          // endlessly block the second temporary storage initialization.
   2066          DropDirectoryLock(directoryLock);
   2067 
   2068          if (aValue.IsReject()) {
   2069            return BoolPromise::CreateAndReject(aValue.RejectValue(), __func__);
   2070          }
   2071 
   2072          return BoolPromise::CreateAndResolve(true, __func__);
   2073        }));
   2074    promises.AppendElement(directoryLock->Acquire());
   2075    promises.AppendElement(quotaManager->InitializeStorage());
   2076    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2077 
   2078    {
   2079      auto value =
   2080          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2081      ASSERT_TRUE(value.IsResolve());
   2082 
   2083      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2084      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2085    }
   2086  });
   2087 
   2088  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2089 
   2090  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2091 }
   2092 
   2093 // Test InitializeTemporaryStorage when a temporary storage initialization
   2094 // already finished.
   2095 TEST_F(TestQuotaManager, InitializeTemporaryStorage_Finished) {
   2096  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2097 
   2098  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2099 
   2100  PerformOnBackgroundThread([]() {
   2101    nsTArray<RefPtr<BoolPromise>> promises;
   2102 
   2103    QuotaManager* quotaManager = QuotaManager::Get();
   2104    ASSERT_TRUE(quotaManager);
   2105 
   2106    promises.AppendElement(quotaManager->InitializeStorage());
   2107    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2108 
   2109    {
   2110      auto value =
   2111          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2112      ASSERT_TRUE(value.IsResolve());
   2113 
   2114      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2115      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2116    }
   2117 
   2118    promises.Clear();
   2119 
   2120    promises.AppendElement(quotaManager->InitializeStorage());
   2121    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2122 
   2123    {
   2124      auto value =
   2125          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2126      ASSERT_TRUE(value.IsResolve());
   2127 
   2128      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2129      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2130    }
   2131  });
   2132 
   2133  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2134 
   2135  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2136 }
   2137 
   2138 TEST_F(TestQuotaManager,
   2139       InitializeTemporaryStorage_FinishedWithScheduledShutdown) {
   2140  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2141 
   2142  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2143 
   2144  PerformOnBackgroundThread([]() {
   2145    nsTArray<RefPtr<BoolPromise>> promises;
   2146 
   2147    QuotaManager* quotaManager = QuotaManager::Get();
   2148    ASSERT_TRUE(quotaManager);
   2149 
   2150    promises.AppendElement(quotaManager->InitializeStorage());
   2151    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2152 
   2153    {
   2154      auto value =
   2155          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2156      ASSERT_TRUE(value.IsResolve());
   2157 
   2158      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2159      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2160    }
   2161 
   2162    promises.Clear();
   2163 
   2164    promises.AppendElement(quotaManager->ShutdownStorage());
   2165    promises.AppendElement(quotaManager->InitializeStorage());
   2166    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2167 
   2168    {
   2169      auto value =
   2170          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2171      ASSERT_TRUE(value.IsResolve());
   2172 
   2173      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2174      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2175    }
   2176  });
   2177 
   2178  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2179 
   2180  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2181 }
   2182 
   2183 TEST_F(TestQuotaManager,
   2184       InitializeTemporaryGroup_OtherExclusiveDirectoryLockAcquired) {
   2185  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2186 
   2187  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2188 
   2189  PerformOnBackgroundThread([]() {
   2190    auto testOriginMetadata = GetTestOriginMetadata();
   2191 
   2192    QuotaManager* quotaManager = QuotaManager::Get();
   2193    ASSERT_TRUE(quotaManager);
   2194 
   2195    {
   2196      auto value = Await(quotaManager->InitializeStorage());
   2197      ASSERT_TRUE(value.IsResolve());
   2198 
   2199      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2200    }
   2201 
   2202    {
   2203      auto value = Await(quotaManager->InitializeTemporaryStorage());
   2204      ASSERT_TRUE(value.IsResolve());
   2205 
   2206      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2207    }
   2208 
   2209    RefPtr<UniversalDirectoryLock> directoryLock =
   2210        quotaManager->CreateDirectoryLockInternal(
   2211            PersistenceScope::CreateFromValue(PERSISTENCE_TYPE_PERSISTENT),
   2212            OriginScope::FromGroup(testOriginMetadata.mGroup),
   2213            ClientStorageScope::CreateFromNull(),
   2214            /* aExclusive */ true);
   2215 
   2216    {
   2217      auto value = Await(directoryLock->Acquire());
   2218      ASSERT_TRUE(value.IsResolve());
   2219    }
   2220 
   2221    {
   2222      auto value =
   2223          Await(quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2224      ASSERT_TRUE(value.IsResolve());
   2225 
   2226      ASSERT_TRUE(
   2227          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2228    }
   2229 
   2230    DropDirectoryLock(directoryLock);
   2231  });
   2232 
   2233  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2234 
   2235  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2236 }
   2237 
   2238 // Test InitializeTemporaryGroup when a temporary group initialization is
   2239 // already ongoing and an exclusive directory lock is requested after that.
   2240 TEST_F(TestQuotaManager,
   2241       InitializeTemporaryGroup_OngoingWithExclusiveDirectoryLock) {
   2242  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2243 
   2244  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2245 
   2246  PerformOnBackgroundThread([]() {
   2247    auto testOriginMetadata = GetTestOriginMetadata();
   2248 
   2249    QuotaManager* quotaManager = QuotaManager::Get();
   2250    ASSERT_TRUE(quotaManager);
   2251 
   2252    RefPtr<UniversalDirectoryLock> directoryLock =
   2253        quotaManager->CreateDirectoryLockInternal(
   2254            PersistenceScope::CreateFromSet(PERSISTENCE_TYPE_TEMPORARY,
   2255                                            PERSISTENCE_TYPE_DEFAULT),
   2256            OriginScope::FromGroup(testOriginMetadata.mGroup),
   2257            ClientStorageScope::CreateFromNull(),
   2258            /* aExclusive */ true);
   2259 
   2260    nsTArray<RefPtr<BoolPromise>> promises;
   2261 
   2262    promises.AppendElement(quotaManager->InitializeStorage());
   2263    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2264    promises.AppendElement(
   2265        quotaManager->InitializeTemporaryGroup(testOriginMetadata)
   2266            ->Then(GetCurrentSerialEventTarget(), __func__,
   2267                   [&directoryLock](
   2268                       const BoolPromise::ResolveOrRejectValue& aValue) {
   2269                     // The exclusive directory lock must be dropped when the
   2270                     // first temporary group initialization is finished,
   2271                     // otherwise it would endlessly block the second temporary
   2272                     // group initialization.
   2273                     DropDirectoryLock(directoryLock);
   2274 
   2275                     if (aValue.IsReject()) {
   2276                       return BoolPromise::CreateAndReject(aValue.RejectValue(),
   2277                                                           __func__);
   2278                     }
   2279 
   2280                     return BoolPromise::CreateAndResolve(true, __func__);
   2281                   }));
   2282    promises.AppendElement(directoryLock->Acquire());
   2283    promises.AppendElement(quotaManager->InitializeStorage());
   2284    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2285    promises.AppendElement(
   2286        quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2287 
   2288    {
   2289      auto value =
   2290          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2291      ASSERT_TRUE(value.IsResolve());
   2292 
   2293      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2294      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2295      ASSERT_TRUE(
   2296          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2297    }
   2298  });
   2299 
   2300  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2301 
   2302  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2303 }
   2304 
   2305 // Test InitializeTemporaryGroup when a temporary group initialization already
   2306 // finished.
   2307 TEST_F(TestQuotaManager, InitializeTemporaryGroup_Finished) {
   2308  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2309 
   2310  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2311 
   2312  PerformOnBackgroundThread([]() {
   2313    auto testOriginMetadata = GetTestOriginMetadata();
   2314 
   2315    nsTArray<RefPtr<BoolPromise>> promises;
   2316 
   2317    QuotaManager* quotaManager = QuotaManager::Get();
   2318    ASSERT_TRUE(quotaManager);
   2319 
   2320    promises.AppendElement(quotaManager->InitializeStorage());
   2321    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2322    promises.AppendElement(
   2323        quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2324 
   2325    {
   2326      auto value =
   2327          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2328      ASSERT_TRUE(value.IsResolve());
   2329 
   2330      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2331      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2332      ASSERT_TRUE(
   2333          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2334    }
   2335 
   2336    promises.Clear();
   2337 
   2338    promises.AppendElement(quotaManager->InitializeStorage());
   2339    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2340    promises.AppendElement(
   2341        quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2342 
   2343    {
   2344      auto value =
   2345          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2346      ASSERT_TRUE(value.IsResolve());
   2347 
   2348      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2349      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2350      ASSERT_TRUE(
   2351          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2352    }
   2353  });
   2354 
   2355  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2356 
   2357  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2358 }
   2359 
   2360 TEST_F(TestQuotaManager,
   2361       InitializeTemporaryGroup_FinishedWithScheduledShutdown) {
   2362  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2363 
   2364  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2365 
   2366  PerformOnBackgroundThread([]() {
   2367    auto testOriginMetadata = GetTestOriginMetadata();
   2368 
   2369    nsTArray<RefPtr<BoolPromise>> promises;
   2370 
   2371    QuotaManager* quotaManager = QuotaManager::Get();
   2372    ASSERT_TRUE(quotaManager);
   2373 
   2374    promises.AppendElement(quotaManager->InitializeStorage());
   2375    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2376    promises.AppendElement(
   2377        quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2378 
   2379    {
   2380      auto value =
   2381          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2382      ASSERT_TRUE(value.IsResolve());
   2383 
   2384      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2385      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2386      ASSERT_TRUE(
   2387          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2388    }
   2389 
   2390    promises.Clear();
   2391 
   2392    promises.AppendElement(quotaManager->ShutdownStorage());
   2393    promises.AppendElement(quotaManager->InitializeStorage());
   2394    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2395    promises.AppendElement(
   2396        quotaManager->InitializeTemporaryGroup(testOriginMetadata));
   2397 
   2398    {
   2399      auto value =
   2400          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2401      ASSERT_TRUE(value.IsResolve());
   2402 
   2403      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2404      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2405      ASSERT_TRUE(
   2406          quotaManager->IsTemporaryGroupInitialized(testOriginMetadata));
   2407    }
   2408  });
   2409 
   2410  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2411 
   2412  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2413 }
   2414 
   2415 TEST_F(TestQuotaManager,
   2416       InitializePersistentOrigin_FinishedWithScheduledShutdown) {
   2417  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2418 
   2419  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2420 
   2421  PerformOnBackgroundThread([]() {
   2422    auto testOriginMetadata = GetTestPersistentOriginMetadata();
   2423 
   2424    nsTArray<RefPtr<BoolPromise>> promises;
   2425 
   2426    QuotaManager* quotaManager = QuotaManager::Get();
   2427    ASSERT_TRUE(quotaManager);
   2428 
   2429    promises.AppendElement(quotaManager->InitializeStorage());
   2430    promises.AppendElement(
   2431        quotaManager->InitializePersistentOrigin(testOriginMetadata));
   2432 
   2433    {
   2434      auto value =
   2435          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2436      ASSERT_TRUE(value.IsResolve());
   2437 
   2438      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2439      ASSERT_TRUE(
   2440          quotaManager->IsPersistentOriginInitialized(testOriginMetadata));
   2441    }
   2442 
   2443    promises.Clear();
   2444 
   2445    promises.AppendElement(quotaManager->ShutdownStorage());
   2446    promises.AppendElement(quotaManager->InitializeStorage());
   2447    promises.AppendElement(
   2448        quotaManager->InitializePersistentOrigin(testOriginMetadata));
   2449 
   2450    {
   2451      auto value =
   2452          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2453      ASSERT_TRUE(value.IsResolve());
   2454 
   2455      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2456      ASSERT_TRUE(
   2457          quotaManager->IsPersistentOriginInitialized(testOriginMetadata));
   2458    }
   2459  });
   2460 
   2461  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2462 
   2463  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2464 }
   2465 
   2466 TEST_F(TestQuotaManager,
   2467       InitializeTemporaryOrigin_FinishedWithScheduledShutdown) {
   2468  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2469 
   2470  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2471 
   2472  PerformOnBackgroundThread([]() {
   2473    auto testOriginMetadata = GetTestOriginMetadata();
   2474 
   2475    nsTArray<RefPtr<BoolPromise>> promises;
   2476 
   2477    QuotaManager* quotaManager = QuotaManager::Get();
   2478    ASSERT_TRUE(quotaManager);
   2479 
   2480    promises.AppendElement(quotaManager->InitializeStorage());
   2481    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2482    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2483        testOriginMetadata,
   2484        /* aCreateIfNonExistent */ false));
   2485 
   2486    {
   2487      auto value =
   2488          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2489      ASSERT_TRUE(value.IsResolve());
   2490 
   2491      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2492      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2493      ASSERT_TRUE(
   2494          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2495    }
   2496 
   2497    promises.Clear();
   2498 
   2499    promises.AppendElement(quotaManager->ShutdownStorage());
   2500    promises.AppendElement(quotaManager->InitializeStorage());
   2501    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2502    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2503        testOriginMetadata,
   2504        /* aCreateIfNonExistent */ true));
   2505 
   2506    {
   2507      auto value =
   2508          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2509      ASSERT_TRUE(value.IsResolve());
   2510 
   2511      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2512      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2513      ASSERT_TRUE(
   2514          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2515    }
   2516  });
   2517 
   2518  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2519 
   2520  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2521 }
   2522 
   2523 TEST_F(TestQuotaManager,
   2524       InitializePersistentClient_FinishedWithScheduledShutdown) {
   2525  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2526 
   2527  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2528 
   2529  PerformOnBackgroundThread([]() {
   2530    auto testClientMetadata = GetTestPersistentClientMetadata();
   2531 
   2532    nsTArray<RefPtr<BoolPromise>> promises;
   2533 
   2534    QuotaManager* quotaManager = QuotaManager::Get();
   2535    ASSERT_TRUE(quotaManager);
   2536 
   2537    promises.AppendElement(quotaManager->InitializeStorage());
   2538    promises.AppendElement(
   2539        quotaManager->InitializePersistentOrigin(testClientMetadata));
   2540    promises.AppendElement(
   2541        quotaManager->InitializePersistentClient(testClientMetadata));
   2542 
   2543    {
   2544      auto value =
   2545          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2546      ASSERT_TRUE(value.IsResolve());
   2547 
   2548      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2549      ASSERT_TRUE(
   2550          quotaManager->IsPersistentOriginInitialized(testClientMetadata));
   2551      ASSERT_TRUE(
   2552          quotaManager->IsPersistentClientInitialized(testClientMetadata));
   2553    }
   2554 
   2555    promises.Clear();
   2556 
   2557    promises.AppendElement(quotaManager->ShutdownStorage());
   2558    promises.AppendElement(quotaManager->InitializeStorage());
   2559    promises.AppendElement(
   2560        quotaManager->InitializePersistentOrigin(testClientMetadata));
   2561    promises.AppendElement(
   2562        quotaManager->InitializePersistentClient(testClientMetadata));
   2563 
   2564    {
   2565      auto value =
   2566          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2567      ASSERT_TRUE(value.IsResolve());
   2568 
   2569      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2570      ASSERT_TRUE(
   2571          quotaManager->IsPersistentOriginInitialized(testClientMetadata));
   2572      ASSERT_TRUE(
   2573          quotaManager->IsPersistentClientInitialized(testClientMetadata));
   2574    }
   2575  });
   2576 
   2577  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2578 
   2579  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2580 }
   2581 
   2582 TEST_F(TestQuotaManager,
   2583       InitializeTemporaryClient_FinishedWithScheduledShutdown) {
   2584  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2585 
   2586  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2587 
   2588  PerformOnBackgroundThread([]() {
   2589    auto testClientMetadata = GetTestClientMetadata();
   2590 
   2591    nsTArray<RefPtr<BoolPromise>> promises;
   2592 
   2593    QuotaManager* quotaManager = QuotaManager::Get();
   2594    ASSERT_TRUE(quotaManager);
   2595 
   2596    promises.AppendElement(quotaManager->InitializeStorage());
   2597    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2598    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2599        testClientMetadata,
   2600        /* aCreateIfNonExistent */ true));
   2601    promises.AppendElement(quotaManager->InitializeTemporaryClient(
   2602        testClientMetadata,
   2603        /* aCreateIfNonExistent */ true));
   2604 
   2605    {
   2606      auto value =
   2607          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2608      ASSERT_TRUE(value.IsResolve());
   2609 
   2610      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2611      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2612      ASSERT_TRUE(
   2613          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   2614      ASSERT_TRUE(
   2615          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   2616    }
   2617 
   2618    promises.Clear();
   2619 
   2620    promises.AppendElement(quotaManager->ShutdownStorage());
   2621    promises.AppendElement(quotaManager->InitializeStorage());
   2622    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2623    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2624        testClientMetadata,
   2625        /* aCreateIfNonExistent */ true));
   2626    promises.AppendElement(quotaManager->InitializeTemporaryClient(
   2627        testClientMetadata,
   2628        /* aCreateIfNonExistent */ true));
   2629 
   2630    {
   2631      auto value =
   2632          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2633      ASSERT_TRUE(value.IsResolve());
   2634 
   2635      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2636      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2637      ASSERT_TRUE(
   2638          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   2639      ASSERT_TRUE(
   2640          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   2641    }
   2642  });
   2643 
   2644  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2645 
   2646  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2647 }
   2648 
   2649 // Test simple SaveOriginAccessTime behavior.
   2650 TEST_F(TestQuotaManager, SaveOriginAccessTime_Simple) {
   2651  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2652 
   2653  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2654 
   2655  PerformOnBackgroundThread([]() {
   2656    auto testOriginMetadata = GetTestOriginMetadata();
   2657 
   2658    nsTArray<RefPtr<BoolPromise>> promises;
   2659 
   2660    QuotaManager* quotaManager = QuotaManager::Get();
   2661    ASSERT_TRUE(quotaManager);
   2662 
   2663    promises.AppendElement(quotaManager->InitializeStorage());
   2664    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2665    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2666        testOriginMetadata,
   2667        /* aCreateIfNonExistent */ false));
   2668 
   2669    {
   2670      auto value =
   2671          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2672      ASSERT_TRUE(value.IsResolve());
   2673 
   2674      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2675      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2676      ASSERT_TRUE(
   2677          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2678    }
   2679 
   2680    {
   2681      auto value =
   2682          Await(quotaManager->SaveOriginAccessTime(testOriginMetadata));
   2683      ASSERT_TRUE(value.IsResolve());
   2684    }
   2685  });
   2686 
   2687  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2688 
   2689  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2690 }
   2691 
   2692 // Test SaveOriginAccessTime when an exclusive client directory lock for a
   2693 // different client scope is acquired.
   2694 TEST_F(TestQuotaManager,
   2695       SaveOriginAccessTime_SimpleWithOtherExclusiveClientDirectoryLock) {
   2696  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2697 
   2698  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2699 
   2700  PerformOnBackgroundThread([]() {
   2701    auto testOriginMetadata = GetTestOriginMetadata();
   2702 
   2703    nsTArray<RefPtr<BoolPromise>> promises;
   2704 
   2705    QuotaManager* quotaManager = QuotaManager::Get();
   2706    ASSERT_TRUE(quotaManager);
   2707 
   2708    // Storage, temporary storage and temporary origin must be initialized
   2709    // before saving the origin access time. This also needs to happen before
   2710    // acquiring the exclusive directory lock below, otherwise it would lead to
   2711    // a hang.
   2712    promises.AppendElement(quotaManager->InitializeStorage());
   2713    promises.AppendElement(quotaManager->InitializeTemporaryStorage());
   2714    promises.AppendElement(quotaManager->InitializeTemporaryOrigin(
   2715        testOriginMetadata,
   2716        /* aCreateIfNonExistent */ false));
   2717 
   2718    {
   2719      auto value =
   2720          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   2721      ASSERT_TRUE(value.IsResolve());
   2722 
   2723      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2724      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2725      ASSERT_TRUE(
   2726          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2727    }
   2728 
   2729    // Acquire an exclusive directory lock for the SimpleDB quota client.
   2730    RefPtr<ClientDirectoryLock> directoryLock =
   2731        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   2732                                          /* aExclusive */ true);
   2733 
   2734    {
   2735      auto value = Await(directoryLock->Acquire());
   2736      ASSERT_TRUE(value.IsResolve());
   2737    }
   2738 
   2739    // Save origin access time while the exclusive directory lock for SimpleDB
   2740    // is held. Verifies that saving origin access time uses a lock that does
   2741    // not overlap with quota client directory locks.
   2742    {
   2743      auto value =
   2744          Await(quotaManager->SaveOriginAccessTime(testOriginMetadata));
   2745      ASSERT_TRUE(value.IsResolve());
   2746    }
   2747 
   2748    DropDirectoryLock(directoryLock);
   2749  });
   2750 
   2751  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2752 
   2753  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2754 }
   2755 
   2756 // Test simple ClearStoragesForOrigin.
   2757 TEST_F(TestQuotaManager, ClearStoragesForOrigin_Simple) {
   2758  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2759 
   2760  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2761  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   2762  ASSERT_NO_FATAL_FAILURE(
   2763      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   2764 
   2765  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   2766  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   2767  ASSERT_NO_FATAL_FAILURE(
   2768      InitializeTemporaryOrigin(GetTestOriginMetadata(),
   2769                                /* aCreateIfNonExistent */ true));
   2770 
   2771  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2772  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   2773  ASSERT_NO_FATAL_FAILURE(
   2774      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   2775 
   2776  PerformOnBackgroundThread([]() {
   2777    auto testOriginMetadata = GetTestOriginMetadata();
   2778 
   2779    nsCOMPtr<nsIPrincipal> principal =
   2780        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   2781    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   2782 
   2783    mozilla::ipc::PrincipalInfo principalInfo;
   2784    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   2785           QM_TEST_FAIL);
   2786 
   2787    QuotaManager* quotaManager = QuotaManager::Get();
   2788    ASSERT_TRUE(quotaManager);
   2789 
   2790    {
   2791      auto value = Await(quotaManager->ClearStoragesForOrigin(
   2792          /* aPersistenceType */ Nothing(), principalInfo));
   2793      ASSERT_TRUE(value.IsResolve());
   2794 
   2795      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2796      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2797      ASSERT_FALSE(
   2798          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2799    }
   2800  });
   2801 
   2802  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2803 
   2804  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2805 }
   2806 
   2807 TEST_F(TestQuotaManager, ClearStoragesForOrigin_NonExistentOriginDirectory) {
   2808  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2809 
   2810  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2811  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   2812  ASSERT_NO_FATAL_FAILURE(
   2813      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   2814 
   2815  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   2816  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   2817  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   2818      GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
   2819 
   2820  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2821  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   2822  ASSERT_NO_FATAL_FAILURE(
   2823      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   2824 
   2825  PerformOnBackgroundThread([]() {
   2826    auto testOriginMetadata = GetTestOriginMetadata();
   2827 
   2828    nsCOMPtr<nsIPrincipal> principal =
   2829        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   2830    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   2831 
   2832    mozilla::ipc::PrincipalInfo principalInfo;
   2833    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   2834           QM_TEST_FAIL);
   2835 
   2836    QuotaManager* quotaManager = QuotaManager::Get();
   2837    ASSERT_TRUE(quotaManager);
   2838 
   2839    {
   2840      auto value = Await(quotaManager->ClearStoragesForOrigin(
   2841          /* aPersistenceType */ Nothing(), principalInfo));
   2842      ASSERT_TRUE(value.IsResolve());
   2843 
   2844      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2845      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2846      ASSERT_FALSE(
   2847          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   2848    }
   2849  });
   2850 
   2851  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2852 
   2853  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2854 }
   2855 
   2856 TEST_F(TestQuotaManager, ClearStoragesForOrigin_ClientDirectoryExists) {
   2857  auto testClientMetadata = GetTestClientMetadata();
   2858 
   2859  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2860 
   2861  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2862  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   2863  ASSERT_NO_FATAL_FAILURE(
   2864      AssertTemporaryOriginNotInitialized(testClientMetadata));
   2865 
   2866  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   2867  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   2868  ASSERT_NO_FATAL_FAILURE(
   2869      InitializeTemporaryOrigin(testClientMetadata,
   2870                                /* aCreateIfNonExistent */ true));
   2871  ASSERT_NO_FATAL_FAILURE(
   2872      InitializeTemporaryClient(testClientMetadata,
   2873                                /* aCreateIfNonExistent */ true));
   2874 
   2875  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2876  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   2877  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testClientMetadata));
   2878 
   2879  PerformOnBackgroundThread([testClientMetadata]() {
   2880    nsCOMPtr<nsIPrincipal> principal =
   2881        BasePrincipal::CreateContentPrincipal(testClientMetadata.mOrigin);
   2882    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   2883 
   2884    mozilla::ipc::PrincipalInfo principalInfo;
   2885    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   2886           QM_TEST_FAIL);
   2887 
   2888    QuotaManager* quotaManager = QuotaManager::Get();
   2889    ASSERT_TRUE(quotaManager);
   2890 
   2891    {
   2892      auto value = Await(quotaManager->ClearStoragesForOrigin(
   2893          /* aPersistenceType */ Nothing(), principalInfo));
   2894      ASSERT_TRUE(value.IsResolve());
   2895 
   2896      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2897      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2898      ASSERT_FALSE(
   2899          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   2900      ASSERT_FALSE(
   2901          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   2902    }
   2903  });
   2904 
   2905  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2906 
   2907  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2908 }
   2909 
   2910 // Test simple ClearStoragesForClient.
   2911 TEST_F(TestQuotaManager, ClearStoragesForClient_Simple) {
   2912  auto testClientMetadata = GetTestClientMetadata();
   2913 
   2914  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2915 
   2916  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2917  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   2918  ASSERT_NO_FATAL_FAILURE(
   2919      AssertTemporaryOriginNotInitialized(testClientMetadata));
   2920 
   2921  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   2922  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   2923  ASSERT_NO_FATAL_FAILURE(
   2924      InitializeTemporaryOrigin(testClientMetadata,
   2925                                /* aCreateIfNonExistent */ true));
   2926  ASSERT_NO_FATAL_FAILURE(
   2927      InitializeTemporaryClient(testClientMetadata,
   2928                                /* aCreateIfNonExistent */ true));
   2929 
   2930  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2931  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   2932  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testClientMetadata));
   2933 
   2934  PerformOnBackgroundThread([testClientMetadata]() {
   2935    nsCOMPtr<nsIPrincipal> principal =
   2936        BasePrincipal::CreateContentPrincipal(testClientMetadata.mOrigin);
   2937    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   2938 
   2939    mozilla::ipc::PrincipalInfo principalInfo;
   2940    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   2941           QM_TEST_FAIL);
   2942 
   2943    QuotaManager* quotaManager = QuotaManager::Get();
   2944    ASSERT_TRUE(quotaManager);
   2945 
   2946    {
   2947      auto value = Await(quotaManager->ClearStoragesForClient(
   2948          /* aPersistenceType */ Nothing(), principalInfo,
   2949          testClientMetadata.mClientType));
   2950      ASSERT_TRUE(value.IsResolve());
   2951 
   2952      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   2953      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   2954      ASSERT_TRUE(
   2955          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   2956      ASSERT_FALSE(
   2957          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   2958    }
   2959  });
   2960 
   2961  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2962 
   2963  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2964 }
   2965 
   2966 // Test simple ClearStoragesForOriginPrefix.
   2967 TEST_F(TestQuotaManager, ClearStoragesForOriginPrefix_Simple) {
   2968  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   2969 
   2970  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   2971  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   2972  ASSERT_NO_FATAL_FAILURE(
   2973      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   2974 
   2975  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   2976  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   2977  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   2978      GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
   2979 
   2980  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   2981  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   2982  ASSERT_NO_FATAL_FAILURE(
   2983      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   2984 
   2985  PerformOnBackgroundThread([]() {
   2986    auto testOriginMetadata = GetTestOriginMetadata();
   2987 
   2988    nsCOMPtr<nsIPrincipal> principal =
   2989        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   2990    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   2991 
   2992    mozilla::ipc::PrincipalInfo principalInfo;
   2993    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   2994           QM_TEST_FAIL);
   2995 
   2996    QuotaManager* quotaManager = QuotaManager::Get();
   2997    ASSERT_TRUE(quotaManager);
   2998 
   2999    {
   3000      auto value = Await(quotaManager->ClearStoragesForOriginPrefix(
   3001          /* aPersistenceType */ Nothing(), principalInfo));
   3002      ASSERT_TRUE(value.IsResolve());
   3003 
   3004      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3005      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3006      ASSERT_FALSE(
   3007          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3008    }
   3009  });
   3010 
   3011  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3012 
   3013  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3014 }
   3015 
   3016 TEST_F(TestQuotaManager,
   3017       ClearStoragesForOriginPrefix_NonExistentOriginDirectory) {
   3018  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3019 
   3020  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3021  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3022  ASSERT_NO_FATAL_FAILURE(
   3023      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   3024 
   3025  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3026  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3027  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3028      GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
   3029 
   3030  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3031  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3032  ASSERT_NO_FATAL_FAILURE(
   3033      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   3034 
   3035  PerformOnBackgroundThread([]() {
   3036    auto testOriginMetadata = GetTestOriginMetadata();
   3037 
   3038    nsCOMPtr<nsIPrincipal> principal =
   3039        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   3040    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3041 
   3042    mozilla::ipc::PrincipalInfo principalInfo;
   3043    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3044           QM_TEST_FAIL);
   3045 
   3046    QuotaManager* quotaManager = QuotaManager::Get();
   3047    ASSERT_TRUE(quotaManager);
   3048 
   3049    {
   3050      auto value = Await(quotaManager->ClearStoragesForOriginPrefix(
   3051          /* aPersistenceType */ Nothing(), principalInfo));
   3052      ASSERT_TRUE(value.IsResolve());
   3053 
   3054      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3055      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3056      ASSERT_FALSE(
   3057          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3058    }
   3059  });
   3060 
   3061  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3062 
   3063  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3064 }
   3065 
   3066 // Test simple ClearStoragesForOriginAttributesPattern.
   3067 TEST_F(TestQuotaManager, ClearStoragesForOriginAttributesPattern_Simple) {
   3068  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3069 
   3070  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3071  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3072  ASSERT_NO_FATAL_FAILURE(
   3073      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   3074 
   3075  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3076  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3077  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3078      GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
   3079 
   3080  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3081  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3082  ASSERT_NO_FATAL_FAILURE(
   3083      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   3084 
   3085  PerformOnBackgroundThread([]() {
   3086    auto testOriginMetadata = GetTestOriginMetadata();
   3087 
   3088    nsCOMPtr<nsIPrincipal> principal =
   3089        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   3090    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3091 
   3092    mozilla::ipc::PrincipalInfo principalInfo;
   3093    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3094           QM_TEST_FAIL);
   3095 
   3096    QuotaManager* quotaManager = QuotaManager::Get();
   3097    ASSERT_TRUE(quotaManager);
   3098 
   3099    {
   3100      auto value = Await(quotaManager->ClearStoragesForOriginAttributesPattern(
   3101          OriginAttributesPattern()));
   3102      ASSERT_TRUE(value.IsResolve());
   3103 
   3104      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3105      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3106      ASSERT_FALSE(
   3107          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3108    }
   3109  });
   3110 
   3111  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3112 
   3113  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3114 }
   3115 
   3116 TEST_F(TestQuotaManager,
   3117       ClearStoragesForOriginAttributesPattern_NonExistentOriginDirectory) {
   3118  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3119 
   3120  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3121  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3122  ASSERT_NO_FATAL_FAILURE(
   3123      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   3124 
   3125  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3126  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3127  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3128      GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
   3129 
   3130  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3131  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3132  ASSERT_NO_FATAL_FAILURE(
   3133      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   3134 
   3135  PerformOnBackgroundThread([]() {
   3136    auto testOriginMetadata = GetTestOriginMetadata();
   3137 
   3138    QuotaManager* quotaManager = QuotaManager::Get();
   3139    ASSERT_TRUE(quotaManager);
   3140 
   3141    {
   3142      auto value = Await(quotaManager->ClearStoragesForOriginAttributesPattern(
   3143          OriginAttributesPattern()));
   3144      ASSERT_TRUE(value.IsResolve());
   3145 
   3146      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3147      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3148      ASSERT_FALSE(
   3149          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3150    }
   3151  });
   3152 
   3153  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3154 
   3155  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3156 }
   3157 
   3158 TEST_F(TestQuotaManager, ClearPrivateRepository_OriginDirectoryExists) {
   3159  auto testOriginMetadata = GetTestPrivateOriginMetadata();
   3160 
   3161  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3162 
   3163  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3164  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3165  ASSERT_NO_FATAL_FAILURE(
   3166      AssertTemporaryOriginNotInitialized(testOriginMetadata));
   3167 
   3168  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3169  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3170  ASSERT_NO_FATAL_FAILURE(
   3171      InitializeTemporaryOrigin(testOriginMetadata,
   3172                                /* aCreateIfNonExistent */ true));
   3173 
   3174  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3175  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3176  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testOriginMetadata));
   3177 
   3178  PerformOnBackgroundThread([testOriginMetadata]() {
   3179    QuotaManager* quotaManager = QuotaManager::Get();
   3180    ASSERT_TRUE(quotaManager);
   3181 
   3182    {
   3183      auto value = Await(quotaManager->ClearPrivateRepository());
   3184      ASSERT_TRUE(value.IsResolve());
   3185 
   3186      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3187      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3188      ASSERT_FALSE(
   3189          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3190    }
   3191  });
   3192 
   3193  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3194 
   3195  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3196 }
   3197 
   3198 TEST_F(TestQuotaManager, ClearPrivateRepository_ClientDirectoryExists) {
   3199  auto testClientMetadata = GetTestPrivateClientMetadata();
   3200 
   3201  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3202 
   3203  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3204  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3205  ASSERT_NO_FATAL_FAILURE(
   3206      AssertTemporaryOriginNotInitialized(testClientMetadata));
   3207 
   3208  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3209  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3210  ASSERT_NO_FATAL_FAILURE(
   3211      InitializeTemporaryOrigin(testClientMetadata,
   3212                                /* aCreateIfNonExistent */ true));
   3213  ASSERT_NO_FATAL_FAILURE(
   3214      InitializeTemporaryClient(testClientMetadata,
   3215                                /* aCreateIfNonExistent */ true));
   3216 
   3217  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3218  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3219  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testClientMetadata));
   3220 
   3221  PerformOnBackgroundThread([testClientMetadata]() {
   3222    QuotaManager* quotaManager = QuotaManager::Get();
   3223    ASSERT_TRUE(quotaManager);
   3224 
   3225    {
   3226      auto value = Await(quotaManager->ClearPrivateRepository());
   3227      ASSERT_TRUE(value.IsResolve());
   3228 
   3229      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3230      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3231      ASSERT_FALSE(
   3232          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   3233      ASSERT_FALSE(
   3234          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   3235    }
   3236  });
   3237 
   3238  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3239 
   3240  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3241 }
   3242 
   3243 // Test simple ShutdownStoragesForOrigin.
   3244 TEST_F(TestQuotaManager, ShutdownStoragesForOrigin_Simple) {
   3245  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3246 
   3247  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3248  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3249  ASSERT_NO_FATAL_FAILURE(
   3250      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   3251 
   3252  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3253  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3254  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3255      GetTestOriginMetadata(), /* aCreateIfNonExistent */ true));
   3256 
   3257  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3258  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3259  ASSERT_NO_FATAL_FAILURE(
   3260      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   3261 
   3262  PerformOnBackgroundThread([]() {
   3263    auto testOriginMetadata = GetTestOriginMetadata();
   3264 
   3265    nsCOMPtr<nsIPrincipal> principal =
   3266        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   3267    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3268 
   3269    mozilla::ipc::PrincipalInfo principalInfo;
   3270    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3271           QM_TEST_FAIL);
   3272 
   3273    QuotaManager* quotaManager = QuotaManager::Get();
   3274    ASSERT_TRUE(quotaManager);
   3275 
   3276    {
   3277      auto value = Await(quotaManager->ShutdownStoragesForOrigin(
   3278          /* aPersistenceType */ Nothing(), principalInfo));
   3279      ASSERT_TRUE(value.IsResolve());
   3280 
   3281      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3282      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3283      ASSERT_FALSE(
   3284          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3285    }
   3286  });
   3287 
   3288  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3289 
   3290  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3291 }
   3292 
   3293 TEST_F(TestQuotaManager, ShutdownStoragesForOrigin_NonExistentOriginDirectory) {
   3294  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3295 
   3296  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3297  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3298  ASSERT_NO_FATAL_FAILURE(
   3299      AssertTemporaryOriginNotInitialized(GetTestOriginMetadata()));
   3300 
   3301  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3302  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3303  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3304      GetTestOriginMetadata(), /* aCreateIfNonExistent */ false));
   3305 
   3306  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3307  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3308  ASSERT_NO_FATAL_FAILURE(
   3309      AssertTemporaryOriginInitialized(GetTestOriginMetadata()));
   3310 
   3311  PerformOnBackgroundThread([]() {
   3312    auto testOriginMetadata = GetTestOriginMetadata();
   3313 
   3314    nsCOMPtr<nsIPrincipal> principal =
   3315        BasePrincipal::CreateContentPrincipal(testOriginMetadata.mOrigin);
   3316    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3317 
   3318    mozilla::ipc::PrincipalInfo principalInfo;
   3319    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3320           QM_TEST_FAIL);
   3321 
   3322    QuotaManager* quotaManager = QuotaManager::Get();
   3323    ASSERT_TRUE(quotaManager);
   3324 
   3325    {
   3326      auto value = Await(quotaManager->ShutdownStoragesForOrigin(
   3327          /* aPersistenceType */ Nothing(), principalInfo));
   3328      ASSERT_TRUE(value.IsResolve());
   3329 
   3330      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3331      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3332      ASSERT_FALSE(
   3333          quotaManager->IsTemporaryOriginInitialized(testOriginMetadata));
   3334    }
   3335  });
   3336 
   3337  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3338 
   3339  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3340 }
   3341 
   3342 TEST_F(TestQuotaManager, ShutdownStoragesForOrigin_ClientDirectoryExists) {
   3343  auto testClientMetadata = GetTestClientMetadata();
   3344 
   3345  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3346 
   3347  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3348  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3349  ASSERT_NO_FATAL_FAILURE(
   3350      AssertTemporaryOriginNotInitialized(testClientMetadata));
   3351 
   3352  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3353  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3354  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3355      testClientMetadata, /* aCreateIfNonExistent */ true));
   3356  ASSERT_NO_FATAL_FAILURE(
   3357      InitializeTemporaryClient(testClientMetadata,
   3358                                /* aCreateIfNonExistent */ true));
   3359 
   3360  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3361  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3362  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testClientMetadata));
   3363 
   3364  PerformOnBackgroundThread([testClientMetadata]() {
   3365    nsCOMPtr<nsIPrincipal> principal =
   3366        BasePrincipal::CreateContentPrincipal(testClientMetadata.mOrigin);
   3367    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3368 
   3369    mozilla::ipc::PrincipalInfo principalInfo;
   3370    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3371           QM_TEST_FAIL);
   3372 
   3373    QuotaManager* quotaManager = QuotaManager::Get();
   3374    ASSERT_TRUE(quotaManager);
   3375 
   3376    {
   3377      auto value = Await(quotaManager->ShutdownStoragesForOrigin(
   3378          /* aPersistenceType */ Nothing(), principalInfo));
   3379      ASSERT_TRUE(value.IsResolve());
   3380 
   3381      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3382      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3383      ASSERT_FALSE(
   3384          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   3385      ASSERT_FALSE(
   3386          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   3387    }
   3388  });
   3389 
   3390  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3391 
   3392  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3393 }
   3394 
   3395 // Test simple ShutdownStoragesForClient.
   3396 TEST_F(TestQuotaManager, ShutdownStoragesForClient_Simple) {
   3397  auto testClientMetadata = GetTestClientMetadata();
   3398 
   3399  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3400 
   3401  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3402  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageNotInitialized());
   3403  ASSERT_NO_FATAL_FAILURE(
   3404      AssertTemporaryOriginNotInitialized(testClientMetadata));
   3405 
   3406  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3407  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3408  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3409      testClientMetadata, /* aCreateIfNonExistent */ true));
   3410  ASSERT_NO_FATAL_FAILURE(
   3411      InitializeTemporaryClient(testClientMetadata,
   3412                                /* aCreateIfNonExistent */ true));
   3413 
   3414  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3415  ASSERT_NO_FATAL_FAILURE(AssertTemporaryStorageInitialized());
   3416  ASSERT_NO_FATAL_FAILURE(AssertTemporaryOriginInitialized(testClientMetadata));
   3417 
   3418  PerformOnBackgroundThread([testClientMetadata]() {
   3419    nsCOMPtr<nsIPrincipal> principal =
   3420        BasePrincipal::CreateContentPrincipal(testClientMetadata.mOrigin);
   3421    QM_TRY(MOZ_TO_RESULT(principal), QM_TEST_FAIL);
   3422 
   3423    mozilla::ipc::PrincipalInfo principalInfo;
   3424    QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)),
   3425           QM_TEST_FAIL);
   3426 
   3427    QuotaManager* quotaManager = QuotaManager::Get();
   3428    ASSERT_TRUE(quotaManager);
   3429 
   3430    {
   3431      auto value = Await(quotaManager->ShutdownStoragesForClient(
   3432          /* aPersistenceType */ Nothing(), principalInfo,
   3433          testClientMetadata.mClientType));
   3434      ASSERT_TRUE(value.IsResolve());
   3435 
   3436      ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3437      ASSERT_TRUE(quotaManager->IsTemporaryStorageInitialized());
   3438      ASSERT_TRUE(
   3439          quotaManager->IsTemporaryOriginInitialized(testClientMetadata));
   3440      ASSERT_FALSE(
   3441          quotaManager->IsTemporaryClientInitialized(testClientMetadata));
   3442    }
   3443  });
   3444 
   3445  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3446 
   3447  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3448 }
   3449 
   3450 // Test simple ShutdownStorage.
   3451 TEST_F(TestQuotaManager, ShutdownStorage_Simple) {
   3452  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3453 
   3454  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3455 
   3456  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3457 
   3458  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3459 
   3460  PerformOnBackgroundThread([]() {
   3461    QuotaManager* quotaManager = QuotaManager::Get();
   3462    ASSERT_TRUE(quotaManager);
   3463 
   3464    {
   3465      auto value = Await(quotaManager->ShutdownStorage());
   3466      ASSERT_TRUE(value.IsResolve());
   3467 
   3468      ASSERT_FALSE(quotaManager->IsStorageInitialized());
   3469    }
   3470  });
   3471 
   3472  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3473 
   3474  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3475 }
   3476 
   3477 // Test ShutdownStorage when a storage shutdown is already ongoing.
   3478 TEST_F(TestQuotaManager, ShutdownStorage_Ongoing) {
   3479  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3480 
   3481  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3482 
   3483  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3484 
   3485  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3486 
   3487  PerformOnBackgroundThread([]() {
   3488    QuotaManager* quotaManager = QuotaManager::Get();
   3489    ASSERT_TRUE(quotaManager);
   3490 
   3491    nsTArray<RefPtr<BoolPromise>> promises;
   3492 
   3493    promises.AppendElement(quotaManager->ShutdownStorage());
   3494    promises.AppendElement(quotaManager->ShutdownStorage());
   3495 
   3496    {
   3497      auto value =
   3498          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   3499      ASSERT_TRUE(value.IsResolve());
   3500 
   3501      ASSERT_FALSE(quotaManager->IsStorageInitialized());
   3502    }
   3503  });
   3504 
   3505  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3506 
   3507  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3508 }
   3509 
   3510 // Test ShutdownStorage when a storage shutdown is already ongoing and storage
   3511 // initialization is scheduled after that.
   3512 TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithScheduledInitialization) {
   3513  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3514 
   3515  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3516 
   3517  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3518 
   3519  ASSERT_NO_FATAL_FAILURE(AssertStorageInitialized());
   3520 
   3521  PerformOnBackgroundThread([]() {
   3522    QuotaManager* quotaManager = QuotaManager::Get();
   3523    ASSERT_TRUE(quotaManager);
   3524 
   3525    nsTArray<RefPtr<BoolPromise>> promises;
   3526 
   3527    promises.AppendElement(quotaManager->ShutdownStorage());
   3528    promises.AppendElement(quotaManager->InitializeStorage());
   3529    promises.AppendElement(quotaManager->ShutdownStorage());
   3530 
   3531    {
   3532      auto value =
   3533          Await(BoolPromise::All(GetCurrentSerialEventTarget(), promises));
   3534      ASSERT_TRUE(value.IsResolve());
   3535 
   3536      ASSERT_FALSE(quotaManager->IsStorageInitialized());
   3537    }
   3538  });
   3539 
   3540  ASSERT_NO_FATAL_FAILURE(AssertStorageNotInitialized());
   3541 
   3542  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3543 }
   3544 
   3545 // Test ShutdownStorage when a storage shutdown is already ongoing and a shared
   3546 // client directory lock is requested after that.
   3547 // The shared client directory lock doesn't have to be explicitly released
   3548 // because it gets invalidated while it's still pending which causes that any
   3549 // directory locks that were blocked by the shared client directory lock become
   3550 // unblocked.
   3551 TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithClientDirectoryLock) {
   3552  PerformOnBackgroundThread([]() {
   3553    QuotaManager* quotaManager = QuotaManager::Get();
   3554    ASSERT_TRUE(quotaManager);
   3555 
   3556    RefPtr<ClientDirectoryLock> directoryLock =
   3557        quotaManager->CreateDirectoryLock(GetTestClientMetadata(),
   3558                                          /* aExclusive */ false);
   3559 
   3560    nsTArray<RefPtr<BoolPromise>> promises;
   3561 
   3562    // This creates an exclusive directory lock internally.
   3563    promises.AppendElement(quotaManager->ShutdownStorage());
   3564 
   3565    // This directory lock can't be acquired yet because a storage shutdown
   3566    // (which uses an exclusive diretory lock internall) is ongoing.
   3567    promises.AppendElement(directoryLock->Acquire());
   3568 
   3569    // This second ShutdownStorage invalidates the directoryLock, so that
   3570    // directory lock can't ever be successfully acquired, the promise for it
   3571    // will be rejected when the first ShutdownStorage is finished (it
   3572    // releases its exclusive directory lock);
   3573    promises.AppendElement(quotaManager->ShutdownStorage());
   3574 
   3575    {
   3576      auto value = Await(
   3577          BoolPromise::AllSettled(GetCurrentSerialEventTarget(), promises));
   3578      ASSERT_TRUE(value.IsResolve());
   3579    }
   3580  });
   3581 }
   3582 
   3583 // Test basic ProcessPendingNormalOriginOperations behavior when a normal
   3584 // origin operation is triggered but not explicitly awaited.
   3585 TEST_F(TestQuotaManager, ProcessPendingNormalOriginOperations_Basic) {
   3586  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3587 
   3588  AssertStorageNotInitialized();
   3589 
   3590  PerformOnBackgroundThread([]() {
   3591    QuotaManager* quotaManager = QuotaManager::Get();
   3592    ASSERT_TRUE(quotaManager);
   3593 
   3594    ASSERT_FALSE(quotaManager->IsStorageInitialized());
   3595 
   3596    // Intentionally do not await the returned promise to test that
   3597    // ProcessPendingNormalOriginOperations correctly processes any pending
   3598    // events and waits for the completion of any normal origin operation,
   3599    // such as the one triggered by InitializeStorage. In theory, any similar
   3600    // method could be used here, InitializeStorage was chosen for its
   3601    // simplicity.
   3602    quotaManager->InitializeStorage();
   3603 
   3604    ASSERT_FALSE(quotaManager->IsStorageInitialized());
   3605 
   3606    quotaManager->ProcessPendingNormalOriginOperations();
   3607 
   3608    ASSERT_TRUE(quotaManager->IsStorageInitialized());
   3609  });
   3610 
   3611  AssertStorageInitialized();
   3612 
   3613  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3614 }
   3615 
   3616 TEST_F(TestQuotaManager, GetOriginStateMetadata_EmptyRepository) {
   3617  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3618 
   3619  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3620  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3621 
   3622  const auto maybeOriginStateMetadata =
   3623      GetOriginStateMetadata(GetTestOriginMetadata());
   3624  ASSERT_FALSE(maybeOriginStateMetadata);
   3625 
   3626  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3627 }
   3628 
   3629 TEST_F(TestQuotaManager, GetOriginStateMetadata_OriginDirectoryExists) {
   3630  auto testOriginMetadata = GetTestOriginMetadata();
   3631 
   3632  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3633 
   3634  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3635  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3636  ASSERT_NO_FATAL_FAILURE(
   3637      InitializeTemporaryOrigin(testOriginMetadata,
   3638                                /* aCreateIfNonExistent */ true));
   3639 
   3640  auto maybeOriginStateMetadata = GetOriginStateMetadata(testOriginMetadata);
   3641  ASSERT_TRUE(maybeOriginStateMetadata);
   3642 
   3643  auto originStateMetadata = maybeOriginStateMetadata.extract();
   3644  ASSERT_GT(originStateMetadata.mLastAccessTime, 0);
   3645  ASSERT_FALSE(originStateMetadata.mAccessed);
   3646  ASSERT_FALSE(originStateMetadata.mPersisted);
   3647 
   3648  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3649 }
   3650 
   3651 TEST_F(TestQuotaManager, TotalDirectoryIterations_ClearingEmptyRepository) {
   3652  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3653 
   3654  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3655  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3656 
   3657  const auto totalDirectoryIterationsBefore = TotalDirectoryIterations();
   3658 
   3659  ClearStoragesForOriginAttributesPattern(u""_ns);
   3660 
   3661  const auto totalDirectoryIterationsAfter = TotalDirectoryIterations();
   3662 
   3663  ASSERT_EQ(totalDirectoryIterationsAfter - totalDirectoryIterationsBefore, 0u);
   3664 
   3665  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3666 }
   3667 
   3668 TEST_F(TestQuotaManager, TotalDirectoryIterations_ClearingNonEmptyRepository) {
   3669  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3670 
   3671  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3672  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3673  ASSERT_NO_FATAL_FAILURE(
   3674      InitializeTemporaryOrigin(GetTestOriginMetadata(),
   3675                                /* aCreateIfNonExistent */ true));
   3676 
   3677  const auto totalDirectoryIterationsBefore = TotalDirectoryIterations();
   3678 
   3679  ClearStoragesForOriginAttributesPattern(u""_ns);
   3680 
   3681  const auto totalDirectoryIterationsAfter = TotalDirectoryIterations();
   3682 
   3683  ASSERT_EQ(totalDirectoryIterationsAfter - totalDirectoryIterationsBefore, 1u);
   3684 
   3685  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3686 }
   3687 
   3688 TEST_F(TestQuotaManager, SaveOriginAccessTimeCount_EmptyRepository) {
   3689  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3690 
   3691  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3692  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3693 
   3694  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
   3695  const auto saveOriginAccessTimeCountInternalBefore =
   3696      SaveOriginAccessTimeCountInternal();
   3697 
   3698  PerformOnBackgroundThread([]() {
   3699    QuotaManager* quotaManager = QuotaManager::Get();
   3700    MOZ_RELEASE_ASSERT(quotaManager);
   3701 
   3702    auto value =
   3703        Await(quotaManager->SaveOriginAccessTime(GetTestOriginMetadata()));
   3704    MOZ_RELEASE_ASSERT(value.IsReject());
   3705  });
   3706 
   3707  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
   3708  const auto saveOriginAccessTimeCountInternalAfter =
   3709      SaveOriginAccessTimeCountInternal();
   3710 
   3711  // Ensure access time update doesn't occur when origin doesn't exist.
   3712  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
   3713            0u);
   3714  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
   3715                saveOriginAccessTimeCountInternalBefore,
   3716            0u);
   3717 
   3718  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3719 }
   3720 
   3721 TEST_F(TestQuotaManager, SaveOriginAccessTimeCount_OriginDirectoryExists) {
   3722  auto testOriginMetadata = GetTestOriginMetadata();
   3723 
   3724  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3725 
   3726  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3727  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3728  ASSERT_NO_FATAL_FAILURE(
   3729      InitializeTemporaryOrigin(testOriginMetadata,
   3730                                /* aCreateIfNonExistent */ true));
   3731 
   3732  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
   3733  const auto saveOriginAccessTimeCountInternalBefore =
   3734      SaveOriginAccessTimeCountInternal();
   3735 
   3736  SaveOriginAccessTime(testOriginMetadata);
   3737 
   3738  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
   3739  const auto saveOriginAccessTimeCountInternalAfter =
   3740      SaveOriginAccessTimeCountInternal();
   3741 
   3742  // Confirm the access time update was recorded.
   3743  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
   3744            1u);
   3745  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
   3746                saveOriginAccessTimeCountInternalBefore,
   3747            1u);
   3748 
   3749  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3750 }
   3751 
   3752 TEST_F(TestQuotaManager, SaveOriginAccessTimeCount_NonExistingOriginDirectory) {
   3753  auto testOriginMetadata = GetTestOriginMetadata();
   3754 
   3755  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3756 
   3757  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3758  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3759  ASSERT_NO_FATAL_FAILURE(
   3760      InitializeTemporaryOrigin(testOriginMetadata,
   3761                                /* aCreateIfNonExistent */ false));
   3762 
   3763  const auto saveOriginAccessTimeCountBefore = SaveOriginAccessTimeCount();
   3764  const auto saveOriginAccessTimeCountInternalBefore =
   3765      SaveOriginAccessTimeCountInternal();
   3766 
   3767  SaveOriginAccessTime(testOriginMetadata);
   3768 
   3769  const auto saveOriginAccessTimeCountAfter = SaveOriginAccessTimeCount();
   3770  const auto saveOriginAccessTimeCountInternalAfter =
   3771      SaveOriginAccessTimeCountInternal();
   3772 
   3773  // Ensure access time update doesn't occur when origin doesn't exist.
   3774  ASSERT_EQ(saveOriginAccessTimeCountAfter - saveOriginAccessTimeCountBefore,
   3775            0u);
   3776  ASSERT_EQ(saveOriginAccessTimeCountInternalAfter -
   3777                saveOriginAccessTimeCountInternalBefore,
   3778            0u);
   3779 
   3780  ASSERT_NO_FATAL_FAILURE(ShutdownStorage());
   3781 }
   3782 
   3783 TEST_P(TestQuotaManagerAndClearStorageWithBoolPair,
   3784       ClearStoragesForOriginAttributesPattern_ThumbnailPrivateIdentity) {
   3785  const BoolPairTestParams& param = GetParam();
   3786 
   3787  const bool createThumbnailPrivateIdentityOrigins = param.first;
   3788  const bool keepTemporaryStorageInitialized = param.second;
   3789 
   3790  const uint32_t thumbnailPrivateIdentityId = PerformOnIOThread([]() {
   3791    QuotaManager* quotaManager = QuotaManager::Get();
   3792    MOZ_RELEASE_ASSERT(quotaManager);
   3793 
   3794    return quotaManager->GetThumbnailPrivateIdentityId();
   3795  });
   3796 
   3797  ASSERT_NO_FATAL_FAILURE(InitializeStorage());
   3798 
   3799  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryStorage());
   3800 
   3801  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3802      GetOriginMetadata(""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns),
   3803      /* aCreateIfNonExistent */ true));
   3804 
   3805  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3806      GetOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
   3807                        "http://www.mozilla.org"_ns),
   3808      /* aCreateIfNonExistent */ true));
   3809 
   3810  ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3811      GetOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
   3812                        "http://www.mozilla.com"_ns),
   3813      /* aCreateIfNonExistent */ true));
   3814 
   3815  if (createThumbnailPrivateIdentityOrigins) {
   3816    ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3817        GetOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3818                                       thumbnailPrivateIdentityId),
   3819                          "mozilla.org"_ns, "http://www.mozilla.org"_ns),
   3820        /* aCreateIfNonExistent */ true));
   3821 
   3822    ASSERT_NO_FATAL_FAILURE(InitializeTemporaryOrigin(
   3823        GetOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3824                                       thumbnailPrivateIdentityId),
   3825                          "mozilla.com"_ns, "http://www.mozilla.com"_ns),
   3826        /* aCreateIfNonExistent */ true));
   3827  }
   3828 
   3829  if (!keepTemporaryStorageInitialized) {
   3830    ASSERT_NO_FATAL_FAILURE(ShutdownTemporaryStorage());
   3831  }
   3832 
   3833  const auto iterationsBefore = TotalDirectoryIterations();
   3834 
   3835  ClearStoragesForOriginAttributesPattern(nsFmtString(
   3836      FMT_STRING(u"{{ \"userContextId\": {} }}"), thumbnailPrivateIdentityId));
   3837 
   3838  const auto iterationsAfter = TotalDirectoryIterations();
   3839 
   3840  const auto iterations = iterationsAfter - iterationsBefore;
   3841 
   3842  uint64_t expectedIterations = createThumbnailPrivateIdentityOrigins ? 5u
   3843                                : !keepTemporaryStorageInitialized    ? 3u
   3844                                                                      : 0u;
   3845  ASSERT_EQ(iterations, expectedIterations);
   3846 
   3847  const auto matchesUserContextId =
   3848      [thumbnailPrivateIdentityId](const auto& origin) {
   3849        return FindInReadable(nsFmtCString(FMT_STRING("userContextId={}"),
   3850                                           thumbnailPrivateIdentityId),
   3851                              origin);
   3852      };
   3853 
   3854  const auto origins = ListOrigins();
   3855 
   3856  const bool anyOriginsMatch =
   3857      std::any_of(origins.cbegin(), origins.cend(), matchesUserContextId);
   3858  ASSERT_FALSE(anyOriginsMatch);
   3859 
   3860  const auto cachedOrigins = ListCachedOrigins();
   3861 
   3862  const bool anyCachedOriginsMatch = std::any_of(
   3863      cachedOrigins.cbegin(), cachedOrigins.cend(), matchesUserContextId);
   3864  ASSERT_FALSE(anyCachedOriginsMatch);
   3865 }
   3866 
   3867 INSTANTIATE_TEST_SUITE_P(
   3868    , TestQuotaManagerAndClearStorageWithBoolPair,
   3869    testing::Values(
   3870        std::make_pair(/* createThumbnailPrivateIdentityOrigins */ true,
   3871                       /* keepTemporaryStorageInitialized */ true),
   3872        std::make_pair(/* createThumbnailPrivateIdentityOrigins */ true,
   3873                       /* keepTemporaryStorageInitialized */ false),
   3874        std::make_pair(/* createThumbnailPrivateIdentityOrigins */ false,
   3875                       /* keepTemporaryStorageInitialized */ true),
   3876        std::make_pair(/* createThumbnailPrivateIdentityOrigins */ false,
   3877                       /* keepTemporaryStorageInitialized */ false)),
   3878    [](const testing::TestParamInfo<BoolPairTestParams>& aParam)
   3879        -> std::string {
   3880      const BoolPairTestParams& param = aParam.param;
   3881 
   3882      const bool createThumbnailPrivateIdentityOrigins = param.first;
   3883      const bool keepTemporaryStorageInitialized = param.second;
   3884 
   3885      std::stringstream ss;
   3886 
   3887      ss << (createThumbnailPrivateIdentityOrigins
   3888                 ? "CreateThumbnailPrivateIdentityOrigins"
   3889                 : "NoThumbnailPrivateIdentityOrigins")
   3890         << "_"
   3891         << (keepTemporaryStorageInitialized ? "KeepTemporaryStorageInitialized"
   3892                                             : "ShutdownTemporaryStorage");
   3893 
   3894      return ss.str();
   3895    });
   3896 
   3897 TEST_F(TestQuotaManagerAndShutdownFixture,
   3898       ThumbnailPrivateIdentityTemporaryOriginCount) {
   3899  PerformOnIOThread([]() {
   3900    QuotaManager* quotaManager = QuotaManager::Get();
   3901    ASSERT_TRUE(quotaManager);
   3902 
   3903    const uint32_t thumbnailPrivateIdentityId =
   3904        quotaManager->GetThumbnailPrivateIdentityId();
   3905 
   3906    {
   3907      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3908                0u);
   3909 
   3910      quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
   3911          ""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3912      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3913                0u);
   3914 
   3915      quotaManager->AddTemporaryOrigin(
   3916          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
   3917                                "http://www.mozilla.org"_ns));
   3918      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3919                0u);
   3920 
   3921      quotaManager->AddTemporaryOrigin(
   3922          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
   3923                                "http://www.mozilla.com"_ns));
   3924      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3925                0u);
   3926 
   3927      quotaManager->AddTemporaryOrigin(
   3928          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3929                                             thumbnailPrivateIdentityId),
   3930                                "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3931      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3932                1u);
   3933 
   3934      quotaManager->AddTemporaryOrigin(
   3935          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3936                                             thumbnailPrivateIdentityId),
   3937                                "mozilla.com"_ns, "http://www.mozilla.com"_ns));
   3938      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3939                2u);
   3940 
   3941      quotaManager->RemoveTemporaryOrigin(GetFullOriginMetadata(
   3942          ""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3943      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3944                2u);
   3945 
   3946      quotaManager->RemoveTemporaryOrigin(
   3947          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
   3948                                "http://www.mozilla.org"_ns));
   3949      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3950                2u);
   3951 
   3952      quotaManager->RemoveTemporaryOrigin(
   3953          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
   3954                                "http://www.mozilla.com"_ns));
   3955      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3956                2u);
   3957 
   3958      quotaManager->RemoveTemporaryOrigin(
   3959          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3960                                             thumbnailPrivateIdentityId),
   3961                                "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3962      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3963                1u);
   3964 
   3965      quotaManager->RemoveTemporaryOrigin(
   3966          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3967                                             thumbnailPrivateIdentityId),
   3968                                "mozilla.com"_ns, "http://www.mozilla.com"_ns));
   3969      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3970                0u);
   3971    }
   3972 
   3973    {
   3974      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3975                0u);
   3976 
   3977      quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
   3978          ""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3979      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3980                0u);
   3981 
   3982      quotaManager->AddTemporaryOrigin(
   3983          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
   3984                                "http://www.mozilla.org"_ns));
   3985      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3986                0u);
   3987 
   3988      quotaManager->AddTemporaryOrigin(
   3989          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
   3990                                "http://www.mozilla.com"_ns));
   3991      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3992                0u);
   3993 
   3994      quotaManager->AddTemporaryOrigin(
   3995          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   3996                                             thumbnailPrivateIdentityId),
   3997                                "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   3998      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   3999                1u);
   4000 
   4001      quotaManager->AddTemporaryOrigin(
   4002          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   4003                                             thumbnailPrivateIdentityId),
   4004                                "mozilla.com"_ns, "http://www.mozilla.com"_ns));
   4005      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4006                2u);
   4007 
   4008      quotaManager->RemoveTemporaryOrigins(PERSISTENCE_TYPE_TEMPORARY);
   4009      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4010                2u);
   4011 
   4012      quotaManager->RemoveTemporaryOrigins(PERSISTENCE_TYPE_DEFAULT);
   4013      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4014                0u);
   4015    }
   4016 
   4017    {
   4018      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4019                0u);
   4020 
   4021      quotaManager->AddTemporaryOrigin(GetFullOriginMetadata(
   4022          ""_ns, "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   4023      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4024                0u);
   4025 
   4026      quotaManager->AddTemporaryOrigin(
   4027          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.org"_ns,
   4028                                "http://www.mozilla.org"_ns));
   4029      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4030                0u);
   4031 
   4032      quotaManager->AddTemporaryOrigin(
   4033          GetFullOriginMetadata("^userContextId=1"_ns, "mozilla.com"_ns,
   4034                                "http://www.mozilla.com"_ns));
   4035      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4036                0u);
   4037 
   4038      quotaManager->AddTemporaryOrigin(
   4039          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   4040                                             thumbnailPrivateIdentityId),
   4041                                "mozilla.org"_ns, "http://www.mozilla.org"_ns));
   4042      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4043                1u);
   4044 
   4045      quotaManager->AddTemporaryOrigin(
   4046          GetFullOriginMetadata(nsFmtCString(FMT_STRING("^userContextId={}"),
   4047                                             thumbnailPrivateIdentityId),
   4048                                "mozilla.com"_ns, "http://www.mozilla.com"_ns));
   4049      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4050                2u);
   4051 
   4052      quotaManager->RemoveTemporaryOrigins();
   4053      ASSERT_EQ(quotaManager->ThumbnailPrivateIdentityTemporaryOriginCount(),
   4054                0u);
   4055    }
   4056  });
   4057 }
   4058 
   4059 }  // namespace mozilla::dom::quota::test