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

#include "content/browser/indexed_db/instance/database.h"

#include <math.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected_macros.h"
#include "base/unguessable_token.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock_id.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h"
#include "components/services/storage/privileged/mojom/indexed_db_internals_types.mojom.h"
#include "content/browser/indexed_db/indexed_db_external_object.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/instance/backing_store.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/callback_helpers.h"
#include "content/browser/indexed_db/instance/connection.h"
#include "content/browser/indexed_db/instance/cursor.h"
#include "content/browser/indexed_db/instance/database_callbacks.h"
#include "content/browser/indexed_db/instance/factory_client.h"
#include "content/browser/indexed_db/instance/index_writer.h"
#include "content/browser/indexed_db/instance/pending_connection.h"
#include "content/browser/indexed_db/instance/transaction.h"
#include "content/browser/indexed_db/status.h"
#include "ipc/constants.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.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/leveldatabase/env_chromium.h"

using blink::IndexedDBDatabaseMetadata;
using blink::IndexedDBIndexKeys;
using blink::IndexedDBIndexMetadata;
using blink::IndexedDBKey;
using blink::IndexedDBKeyPath;
using blink::IndexedDBKeyRange;
using blink::IndexedDBObjectStoreMetadata;

namespace content::indexed_db {
namespace {

// `backing_store_db` can be null only if `mode` is VersionChange.
std::vector<PartitionedLockManager::PartitionedLockRequest>
BuildLockRequestsForLevelDb(const std::u16string& database_name,
                            const BackingStore::Database* backing_store_db,
                            blink::mojom::IDBTransactionMode mode,
                            const std::set<int64_t>& scope) {
  // NB: LevelDB lock IDs are potentially persisted to disk - see
  // `LevelDBPartitionedLock`.
  const constexpr int kDatabaseLockPartition = 0;
  PartitionedLockId database_lock_id{kDatabaseLockPartition,
                                     base::UTF16ToUTF8(database_name)};
  if (mode == blink::mojom::IDBTransactionMode::VersionChange) {
    return {{std::move(database_lock_id),
             PartitionedLockManager::LockType::kExclusive}};
  }
  CHECK(backing_store_db);
  std::vector<PartitionedLockManager::PartitionedLockRequest> lock_requests;
  lock_requests.reserve(1 + scope.size());
  lock_requests.emplace_back(std::move(database_lock_id),
                             PartitionedLockManager::LockType::kShared);
  const constexpr int kObjectStoreLockPartition = 1;
  const auto object_store_lock_type =
      mode == blink::mojom::IDBTransactionMode::ReadOnly
          ? PartitionedLockManager::LockType::kShared
          : PartitionedLockManager::LockType::kExclusive;
  for (int64_t object_store_id : scope) {
    lock_requests.emplace_back(
        PartitionedLockId{
            kObjectStoreLockPartition,
            backing_store_db->GetObjectStoreLockIdKey(object_store_id)},
        object_store_lock_type);
  }
  return lock_requests;
}

std::vector<PartitionedLockManager::PartitionedLockRequest>
BuildLockRequestsForSqlite(uint32_t database_id,
                           blink::mojom::IDBTransactionMode mode,
                           const std::set<int64_t>& scope) {
  // TODO(crbug.com/427608926): Refactor `PartitionedLockId` to not need `key`
  // to be a string.
  const constexpr int kMetadataLockPartition = 0;
  PartitionedLockId metadata_lock_id{kMetadataLockPartition,
                                     base::StringPrintf("%u", database_id)};
  if (mode == blink::mojom::IDBTransactionMode::VersionChange) {
    return {{std::move(metadata_lock_id),
             PartitionedLockManager::LockType::kExclusive}};
  }
  std::vector<PartitionedLockManager::PartitionedLockRequest> lock_requests{
      {std::move(metadata_lock_id), PartitionedLockManager::LockType::kShared}};
  if (mode == blink::mojom::IDBTransactionMode::ReadWrite) {
    const constexpr int kWriteOperationsLockPartition = 1;
    lock_requests.emplace_back(
        PartitionedLockId{kWriteOperationsLockPartition,
                          base::StringPrintf("%u", database_id)},
        PartitionedLockManager::LockType::kExclusive);
  }
  lock_requests.reserve(lock_requests.size() + scope.size());
  const constexpr int kObjectStoreLockPartition = 2;
  const auto object_store_lock_type =
      mode == blink::mojom::IDBTransactionMode::ReadOnly
          ? PartitionedLockManager::LockType::kShared
          : PartitionedLockManager::LockType::kExclusive;
  for (int64_t object_store_id : scope) {
    lock_requests.emplace_back(
        PartitionedLockId{
            kObjectStoreLockPartition,
            base::StringPrintf("%u|%lld", database_id, object_store_id)},
        object_store_lock_type);
  }
  return lock_requests;
}

// Values returned to the IDB client may contain a primary key value generated
// by IDB. This is optional and only done when using a key generator. This key
// value cannot (at least easily) be amended to the object being written to the
// database, so they are kept separately, and sent back with the original data
// so that the render process can amend the returned object.
blink::mojom::IDBReturnValuePtr ConvertValueToReturnValue(
    Transaction& transaction,
    IndexedDBValue value,
    blink::IndexedDBKey primary_key,
    blink::IndexedDBKeyPath key_path) {
  auto mojo_value = blink::mojom::IDBReturnValue::New();
  if (primary_key.IsValid()) {
    mojo_value->primary_key = std::move(primary_key);
    mojo_value->key_path = std::move(key_path);
  }
  mojo_value->value = transaction.BuildMojoValue(std::move(value));
  return mojo_value;
}

// Returns an `IDBReturnValuePtr` created from the cursor's current position.
blink::mojom::IDBReturnValuePtr ExtractReturnValueFromCursorValue(
    Transaction& transaction,
    const IndexedDBObjectStoreMetadata& object_store_metadata,
    BackingStore::Cursor& cursor) {
  IndexedDBValue value(std::move(cursor.GetValue()));

  const bool is_generated_key = !value.empty() &&
                                object_store_metadata.auto_increment &&
                                !object_store_metadata.key_path.IsNull();
  blink::IndexedDBKey primary_key;
  blink::IndexedDBKeyPath key_path;

  if (is_generated_key) {
    primary_key = cursor.GetPrimaryKey().Clone();
    key_path = object_store_metadata.key_path;
  }

  return ConvertValueToReturnValue(transaction, std::move(value),
                                   std::move(primary_key), std::move(key_path));
}

blink::mojom::IDBErrorPtr CreateIDBErrorPtr(blink::mojom::IDBException code,
                                            const std::string& message,
                                            Transaction* transaction) {
  transaction->IncrementNumErrorsSent();
  return blink::mojom::IDBError::New(code, base::UTF8ToUTF16(message));
}

}  // namespace

Database::OpenCursorOperationParams::OpenCursorOperationParams() = default;
Database::OpenCursorOperationParams::~OpenCursorOperationParams() = default;

Database::Database(uint32_t id_for_locks,
                   const std::u16string& name,
                   BucketContext& bucket_context)
    : id_for_locks_(id_for_locks),
      name_(name),
      bucket_context_(bucket_context),
      connection_coordinator_(this, bucket_context) {}

Database::~Database() = default;

BackingStore* Database::backing_store() {
  return bucket_context_->backing_store();
}

PartitionedLockManager& Database::lock_manager() {
  return bucket_context_->lock_manager();
}

int64_t Database::version() const {
  return backing_store_db_ ? metadata().version
                           : blink::IndexedDBDatabaseMetadata::NO_VERSION;
}

bool Database::IsInitialized() const {
  return backing_store_db_ != nullptr;
}

StatusOr<int64_t> Database::DeleteDatabase(std::vector<PartitionedLock> locks,
                                           base::OnceClosure on_complete) {
  if (!backing_store_db_) {
    return blink::IndexedDBDatabaseMetadata::DEFAULT_VERSION;
  }

  const int64_t old_version = version();
  Status s = backing_store_db_->DeleteDatabase(std::move(locks),
                                               std::move(on_complete));
  backing_store_db_.reset();
  if (!s.ok()) {
    return base::unexpected(s);
  }
  return old_version;
}

std::vector<PartitionedLockManager::PartitionedLockRequest>
Database::BuildLockRequestsForTransaction(
    blink::mojom::IDBTransactionMode mode,
    const std::set<int64_t>& scope) const {
  return bucket_context_->ShouldUseSqlite()
             ? BuildLockRequestsForSqlite(id_for_locks_, mode, scope)
             : BuildLockRequestsForLevelDb(name_, backing_store_db_.get(), mode,
                                           scope);
}

bool Database::OnlyHasOneClient() const {
  if (connections_.empty()) {
    return true;
  }

  const base::UnguessableToken& token = (*connections_.begin())->client_token();
  return std::all_of(connections_.begin(), connections_.end(),
                     [&token](Connection* connection) {
                       return connection->client_token() == token;
                     });
}

void Database::RequireBlockingTransactionClientsToBeActive(
    Transaction* current_transaction,
    std::vector<PartitionedLockManager::PartitionedLockRequest>&
        lock_requests) {
  if (OnlyHasOneClient()) {
    return;
  }

  std::vector<PartitionedLockId> blocked_lock_ids =
      lock_manager().GetUnacquirableLocks(lock_requests);

  if (blocked_lock_ids.empty()) {
    return;
  }

  for (Connection* connection : connections_) {
    if (connection->client_token() ==
        current_transaction->connection()->client_token()) {
      continue;
    }

    // If any of the connection's transactions is holding one of the blocked
    // lock IDs, require that client to be active.
    if (connection->IsHoldingLocks(blocked_lock_ids)) {
      connection->DisallowInactiveClient(
          storage::mojom::DisallowInactiveClientReason::
              kTransactionIsAcquiringLocks,
          base::DoNothing());
    }
  }
}

void Database::RegisterAndScheduleTransaction(Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::RegisterAndScheduleTransaction",
               "txn.id", transaction->id());
  // Locks for version change transactions are covered by `ConnectionRequest`.
  DCHECK_NE(transaction->mode(),
            blink::mojom::IDBTransactionMode::VersionChange);
  std::vector<PartitionedLockManager::PartitionedLockRequest> lock_requests =
      BuildLockRequestsForTransaction(transaction->mode(),
                                      transaction->scope());

  RequireBlockingTransactionClientsToBeActive(transaction, lock_requests);

  lock_manager().AcquireLocks(
      std::move(lock_requests), *transaction->mutable_locks_receiver(),
      base::BindOnce(&Transaction::Start, transaction->AsWeakPtr()),
      base::BindRepeating(&Connection::HasHigherPriorityThan,
                          transaction->mutable_locks_receiver()));
}

Status Database::RunTasks() {
  // First execute any pending tasks in the connection coordinator.
  ConnectionCoordinator::ExecuteTaskResult task_state;
  Status status;
  do {
    std::tie(task_state, status) =
        connection_coordinator_.ExecuteTask(!connections_.empty());
  } while (task_state == ConnectionCoordinator::ExecuteTaskResult::kMoreTasks);

  if (task_state == ConnectionCoordinator::ExecuteTaskResult::kError) {
    CHECK(!status.ok());
    return status;
  }

  bool transactions_removed = true;

  // Finally, execute transactions that have tasks & remove those that are
  // complete.
  while (transactions_removed) {
    transactions_removed = false;
    Transaction* finished_upgrade_transaction = nullptr;
    bool upgrade_transaction_commmitted = false;
    for (Connection* connection : connections_) {
      std::vector<int64_t> txns_to_remove;
      for (const auto& id_txn_pair : connection->transactions()) {
        Transaction* txn = id_txn_pair.second.get();
        // Determine if the transaction's task queue should be processed.
        switch (txn->state()) {
          case Transaction::FINISHED:
            if (txn->mode() ==
                blink::mojom::IDBTransactionMode::VersionChange) {
              finished_upgrade_transaction = txn;
              upgrade_transaction_commmitted = !txn->aborted();
            }
            txns_to_remove.push_back(id_txn_pair.first);
            continue;
          case Transaction::CREATED:
            continue;
          case Transaction::STARTED:
          case Transaction::COMMITTING:
            break;
        }

        // Process the queue for transactions that are STARTED or COMMITTING.
        // Add transactions that can be removed to a queue.
        StatusOr<Transaction::RunTasksResult> task_result = txn->RunTasks();
        if (!task_result.has_value()) {
          return task_result.error();
        }

        switch (task_result.value()) {
          case Transaction::RunTasksResult::kCommitted:
          case Transaction::RunTasksResult::kAborted:
            if (txn->mode() ==
                blink::mojom::IDBTransactionMode::VersionChange) {
              DCHECK(!finished_upgrade_transaction);
              finished_upgrade_transaction = txn;
              upgrade_transaction_commmitted = !txn->aborted();
            }
            txns_to_remove.push_back(txn->id());
            break;
          case Transaction::RunTasksResult::kNotFinished:
            continue;
        }
      }
      // Do the removals.
      for (int64_t id : txns_to_remove) {
        connection->RemoveTransaction(id);
        transactions_removed = true;
      }
      if (finished_upgrade_transaction) {
        connection_coordinator_.OnUpgradeTransactionFinished(
            upgrade_transaction_commmitted);
      }
    }
  }
  return Status::OK();
}

size_t Database::GetNumTransactionsAcrossAllConnections() const {
  size_t num_transactions = 0;
  for (auto& connection : connections_) {
    num_transactions += connection->transactions().size();
  }
  return num_transactions;
}

Status Database::ForceCloseAndRunTasks(const std::string& message) {
  if (!bucket_context_->ShouldUseSqlite()) {
    DCHECK(!force_closing_);
  } else if (force_closing_) {
    // Re-entrancy can validly occur if there's an error in the code below,
    // e.g. in `CloseAndReportForceClose`.
    return Status::OK();
  }

  force_closing_ = true;
  for (Connection* connection : connections_) {
    connection->CloseAndReportForceClose(message);
  }
  connections_.clear();
  IDB_RETURN_IF_ERROR(connection_coordinator_.PruneTasksForForceClose(message));
  connection_coordinator_.OnNoConnections();

  // Execute any pending tasks in the connection coordinator.
  ConnectionCoordinator::ExecuteTaskResult task_state;
  Status status;
  do {
    std::tie(task_state, status) = connection_coordinator_.ExecuteTask(false);
    DCHECK(task_state !=
           ConnectionCoordinator::ExecuteTaskResult::kPendingAsyncWork)
        << "There are no more connections, so all tasks should be able to "
           "complete synchronously.";
  } while (task_state != ConnectionCoordinator::ExecuteTaskResult::kDone &&
           task_state != ConnectionCoordinator::ExecuteTaskResult::kError);
  DCHECK(connections_.empty());
  bucket_context_->QueueRunTasks();
  return status;
}

void Database::ScheduleOpenConnection(
    std::unique_ptr<PendingConnection> connection) {
  CHECK(IsAcceptingConnections());

  connection_coordinator_.ScheduleOpenConnection(std::move(connection));
}

void Database::ScheduleDeleteDatabase(
    std::unique_ptr<FactoryClient> factory_client,
    base::OnceClosure on_deletion_complete) {
  connection_coordinator_.ScheduleDeleteDatabase(
      std::move(factory_client), std::move(on_deletion_complete));
}

Status Database::VersionChangeOperation(int64_t version,
                                        Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::VersionChangeOperation", "txn.id",
               transaction->id());
  int64_t old_version = metadata().version;
  DCHECK_GT(version, old_version);

  IDB_RETURN_IF_ERROR(
      transaction->BackingStoreTransaction()->SetDatabaseVersion(version));

  connection_coordinator_.BindVersionChangeTransactionReceiver();
  connection_coordinator_.OnUpgradeTransactionStarted(old_version);
  return Status::OK();
}

Status Database::GetOperation(int64_t object_store_id,
                              int64_t index_id,
                              IndexedDBKeyRange key_range,
                              CursorType cursor_type,
                              blink::mojom::IDBDatabase::GetCallback callback,
                              Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::GetOperation", "txn.id",
               transaction->id());

  const IndexedDBObjectStoreMetadata& object_store_metadata =
      GetObjectStoreMetadata(object_store_id);

  IndexedDBKey key;
  if (key_range.IsOnlyKey()) {
    key = std::move(key_range).TakeOnlyKey();
  } else {
    StatusOr<std::unique_ptr<BackingStore::Cursor>> backing_store_cursor;
    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
      // ObjectStore Retrieval Operation
      if (cursor_type == CursorType::kKeyOnly) {
        backing_store_cursor =
            transaction->BackingStoreTransaction()->OpenObjectStoreKeyCursor(
                object_store_id, key_range,
                blink::mojom::IDBCursorDirection::Next);
      } else {
        backing_store_cursor =
            transaction->BackingStoreTransaction()->OpenObjectStoreCursor(
                object_store_id, key_range,
                blink::mojom::IDBCursorDirection::Next);
      }
    } else if (cursor_type == CursorType::kKeyOnly) {
      // Index Value Retrieval Operation
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenIndexKeyCursor(
              object_store_id, index_id, key_range,
              blink::mojom::IDBCursorDirection::Next);
    } else {
      // Index Referenced Value Retrieval Operation
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenIndexCursor(
              object_store_id, index_id, key_range,
              blink::mojom::IDBCursorDirection::Next);
    }

    if (!backing_store_cursor.has_value()) {
      std::move(callback).Run(
          blink::mojom::IDBDatabaseGetResult::NewErrorResult(CreateIDBErrorPtr(
              blink::mojom::IDBException::kUnknownError,
              "Corruption detected, unable to continue", transaction)));
      return backing_store_cursor.error();
    }

    if (!*backing_store_cursor) {
      // This means we've run out of data.
      std::move(callback).Run(
          blink::mojom::IDBDatabaseGetResult::NewEmpty(true));
      return Status::OK();
    }

    key = std::move(**backing_store_cursor).TakeKey();
  }

  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
    // Object Store Retrieval Operation
    ASSIGN_OR_RETURN(
        IndexedDBValue value,
        transaction->BackingStoreTransaction()->GetRecord(object_store_id, key),
        [&callback, transaction](const Status& status) {
          std::move(callback).Run(
              blink::mojom::IDBDatabaseGetResult::NewErrorResult(
                  CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
                                    "Unknown error", transaction)));
          return status;
        });

    if (value.empty()) {
      std::move(callback).Run(
          blink::mojom::IDBDatabaseGetResult::NewEmpty(true));
      return Status::OK();
    }

    if (cursor_type == CursorType::kKeyOnly) {
      std::move(callback).Run(
          blink::mojom::IDBDatabaseGetResult::NewKey(std::move(key)));
      return Status::OK();
    }

    blink::IndexedDBKey primary_key;
    blink::IndexedDBKeyPath key_path;

    if (object_store_metadata.auto_increment &&
        !object_store_metadata.key_path.IsNull()) {
      primary_key = std::move(key);
      key_path = object_store_metadata.key_path;
    }

    blink::mojom::IDBReturnValuePtr mojo_value =
        ConvertValueToReturnValue(*transaction, std::move(value),
                                  std::move(primary_key), std::move(key_path));
    std::move(callback).Run(
        blink::mojom::IDBDatabaseGetResult::NewValue(std::move(mojo_value)));
    return Status::OK();
  }

  // From here we are dealing only with indexes.
  ASSIGN_OR_RETURN(
      IndexedDBKey primary_key,
      transaction->BackingStoreTransaction()->GetFirstPrimaryKeyForIndexKey(
          object_store_id, index_id, key),
      [&callback, transaction](const Status& status) {
        std::move(callback).Run(
            blink::mojom::IDBDatabaseGetResult::NewErrorResult(
                CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
                                  "Unknown error", transaction)));
        return status;
      });

  if (!primary_key.IsValid()) {
    std::move(callback).Run(blink::mojom::IDBDatabaseGetResult::NewEmpty(true));
    return Status::OK();
  }
  if (cursor_type == CursorType::kKeyOnly) {
    // Index Value Retrieval Operation
    std::move(callback).Run(
        blink::mojom::IDBDatabaseGetResult::NewKey(std::move(primary_key)));
    return Status::OK();
  }

  // Index Referenced Value Retrieval Operation
  ASSIGN_OR_RETURN(
      IndexedDBValue value,
      transaction->BackingStoreTransaction()->GetRecord(object_store_id,
                                                        primary_key),
      [&callback, transaction](const Status& status) {
        std::move(callback).Run(
            blink::mojom::IDBDatabaseGetResult::NewErrorResult(
                CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
                                  "Unknown error", transaction)));
        return status;
      });

  if (value.empty()) {
    std::move(callback).Run(blink::mojom::IDBDatabaseGetResult::NewEmpty(true));
    return Status::OK();
  }

  blink::IndexedDBKey primary_key_return;
  blink::IndexedDBKeyPath key_path_return;

  if (object_store_metadata.auto_increment &&
      !object_store_metadata.key_path.IsNull()) {
    primary_key_return = std::move(primary_key);
    key_path_return = object_store_metadata.key_path;
  }

  blink::mojom::IDBReturnValuePtr mojo_value = ConvertValueToReturnValue(
      *transaction, std::move(value), std::move(primary_key_return),
      std::move(key_path_return));
  std::move(callback).Run(
      blink::mojom::IDBDatabaseGetResult::NewValue(std::move(mojo_value)));
  return Status::OK();
}

Transaction::Operation Database::CreateGetAllOperation(
    int64_t object_store_id,
    int64_t index_id,
    blink::IndexedDBKeyRange key_range,
    blink::mojom::IDBGetAllResultType result_type,
    int64_t max_count,
    blink::mojom::IDBCursorDirection direction,
    blink::mojom::IDBDatabase::GetAllCallback callback,
    Transaction* transaction) {
  return BindWeakOperation(&Database::GetAllOperation, AsWeakPtr(),
                           object_store_id, index_id, std::move(key_range),
                           result_type, max_count, direction,
                           std::make_unique<GetAllResultSinkWrapper>(
                               transaction->AsWeakPtr(), std::move(callback)));
}

static_assert(sizeof(size_t) >= sizeof(int32_t),
              "Size of size_t is less than size of int32");
static_assert(blink::mojom::kIDBMaxMessageOverhead <= INT32_MAX,
              "kIDBMaxMessageOverhead is more than INT32_MAX");

Database::GetAllResultSinkWrapper::GetAllResultSinkWrapper(
    base::WeakPtr<Transaction> transaction,
    blink::mojom::IDBDatabase::GetAllCallback callback)
    : transaction_(transaction), callback_(std::move(callback)) {}

Database::GetAllResultSinkWrapper::~GetAllResultSinkWrapper() {
  if (!callback_) {
    return;
  }

  if (transaction_) {
    transaction_->IncrementNumErrorsSent();
    // If we're reaching this line because the Connection has been
    // disconnected from its remote, then `result_sink_` won't have been
    // successfully associated, and invoking any methods on it will CHECK.
    // See crbug.com/346955148.
    // TODO(crbug.com/347047640): remove this workaround when 347047640 is
    // fixed.
    if (!transaction_->connection()->is_shutting_down()) {
      DatabaseError error(blink::mojom::IDBException::kIgnorableAbortError,
                          "Backend aborted error");
      Get()->OnError(
          blink::mojom::IDBError::New(error.code(), error.message()));
    }
  } else {
    // Make sure `callback_` is invoked because the Mojo client is waiting for a
    // response.
    Get();
  }
}

mojo::AssociatedRemote<blink::mojom::IDBDatabaseGetAllResultSink>&
Database::GetAllResultSinkWrapper::Get() {
  if (!result_sink_) {
    mojo::PendingAssociatedReceiver<blink::mojom::IDBDatabaseGetAllResultSink>
        pending_receiver;
    if (use_dedicated_receiver_for_testing_) {
      pending_receiver = result_sink_.BindNewEndpointAndPassDedicatedReceiver();
    } else {
      pending_receiver = result_sink_.BindNewEndpointAndPassReceiver();
    }
    std::move(callback_).Run(std::move(pending_receiver));
  }
  return result_sink_;
}

Status Database::GetAllOperation(
    int64_t object_store_id,
    int64_t index_id,
    IndexedDBKeyRange key_range,
    blink::mojom::IDBGetAllResultType result_type,
    int64_t max_count,
    blink::mojom::IDBCursorDirection direction,
    std::unique_ptr<GetAllResultSinkWrapper> result_sink,
    Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::GetAllOperation", "txn.id",
               transaction->id());

  DCHECK_GT(max_count, 0);

  const IndexedDBObjectStoreMetadata& object_store_metadata =
      GetObjectStoreMetadata(object_store_id);

  StatusOr<std::unique_ptr<BackingStore::Cursor>> cursor;

  if (result_type == blink::mojom::IDBGetAllResultType::Keys) {
    // Retrieving keys
    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
      // Object Store: Key Retrieval Operation
      cursor = transaction->BackingStoreTransaction()->OpenObjectStoreKeyCursor(
          object_store_id, key_range, direction);
    } else {
      // Index Value: (Primary Key) Retrieval Operation
      cursor = transaction->BackingStoreTransaction()->OpenIndexKeyCursor(
          object_store_id, index_id, key_range, direction);
    }
  } else {
    // Retrieving values
    if (index_id == IndexedDBIndexMetadata::kInvalidId) {
      // Object Store: Value Retrieval Operation
      cursor = transaction->BackingStoreTransaction()->OpenObjectStoreCursor(
          object_store_id, key_range, direction);
    } else {
      // Object Store: Referenced Value Retrieval Operation
      cursor = transaction->BackingStoreTransaction()->OpenIndexCursor(
          object_store_id, index_id, key_range, direction);
    }
  }

  if (!cursor.has_value()) {
    DLOG(ERROR) << "Unable to open cursor operation: "
                << cursor.error().ToString();
    result_sink->Get()->OnError(CreateIDBErrorPtr(
        blink::mojom::IDBException::kUnknownError,
        "Corruption detected, unable to continue", transaction));
    return cursor.error();
  }

  std::vector<blink::mojom::IDBRecordPtr> found_records;

  auto send_records = [&](bool done) {
    result_sink->Get()->ReceiveResults(std::move(found_records), done);
    found_records.clear();
  };

  // No records found.
  if (!*cursor) {
    send_records(/*done=*/true);
    return Status::OK();
  }

  bool did_first_seek = false;

  // Max idbvalue size before blob wrapping is 64k, so make an assumption
  // that max key/value size is 128kb tops, to fit under 128mb mojo limit.
  // This value is just a heuristic and is an attempt to make sure that
  // GetAll fits under the message limit size.
  static_assert(
      blink::mojom::kIDBMaxMessageSize >
          blink::mojom::kIDBGetAllChunkSize * blink::mojom::kIDBWrapThreshold,
      "Chunk heuristic too large");

  const size_t max_values_before_sending = blink::mojom::kIDBGetAllChunkSize;
  int64_t num_found_items = 0;
  while (num_found_items++ < max_count) {
    StatusOr<bool> cursor_valid = true;
    if (did_first_seek) {
      cursor_valid = (*cursor)->Continue();
    } else {
      // Cursor creation performs the first seek, returning a nullptr cursor
      // when invalid.
      did_first_seek = true;
    }
    if (!cursor_valid.has_value()) {
      result_sink->Get()->OnError(
          CreateIDBErrorPtr(blink::mojom::IDBException::kUnknownError,
                            "Seek failure, unable to continue", transaction));
      return cursor_valid.error();
    }

    if (!cursor_valid.value()) {
      break;
    }

    blink::mojom::IDBRecordPtr return_record;

    if (result_type == blink::mojom::IDBGetAllResultType::Keys) {
      return_record =
          blink::mojom::IDBRecord::New((*cursor)->GetPrimaryKey().Clone(),
                                       /*value=*/nullptr,
                                       /*index_key=*/std::nullopt);
    } else if (result_type == blink::mojom::IDBGetAllResultType::Values) {
      blink::mojom::IDBReturnValuePtr return_value =
          ExtractReturnValueFromCursorValue(*transaction, object_store_metadata,
                                            **cursor);
      return_record = blink::mojom::IDBRecord::New(
          /*primary_key=*/std::nullopt, std::move(return_value),
          /*index_key=*/std::nullopt);
    } else if (result_type == blink::mojom::IDBGetAllResultType::Records) {
      // Construct the record, which includes the primary key, value and index
      // key.
      blink::mojom::IDBReturnValuePtr return_value =
          ExtractReturnValueFromCursorValue(*transaction, object_store_metadata,
                                            **cursor);
      std::optional<IndexedDBKey> index_key;
      if (index_id != IndexedDBIndexMetadata::kInvalidId) {
        // The index key only exists for `IDBIndex::getAllRecords()`.
        index_key = (*cursor)->GetKey().Clone();
      }
      return_record = blink::mojom::IDBRecord::New(
          (*cursor)->GetPrimaryKey().Clone(), std::move(return_value),
          std::move(index_key));
    } else {
      NOTREACHED();
    }

    found_records.emplace_back(std::move(return_record));

    // Periodically stream records if we have too many.
    if (found_records.size() >= max_values_before_sending) {
      send_records(/*done=*/false);
    }
  }
  send_records(/*done=*/true);
  return Status::OK();
}

Status Database::OpenCursorOperation(
    std::unique_ptr<OpenCursorOperationParams> params,
    const storage::BucketLocator& bucket_locator,
    Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::OpenCursorOperation", "txn.id",
               transaction->id());

  // The frontend has begun indexing, so this pauses the transaction
  // until the indexing is complete. This can't happen any earlier
  // because we don't want to switch to early mode in case multiple
  // indexes are being created in a row, with Put()'s in between.
  if (params->task_type == blink::mojom::IDBTaskType::Preemptive) {
    transaction->AddPreemptiveEvent();
  }

  StatusOr<std::unique_ptr<BackingStore::Cursor>> backing_store_cursor;
  if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
    if (params->cursor_type == CursorType::kKeyOnly) {
      DCHECK_EQ(params->task_type, blink::mojom::IDBTaskType::Normal);
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenObjectStoreKeyCursor(
              params->object_store_id, params->key_range, params->direction);
    } else {
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenObjectStoreCursor(
              params->object_store_id, params->key_range, params->direction);
    }
  } else {
    DCHECK_EQ(params->task_type, blink::mojom::IDBTaskType::Normal);
    if (params->cursor_type == CursorType::kKeyOnly) {
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenIndexKeyCursor(
              params->object_store_id, params->index_id, params->key_range,
              params->direction);
    } else {
      backing_store_cursor =
          transaction->BackingStoreTransaction()->OpenIndexCursor(
              params->object_store_id, params->index_id, params->key_range,
              params->direction);
    }
  }

  if (!backing_store_cursor.has_value()) {
    DLOG(ERROR) << "Unable to open cursor operation: "
                << backing_store_cursor.error().ToString();
    return backing_store_cursor.error();
  }

  if (!*backing_store_cursor) {
    // Occurs when we've reached the end of cursor's data.
    std::move(params->callback)
        .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewEmpty(true));
    return Status::OK();
  }

  mojo::PendingAssociatedRemote<blink::mojom::IDBCursor> pending_remote;
  Cursor* cursor = Cursor::CreateAndBind(
      std::move(*backing_store_cursor), params->cursor_type, params->task_type,
      transaction->AsWeakPtr(), pending_remote);
  transaction->RegisterOpenCursor(cursor);

  blink::mojom::IDBValuePtr mojo_value;
  if (cursor->Value()) {
    mojo_value = transaction->BuildMojoValue(std::move(*cursor->Value()));
  }

  std::move(params->callback)
      .Run(blink::mojom::IDBDatabaseOpenCursorResult::NewValue(
          blink::mojom::IDBDatabaseOpenCursorValue::New(
              std::move(pending_remote), cursor->key().Clone(),
              cursor->primary_key().Clone(), std::move(mojo_value))));
  return Status::OK();
}

Status Database::CountOperation(
    int64_t object_store_id,
    int64_t index_id,
    IndexedDBKeyRange key_range,
    blink::mojom::IDBDatabase::CountCallback callback,
    Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::CountOperation", "txn.id",
               transaction->id());

  uint32_t count = -1;
  if (index_id == IndexedDBIndexMetadata::kInvalidId) {
    ASSIGN_OR_RETURN(
        count, transaction->BackingStoreTransaction()->GetObjectStoreKeyCount(
                   object_store_id, std::move(key_range)));

  } else {
    ASSIGN_OR_RETURN(count,
                     transaction->BackingStoreTransaction()->GetIndexKeyCount(
                         object_store_id, index_id, std::move(key_range)));
  }
  std::move(callback).Run(/*success=*/true, count);
  return Status::OK();
}

Status Database::DeleteRangeOperation(
    int64_t object_store_id,
    IndexedDBKeyRange key_range,
    blink::mojom::IDBDatabase::DeleteRangeCallback success_callback,
    Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::DeleteRangeOperation", "txn.id",
               transaction->id());

  Status s = transaction->BackingStoreTransaction()->DeleteRange(
      object_store_id, key_range);
  if (s.ok()) {
    const IndexedDBObjectStoreMetadata& object_store_metadata =
        GetObjectStoreMetadata(object_store_id);
    bucket_context_->delegate().on_content_changed.Run(
        metadata().name, object_store_metadata.name);
  }
  std::move(success_callback).Run(s.ok());
  return s;
}

Status Database::GetKeyGeneratorCurrentNumberOperation(
    int64_t object_store_id,
    blink::mojom::IDBDatabase::GetKeyGeneratorCurrentNumberCallback callback,
    Transaction* transaction) {
  ASSIGN_OR_RETURN(
      int64_t current_number,
      transaction->BackingStoreTransaction()->GetKeyGeneratorCurrentNumber(
          object_store_id),
      [&callback, transaction](const Status& status) {
        std::move(callback).Run(
            -1, CreateIDBErrorPtr(
                    blink::mojom::IDBException::kDataError,
                    "Failed to get the current number of key generator.",
                    transaction));
        return status;
      });

  std::move(callback).Run(current_number, nullptr);
  return Status::OK();
}

Status Database::ClearOperation(
    int64_t object_store_id,
    blink::mojom::IDBDatabase::ClearCallback success_callback,
    Transaction* transaction) {
  TRACE_EVENT1("IndexedDB", "Database::ClearOperation", "txn.id",
               transaction->id());
  Status s =
      transaction->BackingStoreTransaction()->ClearObjectStore(object_store_id);
  if (s.ok()) {
    const IndexedDBObjectStoreMetadata& object_store_metadata =
        GetObjectStoreMetadata(object_store_id);
    bucket_context_->delegate().on_content_changed.Run(
        name_, object_store_metadata.name);
  }
  std::move(success_callback).Run(s.ok());
  return s;
}

bool Database::IsObjectStoreIdInMetadata(int64_t object_store_id) const {
  return base::Contains(metadata().object_stores, object_store_id);
}

bool Database::IsObjectStoreIdAndMaybeIndexIdInMetadata(
    int64_t object_store_id,
    int64_t index_id) const {
  if (!IsObjectStoreIdInMetadata(object_store_id)) {
    return false;
  }
  const IndexedDBObjectStoreMetadata& object_store_metadata =
      GetObjectStoreMetadata(object_store_id);
  return index_id == IndexedDBIndexMetadata::kInvalidId ||
         base::Contains(object_store_metadata.indexes, index_id);
}

storage::mojom::IdbDatabaseMetadataPtr Database::GetIdbInternalsMetadata()
    const {
  storage::mojom::IdbDatabaseMetadataPtr info =
      storage::mojom::IdbDatabaseMetadata::New();
  info->name = name();
  info->connection_count = ConnectionCount();
  info->active_open_delete = ActiveOpenDeleteCount();
  info->pending_open_delete = PendingOpenDeleteCount();
  for (const Connection* connection : connections()) {
    for (const auto& [_, transaction] : connection->transactions()) {
      info->transactions.push_back(transaction->GetIdbInternalsMetadata());
    }
  }
  return info;
}

void Database::NotifyOfIdbInternalsRelevantChange() {
  // This metadata is included in the context metadata, so call up the chain.
  bucket_context_->NotifyOfIdbInternalsRelevantChange();
}

// kIDBMaxMessageSize is defined based on the original
// IPC::mojom::kChannelMaximumMessageSize value.  We use kIDBMaxMessageSize to
// limit the size of arguments we pass into our Mojo calls.  We want to ensure
// this value is always no bigger than the current kMaximumMessageSize value
// which also ensures it is always no bigger than the current Mojo message
// size limit.
static_assert(
    blink::mojom::kIDBMaxMessageSize <= IPC::mojom::kChannelMaximumMessageSize,
    "kIDBMaxMessageSize is bigger than IPC::mojom::kChannelMaximumMessageSize");

void Database::CallUpgradeTransactionStartedForTesting(int64_t old_version) {
  connection_coordinator_.OnUpgradeTransactionStarted(old_version);
}

Status Database::OpenInternal() {
  auto result = backing_store()->CreateOrOpenDatabase(name_);
  if (result.has_value()) {
    backing_store_db_ = std::move(result.value());
    return Status::OK();
  }
  return result.error();
}

std::unique_ptr<Connection> Database::CreateConnection(
    std::unique_ptr<DatabaseCallbacks> database_callbacks,
    mojo::Remote<storage::mojom::IndexedDBClientStateChecker>
        client_state_checker,
    base::UnguessableToken client_token,
    int scheduling_priority) {
  auto connection = std::make_unique<Connection>(
      *bucket_context_, weak_factory_.GetWeakPtr(),
      base::BindRepeating(&Database::VersionChangeIgnored,
                          weak_factory_.GetWeakPtr()),
      base::BindOnce(&Database::ConnectionClosed, weak_factory_.GetWeakPtr()),
      std::move(database_callbacks), std::move(client_state_checker),
      client_token, scheduling_priority);
  connections_.insert(connection.get());
  return connection;
}

void Database::VersionChangeIgnored() {
  connection_coordinator_.OnVersionChangeIgnored();
}

bool Database::HasNoConnections() const {
  return force_closing_ || connections().empty();
}

void Database::SendVersionChangeToAllConnections(int64_t old_version,
                                                 int64_t new_version) {
  if (force_closing_) {
    return;
  }
  for (auto* connection : connections()) {
    // Before invoking this method, the `ConnectionCoordinator` had
    // set the request state to `kPendingNoConnections`. Now the request will
    // be blocked until all the existing connections to this database is
    // closed. There are three possible ways for the connection to be closed:
    // 1. If the client is already pending close, then the `VersionChange`
    // event will be ignored and the open request will be deemed blocked until
    // the pending close completes.
    // 2. If the client is active, the `VersionChange` event will be enqueued
    // and the registered event listener will be fired asynchronously. The
    // event listener should be responsible for actively closing the IndexedDB
    // connection. The document won't be eligible for BFCache before the
    // connection is closed if it receives the `versionchange` event.
    // 3. While the above two cases rely on the `VersionChange` event to be
    // delivered to the renderer process, the third case happens purely from
    // the IndexedDB/browser context. If the client is inactive, the
    // `VersionChange` event will not be delivered, instead, a mojo call is
    // sent to the browser process to disallow the activation of the inactive
    // client, which will close the connection as part of the destruction. No
    // matter which path it follows, the `SendVersionChangeToAllConnections`
    // method is executed asynchronously.
    connection->DisallowInactiveClient(
        storage::mojom::DisallowInactiveClientReason::kVersionChangeEvent,
        base::BindOnce(
            [](base::WeakPtr<Connection> connection, int64_t old_version,
               int64_t new_version, bool was_client_active) {
              if (connection && connection->IsConnected() &&
                  was_client_active) {
                connection->callbacks()->OnVersionChange(old_version,
                                                         new_version);
              }
            },
            connection->GetWeakPtr(), old_version, new_version));
  }
}

void Database::ConnectionClosed(Connection* connection) {
  TRACE_EVENT0("IndexedDB", "Database::ConnectionClosed");
  // Ignore connection closes during force close to prevent re-entry.
  if (force_closing_) {
    return;
  }
  connections_.erase(connection);
  connection_coordinator_.OnConnectionClosed(connection);
  if (connections_.empty()) {
    connection_coordinator_.OnNoConnections();
  }
  if (CanBeDestroyed()) {
    bucket_context_->QueueRunTasks();
  }
}

bool Database::CanBeDestroyed() {
  return !connection_coordinator_.HasTasks() && connections_.empty();
}

const IndexedDBObjectStoreMetadata& Database::GetObjectStoreMetadata(
    int64_t object_store_id) const {
  auto object_store_it = metadata().object_stores.find(object_store_id);
  CHECK(object_store_it != metadata().object_stores.end());
  return object_store_it->second;
}

}  // namespace content::indexed_db
