// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <inttypes.h>

#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <ostream>
#include <set>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "base/auto_reset.h"
#include "base/barrier_closure.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock_id.h"
#include "components/services/storage/privileged/cpp/bucket_client_info.h"
#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h"
#include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h"
#include "components/services/storage/public/cpp/buckets/bucket_id.h"
#include "components/services/storage/public/cpp/buckets/bucket_info.h"
#include "components/services/storage/public/cpp/buckets/bucket_init_params.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "components/services/storage/public/cpp/quota_error_or.h"
#include "components/services/storage/public/mojom/storage_policy_update.mojom.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_data_format_version.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/instance/bucket_context.h"
#include "content/browser/indexed_db/instance/bucket_context_handle.h"
#include "content/browser/indexed_db/instance/connection.h"
#include "content/browser/indexed_db/instance/leveldb/backing_store.h"
#include "content/browser/indexed_db/instance/mock_blob_storage_context.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_factory_client.h"
#include "content/browser/indexed_db/status.h"
#include "env_chromium.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "net/base/features.h"
#include "net/base/schemeful_site.h"
#include "storage/browser/test/mock_quota_manager.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
#include "third_party/blink/public/mojom/storage_key/ancestor_chain_bit.mojom-shared.h"
#include "url/gurl.h"
#include "url/origin.h"

using base::test::RunClosure;
using blink::IndexedDBDatabaseMetadata;
using blink::IndexedDBIndexKeys;
using blink::IndexedDBKey;
using storage::BucketLocator;
using testing::_;
using testing::StrictMock;
using url::Origin;

namespace content::indexed_db {
namespace {

constexpr char16_t kDatabaseName[] = u"db";
constexpr char kOrigin[] = "https://www.example.com";

// TODO(crbug.com/41417435): Replace with common converter.
url::Origin ToOrigin(const std::string& url) {
  return url::Origin::Create(GURL(url));
}

MATCHER_P(IsAssociatedInterfacePtrInfoValid,
          tf,
          std::string(negation ? "isn't" : "is") + " " +
              std::string(tf ? "valid" : "invalid")) {
  return tf == arg->is_valid();
}

ACTION_P(QuitLoop, run_loop) {
  run_loop->Quit();
}

ACTION_TEMPLATE(MoveArgPointee,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(out)) {
  *out = std::move(*::testing::get<k>(args));
}

base::FilePath CreateAndReturnTempDir(base::ScopedTempDir* temp_dir) {
  CHECK(temp_dir->CreateUniqueTempDir());
  return temp_dir->GetPath();
}

storage::BucketInfo ToBucketInfo(const BucketLocator& bucket_locator) {
  storage::BucketInfo bucket_info;
  bucket_info.id = bucket_locator.id;
  bucket_info.storage_key = bucket_locator.storage_key;
  bucket_info.name = storage::kDefaultBucketName;
  return bucket_info;
}

// Stores data specific to a connection.
struct TestDatabaseConnection {
  TestDatabaseConnection() = default;

  TestDatabaseConnection(scoped_refptr<base::SequencedTaskRunner> task_runner,
                         url::Origin origin,
                         std::u16string db_name,
                         int64_t version,
                         int64_t upgrade_txn_id)
      : task_runner(std::move(task_runner)),
        origin(std::move(origin)),
        db_name(std::move(db_name)),
        version(version),
        upgrade_txn_id(upgrade_txn_id),
        open_callbacks(std::make_unique<StrictMock<MockMojoFactoryClient>>()),
        connection_callbacks(
            std::make_unique<StrictMock<MockMojoDatabaseCallbacks>>()) {}

  TestDatabaseConnection(const TestDatabaseConnection&) = delete;
  TestDatabaseConnection& operator=(const TestDatabaseConnection&) = delete;

  TestDatabaseConnection(TestDatabaseConnection&&) noexcept = default;
  TestDatabaseConnection& operator=(TestDatabaseConnection&&) noexcept =
      default;

  ~TestDatabaseConnection() = default;

  void Open(blink::mojom::IDBFactory* factory) {
    factory->Open(
        open_callbacks->CreateInterfacePtrAndBind(),
        connection_callbacks->CreateInterfacePtrAndBind(), db_name, version,
        version_change_transaction.BindNewEndpointAndPassReceiver(task_runner),
        upgrade_txn_id, /*priority=*/0);
    // ForcedClose is called on shutdown and depending on ordering and timing
    // may or may not happen, which is fine.
    EXPECT_CALL(*connection_callbacks, ForcedClose())
        .Times(testing::AnyNumber());
  }

  scoped_refptr<base::SequencedTaskRunner> task_runner;
  url::Origin origin;
  std::u16string db_name;
  int64_t version;
  int64_t upgrade_txn_id;

  mojo::AssociatedRemote<blink::mojom::IDBDatabase> database;
  mojo::AssociatedRemote<blink::mojom::IDBTransaction>
      version_change_transaction;

  std::unique_ptr<MockMojoFactoryClient> open_callbacks;
  std::unique_ptr<MockMojoDatabaseCallbacks> connection_callbacks;
};

class TestIndexedDBObserver : public storage::mojom::IndexedDBObserver {
 public:
  explicit TestIndexedDBObserver(
      mojo::PendingReceiver<storage::mojom::IndexedDBObserver> receiver)
      : receiver_(this, std::move(receiver)) {}

  void OnIndexedDBListChanged(const BucketLocator& bucket_locator) override {
    ++notify_list_changed_count;
  }

  void OnIndexedDBContentChanged(
      const BucketLocator& bucket_locator,
      const std::u16string& database_name,
      const std::u16string& object_store_name) override {
    ++notify_content_changed_count;
  }

  int notify_list_changed_count = 0;
  int notify_content_changed_count = 0;

 private:
  mojo::Receiver<storage::mojom::IndexedDBObserver> receiver_;
};

}  // namespace

class IndexedDBTest : public testing::Test,
                      public testing::WithParamInterface<bool> {
 public:
  blink::StorageKey kNormalFirstPartyStorageKey;
  BucketLocator kNormalFirstPartyBucketLocator;
  blink::StorageKey kSessionOnlyFirstPartyStorageKey;
  BucketLocator kSessionOnlyFirstPartyBucketLocator;
  blink::StorageKey kSessionOnlySubdomainFirstPartyStorageKey;
  BucketLocator kSessionOnlySubdomainFirstPartyBucketLocator;
  blink::StorageKey kNormalThirdPartyStorageKey;
  BucketLocator kNormalThirdPartyBucketLocator;
  blink::StorageKey kSessionOnlyThirdPartyStorageKey;
  BucketLocator kSessionOnlyThirdPartyBucketLocator;
  blink::StorageKey kSessionOnlySubdomainThirdPartyStorageKey;
  BucketLocator kSessionOnlySubdomainThirdPartyBucketLocator;
  blink::StorageKey kInvertedNormalThirdPartyStorageKey;
  BucketLocator kInvertedNormalThirdPartyBucketLocator;
  blink::StorageKey kInvertedSessionOnlyThirdPartyStorageKey;
  BucketLocator kInvertedSessionOnlyThirdPartyBucketLocator;
  blink::StorageKey kInvertedSessionOnlySubdomainThirdPartyStorageKey;
  BucketLocator kInvertedSessionOnlySubdomainThirdPartyBucketLocator;

  IndexedDBTest()
      : sqlite_override_(BucketContext::OverrideShouldUseSqliteForTesting(
            IsSqliteBackingStoreEnabled())),
        special_storage_policy_(
            base::MakeRefCounted<storage::MockSpecialStoragePolicy>()),
        quota_manager_(base::MakeRefCounted<storage::MockQuotaManager>(
            /*is_incognito=*/false,
            CreateAndReturnTempDir(&temp_dir_),
            base::SingleThreadTaskRunner::GetCurrentDefault(),
            special_storage_policy_)),
        quota_manager_proxy_(
            base::MakeRefCounted<storage::MockQuotaManagerProxy>(
                quota_manager_.get(),
                base::SequencedTaskRunner::GetCurrentDefault())) {
    mojo::PendingRemote<storage::mojom::BlobStorageContext>
        pending_blob_storage_context;
    blob_storage_context_.Clone(
        pending_blob_storage_context.InitWithNewPipeAndPassReceiver());
    context_ = std::make_unique<IndexedDBContextImpl>(
        temp_dir_.GetPath(), quota_manager_proxy_.get(),
        std::move(pending_blob_storage_context),
        /*file_system_access_context=*/mojo::NullRemote(),
        base::SequencedTaskRunner::GetCurrentDefault());
    // Let the mojo pipes be bound before proceeding. See
    // IndexedDBContextImpl::BindPipesOnIDBSequence().
    RunPostedTasks();

    kNormalFirstPartyStorageKey =
        blink::StorageKey::CreateFromStringForTesting("http://normal.com/");
    storage::BucketInfo bucket_info = InitBucket(kNormalFirstPartyStorageKey);
    kNormalFirstPartyBucketLocator = bucket_info.ToBucketLocator();

    kSessionOnlyFirstPartyStorageKey =
        blink::StorageKey::CreateFromStringForTesting(
            "http://session-only.com/");
    bucket_info = InitBucket(kSessionOnlyFirstPartyStorageKey);
    kSessionOnlyFirstPartyBucketLocator = bucket_info.ToBucketLocator();

    kSessionOnlySubdomainFirstPartyStorageKey =
        blink::StorageKey::CreateFromStringForTesting(
            "http://subdomain.session-only.com/");
    bucket_info = InitBucket(kSessionOnlySubdomainFirstPartyStorageKey);
    kSessionOnlySubdomainFirstPartyBucketLocator =
        bucket_info.ToBucketLocator();

    kNormalThirdPartyStorageKey = blink::StorageKey::Create(
        url::Origin::Create(GURL("http://normal.com/")),
        net::SchemefulSite(GURL("http://rando.com/")),
        blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kNormalThirdPartyStorageKey);
    kNormalThirdPartyBucketLocator = bucket_info.ToBucketLocator();

    kSessionOnlyThirdPartyStorageKey = blink::StorageKey::Create(
        url::Origin::Create(GURL("http://session-only.com/")),
        net::SchemefulSite(GURL("http://rando.com/")),
        blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kSessionOnlyThirdPartyStorageKey);
    kSessionOnlyThirdPartyBucketLocator = bucket_info.ToBucketLocator();

    kSessionOnlySubdomainThirdPartyStorageKey = blink::StorageKey::Create(
        url::Origin::Create(GURL("http://subdomain.session-only.com/")),
        net::SchemefulSite(GURL("http://rando.com/")),
        blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kSessionOnlySubdomainThirdPartyStorageKey);
    kSessionOnlySubdomainThirdPartyBucketLocator =
        bucket_info.ToBucketLocator();

    kInvertedNormalThirdPartyStorageKey = blink::StorageKey::Create(
        url::Origin::Create(GURL("http://rando.com/")),
        net::SchemefulSite(GURL("http://normal.com/")),
        blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kInvertedNormalThirdPartyStorageKey);
    kInvertedNormalThirdPartyBucketLocator = bucket_info.ToBucketLocator();

    kInvertedSessionOnlyThirdPartyStorageKey = blink::StorageKey::Create(
        url::Origin::Create(GURL("http://rando.com/")),
        net::SchemefulSite(GURL("http://session-only.com/")),
        blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kInvertedSessionOnlyThirdPartyStorageKey);
    kInvertedSessionOnlyThirdPartyBucketLocator = bucket_info.ToBucketLocator();

    kInvertedSessionOnlySubdomainThirdPartyStorageKey =
        blink::StorageKey::Create(
            url::Origin::Create(GURL("http://rando.com/")),
            net::SchemefulSite(GURL("http://subdomain.session-only.com/")),
            blink::mojom::AncestorChainBit::kCrossSite);
    bucket_info = InitBucket(kInvertedSessionOnlySubdomainThirdPartyStorageKey);
    kInvertedSessionOnlySubdomainThirdPartyBucketLocator =
        bucket_info.ToBucketLocator();

    std::vector<storage::mojom::StoragePolicyUpdatePtr> policy_updates;
    policy_updates.emplace_back(storage::mojom::StoragePolicyUpdate::New(
        url::Origin::Create(GURL("http://subdomain.session-only.com")),
        /*should_purge_on_shutdown=*/true));
    context_->ApplyPolicyUpdates(std::move(policy_updates));
  }

  IndexedDBTest(const IndexedDBTest&) = delete;
  IndexedDBTest& operator=(const IndexedDBTest&) = delete;

  ~IndexedDBTest() override = default;

  bool IsSqliteBackingStoreEnabled() { return GetParam(); }

  storage::BucketInfo InitBucket(const blink::StorageKey& storage_key) {
    storage::BucketInfo bucket;
    quota_manager_->UpdateOrCreateBucket(
        storage::BucketInitParams::ForDefaultBucket(storage_key),
        base::BindOnce(
            [](storage::BucketInfo* info,
               storage::QuotaErrorOr<storage::BucketInfo> bucket_info) {
              *info = bucket_info.value();
            },
            &bucket));
    return bucket;
  }

  void SetUpInMemoryContext() {
    mojo::PendingRemote<storage::mojom::BlobStorageContext>
        pending_blob_storage_context;
    blob_storage_context_.Clone(
        pending_blob_storage_context.InitWithNewPipeAndPassReceiver());
    context_ = std::make_unique<IndexedDBContextImpl>(
        base::FilePath(), quota_manager_proxy_.get(),
        std::move(pending_blob_storage_context),
        /*file_system_access_context=*/mojo::NullRemote(),
        base::SequencedTaskRunner::GetCurrentDefault());
    // The mojo pipes are bound asynchronously, and must be bound before
    // proceeding with testing.
    RunPostedTasks();
  }

  void RunPostedTasks() {
    base::RunLoop loop;
    context_->IDBTaskRunner()->PostTask(FROM_HERE, loop.QuitClosure());
    loop.Run();
  }

  void SetUp() override { ResetGlobalSweepAndCompactionTimesForTest(); }

  void TearDown() override {
    factory_remote_.reset();

    if (context_ && !context_->in_memory()) {
      std::set<BucketLocator> buckets = context_->bucket_set_;
      for (const BucketLocator& bucket_locator : buckets) {
        context_->DeleteBucketData(bucket_locator, base::DoNothing());
      }

      while (!context_->GetOpenBucketIdsForTesting().empty()) {
        RunPostedTasks();
      }
    }

    if (temp_dir_.IsValid()) {
      ASSERT_TRUE(temp_dir_.Delete());
    }
  }

  base::FilePath GetFilePathForTesting(const BucketLocator& bucket_locator) {
    return context()->GetFilePathForTesting(bucket_locator,
                                            IsSqliteBackingStoreEnabled());
  }

  bool IsThirdPartyStoragePartitioningEnabled() {
    // Enabled by default since 2023 for most platforms, but still off by
    // default for Android WebView.
    return base::FeatureList::IsEnabled(
        net::features::kThirdPartyStoragePartitioning);
  }

  bool DeleteBucket(const storage::BucketInfo* bucket_info) {
    base::test::TestFuture<blink::mojom::QuotaStatusCode> result_code;
    context()->DeleteBucketData(bucket_info->ToBucketLocator(),
                                result_code.GetCallback());
    return result_code.Get() == blink::mojom::QuotaStatusCode::kOk;
  }

  void BindFactory(
      mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
          checker_remote,
      mojo::PendingReceiver<blink::mojom::IDBFactory> receiver,
      storage::QuotaErrorOr<storage::BucketInfo> bucket_info) {
    context()->BindIndexedDBImpl(storage::BucketClientInfo{},
                                 std::move(checker_remote), std::move(receiver),
                                 bucket_info);
  }

  blink::StorageKey GetTestStorageKey() {
    return blink::StorageKey::CreateFromStringForTesting("http://test/");
  }

  // Opens a database connection, runs `action`, and verifies that the
  // connection was forced closed.
  void VerifyForcedClosedCalled(base::OnceClosure action,
                                storage::BucketInfo* out_info = nullptr) {
    storage::BucketInfo bucket_info = InitBucket(GetTestStorageKey());
    if (out_info) {
      *out_info = bucket_info;
    }
    BucketLocator bucket_locator = bucket_info.ToBucketLocator();
    base::FilePath test_path = GetFilePathForTesting(bucket_locator);

    // Bind the IDBFactory.
    mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
        checker_remote;
    BindFactory(std::move(checker_remote),
                factory_remote_.BindNewPipeAndPassReceiver(), bucket_info);

    // Open new connection/database, wait for success.
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    // It's necessary to hang onto the database connection or the connection
    // will shut itself down and there will be no `ForcedClosed()`.
    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
    EXPECT_CALL(client, MockedOpenSuccess)
        .WillOnce(
            testing::DoAll(MoveArgPointee<0>(&pending_database),
                           ::base::test::RunClosure(run_loop.QuitClosure())));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote_->Open(client.CreateInterfacePtrAndBind(),
                          database_callbacks.CreateInterfacePtrAndBind(),
                          u"opendb", /*version=*/0,
                          transaction_remote.BindNewEndpointAndPassReceiver(),
                          /*host_transaction_id=*/0, /*priority=*/0);
    run_loop.Run();
    EXPECT_TRUE(base::DirectoryExists(test_path));

    // Expect that deleting the data force closes the open database connection.
    base::RunLoop run_loop2;
    EXPECT_CALL(database_callbacks, ForcedClose())
        .WillOnce(::base::test::RunClosure(run_loop2.QuitClosure()));
    std::move(action).Run();
    run_loop2.Run();
  }

  BucketContext& GetOrCreateBucketContext(
      const storage::BucketInfo& bucket,
      const base::FilePath& data_directory) {
    context_->EnsureBucketContext(bucket, data_directory);
    return *GetBucketContext(bucket.id);
  }

  BucketContext* GetBucketContext(storage::BucketId id) {
    auto* sequence_bound = context_->GetBucketContextForTesting(id);
    if (!sequence_bound) {
      return nullptr;
    }
    base::test::TestFuture<BucketContext*> future;
    sequence_bound->AsyncCall(&BucketContext::GetReferenceForTesting)
        .Then(future.GetCallback());
    return future.Get();
  }

  storage::BucketInfo GetOrCreateBucket(
      const storage::BucketInitParams& params) {
    base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> future;
    quota_manager_proxy_->UpdateOrCreateBucket(
        params, base::SingleThreadTaskRunner::GetCurrentDefault(),
        future.GetCallback());
    return future.Take().value();
  }

  BucketContextHandle CreateBucketHandle(
      std::optional<storage::BucketLocator> bucket_locator = std::nullopt) {
    if (!bucket_locator) {
      const blink::StorageKey storage_key =
          blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
      bucket_locator = BucketLocator();
      bucket_locator->storage_key = storage_key;
    }
    context_->EnsureBucketContext(ToBucketInfo(*bucket_locator),
                                  context()->GetDataPath(*bucket_locator));
    BucketContextHandle bucket_context_handle(
        *GetBucketContext(bucket_locator->id));
    bucket_context_handle->InitBackingStore(
        /*create_if_missing=*/true);
    return bucket_context_handle;
  }

  void VerifyBucketContextWaitIfNeeded(const storage::BucketId& id,
                                       bool expected_context_exists) {
    while (expected_context_exists != context_->BucketContextExists(id)) {
      RunPostedTasks();
    }
    VerifyBucketContext(id, expected_context_exists);
  }

  void VerifyBucketContext(
      const storage::BucketId& id,
      bool expected_context_exists,
      std::optional<bool> expected_backing_store_exists = std::nullopt) {
    BucketContext* context = GetBucketContext(id);
    if (!expected_context_exists) {
      EXPECT_FALSE(context);
      EXPECT_FALSE(expected_backing_store_exists.has_value());
    } else {
      ASSERT_TRUE(context);
      if (expected_backing_store_exists.has_value()) {
        EXPECT_EQ(*expected_backing_store_exists, !!context->backing_store());
      }
    }
  }

 protected:
  IndexedDBContextImpl* context() const { return context_.get(); }
  base::AutoReset<std::optional<bool>> sqlite_override_;

  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  base::ScopedTempDir temp_dir_;
  scoped_refptr<storage::MockSpecialStoragePolicy> special_storage_policy_;
  scoped_refptr<storage::MockQuotaManager> quota_manager_;
  scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_;
  MockBlobStorageContext blob_storage_context_;
  std::unique_ptr<IndexedDBContextImpl> context_;
  mojo::Remote<blink::mojom::IDBFactory> factory_remote_;
};

INSTANTIATE_TEST_SUITE_P(
    /* no prefix */,
    IndexedDBTest,
    /*use SQLite backing store*/ testing::Bool(),
    [](const testing::TestParamInfo<IndexedDBTest::ParamType>& info) {
      return info.param ? "SQLite" : "LevelDB";
    });

TEST_P(IndexedDBTest, CloseConnectionBeforeUpgrade) {
  const int64_t kDBVersion = 1;
  const int64_t kTransactionId = 1;
  std::unique_ptr<TestDatabaseConnection> connection;
  IndexedDBDatabaseMetadata metadata;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              storage::BucketInfo());

  base::RunLoop loop;
  connection = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      kTransactionId);
  EXPECT_CALL(
      *connection->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(""), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
                               testing::SaveArg<4>(&metadata),
                               QuitLoop(&loop)));

  connection->Open(bounded_factory_remote.get());

  loop.Run();

  EXPECT_TRUE(pending_database.is_valid());
  EXPECT_EQ(connection->version, metadata.version);
  EXPECT_EQ(connection->db_name, metadata.name);

  // Close the connection to finish the test nicely.
  connection.reset();
}

TEST_P(IndexedDBTest, CloseAfterUpgrade) {
  const int64_t kDBVersion = 1;
  const int64_t kTransactionId = 1;
  const int64_t kObjectStoreId = 10;
  const char16_t kObjectStoreName[] = u"os";
  std::unique_ptr<TestDatabaseConnection> connection;
  IndexedDBDatabaseMetadata metadata;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              storage::BucketInfo());

  base::RunLoop loop;
  // Open connection.
  connection = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      kTransactionId);

  EXPECT_CALL(
      *connection->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(""), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
                               testing::SaveArg<4>(&metadata),
                               QuitLoop(&loop)));

  // Queue open request message.
  connection->Open(bounded_factory_remote.get());

  loop.Run();

  ASSERT_TRUE(pending_database.is_valid());
  EXPECT_EQ(connection->version, metadata.version);
  EXPECT_EQ(connection->db_name, metadata.name);

  base::RunLoop loop2;
  base::RepeatingClosure quit_closure2 =
      base::BarrierClosure(2, loop2.QuitClosure());

  ::testing::InSequence dummy;
  EXPECT_CALL(*connection->connection_callbacks, Complete(kTransactionId))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
      .Times(1)
      .WillOnce(RunClosure(std::move(quit_closure2)));

  connection->database.Bind(std::move(pending_database));
  ASSERT_TRUE(connection->database.is_bound());
  ASSERT_TRUE(connection->version_change_transaction.is_bound());
  connection->version_change_transaction->CreateObjectStore(
      kObjectStoreId, kObjectStoreName, blink::IndexedDBKeyPath(), false);
  connection->version_change_transaction->Commit(0);

  loop2.Run();

  // Close the connections to finish the test nicely.
  connection.reset();
}

// TODO(crbug.com/40813013): Test is flaky on Mac in debug.
#if BUILDFLAG(IS_MAC) && !defined(NDEBUG)
#define MAYBE_OpenNewConnectionWhileUpgrading \
  DISABLED_OpenNewConnectionWhileUpgrading
#else
#define MAYBE_OpenNewConnectionWhileUpgrading OpenNewConnectionWhileUpgrading
#endif
TEST_P(IndexedDBTest, MAYBE_OpenNewConnectionWhileUpgrading) {
  const int64_t kDBVersion = 1;
  const int64_t kTransactionId = 1;
  const int64_t kObjectStoreId = 10;
  const char16_t kObjectStoreName[] = u"os";
  std::unique_ptr<TestDatabaseConnection> connection1;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database1;
  IndexedDBDatabaseMetadata metadata1;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              storage::BucketInfo());

  base::RunLoop loop;
  // Open connection 1, and expect the upgrade needed.
  connection1 = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      kTransactionId);

  EXPECT_CALL(
      *connection1->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(""), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database1),
                               testing::SaveArg<4>(&metadata1),
                               QuitLoop(&loop)));

  // Queue open request message.
  connection1->Open(bounded_factory_remote.get());

  loop.Run();

  std::unique_ptr<TestDatabaseConnection> connection2;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database2;
  IndexedDBDatabaseMetadata metadata2;

  base::RunLoop loop2;
  base::RepeatingClosure quit_closure2 =
      base::BarrierClosure(3, loop2.QuitClosure());

  connection2 = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      0);

  // Check that we're called in order and the second connection gets it's
  // database after the first connection completes.
  ::testing::InSequence dummy;
  EXPECT_CALL(*connection1->connection_callbacks, Complete(kTransactionId))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection1->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection2->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(true), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database2),
                               testing::SaveArg<1>(&metadata2),
                               RunClosure(std::move(quit_closure2))));

  connection1->database.Bind(std::move(pending_database1));
  ASSERT_TRUE(connection1->database.is_bound());
  ASSERT_TRUE(connection1->version_change_transaction.is_bound());

  // Open connection 2, but expect that we won't be called back.
  connection2->Open(bounded_factory_remote.get());

  // Create object store.
  connection1->version_change_transaction->CreateObjectStore(
      kObjectStoreId, kObjectStoreName, blink::IndexedDBKeyPath(), false);
  connection1->version_change_transaction->Commit(0);

  loop2.Run();

  EXPECT_TRUE(pending_database2.is_valid());
  EXPECT_EQ(connection2->version, metadata2.version);
  EXPECT_EQ(connection2->db_name, metadata2.name);

  // Close the connections to finish the test nicely.
  connection1.reset();
  connection2.reset();
}

MATCHER_P(IsCallbackError, error_code, "") {
  if (arg->is_error_result() &&
      arg->get_error_result()->error_code == error_code) {
    return true;
  }
  return false;
}

// See https://crbug.com/989723 for more context, this test seems to flake.
TEST_P(IndexedDBTest, DISABLED_PutWithInvalidBlob) {
  const int64_t kDBVersion = 1;
  const int64_t kTransactionId = 1;
  const int64_t kObjectStoreId = 10;
  const char16_t kObjectStoreName[] = u"os";
  std::unique_ptr<TestDatabaseConnection> connection;
  IndexedDBDatabaseMetadata metadata;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              storage::BucketInfo());

  base::RunLoop loop;
  // Open connection.
  connection = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      kTransactionId);

  EXPECT_CALL(
      *connection->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(""), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
                               testing::SaveArg<4>(&metadata),
                               QuitLoop(&loop)));

  // Queue open request message.
  connection->Open(bounded_factory_remote.get());
  loop.Run();

  ASSERT_TRUE(pending_database.is_valid());
  EXPECT_EQ(connection->version, metadata.version);
  EXPECT_EQ(connection->db_name, metadata.name);

  base::MockCallback<blink::mojom::IDBTransaction::PutCallback> put_callback;

  base::RunLoop loop2;
  base::RepeatingClosure quit_closure2 =
      base::BarrierClosure(3, loop2.QuitClosure());

  ::testing::InSequence dummy;

  EXPECT_CALL(put_callback,
              Run(IsCallbackError(blink::mojom::IDBException::kUnknownError)))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));

  EXPECT_CALL(
      *connection->connection_callbacks,
      Abort(kTransactionId, blink::mojom::IDBException::kUnknownError, _))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));

  EXPECT_CALL(*connection->open_callbacks,
              Error(blink::mojom::IDBException::kAbortError, _))
      .Times(1)
      .WillOnce(RunClosure(std::move(quit_closure2)));

  connection->database.Bind(std::move(pending_database));
  ASSERT_TRUE(connection->database.is_bound());
  ASSERT_TRUE(connection->version_change_transaction.is_bound());
  connection->version_change_transaction->CreateObjectStore(
      kObjectStoreId, kObjectStoreName, blink::IndexedDBKeyPath(), false);
  // Call Put with an invalid blob.
  std::vector<blink::mojom::IDBExternalObjectPtr> external_objects;
  mojo::PendingRemote<blink::mojom::Blob> blob;
  // Ignore the result of InitWithNewPipeAndPassReceiver, to end up with
  // an invalid blob.
  std::ignore = blob.InitWithNewPipeAndPassReceiver();
  external_objects.push_back(blink::mojom::IDBExternalObject::NewBlobOrFile(
      blink::mojom::IDBBlobInfo::New(std::move(blob), std::u16string(), 100,
                                     nullptr)));

  auto new_value = blink::mojom::IDBValue::New();
  auto value = base::span_from_cstring("hello");
  new_value->bits.assign(value.begin(), value.end());
  new_value->external_objects = std::move(external_objects);

  connection->version_change_transaction->Put(
      kObjectStoreId, std::move(new_value), IndexedDBKey(u"hello"),
      blink::mojom::IDBPutMode::AddOnly, std::vector<IndexedDBIndexKeys>(),
      put_callback.Get());
  connection->version_change_transaction->Commit(0);

  loop2.Run();

  // Close the connection to finish the test nicely.
  connection.reset();
}

TEST_P(IndexedDBTest, NotifyIndexedDBListChanged) {
  const int64_t kDBVersion1 = 1;
  const int64_t kDBVersion2 = 2;
  const int64_t kDBVersion3 = 3;
  const int64_t kTransactionId1 = 1;
  const int64_t kTransactionId2 = 2;
  const int64_t kTransactionId3 = 3;
  const int64_t kObjectStoreId = 10;
  const int64_t kIndexId = 100;
  const char16_t kObjectStoreName[] = u"os";
  const char16_t kIndexName[] = u"index";

  mojo::PendingReceiver<storage::mojom::IndexedDBObserver> receiver;
  mojo::PendingRemote<storage::mojom::IndexedDBObserver> remote;
  TestIndexedDBObserver observer(remote.InitWithNewPipeAndPassReceiver());
  context()->AddObserver(std::move(remote));

  EXPECT_EQ(0, observer.notify_list_changed_count);
  EXPECT_EQ(0, observer.notify_content_changed_count);

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  const BucketLocator& bucket_locator = bucket_context_handle->bucket_locator();
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Open connection 1.
  std::unique_ptr<TestDatabaseConnection> connection1;

  IndexedDBDatabaseMetadata metadata1;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database1;
  EXPECT_EQ(0, observer.notify_list_changed_count);
  {
    base::RunLoop loop;
    connection1 = std::make_unique<TestDatabaseConnection>(
        context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName,
        kDBVersion1, kTransactionId1);

    EXPECT_CALL(
        *connection1->open_callbacks,
        MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                            IndexedDBDatabaseMetadata::NO_VERSION,
                            blink::mojom::IDBDataLoss::None, std::string(), _))
        .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database1),
                                 testing::SaveArg<4>(&metadata1),
                                 QuitLoop(&loop)));

    // Queue open request message.
    connection1->Open(bounded_factory_remote.get());
    loop.Run();
  }
  EXPECT_TRUE(pending_database1.is_valid());
  EXPECT_EQ(connection1->version, metadata1.version);
  EXPECT_EQ(connection1->db_name, metadata1.name);

  {
    ::testing::InSequence dummy;
    base::RunLoop loop;
    base::RepeatingClosure quit_closure =
        base::BarrierClosure(2, loop.QuitClosure());

    // Create object store and index.
    connection1->database.Bind(std::move(pending_database1));
    ASSERT_TRUE(connection1->database.is_bound());
    ASSERT_TRUE(connection1->version_change_transaction.is_bound());

    EXPECT_CALL(*connection1->connection_callbacks, Complete(kTransactionId1))
        .Times(1)
        .WillOnce(RunClosure(quit_closure));
    EXPECT_CALL(*connection1->open_callbacks,
                MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
        .Times(1)
        .WillOnce(RunClosure(std::move(quit_closure)));

    ASSERT_TRUE(connection1->database.is_bound());
    connection1->version_change_transaction->CreateObjectStore(
        kObjectStoreId, kObjectStoreName, blink::IndexedDBKeyPath(), false);
    connection1->database->CreateIndex(
        kTransactionId1, kObjectStoreId,
        blink::IndexedDBIndexMetadata(kIndexName, kIndexId,
                                      blink::IndexedDBKeyPath(), false, false));
    connection1->version_change_transaction->Commit(0);

    loop.Run();
  }

  EXPECT_EQ(1, observer.notify_list_changed_count);

  // Connection need to be closed before opening another connection. Because if
  // one connection triggers a version change, it can affect other open
  // connections as well.
  connection1.reset();
  // Open connection 2.
  std::unique_ptr<TestDatabaseConnection> connection2;

  IndexedDBDatabaseMetadata metadata2;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database2;
  {
    ::testing::InSequence dummy;
    base::RunLoop loop;
    base::RepeatingClosure quit_closure =
        base::BarrierClosure(2, loop.QuitClosure());

    connection2 = std::make_unique<TestDatabaseConnection>(
        context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName,
        kDBVersion2, kTransactionId2);

    EXPECT_CALL(*connection2->open_callbacks,
                MockedUpgradeNeeded(
                    IsAssociatedInterfacePtrInfoValid(true), kDBVersion1,
                    blink::mojom::IDBDataLoss::None, std::string(), _))
        .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database2),
                                 testing::SaveArg<4>(&metadata2),
                                 QuitLoop(&loop)));

    // Queue open request message.
    connection2->Open(bounded_factory_remote.get());

    loop.Run();
  }
  EXPECT_TRUE(pending_database2.is_valid());
  EXPECT_EQ(connection2->version, metadata2.version);
  EXPECT_EQ(connection2->db_name, metadata2.name);

  {
    ::testing::InSequence dummy;
    base::RunLoop loop;
    base::RepeatingClosure quit_closure =
        base::BarrierClosure(2, loop.QuitClosure());

    // Delete index.
    connection2->database.Bind(std::move(pending_database2));
    ASSERT_TRUE(connection2->database.is_bound());
    ASSERT_TRUE(connection2->version_change_transaction.is_bound());

    EXPECT_CALL(*connection2->connection_callbacks, Complete(kTransactionId2))
        .Times(1)
        .WillOnce(RunClosure(quit_closure));
    EXPECT_CALL(*connection2->open_callbacks,
                MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
        .Times(1)
        .WillOnce(RunClosure(std::move(quit_closure)));

    ASSERT_TRUE(connection2->database.is_bound());
    connection2->database->DeleteIndex(kTransactionId2, kObjectStoreId,
                                       kIndexId);
    connection2->version_change_transaction->Commit(0);

    loop.Run();
  }
  EXPECT_EQ(2, observer.notify_list_changed_count);

  connection2.reset();

  // Open connection 3.
  std::unique_ptr<TestDatabaseConnection> connection3;

  IndexedDBDatabaseMetadata metadata3;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database3;
  {
    ::testing::InSequence dummy;
    base::RunLoop loop;
    connection3 = std::make_unique<TestDatabaseConnection>(
        context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName,
        kDBVersion3, kTransactionId3);

    EXPECT_CALL(*connection3->open_callbacks,
                MockedUpgradeNeeded(
                    IsAssociatedInterfacePtrInfoValid(true), kDBVersion2,
                    blink::mojom::IDBDataLoss::None, std::string(), _))
        .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database3),
                                 testing::SaveArg<4>(&metadata3),
                                 QuitLoop(&loop)));

    // Queue open request message.
    connection3->Open(bounded_factory_remote.get());

    loop.Run();
  }
  EXPECT_TRUE(pending_database3.is_valid());
  EXPECT_EQ(connection3->version, metadata3.version);
  EXPECT_EQ(connection3->db_name, metadata3.name);

  {
    ::testing::InSequence dummy;
    base::RunLoop loop;
    base::RepeatingClosure quit_closure =
        base::BarrierClosure(2, loop.QuitClosure());

    // Delete object store.
    connection3->database.Bind(std::move(pending_database3));
    ASSERT_TRUE(connection3->database.is_bound());
    ASSERT_TRUE(connection3->version_change_transaction.is_bound());

    EXPECT_CALL(*connection3->connection_callbacks, Complete(kTransactionId3))
        .Times(1)
        .WillOnce(RunClosure(quit_closure));
    EXPECT_CALL(*connection3->open_callbacks,
                MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
        .Times(1)
        .WillOnce(RunClosure(std::move(quit_closure)));

    ASSERT_TRUE(connection3->database.is_bound());
    connection3->version_change_transaction->DeleteObjectStore(kObjectStoreId);
    connection3->version_change_transaction->Commit(0);

    loop.Run();
  }
  EXPECT_EQ(3, observer.notify_list_changed_count);

  // Close the connections to finish the test nicely.
  connection3.reset();
}

MATCHER(IsSuccessKey, "") {
  return arg->is_key();
}

TEST_P(IndexedDBTest, NotifyIndexedDBContentChanged) {
  const int64_t kDBVersion1 = 1;
  const int64_t kDBVersion2 = 2;
  const int64_t kTransactionId1 = 1;
  const int64_t kTransactionId2 = 2;
  const int64_t kObjectStoreId = 10;
  const char16_t kObjectStoreName[] = u"os";

  mojo::PendingReceiver<storage::mojom::IndexedDBObserver> receiver;
  mojo::PendingRemote<storage::mojom::IndexedDBObserver> remote;
  TestIndexedDBObserver observer(remote.InitWithNewPipeAndPassReceiver());
  context()->AddObserver(std::move(remote));
  EXPECT_EQ(0, observer.notify_list_changed_count);
  EXPECT_EQ(0, observer.notify_content_changed_count);

  std::unique_ptr<TestDatabaseConnection> connection1;
  IndexedDBDatabaseMetadata metadata1;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database1;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;

  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  const BucketLocator& bucket_locator = bucket_context_handle->bucket_locator();
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  base::RunLoop loop;
  // Open connection 1.
  connection1 = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion1,
      kTransactionId1);

  EXPECT_CALL(
      *connection1->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database1),
                               testing::SaveArg<4>(&metadata1),
                               QuitLoop(&loop)));

  // Queue open request message.
  connection1->Open(bounded_factory_remote.get());

  loop.Run();

  EXPECT_TRUE(pending_database1.is_valid());
  EXPECT_EQ(connection1->version, metadata1.version);
  EXPECT_EQ(connection1->db_name, metadata1.name);

  base::MockCallback<blink::mojom::IDBTransaction::PutCallback> put_callback;

  // Add object store entry.
  base::RunLoop loop2;
  base::RepeatingClosure quit_closure2 =
      base::BarrierClosure(3, loop2.QuitClosure());
  ::testing::InSequence dummy;

  EXPECT_CALL(put_callback, Run(IsSuccessKey()))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection1->connection_callbacks, Complete(kTransactionId1))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection1->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
      .Times(1)
      .WillOnce(RunClosure(std::move(quit_closure2)));

  connection1->database.Bind(std::move(pending_database1));
  ASSERT_TRUE(connection1->database.is_bound());
  ASSERT_TRUE(connection1->version_change_transaction.is_bound());
  connection1->version_change_transaction->CreateObjectStore(
      kObjectStoreId, kObjectStoreName, blink::IndexedDBKeyPath(), false);

  auto new_value = blink::mojom::IDBValue::New();
  auto value = base::span_from_cstring("value");
  new_value->bits.assign(value.begin(), value.end());

  connection1->version_change_transaction->Put(
      kObjectStoreId, std::move(new_value), IndexedDBKey(u"key"),
      blink::mojom::IDBPutMode::AddOnly, std::vector<IndexedDBIndexKeys>(),
      put_callback.Get());
  connection1->version_change_transaction->Commit(0);

  loop2.Run();

  EXPECT_EQ(1, observer.notify_list_changed_count);
  EXPECT_EQ(1, observer.notify_content_changed_count);

  // Connection need to be closed before opening another connection. Because if
  // one connection triggers a version change, it can affect other open
  // connections as well.
  connection1.reset();

  std::unique_ptr<TestDatabaseConnection> connection2;
  IndexedDBDatabaseMetadata metadata2;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database2;

  // Open connection 2.
  base::RunLoop loop4;
  connection2 = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion2,
      kTransactionId2);

  EXPECT_CALL(
      *connection2->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true), kDBVersion1,
                          blink::mojom::IDBDataLoss::None, std::string(), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database2),
                               testing::SaveArg<4>(&metadata2),
                               QuitLoop(&loop4)));

  // Queue open request message.
  connection2->Open(bounded_factory_remote.get());

  loop4.Run();

  EXPECT_TRUE(pending_database2.is_valid());
  EXPECT_EQ(connection2->version, metadata2.version);
  EXPECT_EQ(connection2->db_name, metadata2.name);

  // Clear object store.
  base::RunLoop loop5;
  base::RepeatingClosure quit_closure5 =
      base::BarrierClosure(3, loop5.QuitClosure());

  EXPECT_CALL(*connection2->connection_callbacks, Complete(kTransactionId2))
      .Times(1)
      .WillOnce(RunClosure(quit_closure5));
  EXPECT_CALL(*connection2->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
      .Times(1)
      .WillOnce(RunClosure(quit_closure5));

  connection2->database.Bind(std::move(pending_database2));
  ASSERT_TRUE(connection2->database.is_bound());
  ASSERT_TRUE(connection2->version_change_transaction.is_bound());
  connection2->database->Clear(kTransactionId2, kObjectStoreId,
                               base::IgnoreArgs<bool>(quit_closure5));
  connection2->version_change_transaction->Commit(0);

  loop5.Run();

  // +1 list changed for the transaction
  EXPECT_EQ(2, observer.notify_list_changed_count);
  EXPECT_EQ(2, observer.notify_content_changed_count);

  // Close the connection to finish the test nicely.
  connection2.reset();
}

// The test is flaky. See https://crbug.com/324282438
TEST_P(IndexedDBTest, DISABLED_DatabaseOperationSequencing) {
  const int64_t kDBVersion = 1;
  const int64_t kTransactionId = 1;
  const std::u16string kObjectStoreName1 = u"os1";
  const std::u16string kObjectStoreName2 = u"os2";
  const std::u16string kObjectStoreName3 = u"os3";

  std::unique_ptr<TestDatabaseConnection> connection;
  IndexedDBDatabaseMetadata metadata;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;

  // Bind the IDBFactory.
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  mojo::Remote<blink::mojom::IDBFactory> bounded_factory_remote;
  BindFactory(std::move(checker_remote),
              bounded_factory_remote.BindNewPipeAndPassReceiver(),
              storage::BucketInfo());

  // Open the connection, which will initiate the "upgrade" transaction.
  base::RunLoop loop;
  // Open connection.
  connection = std::make_unique<TestDatabaseConnection>(
      context()->IDBTaskRunner(), ToOrigin(kOrigin), kDatabaseName, kDBVersion,
      kTransactionId);

  EXPECT_CALL(
      *connection->open_callbacks,
      MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
                          IndexedDBDatabaseMetadata::NO_VERSION,
                          blink::mojom::IDBDataLoss::None, std::string(""), _))
      .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
                               testing::SaveArg<4>(&metadata),
                               QuitLoop(&loop)));

  // Queue open request message.
  connection->Open(bounded_factory_remote.get());

  loop.Run();

  ASSERT_TRUE(pending_database.is_valid());
  EXPECT_EQ(connection->version, metadata.version);
  EXPECT_EQ(connection->db_name, metadata.name);

  EXPECT_EQ(0ULL, metadata.object_stores.size());

  // Within the "upgrade" transaction, create/delete/create object store. This
  // should leave only one store around if everything is processed in the
  // correct order.
  IndexedDBDatabaseMetadata metadata2;
  int64_t object_store_id = 1001;

  base::RunLoop loop2;
  base::RepeatingClosure quit_closure2 =
      base::BarrierClosure(2, loop2.QuitClosure());
  ::testing::InSequence dummy;

  EXPECT_CALL(*connection->connection_callbacks, Complete(kTransactionId))
      .Times(1)
      .WillOnce(RunClosure(quit_closure2));
  EXPECT_CALL(*connection->open_callbacks,
              MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
      .Times(1)
      .WillOnce(testing::DoAll(testing::SaveArg<1>(&metadata2),
                               RunClosure(std::move(quit_closure2))));

  connection->database.Bind(std::move(pending_database));
  ASSERT_TRUE(connection->database.is_bound());
  ASSERT_TRUE(connection->version_change_transaction.is_bound());

  // This will cause a CreateObjectStoreOperation to be queued and
  // run synchronously...
  connection->version_change_transaction->CreateObjectStore(
      ++object_store_id, kObjectStoreName1, blink::IndexedDBKeyPath(),
      /*auto_increment=*/false);

  // The following operations will queue operations, but the
  // operations will run asynchronously.

  // First, delete the previous store. Ensure that this succeeds
  // even if the previous action completed synchronously.
  connection->version_change_transaction->DeleteObjectStore(object_store_id);

  // Ensure that a create/delete pair where both parts are queued
  // succeeds.
  connection->version_change_transaction->CreateObjectStore(
      ++object_store_id, kObjectStoreName2, blink::IndexedDBKeyPath(),
      /*auto_increment=*/false);
  connection->version_change_transaction->DeleteObjectStore(object_store_id);

  // This store is left over, just to verify that everything
  // ran correctly.
  connection->version_change_transaction->CreateObjectStore(
      ++object_store_id, kObjectStoreName3, blink::IndexedDBKeyPath(),
      /*auto_increment=*/false);

  connection->version_change_transaction->Commit(0);

  loop2.Run();

  EXPECT_EQ(1ULL, metadata2.object_stores.size());
  EXPECT_EQ(metadata2.object_stores[object_store_id].name, kObjectStoreName3);

  // Close the connection to finish the test nicely.
  connection.reset();
}

TEST_P(IndexedDBTest, ClearSessionOnlyDatabases) {
  base::FilePath normal_path_first_party;
  base::FilePath session_only_path_first_party;
  base::FilePath session_only_subdomain_path_first_party;
  base::FilePath normal_path_third_party;
  base::FilePath session_only_path_third_party;
  base::FilePath session_only_subdomain_path_third_party;
  base::FilePath inverted_normal_path_third_party;
  base::FilePath inverted_session_only_path_third_party;
  base::FilePath inverted_session_only_subdomain_path_third_party;

  normal_path_first_party =
      GetFilePathForTesting(kNormalFirstPartyBucketLocator);
  session_only_path_first_party =
      GetFilePathForTesting(kSessionOnlyFirstPartyBucketLocator);
  session_only_subdomain_path_first_party =
      GetFilePathForTesting(kSessionOnlySubdomainFirstPartyBucketLocator);
  normal_path_third_party =
      GetFilePathForTesting(kNormalThirdPartyBucketLocator);
  session_only_path_third_party =
      GetFilePathForTesting(kSessionOnlyThirdPartyBucketLocator);
  session_only_subdomain_path_third_party =
      GetFilePathForTesting(kSessionOnlySubdomainThirdPartyBucketLocator);
  inverted_normal_path_third_party =
      GetFilePathForTesting(kInvertedNormalThirdPartyBucketLocator);
  inverted_session_only_path_third_party =
      GetFilePathForTesting(kInvertedSessionOnlyThirdPartyBucketLocator);
  inverted_session_only_subdomain_path_third_party = GetFilePathForTesting(
      kInvertedSessionOnlySubdomainThirdPartyBucketLocator);
  if (IsThirdPartyStoragePartitioningEnabled()) {
    EXPECT_NE(normal_path_first_party, normal_path_third_party);
    EXPECT_NE(session_only_path_first_party, session_only_path_third_party);
    EXPECT_NE(session_only_subdomain_path_first_party,
              session_only_subdomain_path_third_party);
    EXPECT_NE(inverted_normal_path_third_party,
              inverted_session_only_path_third_party);
    EXPECT_NE(inverted_normal_path_third_party,
              inverted_session_only_subdomain_path_third_party);
  } else {
    EXPECT_EQ(normal_path_first_party, normal_path_third_party);
    EXPECT_EQ(session_only_path_first_party, session_only_path_third_party);
    EXPECT_EQ(session_only_subdomain_path_first_party,
              session_only_subdomain_path_third_party);
    EXPECT_EQ(inverted_normal_path_third_party,
              inverted_session_only_path_third_party);
    EXPECT_EQ(inverted_normal_path_third_party,
              inverted_session_only_subdomain_path_third_party);
  }

  ASSERT_TRUE(base::CreateDirectory(normal_path_first_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_path_first_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_subdomain_path_first_party));
  ASSERT_TRUE(base::CreateDirectory(normal_path_third_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_path_third_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_subdomain_path_third_party));
  ASSERT_TRUE(base::CreateDirectory(inverted_normal_path_third_party));
  ASSERT_TRUE(base::CreateDirectory(inverted_session_only_path_third_party));
  ASSERT_TRUE(
      base::CreateDirectory(inverted_session_only_subdomain_path_third_party));

  base::RunLoop run_loop;
  context()->ForceInitializeFromFilesForTesting(run_loop.QuitClosure());
  run_loop.Run();

  IndexedDBContextImpl::Shutdown(std::move(context_));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(base::DirectoryExists(normal_path_first_party));
  EXPECT_TRUE(base::DirectoryExists(session_only_path_first_party));
  EXPECT_FALSE(base::DirectoryExists(session_only_subdomain_path_first_party));
  EXPECT_TRUE(base::DirectoryExists(normal_path_third_party));
  EXPECT_TRUE(base::DirectoryExists(session_only_path_third_party));
  EXPECT_FALSE(base::DirectoryExists(session_only_subdomain_path_third_party));
  EXPECT_TRUE(base::DirectoryExists(inverted_normal_path_third_party));
  // When storage partitioning is enabled these will be deleted because they
  // have a matching top-level site, but otherwise they won't be because the
  // deletion logic only considers the origin.
  if (IsThirdPartyStoragePartitioningEnabled()) {
    EXPECT_FALSE(base::DirectoryExists(inverted_session_only_path_third_party));
    EXPECT_FALSE(base::DirectoryExists(
        inverted_session_only_subdomain_path_third_party));
  } else {
    EXPECT_TRUE(base::DirectoryExists(inverted_session_only_path_third_party));
    EXPECT_TRUE(base::DirectoryExists(
        inverted_session_only_subdomain_path_third_party));
  }
}

TEST_P(IndexedDBTest, SetForceKeepSessionState) {
  base::FilePath normal_path_first_party;
  base::FilePath session_only_path_first_party;
  base::FilePath normal_path_third_party;
  base::FilePath session_only_path_third_party;

  // Save session state. This should bypass the destruction-time deletion.
  context()->SetForceKeepSessionState();

  normal_path_first_party =
      GetFilePathForTesting(kNormalFirstPartyBucketLocator);
  session_only_path_first_party =
      GetFilePathForTesting(kSessionOnlyFirstPartyBucketLocator);
  normal_path_third_party =
      GetFilePathForTesting(kNormalThirdPartyBucketLocator);
  session_only_path_third_party =
      GetFilePathForTesting(kSessionOnlyThirdPartyBucketLocator);
  if (IsThirdPartyStoragePartitioningEnabled()) {
    EXPECT_NE(normal_path_first_party, normal_path_third_party);
    EXPECT_NE(session_only_path_first_party, session_only_path_third_party);
  } else {
    EXPECT_EQ(normal_path_first_party, normal_path_third_party);
    EXPECT_EQ(session_only_path_first_party, session_only_path_third_party);
  }

  ASSERT_TRUE(base::CreateDirectory(normal_path_first_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_path_first_party));
  ASSERT_TRUE(base::CreateDirectory(normal_path_third_party));
  ASSERT_TRUE(base::CreateDirectory(session_only_path_third_party));

  context()->ForceInitializeFromFilesForTesting(base::DoNothing());
  base::RunLoop().RunUntilIdle();

  IndexedDBContextImpl::Shutdown(std::move(context_));
  base::RunLoop().RunUntilIdle();

  // No data was cleared because of SetForceKeepSessionState.
  EXPECT_TRUE(base::DirectoryExists(normal_path_first_party));
  EXPECT_TRUE(base::DirectoryExists(session_only_path_first_party));
  EXPECT_TRUE(base::DirectoryExists(normal_path_third_party));
  EXPECT_TRUE(base::DirectoryExists(session_only_path_third_party));
}

// Verifies that the IDB connection is force closed and the directory is deleted
// when the bucket is deleted.
TEST_P(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
  storage::BucketInfo bucket_info;
  VerifyForcedClosedCalled(
      base::BindOnce(base::IgnoreResult(&IndexedDBTest::DeleteBucket),
                     base::Unretained(this), &bucket_info),
      &bucket_info);
  // Additionally, the directory should be deleted.
  base::FilePath test_path =
      GetFilePathForTesting(bucket_info.ToBucketLocator());
  EXPECT_FALSE(base::DirectoryExists(test_path));
}

// Verifies that the IDB connection is force closed when the backing store has
// an error.
TEST_P(IndexedDBTest, ForceCloseOpenDatabasesOnDatabaseError) {
  storage::BucketInfo bucket_info;
  VerifyForcedClosedCalled(
      base::BindOnce(
          [](IndexedDBTest* test, storage::BucketInfo* bucket_info) {
            BucketContext* bucket = test->GetBucketContext(bucket_info->id);
            const auto& dbs = bucket->GetDatabasesForTesting();
            ASSERT_EQ(1U, dbs.size());
            for (auto& [name, db] : dbs) {
              bucket->OnDatabaseError(
                  db.get(), Status::InvalidArgument("operation not supported"),
                  std::string());
            }
          },
          this, &bucket_info),
      &bucket_info);
}

// Verifies that the IDB connection is force closed when the database is deleted
// via the mojo API.
TEST_P(IndexedDBTest, ForceCloseOpenDatabasesOnDeleteDatabase) {
  storage::BucketInfo bucket_info;
  VerifyForcedClosedCalled(
      base::BindOnce(
          [](mojo::Remote<blink::mojom::IDBFactory>* factory_remote) {
            MockMojoFactoryClient delete_client;
            (*factory_remote)
                ->DeleteDatabase(delete_client.CreateInterfacePtrAndBind(),
                                 u"opendb",
                                 /*force_close=*/true);
          },
          &this->factory_remote_),
      &bucket_info);
  base::FilePath test_path =
      GetFilePathForTesting(bucket_info.ToBucketLocator());
  EXPECT_TRUE(base::DirectoryExists(test_path));
}

// Regression test for https://crbug.com/446722008
TEST_P(IndexedDBTest, AvoidCrashAfterForceCloseDbAndThenOpen) {
  storage::BucketInfo bucket_info = InitBucket(GetTestStorageKey());
  BucketLocator bucket_locator = bucket_info.ToBucketLocator();
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote_.BindNewPipeAndPassReceiver(), bucket_info);

  // Open a database.
  base::RunLoop run_loop_for_first_open;
  MockMojoDatabaseCallbacks database_callbacks;
  EXPECT_CALL(database_callbacks, ForcedClose())
      .WillOnce(
          ::base::test::RunClosure(run_loop_for_first_open.QuitClosure()));
  MockMojoFactoryClient client;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
  EXPECT_CALL(client, MockedOpenSuccess)
      .WillOnce(MoveArgPointee<0>(&pending_database));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
  factory_remote_->Open(client.CreateInterfacePtrAndBind(),
                        database_callbacks.CreateInterfacePtrAndBind(),
                        u"opendb", /*version=*/0,
                        transaction_remote.BindNewEndpointAndPassReceiver(),
                        /*host_transaction_id=*/0, /*priority=*/0);

  // Delete with force_close = true.
  MockMojoFactoryClient delete_client;
  factory_remote_->DeleteDatabase(delete_client.CreateInterfacePtrAndBind(),
                                  u"opendb",
                                  /*force_close=*/true);

  // Open the database again, without waiting for any of the previous steps to
  // finish. The timing of this is very particular, which is why this test does
  // not use `VerifyForcedClosedCalled()`. If the second open() comes any later,
  // it will succeed because the original Database will have finished being
  // deleted. We want to verify that there is no crash in the situation where
  // the second open is handled while the database is still in the process of
  // being deleted.
  MockMojoFactoryClient client2;
  EXPECT_CALL(client2, Error);
  MockMojoDatabaseCallbacks database_callbacks2;
  base::RunLoop run_loop_for_second_open;
  EXPECT_CALL(database_callbacks2, ForcedClose())
      .WillOnce(
          ::base::test::RunClosure(run_loop_for_second_open.QuitClosure()));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote2;
  factory_remote_->Open(
      client2.CreateInterfacePtrAndBind(),
      database_callbacks2.CreateInterfacePtrAndBind(), u"opendb",
      /*version=*/0, transaction_remote2.BindNewEndpointAndPassReceiver(),
      /*host_transaction_id=*/42, /*priority=*/0);

  // Block until expectations are satisfied.
  run_loop_for_first_open.Run();
  run_loop_for_second_open.Run();
}

TEST_P(IndexedDBTest, BasicFactoryCreationAndTearDown) {
  const blink::StorageKey storage_key_1 =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  storage::BucketInfo bucket_1 = GetOrCreateBucket(
      storage::BucketInitParams::ForDefaultBucket(storage_key_1));
  BucketLocator bucket_locator_1 = bucket_1.ToBucketLocator();
  base::FilePath file_1 =
      GetFilePathForTesting(bucket_locator_1).AppendASCII("1.json");
  ASSERT_TRUE(CreateDirectory(file_1.DirName()));
  ASSERT_TRUE(base::WriteFile(file_1, std::string(10, 'a')));

  const blink::StorageKey storage_key_2 =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:82");
  storage::BucketInfo bucket_2 = GetOrCreateBucket(
      storage::BucketInitParams::ForDefaultBucket(storage_key_2));
  BucketLocator bucket_locator_2 = bucket_2.ToBucketLocator();
  base::FilePath file_2 =
      GetFilePathForTesting(bucket_locator_2).AppendASCII("2.json");
  ASSERT_TRUE(CreateDirectory(file_2.DirName()));
  ASSERT_TRUE(base::WriteFile(file_2, std::string(100, 'a')));

  const blink::StorageKey storage_key_3 =
      blink::StorageKey::CreateFromStringForTesting("http://localhost2:82");
  storage::BucketInfo bucket_3 = GetOrCreateBucket(
      storage::BucketInitParams::ForDefaultBucket(storage_key_3));
  BucketLocator bucket_locator_3 = bucket_3.ToBucketLocator();
  base::FilePath file_3 =
      GetFilePathForTesting(bucket_locator_3).AppendASCII("3.json");
  ASSERT_TRUE(CreateDirectory(file_3.DirName()));
  ASSERT_TRUE(base::WriteFile(file_3, std::string(1000, 'a')));

  const blink::StorageKey storage_key_4 = blink::StorageKey::Create(
      storage_key_1.origin(), net::SchemefulSite(storage_key_3.origin()),
      blink::mojom::AncestorChainBit::kCrossSite);
  storage::BucketInfo bucket_4 = GetOrCreateBucket(
      storage::BucketInitParams::ForDefaultBucket(storage_key_4));
  BucketLocator bucket_locator_4 = bucket_4.ToBucketLocator();
  base::FilePath file_4 =
      GetFilePathForTesting(bucket_locator_4).AppendASCII("4.json");
  ASSERT_TRUE(CreateDirectory(file_4.DirName()));
  ASSERT_TRUE(base::WriteFile(file_4, std::string(10000, 'a')));

  const blink::StorageKey storage_key_5 = storage_key_1;
  storage::BucketInitParams params(storage_key_5, "inbox");
  storage::BucketInfo bucket_5 = GetOrCreateBucket(params);
  BucketLocator bucket_locator_5 = bucket_5.ToBucketLocator();
  base::FilePath file_5 =
      GetFilePathForTesting(bucket_locator_5).AppendASCII("5.json");
  ASSERT_TRUE(CreateDirectory(file_5.DirName()));
  ASSERT_TRUE(base::WriteFile(file_5, std::string(20000, 'a')));
  EXPECT_NE(file_5.DirName(), file_1.DirName());

  GetOrCreateBucketContext(bucket_1, context()->GetDataPath(bucket_locator_1))
      .InitBackingStore(true);

  GetOrCreateBucketContext(bucket_2, context()->GetDataPath(bucket_locator_2))
      .InitBackingStore(true);

  GetOrCreateBucketContext(bucket_3, context()->GetDataPath(bucket_locator_3))
      .InitBackingStore(true);

  GetOrCreateBucketContext(bucket_4, context()->GetDataPath(bucket_locator_4))
      .InitBackingStore(true);

  GetOrCreateBucketContext(bucket_5, context()->GetDataPath(bucket_locator_5))
      .InitBackingStore(true);

  int64_t bucket_size_1 = base::ComputeDirectorySize(file_1.DirName());
  int64_t bucket_size_4 = base::ComputeDirectorySize(file_4.DirName());
  int64_t bucket_size_5 = base::ComputeDirectorySize(file_5.DirName());

  if (IsThirdPartyStoragePartitioningEnabled()) {
    // If third party storage partitioning is on, additional space is taken
    // by supporting files for the independent buckets.
    EXPECT_NE(bucket_size_1, bucket_size_4);
  }
  EXPECT_NE(bucket_size_1, bucket_size_5);

  if (IsThirdPartyStoragePartitioningEnabled()) {
    EXPECT_EQ(5ul, context_->GetOpenBucketIdsForTesting().size());
  } else {
    EXPECT_EQ(4ul, context_->GetOpenBucketIdsForTesting().size());
  }
}

TEST_P(IndexedDBTest, CloseSequenceStarts) {
  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  const storage::BucketId bucket_id =
      bucket_context_handle->bucket_locator().id;
  bucket_context_handle.Release();

  VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/true);
  EXPECT_TRUE(GetBucketContext(bucket_id)->IsClosing());

  context_->ForceClose(bucket_id, {}, base::DoNothing());
  VerifyBucketContextWaitIfNeeded(bucket_id, /*expected_context_exists=*/false);
}

// Similar to the above, but installs a receiver which prevents the bucket
// context from being destroyed.
TEST_P(IndexedDBTest, CloseWithReceiversActive) {
  // Create bucket context.
  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  const storage::BucketId bucket_id =
      bucket_context_handle->bucket_locator().id;
  // Connect an IDBFactory mojo client.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  bucket_context_handle->AddReceiver(
      storage::BucketClientInfo{}, std::move(checker_remote),
      factory_remote.BindNewPipeAndPassReceiver());

  // The bucket context and the backing store should exist.
  VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/true);

  // The last handle to the bucket context is released and the grace period
  // elapses.
  bucket_context_handle.Release();
  task_environment_.FastForwardBy(base::Seconds(2));

  // This destroys the backing store, but the bucket context itself still
  // exists...
  VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/false);

  // ...until the last mojo client is disconnected.
  factory_remote.reset();
  task_environment_.RunUntilIdle();

  VerifyBucketContext(bucket_id, /*expected_context_exists=*/false);
}

// Similar to the above, but reverses the order of receiver disconnection and
// handle destruction.
TEST_P(IndexedDBTest, CloseWithReceiversInactive) {
  // Create bucket context.
  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  const storage::BucketId bucket_id =
      bucket_context_handle->bucket_locator().id;
  // Connect an IDBFactory mojo client.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  bucket_context_handle->AddReceiver(
      storage::BucketClientInfo{}, std::move(checker_remote),
      factory_remote.BindNewPipeAndPassReceiver());

  // The bucket context and the backing store should exist.
  VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/true);

  // The last mojo client is disconnected.
  factory_remote.reset();
  task_environment_.RunUntilIdle();

  // The bucket context and the backing store should still exist.
  VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/true);

  // The last handle to the bucket context is released and the grace period
  // elapses.
  bucket_context_handle.Release();
  task_environment_.FastForwardBy(base::Seconds(2));

  VerifyBucketContext(bucket_id, /*expected_context_exists=*/false);
}

TEST_P(IndexedDBTest, PreCloseTasksStart) {
  if (IsSqliteBackingStoreEnabled()) {
    // SQLite doesn't have any pre-close tasks, although it may in the future,
    // such as vacuuming. For now this test is not relevant.
    GTEST_SKIP();
  }

  {
    // Open a connection & immediately release it to cause the closing sequence
    // to start.
    BucketContextHandle bucket_context_handle = CreateBucketHandle();
    storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id;

    mojo::Remote<blink::mojom::IDBFactory> factory_remote;
    mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
        checker_remote;
    BindFactory(std::move(checker_remote),
                factory_remote.BindNewPipeAndPassReceiver(),
                ToBucketInfo(bucket_context_handle->bucket_locator()));

    bucket_context_handle.Release();

    VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                        /*expected_backing_store_exists=*/true);
    EXPECT_TRUE(GetBucketContext(bucket_id)->IsClosing());

    EXPECT_EQ(BucketContext::ClosingState::kPreCloseGracePeriod,
              GetBucketContext(bucket_id)->closing_stage());

    task_environment_.FastForwardBy(base::Seconds(2));

    // The factory should be closed, as the pre close tasks are delayed.
    VerifyBucketContext(bucket_id, /*expected_context_exists=*/true,
                        /*expected_backing_store_exists=*/false);
  }

  // Move the clock to run the tasks in the next close sequence.
  // NOTE: The constants rate-limiting sweeps and compaction are currently the
  // same. This test may need to be restructured if these values diverge.
  task_environment_.FastForwardBy(kMaxGlobalSweepDelay);

  // Note that once the closing sequence has started, as is the case in the next
  // block, and if the test does anything to spin the message loop, such as
  // using a future to get the bucket context, the bucket context will be
  // destroyed. For that reason, the bucket context pointer is stored in
  // `bucket_context`.
  BucketContext* bucket_context = nullptr;

  {
    // Open a connection & immediately release it to cause the closing sequence
    // to start again.
    BucketContextHandle bucket_context_handle = CreateBucketHandle();
    bucket_context = bucket_context_handle.bucket_context();
    bucket_context_handle.Release();

    // Manually execute the timer so that the PreCloseTaskList task doesn't also
    // run.
    bucket_context->close_timer()->FireNow();

    // The pre-close tasks should be running now.
    EXPECT_EQ(BucketContext::ClosingState::kRunningPreCloseTasks,
              bucket_context->closing_stage());
  }

  {
    // Stop sweep by opening a connection.
    BucketContextHandle bucket_context_handle(*bucket_context);
    storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id;
    EXPECT_NE(BucketContext::ClosingState::kRunningPreCloseTasks,
              bucket_context->closing_stage());

    // Move clock forward to trigger next sweep, but storage key has longer
    // sweep minimum, so no tasks should execute.
    task_environment_.FastForwardBy(kMaxGlobalSweepDelay);

    bucket_context_handle.Release();
    EXPECT_EQ(BucketContext::ClosingState::kPreCloseGracePeriod,
              bucket_context->closing_stage());

    // Manually execute the timer so that the PreCloseTaskList task doesn't also
    // run.
    bucket_context->close_timer()->FireNow();
    ASSERT_TRUE(context_->BucketContextExists(bucket_id));
    EXPECT_TRUE(!!bucket_context->backing_store());

    VerifyBucketContextWaitIfNeeded(bucket_id,
                                    /*expected_context_exists=*/false);
  }

  {
    //  Finally, move the clock forward so the storage key should allow a sweep.
    task_environment_.FastForwardBy(kMaxBucketSweepDelay);
    BucketContextHandle bucket_context_handle = CreateBucketHandle();
    bucket_context = bucket_context_handle.bucket_context();
    storage::BucketId bucket_id = bucket_context_handle->bucket_locator().id;
    bucket_context_handle.Release();
    bucket_context->close_timer()->FireNow();

    ASSERT_TRUE(context_->BucketContextExists(bucket_id));
    EXPECT_EQ(BucketContext::ClosingState::kRunningPreCloseTasks,
              bucket_context->closing_stage());
  }
}

TEST_P(IndexedDBTest, InMemoryFactoriesStay) {
  SetUpInMemoryContext();

  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  BucketLocator bucket_locator = bucket_context_handle->bucket_locator();

  EXPECT_TRUE(bucket_context_handle->in_memory());
  BucketContext* bucket_context = bucket_context_handle.bucket_context();
  bucket_context_handle.Release();
  RunPostedTasks();

  EXPECT_TRUE(context_->BucketContextExists(bucket_locator.id));
  EXPECT_FALSE(bucket_context->IsClosing());

  context_->ForceClose(
      bucket_locator.id,
      storage::mojom::ForceCloseReason::FORCE_CLOSE_INTERNALS_PAGE,
      base::DoNothing());
  // Verify the in-memory factory sticks around. Since it would be destroyed
  // asynchronously, there's no reliable point in time to verify that
  // destruction *hasn't* happened, so just wait a bit before verifying.
  RunPostedTasks();
  RunPostedTasks();
  RunPostedTasks();

  VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/true);

  context_->ForceClose(
      bucket_locator.id,
      storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN,
      base::DoNothing());
  VerifyBucketContextWaitIfNeeded(bucket_locator.id,
                                  /*expected_context_exists=*/false);
}

TEST_P(IndexedDBTest, TooLongOrigin) {
  base::FilePath temp_dir =
      context()->GetFirstPartyDataPathForTesting().DirName();
  int limit = base::GetMaximumPathComponentLength(temp_dir);
  EXPECT_GT(limit, 0);

  std::string origin(limit + 1, 'x');
  const blink::StorageKey too_long_storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://" + origin +
                                                    ":81/");
  storage::BucketInfo bucket_info = GetOrCreateBucket(
      storage::BucketInitParams::ForDefaultBucket(too_long_storage_key));
  BucketLocator bucket_locator = bucket_info.ToBucketLocator();

  BucketContextHandle bucket_context_handle(GetOrCreateBucketContext(
      ToBucketInfo(bucket_locator), context()->GetDataPath(bucket_locator)));
  Status s;
  std::tie(s, std::ignore, std::ignore) =
      bucket_context_handle->InitBackingStore(
          /*create_if_missing=*/true);

  EXPECT_TRUE(s.IsIOError());
}

TEST_P(IndexedDBTest, FactoryForceClose) {
  BucketContextHandle bucket_context_handle = CreateBucketHandle();
  BucketLocator bucket_locator = bucket_context_handle->bucket_locator();

  bucket_context_handle->ForceClose(
      /*doom=*/false, "The database is force-closed for testing.");
  BucketContext* bucket_context = bucket_context_handle.bucket_context();
  bucket_context_handle.Release();

  ASSERT_TRUE(context_->BucketContextExists(bucket_locator.id));
  EXPECT_TRUE(!!bucket_context->backing_store());
  VerifyBucketContextWaitIfNeeded(bucket_locator.id,
                                  /*expected_context_exists=*/false);
}

// This test aims to verify the behavior of
// BucketContext::Delegate::on_receiver_bounced.
TEST_P(IndexedDBTest, CloseThenAddReceiver) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Trigger the bucket context to be created.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote1;
  BindFactory(
      mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>(),
      factory_remote1.BindNewPipeAndPassReceiver(),
      ToBucketInfo(bucket_locator));

  ASSERT_TRUE(context()->BucketContextExists(bucket_locator.id));

  // Remove the factory binding, and since there is no backing store yet, this
  // should trigger the destruction of the bucket context.
  factory_remote1.reset();

  // However, the bucket context still exists for now because shutdown is not
  // synchronous.
  ASSERT_TRUE(context()->BucketContextExists(bucket_locator.id));

  // Bind another IDB factory. It's important that this is called
  // synchronously because it will initially attempt to bind to the existing
  // bucket context above, but that fails in
  // BucketContext::AddReceiver().
  mojo::Remote<blink::mojom::IDBFactory> factory_remote2;
  BindFactory(
      mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>(),
      factory_remote2.BindNewPipeAndPassReceiver(),
      ToBucketInfo(bucket_locator));

  // Round trip a message through the new mojo pipe to verify that it is set
  // up correctly.
  factory_remote2.FlushForTesting();

  // It would be nice to re-verify that the new BucketContext is not the same
  // as the old one, but there's no good way to identify them through mojo and
  // no guarantee their memory addresses are different either.
}

// Tests that the backing store is closed when the connection is closed during
// upgrade.
TEST_P(IndexedDBTest, ConnectionCloseDuringUpgrade) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Now create a database and thus the backing store.
  MockMojoFactoryClient client;
  MockMojoDatabaseCallbacks database_callbacks;
  base::RunLoop run_loop;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
  EXPECT_CALL(client, MockedUpgradeNeeded)
      .WillOnce(
          testing::DoAll(MoveArgPointee<0>(&pending_database),
                         ::base::test::RunClosure(run_loop.QuitClosure())));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
  factory_remote->Open(client.CreateInterfacePtrAndBind(),
                       database_callbacks.CreateInterfacePtrAndBind(), u"db",
                       /*version=*/1,
                       transaction_remote.BindNewEndpointAndPassReceiver(),
                       /*transaction_id=*/1, /*priority=*/0);
  run_loop.Run();

  ASSERT_TRUE(context_->BucketContextExists(bucket_locator.id));
  EXPECT_FALSE(GetBucketContext(bucket_locator.id)->IsClosing());

  // Drop the connection.
  pending_database.reset();
  factory_remote.FlushForTesting();
  EXPECT_TRUE(GetBucketContext(bucket_locator.id)->IsClosing());
}

TEST_P(IndexedDBTest, DeleteDatabase) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Don't create a backing store if one doesn't exist.
  {
    // Delete db.
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, DeleteSuccess)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db",
                                   /*force_close=*/false);
    run_loop.Run();

    // Backing store shouldn't exist.
    ASSERT_TRUE(context_->BucketContextExists(bucket_locator.id));
    EXPECT_FALSE(GetBucketContext(bucket_locator.id)->backing_store());
  }

  // Now create a database and thus the backing store.
  {
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, MockedOpenSuccess)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(), u"db",
                         /*version=*/0,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/1, /*priority=*/0);
    run_loop.Run();
  }

  // Delete the database now that the backing store actually exists.
  {
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, DeleteSuccess)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db",
                                   /*force_close=*/false);
    run_loop.Run();

    // Since there are no more references the factory should be closing.
    ASSERT_TRUE(context_->BucketContextExists(bucket_locator.id));
    EXPECT_TRUE(GetBucketContext(bucket_locator.id)->IsClosing());
  }
}

// Verifies that deleting an existing database that is not currently open in the
// backing store works as expected.
TEST_P(IndexedDBTest, DeleteDatabase_Cold) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Create a database with a valid version so that it gets persisted.
  {
    base::HistogramTester histogram_tester;
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
    base::RunLoop upgrade_run_loop;
    EXPECT_CALL(client, MockedUpgradeNeeded)
        .WillOnce(testing::DoAll(
            MoveArgPointee<0>(&pending_database),
            ::base::test::RunClosure(upgrade_run_loop.QuitClosure())));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(), u"db",
                         /*version=*/1,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/1, /*priority=*/0);
    upgrade_run_loop.Run();

    // Commit the versionchange transaction, lest it be aborted and rolled back
    // and the database deleted.
    mojo::AssociatedRemote<blink::mojom::IDBDatabase> connection(
        std::move(pending_database));
    transaction_remote->Commit(0);

    base::RunLoop success_run_loop;
    EXPECT_CALL(client, MockedOpenSuccess)
        .WillOnce(::base::test::RunClosure(success_run_loop.QuitClosure()));
    success_run_loop.Run();

    histogram_tester.ExpectUniqueSample(
        "IndexedDB.BackingStore.CreateIfMissing.OnDisk",
        0 /*Status::Type::kOk*/, 1);
    histogram_tester.ExpectUniqueSample(
        "IndexedDB.BackingStore.CreateOrOpenDatabase.OnDisk",
        0 /*Status::Type::kOk*/, 1);
  }

  // Fast forward by the grace period so that the backing store gets closed.
  task_environment_.FastForwardBy(base::Seconds(2));
  VerifyBucketContext(bucket_locator.id, /*expected_context_exists=*/true,
                      /*expected_backing_store_exists=*/false);

  // Delete the database now, which should require reopening the backing store
  // (and the database).
  {
    base::HistogramTester histogram_tester;
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, DeleteSuccess)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->DeleteDatabase(client.CreateInterfacePtrAndBind(), u"db",
                                   /*force_close=*/false);
    run_loop.Run();

    // The backing store itself should not be created, just opened.
    histogram_tester.ExpectTotalCount(
        "IndexedDB.BackingStore.CreateIfMissing.OnDisk", 0);
    histogram_tester.ExpectUniqueSample(
        "IndexedDB.BackingStore.CreateOrOpenDatabase.OnDisk",
        0 /*Status::Type::kOk*/, 1);
  }
}

TEST_P(IndexedDBTest, GetDatabaseNames_NoFactory) {
  base::HistogramTester histogram_tester;
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Don't create a backing store if one doesn't exist.
  {
    base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>,
                           blink::mojom::IDBErrorPtr>
        info_future;
    factory_remote->GetDatabaseInfo(info_future.GetCallback());
    ASSERT_TRUE(info_future.Wait());
    EXPECT_FALSE(GetBucketContext(bucket_locator.id)->backing_store());
    // The duration histogram should not be recorded since this was a trivial
    // request (the backing store was not involved).
    histogram_tester.ExpectTotalCount(
        "IndexedDB.IDBFactory.GetDatabaseInfo.Duration.OnDisk", 0);
  }

  // Now create a database and thus the backing store.
  MockMojoFactoryClient client;
  MockMojoDatabaseCallbacks database_callbacks;
  base::RunLoop run_loop;
  // It's necessary to hang onto the database connection or the connection
  // will shut itself down and the backing store will close on its own.
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
  EXPECT_CALL(client, MockedOpenSuccess)
      .WillOnce(
          testing::DoAll(MoveArgPointee<0>(&pending_database),
                         ::base::test::RunClosure(run_loop.QuitClosure())));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
  factory_remote->Open(client.CreateInterfacePtrAndBind(),
                       database_callbacks.CreateInterfacePtrAndBind(), u"db",
                       /*version=*/0,
                       transaction_remote.BindNewEndpointAndPassReceiver(),
                       /*transaction_id=*/1, /*priority=*/0);
  run_loop.Run();
  // GetDatabaseInfo didn't create the factory, so it shouldn't close it.
  {
    base::test::TestFuture<std::vector<blink::mojom::IDBNameAndVersionPtr>,
                           blink::mojom::IDBErrorPtr>
        info_future;
    factory_remote->GetDatabaseInfo(info_future.GetCallback());
    ASSERT_TRUE(info_future.Wait());

    ASSERT_TRUE(context_->BucketContextExists(bucket_locator.id));
    EXPECT_FALSE(GetBucketContext(bucket_locator.id)->IsClosing());

    histogram_tester.ExpectUniqueSample(
        "IndexedDB.BackingStore.GetDatabaseNamesAndVersions.OnDisk",
        0 /*Status::Type::kOk*/, 1);
    histogram_tester.ExpectTotalCount(
        "IndexedDB.IDBFactory.GetDatabaseInfo.Duration.OnDisk", 1);
  }
}

// Regression test for crbug.com/376461709
TEST_P(IndexedDBTest, UpdatePriorityAfterForceClose) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Bind a connection/database.
  MockMojoFactoryClient client;
  MockMojoDatabaseCallbacks database_callbacks;
  base::RunLoop run_loop;
  mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
  EXPECT_CALL(client, MockedOpenSuccess)
      .WillOnce(
          testing::DoAll(MoveArgPointee<0>(&pending_database),
                         ::base::test::RunClosure(run_loop.QuitClosure())));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
  factory_remote->Open(client.CreateInterfacePtrAndBind(),
                       database_callbacks.CreateInterfacePtrAndBind(), u"db",
                       /*version=*/0,
                       transaction_remote.BindNewEndpointAndPassReceiver(),
                       /*transaction_id=*/1, /*priority=*/0);
  run_loop.Run();

  mojo::AssociatedRemote<blink::mojom::IDBDatabase> connection(
      std::move(pending_database));
  // Simulate force closing the context while `UpdatePriority` is in flight.
  context_->ForceClose(bucket_locator.id, {}, base::DoNothing());
  // Call this second in the unit test context to simulate losing the race.
  connection->UpdatePriority(1);
  connection.FlushForTesting();

  // Not crashing indicates success.
}

TEST_P(IndexedDBTest, QuotaErrorOnDbOpenError) {
  base::HistogramTester histograms;
  if (IsSqliteBackingStoreEnabled()) {
    // The mechanism used to induce errors (`MakeFileUnwritable`) doesn't work
    // on Fuchsia.
#if BUILDFLAG(IS_FUCHSIA)
    GTEST_SKIP();
#endif  // BUILDFLAG(IS_FUCHSIA)
  } else {
    leveldb_env::SetDBFactoryForTesting(base::BindRepeating(
        [](const leveldb_env::Options& options, const std::string& name,
           std::unique_ptr<leveldb::DB>* dbptr) {
          return leveldb_env::MakeIOError("foobar", "disk full",
                                          leveldb_env::MethodID::kCreateDir,
                                          base::File::FILE_ERROR_NO_SPACE);
        }));
  }

  // Bind the IDBFactory.
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.is_default = true;
  bucket_locator.storage_key = storage_key;
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  std::optional<base::FilePermissionRestorer> permission_restorer;
  if (IsSqliteBackingStoreEnabled()) {
    // First create a database successfully so that the directory exists, then
    // make the directory unwritable. This will make future attempts to open the
    // file fail.
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, MockedOpenSuccess)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(), u"db2",
                         /*version=*/0,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/1, /*priority=*/0);
    run_loop.Run();

    base::FilePath data_path = GetFilePathForTesting(bucket_locator);
    permission_restorer.emplace(data_path);
    ASSERT_TRUE(base::MakeFileUnwritable(data_path))
        << base::File::GetLastFileError();
    histograms.ExpectTotalCount("IndexedDB.SQLite.OpenRetryResult", 0);
  }

  // Expect an error when opening.
  MockMojoFactoryClient client;
  MockMojoDatabaseCallbacks database_callbacks;
  base::RunLoop run_loop;
  EXPECT_CALL(client, Error)
      .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
  mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
  factory_remote->Open(client.CreateInterfacePtrAndBind(),
                       database_callbacks.CreateInterfacePtrAndBind(), u"db",
                       /*version=*/1,
                       transaction_remote.BindNewEndpointAndPassReceiver(),
                       /*transaction_id=*/2, /*priority=*/0);
  run_loop.Run();

  if (IsSqliteBackingStoreEnabled()) {
    histograms.ExpectUniqueSample("IndexedDB.SQLite.OpenRetryResult",
                                  5 /*Status::Type::kDatabaseEngine*/, 1);
  }

  // An error on open results in a write error reported to the quota system.
  ASSERT_EQ(1U, quota_manager_->write_error_tracker().size());
  EXPECT_EQ(storage_key, quota_manager_->write_error_tracker().begin()->first);
  EXPECT_EQ(1, quota_manager_->write_error_tracker().begin()->second);

  leveldb_env::SetDBFactoryForTesting({});
}

TEST_P(IndexedDBTest, DatabaseFailedOpen) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;
  const std::u16string db_name(u"db");

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Open at version 2.
  {
    const int64_t db_version = 2;
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    base::RunLoop run_loop;
    EXPECT_CALL(client, MockedUpgradeNeeded)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(),
                         db_name, db_version,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/1, /*priority=*/0);
    run_loop.Run();
  }

  // Open at version < 2, which will fail.
  {
    const int64_t db_version = 1;
    base::RunLoop run_loop;
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    EXPECT_CALL(client, Error)
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(),
                         db_name, db_version,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/2, /*priority=*/0);
    run_loop.Run();
    BucketContext* bucket_context = GetBucketContext(bucket_locator.id);
    ASSERT_TRUE(bucket_context);
    EXPECT_FALSE(
        base::Contains(bucket_context->GetDatabasesForTesting(), db_name));
  }
}

// Test for `IndexedDBDataFormatVersion`.
TEST_P(IndexedDBTest, DataLoss) {
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;
  const std::u16string db_name(u"test_db");

  // Bind the IDBFactory.
  mojo::Remote<blink::mojom::IDBFactory> factory_remote;
  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
      checker_remote;
  BindFactory(std::move(checker_remote),
              factory_remote.BindNewPipeAndPassReceiver(),
              ToBucketInfo(bucket_locator));

  // Set a data format version and create a new database. No data loss.
  {
    base::AutoReset<IndexedDBDataFormatVersion> override_version(
        &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(),
        IndexedDBDataFormatVersion(3, 4));
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
    base::RunLoop run_loop;
    EXPECT_CALL(client, MockedUpgradeNeeded(
                            _, _, blink::mojom::IDBDataLoss::None, _, _))
        .WillOnce(
            testing::DoAll(MoveArgPointee<0>(&pending_database),
                           ::base::test::RunClosure(run_loop.QuitClosure())));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(),
                         db_name, /*version=*/1,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/1, /*priority=*/0);
    run_loop.Run();

    // Commit the versionchange transaction, lest it be aborted and rolled back
    // and the database deleted.
    mojo::AssociatedRemote<blink::mojom::IDBDatabase> connection(
        std::move(pending_database));
    transaction_remote->Commit(0);
    transaction_remote.FlushForTesting();

    // This step is necessary to make sure the backing store is closed so that
    // the second `Open` will initialize it with the new (older) data format
    // version. Without this step, the same `BackingStore` is reused because
    // it's kept around for 2 seconds after the last connection is dropped.
    base::RunLoop run_loop2;
    context_->ForceClose(
        bucket_locator.id,
        storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE,
        run_loop2.QuitClosure());
    run_loop2.Run();
  }

  // Set an older data format version and try to reopen said database. Expect
  // total data loss.
  {
    base::HistogramTester histograms;
    base::AutoReset<IndexedDBDataFormatVersion> override_version(
        &IndexedDBDataFormatVersion::GetMutableCurrentForTesting(),
        IndexedDBDataFormatVersion(3, 3));
    base::RunLoop run_loop;
    MockMojoFactoryClient client;
    MockMojoDatabaseCallbacks database_callbacks;
    EXPECT_CALL(client, MockedUpgradeNeeded(
                            _, _, blink::mojom::IDBDataLoss::Total, _, _))
        .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
    mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
    factory_remote->Open(client.CreateInterfacePtrAndBind(),
                         database_callbacks.CreateInterfacePtrAndBind(),
                         db_name, /*version=*/1,
                         transaction_remote.BindNewEndpointAndPassReceiver(),
                         /*transaction_id=*/2, /*priority=*/0);
    run_loop.Run();
    if (IsSqliteBackingStoreEnabled()) {
      histograms.ExpectUniqueSample("IndexedDB.SQLite.OpenRetryResult",
                                    0 /*Status::Type::kOk*/, 1);
    }
  }
}

#if BUILDFLAG(IS_WIN)
TEST_P(IndexedDBTest, FilePathLengthLogging) {
  base::HistogramTester histograms;

  // Open with a normal length origin; success.
  const blink::StorageKey storage_key =
      blink::StorageKey::CreateFromStringForTesting("http://localhost:81");
  BucketLocator bucket_locator = BucketLocator();
  bucket_locator.storage_key = storage_key;

  {
    mojo::Remote<blink::mojom::IDBFactory> factory_remote;
    mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
        checker_remote;
    BindFactory(std::move(checker_remote),
                factory_remote.BindNewPipeAndPassReceiver(),
                ToBucketInfo(bucket_locator));

    {
      const int64_t db_version = 1;
      MockMojoFactoryClient client;
      MockMojoDatabaseCallbacks database_callbacks;
      base::RunLoop run_loop;
      EXPECT_CALL(client, MockedUpgradeNeeded)
          .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
      mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
      factory_remote->Open(client.CreateInterfacePtrAndBind(),
                           database_callbacks.CreateInterfacePtrAndBind(),
                           /*db_name=*/u"db", db_version,
                           transaction_remote.BindNewEndpointAndPassReceiver(),
                           /*transaction_id=*/1, /*priority=*/0);
      run_loop.Run();
    }
  }

  if (IsSqliteBackingStoreEnabled()) {
    histograms.ExpectTotalCount("IndexedDB.FilePathLengthOverflow.LevelDB", 0);
  } else {
    // Normal origin: no path length issues; underflow buckets.
    histograms.ExpectUniqueSample("IndexedDB.FilePathLengthOverflow.LevelDB", 0,
                                  1);
    histograms.ExpectUniqueSample("IndexedDB.FilePathLengthOverflow.SQLite", 0,
                                  1);
  }

  // Open with a super long origin; error.
  bucket_locator.storage_key = blink::StorageKey::CreateFromStringForTesting(
      std::string("https://") + std::string(230, 'a') + ".com:81");
  bucket_locator.id = storage::BucketId::FromUnsafeValue(2);
  {
    mojo::Remote<blink::mojom::IDBFactory> factory_remote;
    mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
        checker_remote;
    BindFactory(std::move(checker_remote),
                factory_remote.BindNewPipeAndPassReceiver(),
                ToBucketInfo(bucket_locator));

    {
      const int64_t db_version = 1;
      MockMojoFactoryClient client;
      MockMojoDatabaseCallbacks database_callbacks;
      base::RunLoop run_loop;
      EXPECT_CALL(client, Error)
          .WillOnce(::base::test::RunClosure(run_loop.QuitClosure()));
      mojo::AssociatedRemote<blink::mojom::IDBTransaction> transaction_remote;
      factory_remote->Open(client.CreateInterfacePtrAndBind(),
                           database_callbacks.CreateInterfacePtrAndBind(),
                           /*db_name=*/u"db", db_version,
                           transaction_remote.BindNewEndpointAndPassReceiver(),
                           /*transaction_id=*/1, /*priority=*/0);
      run_loop.Run();
    }
  }

  if (IsSqliteBackingStoreEnabled()) {
    histograms.ExpectTotalCount("IndexedDB.FilePathLengthOverflow.LevelDB", 0);
  } else {
    // Expect additional logs to both of the histograms. Note that the exact
    // bucket depends on the length of the temp dir.
    histograms.ExpectTotalCount("IndexedDB.FilePathLengthOverflow.LevelDB", 2);
    histograms.ExpectTotalCount("IndexedDB.FilePathLengthOverflow.SQLite", 2);

    // The longest SQLite file name overflows by more than the LevelDB
    // equivalent.
    EXPECT_LT(
        histograms.GetTotalSum("IndexedDB.FilePathLengthOverflow.LevelDB"),
        histograms.GetTotalSum("IndexedDB.FilePathLengthOverflow.SQLite"));
  }
}
#endif

}  // namespace content::indexed_db
