// 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/transaction.h"

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

#include "base/auto_reset.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/not_fatal_until.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.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_manager.h"
#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom-shared.h"
#include "components/services/storage/privileged/mojom/indexed_db_internals_types.mojom.h"
#include "components/services/storage/public/mojom/blob_storage_context.mojom-shared.h"
#include "content/browser/indexed_db/indexed_db_external_object.h"
#include "content/browser/indexed_db/indexed_db_external_object_storage.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.h"
#include "content/browser/indexed_db/instance/database_callbacks.h"
#include "content/browser/indexed_db/instance/index_writer.h"
#include "content/browser/indexed_db/instance/lock_request_data.h"
#include "content/browser/indexed_db/status.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"

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

namespace content::indexed_db {

namespace {

std::string WriteBlobToFileResultToString(
    storage::mojom::WriteBlobToFileResult result) {
  switch (result) {
    case storage::mojom::WriteBlobToFileResult::kError:
      return "Error";
    case storage::mojom::WriteBlobToFileResult::kBadPath:
      return "BadPath";
    case storage::mojom::WriteBlobToFileResult::kInvalidBlob:
      return "InvalidBlob";
    case storage::mojom::WriteBlobToFileResult::kIOError:
      return "IOError";
    case storage::mojom::WriteBlobToFileResult::kTimestampError:
      return "TimestampError";
    case storage::mojom::WriteBlobToFileResult::kSuccess:
      return "Success";
  }
  NOTREACHED();
}

// Disabled in some tests.
bool g_inactivity_timeout_enabled = true;

// Used for UMA metrics - do not change values.
enum UmaIDBException {
  UmaIDBExceptionUnknownError = 0,
  UmaIDBExceptionConstraintError = 1,
  UmaIDBExceptionDataError = 2,
  UmaIDBExceptionVersionError = 3,
  UmaIDBExceptionAbortError = 4,
  UmaIDBExceptionQuotaError = 5,
  UmaIDBExceptionTimeoutError = 6,
  UmaIDBExceptionExclusiveMaxValue = 7
};

// Used for UMA metrics - do not change mappings.
UmaIDBException ExceptionCodeToUmaEnum(blink::mojom::IDBException code) {
  switch (code) {
    case blink::mojom::IDBException::kUnknownError:
      return UmaIDBExceptionUnknownError;
    case blink::mojom::IDBException::kConstraintError:
      return UmaIDBExceptionConstraintError;
    case blink::mojom::IDBException::kDataError:
      return UmaIDBExceptionDataError;
    case blink::mojom::IDBException::kVersionError:
      return UmaIDBExceptionVersionError;
    case blink::mojom::IDBException::kAbortError:
      return UmaIDBExceptionAbortError;
    case blink::mojom::IDBException::kQuotaError:
      return UmaIDBExceptionQuotaError;
    case blink::mojom::IDBException::kTimeoutError:
      return UmaIDBExceptionTimeoutError;
    default:
      NOTREACHED();
  }
}

}  // namespace

Transaction::TaskQueue::TaskQueue() = default;
Transaction::TaskQueue::~TaskQueue() = default;

void Transaction::TaskQueue::clear() {
  while (!queue_.empty()) {
    queue_.pop();
  }
}

Transaction::TaskQueue::Task Transaction::TaskQueue::pop() {
  DCHECK(!queue_.empty());
  Task task = std::move(queue_.front());
  queue_.pop();
  return task;
}

Transaction::Transaction(
    int64_t id,
    Connection* connection,
    const std::set<int64_t>& object_store_ids,
    blink::mojom::IDBTransactionMode mode,
    blink::mojom::IDBTransactionDurability durability,
    BucketContextHandle bucket_context,
    std::unique_ptr<BackingStore::Transaction> backing_store_transaction)
    : id_(id),
      object_store_ids_(object_store_ids),
      mode_(mode),
      durability_(durability),
      connection_(connection->GetWeakPtr()),
      bucket_context_(std::move(bucket_context)),
      backing_store_transaction_(std::move(backing_store_transaction)),
      receiver_(this) {
  TRACE_EVENT_BEGIN("IndexedDB", "Transaction::lifetime",
                    perfetto::Track::FromPointer(this));

  locks_receiver_.SetUserData(
      LockRequestData::kKey,
      std::make_unique<LockRequestData>(connection->client_token(),
                                        connection->scheduling_priority()));

  database_ = connection_->database();
  if (database_) {
    for (const PartitionedLockManager::PartitionedLockRequest& lock_request :
         database_->BuildLockRequestsForTransaction(mode_, scope())) {
      lock_ids_.insert(lock_request.lock_id);
    }
  }

  diagnostics_.tasks_scheduled = 0;
  diagnostics_.tasks_completed = 0;
  diagnostics_.creation_time = base::Time::Now();
  SetState(state_);  // Process the initial state.
}

Transaction::~Transaction() {
  // Corresponds to the TRACE_EVENT_BEGIN in the constructor.
  TRACE_EVENT_END("IndexedDB", perfetto::Track::FromPointer(this));
  // It shouldn't be possible for this object to get deleted until it's either
  // complete or aborted.
  DCHECK_EQ(state_, FINISHED);
  DCHECK(preemptive_task_queue_.empty());
  DCHECK_EQ(pending_preemptive_events_, 0);
  DCHECK(task_queue_.empty());
  DCHECK(!processing_event_queue_);
}

void Transaction::BindReceiver(
    mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction>
        mojo_receiver) {
  receiver_.Bind(std::move(mojo_receiver));
  if (receiver_.is_bound()) {
    // `receiver_` might not be bound in tests that pass an invalid pending
    // receiver.
    receiver_.set_disconnect_handler(base::BindOnce(
        &Transaction::OnMojoReceiverDisconnected, ptr_factory_.GetWeakPtr()));
  }
}

void Transaction::SetCommitFlag() {
  // The frontend suggests that we commit, but we may have previously initiated
  // an abort.
  if (!IsAcceptingRequests()) {
    return;
  }

  is_commit_pending_ = true;
  bucket_context_->QueueRunTasks();
}

void Transaction::ScheduleTask(blink::mojom::IDBTaskType type,
                               Operation task,
                               VerificationCallback verify) {
  TRACE_EVENT0("IndexedDB", "Transaction::ScheduleTask");

  if (state_ == FINISHED) {
    TRACE_EVENT_INSTANT("IndexedDB", "Transaction::ScheduleTask - Finished");
    return;
  }

  ResetTimeoutTimer();
  used_ = true;
  if (type == blink::mojom::IDBTaskType::Normal) {
    task_queue_.push(std::move(task), std::move(verify));
    ++diagnostics_.tasks_scheduled;
    NotifyOfIdbInternalsRelevantChange();
  } else {
    preemptive_task_queue_.push(std::move(task), std::move(verify));
  }
  if (state() == STARTED) {
    bucket_context_->QueueRunTasks();
  } else {
    TRACE_EVENT_INSTANT("IndexedDB", "Transaction::ScheduleTask - Not started");
  }
}

Status Transaction::Abort(const DatabaseError& error) {
  if (state_ == FINISHED) {
    return Status::OK();
  }

  base::UmaHistogramEnumeration("WebCore.IndexedDB.TransactionAbortReason",
                                ExceptionCodeToUmaEnum(error.code()),
                                UmaIDBExceptionExclusiveMaxValue);

  aborted_ = true;
  ResetTimeoutTimer();

  SetState(FINISHED);

  if (backing_store_transaction_begun_) {
    backing_store_transaction_->Rollback();
  }

  preemptive_task_queue_.clear();
  pending_preemptive_events_ = 0;

  task_queue_.clear();

  // Backing store resources (held via cursors) must be released
  // before script callbacks are fired, as the script callbacks may
  // release references and allow the backing store itself to be
  // released, and order is critical.
  CloseOpenCursors();
  backing_store_transaction_.reset();

  // Transactions must also be marked as completed before the
  // front-end is notified, as the transaction completion unblocks
  // operations like closing connections.
  locks_receiver_.locks.clear();
  locks_receiver_.CancelLockRequest();

  connection()->callbacks()->OnAbort(*this, error);

  bucket_context_->QueueRunTasks();
  bucket_context_.Release();
  return Status::OK();
}

// static
Status Transaction::CommitPhaseTwoProxy(Transaction* transaction) {
  return transaction->CommitPhaseTwo();
}

bool Transaction::IsTaskQueueEmpty() const {
  return preemptive_task_queue_.empty() && task_queue_.empty();
}

bool Transaction::HasPendingTasks() const {
  return pending_preemptive_events_ || !IsTaskQueueEmpty();
}

void Transaction::RegisterOpenCursor(Cursor* cursor) {
  open_cursors_.insert(cursor);
}

void Transaction::UnregisterOpenCursor(Cursor* cursor) {
  open_cursors_.erase(cursor);
}

void Transaction::DontAllowInactiveClientToBlockOthers(
    storage::mojom::DisallowInactiveClientReason reason) {
  if (state_ == STARTED && IsTransactionBlockingOtherClients()) {
    connection_->DisallowInactiveClient(reason, base::DoNothing());
  }
}

bool Transaction::IsTransactionBlockingOtherClients(
    bool consider_priority) const {
  CHECK_EQ(state_, STARTED);

  if (database_->OnlyHasOneClient()) {
    return false;
  }

  base::TimeTicks start = base::TimeTicks::Now();
  std::optional<int> scheduling_priority;
  if (consider_priority) {
    scheduling_priority = connection_->scheduling_priority();
  }
  const bool is_blocking_others =
      bucket_context_->lock_manager().IsBlockingAnyRequest(
          lock_ids(),
          base::BindRepeating(
              [](std::optional<int> this_priority,
                 const base::UnguessableToken& this_token,
                 PartitionedLockHolder* blocked_lock_holder) {
                auto* lock_request_data = static_cast<LockRequestData*>(
                    blocked_lock_holder->GetUserData(LockRequestData::kKey));
                if (!lock_request_data) {
                  return true;
                }
                // If `this`
                //   * comes from a background client (priority > 0), and
                //   * is equal or higher priority than the blocked
                //   transaction's client
                //     (aka equally or less severely throttled)
                // then don't worry about blocking it.
                if (this_priority && (*this_priority > 0) &&
                    (*this_priority <=
                     lock_request_data->scheduling_priority)) {
                  return false;
                }
                return lock_request_data->client_token != this_token;
              },
              scheduling_priority, connection_->client_token()));
  base::TimeDelta duration = base::TimeTicks::Now() - start;
  if (duration > base::Milliseconds(2)) {
    base::UmaHistogramTimes("IndexedDB.CalculateBlockingStatusLongTimes",
                            duration);
    base::UmaHistogramCounts100000(
        "IndexedDB.CalculateBlockingStatusRequestQueueSize",
        bucket_context_->lock_manager().RequestsWaitingForMetrics());
  }
  return is_blocking_others;
}

void Transaction::Start() {
  TRACE_EVENT0("IndexedDB", "Transaction::Start");

  // The transaction has the potential to be aborted after the Start() task was
  // posted.
  if (state_ == FINISHED) {
    DCHECK(locks_receiver_.locks.empty());
    return;
  }
  DCHECK_EQ(CREATED, state_);
  std::optional scheduling_priority_at_last_state_change =
      scheduling_priority_at_last_state_change_;
  SetState(STARTED);
  DCHECK(!locks_receiver_.locks.empty());
  diagnostics_.start_time = base::Time::Now();

  // If the client is in BFCache, the transaction will get stuck, so evict it if
  // necessary.
  DontAllowInactiveClientToBlockOthers(
      storage::mojom::DisallowInactiveClientReason::
          kTransactionIsStartingWhileBlockingOthers);

  const base::TimeDelta time_queued =
      diagnostics_.start_time - diagnostics_.creation_time;
  switch (mode_) {
    case blink::mojom::IDBTransactionMode::ReadOnly:
      base::UmaHistogramMediumTimes(
          "WebCore.IndexedDB.Transaction.ReadOnly.TimeQueued", time_queued);
      if (scheduling_priority_at_last_state_change == 0) {
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.ReadOnly.TimeQueued.Foreground",
            time_queued);
      }
      break;
    case blink::mojom::IDBTransactionMode::ReadWrite:
      base::UmaHistogramMediumTimes(
          "WebCore.IndexedDB.Transaction.ReadWrite.TimeQueued", time_queued);
      if (scheduling_priority_at_last_state_change == 0) {
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.ReadWrite.TimeQueued.Foreground",
            time_queued);
      }
      break;
    case blink::mojom::IDBTransactionMode::VersionChange:
      base::UmaHistogramMediumTimes(
          "WebCore.IndexedDB.Transaction.VersionChange.TimeQueued",
          time_queued);
      if (scheduling_priority_at_last_state_change == 0) {
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.VersionChange.TimeQueued.Foreground",
            time_queued);
      }
      break;
  }

  bucket_context_->QueueRunTasks();
}

// static
void Transaction::DisableInactivityTimeoutForTesting() {
  g_inactivity_timeout_enabled = false;
}

void Transaction::CreateObjectStore(int64_t object_store_id,
                                    const std::u16string& name,
                                    const IndexedDBKeyPath& key_path,
                                    bool auto_increment) {
  if (!connection()
           ->GetTransactionAndVerifyState(
               id(), blink::mojom::IDBTransactionMode::VersionChange)
           .has_value()) {
    return;
  }

  ScheduleTask(
      blink::mojom::IDBTaskType::Preemptive,
      base::BindOnce(
          [](int64_t object_store_id, const std::u16string& name,
             const IndexedDBKeyPath& key_path, bool auto_increment,
             Transaction* transaction) {
            return transaction->BackingStoreTransaction()->CreateObjectStore(
                object_store_id, name, key_path, auto_increment);
          },
          object_store_id, name, key_path, auto_increment),
      // The object store ID must be a valid new ID.
      base::BindOnce(
          [](int64_t object_store_id,
             mojo::ReportBadMessageCallback report_bad_message_callback,
             Transaction& transaction) {
            if (transaction.connection()->database()->IsObjectStoreIdInMetadata(
                    object_store_id) ||
                object_store_id <= transaction.connection()
                                       ->database()
                                       ->metadata()
                                       .max_object_store_id) {
              std::move(report_bad_message_callback)
                  .Run("Invalid object_store_id");
              return Status::InvalidArgument("Invalid object_store_id.");
            }

            return Status::OK();
          },
          object_store_id, mojo::GetBadMessageCallback()));
}

void Transaction::DeleteObjectStore(int64_t object_store_id) {
  if (!connection()
           ->GetTransactionAndVerifyState(
               id(), blink::mojom::IDBTransactionMode::VersionChange)
           .has_value()) {
    return;
  }

  ScheduleTask(
      base::BindOnce(
          [](int64_t object_store_id, Transaction* transaction) {
            return transaction->BackingStoreTransaction()->DeleteObjectStore(
                object_store_id);
          },
          object_store_id),
      ObjectStoreMustExist(object_store_id));
}

void Transaction::Put(int64_t object_store_id,
                      blink::mojom::IDBValuePtr input_value,
                      IndexedDBKey key,
                      blink::mojom::IDBPutMode mode,
                      std::vector<IndexedDBIndexKeys> index_keys,
                      blink::mojom::IDBTransaction::PutCallback callback) {
  if (!IsAcceptingRequests()) {
    return;
  }

  if (!connection()->IsConnected()) {
    DatabaseError error(blink::mojom::IDBException::kUnknownError,
                        "Not connected.");
    std::move(callback).Run(
        blink::mojom::IDBTransactionPutResult::NewErrorResult(
            blink::mojom::IDBError::New(error.code(), error.message())));
    return;
  }

  if (input_value->bits.storage_type() ==
      mojo_base::BigBuffer::StorageType::kInvalidBuffer) {
    mojo::ReportBadMessage("Attempted to Put invalid SSV.");
    return;
  }

  std::vector<IndexedDBExternalObject> external_objects;
  uint64_t total_blob_size = 0;
  if (!input_value->external_objects.empty() &&
      !CreateExternalObjects(input_value, &external_objects,
                             &total_blob_size)) {
    mojo::ReportBadMessage("Couldn't deserialize external objects.");
    return;
  }

  // Increment the total transaction size by the size of this put.
  preliminary_size_estimate_ +=
      input_value->bits.size() + key.size_estimate() + total_blob_size;
  // Warm up the disk space cache.
  bucket_context()->CheckCanUseDiskSpace(preliminary_size_estimate_, {});

  IndexedDBValue value;
  value.bits = std::move(input_value->bits);
  value.external_objects = std::move(external_objects);

  blink::mojom::IDBTransaction::PutCallback wrapped_callback =
      CreateCallbackAbortOnDestruct<blink::mojom::IDBTransaction::PutCallback,
                                    blink::mojom::IDBTransactionPutResultPtr>(
          std::move(callback), AsWeakPtr());

  // This is decremented in DoPut.
  in_flight_memory_ += value.SizeEstimate();
  ScheduleTask(
      base::BindOnce(&Transaction::DoPut, base::Unretained(this),
                     object_store_id, std::move(value), std::move(key), mode,
                     std::move(index_keys), std::move(wrapped_callback)),
      ObjectStoreMustExist(object_store_id));
}

Status Transaction::DoPut(int64_t object_store_id,
                          IndexedDBValue value,
                          IndexedDBKey key,
                          blink::mojom::IDBPutMode put_mode,
                          std::vector<IndexedDBIndexKeys> index_keys,
                          blink::mojom::IDBTransaction::PutCallback callback,
                          Transaction* txn) {
  DCHECK_EQ(this, txn);
  TRACE_EVENT2("IndexedDB", "Database::PutOperation", "txn.id", id(), "size",
               value.SizeEstimate());
  DCHECK_NE(mode(), blink::mojom::IDBTransactionMode::ReadOnly);
  bool key_was_generated = false;
  in_flight_memory_ -= value.SizeEstimate();
  DCHECK(in_flight_memory_.IsValid());

  auto on_put_error = [&txn](blink::mojom::IDBTransaction::PutCallback callback,
                             blink::mojom::IDBException code,
                             const std::u16string& message) {
    txn->IncrementNumErrorsSent();
    std::move(callback).Run(
        blink::mojom::IDBTransactionPutResult::NewErrorResult(
            blink::mojom::IDBError::New(code, message)));
  };

  if (!connection()->database()->IsObjectStoreIdInMetadata(object_store_id)) {
    on_put_error(std::move(callback), blink::mojom::IDBException::kUnknownError,
                 u"Bad request");
    return Status::InvalidArgument("Invalid object_store_id.");
  }

  const IndexedDBObjectStoreMetadata& object_store =
      connection()->database()->GetObjectStoreMetadata(object_store_id);
  DCHECK(object_store.auto_increment || key.IsValid());
  if (put_mode != blink::mojom::IDBPutMode::CursorUpdate &&
      object_store.auto_increment && !key.IsValid()) {
    IndexedDBKey auto_inc_key = GenerateAutoIncrementKey(object_store_id);
    key_was_generated = true;
    if (!auto_inc_key.IsValid()) {
      on_put_error(std::move(callback),
                   blink::mojom::IDBException::kConstraintError,
                   u"Maximum key generator value reached.");
      return Status::OK();
    }
    key = std::move(auto_inc_key);
  }

  if (!key.IsValid()) {
    return Status::InvalidArgument("Invalid key");
  }

  if (put_mode == blink::mojom::IDBPutMode::AddOnly) {
    ASSIGN_OR_RETURN(
        std::optional<BackingStore::RecordIdentifier> preexisting_record,
        BackingStoreTransaction()->KeyExistsInObjectStore(object_store_id,
                                                          key));
    if (preexisting_record) {
      on_put_error(std::move(callback),
                   blink::mojom::IDBException::kConstraintError,
                   u"Key already exists in the object store.");
      return Status::OK();
    }
  }

  std::vector<std::unique_ptr<IndexWriter>> index_writers;
  std::string error_message;
  bool obeys_constraints = false;
  bool backing_store_success = MakeIndexWriters(
      this, object_store, key, key_was_generated, std::move(index_keys),
      &index_writers, &error_message, &obeys_constraints);
  if (!backing_store_success) {
    on_put_error(std::move(callback), blink::mojom::IDBException::kUnknownError,
                 u"Internal error: backing store error updating index keys.");
    return Status::OK();
  }
  if (!obeys_constraints) {
    on_put_error(std::move(callback),
                 blink::mojom::IDBException::kConstraintError,
                 base::UTF8ToUTF16(error_message));
    return Status::OK();
  }

  // Before this point, don't do any mutation. After this point, rollback the
  // transaction in case of error.
  ASSIGN_OR_RETURN(BackingStore::RecordIdentifier new_record,
                   BackingStoreTransaction()->PutRecord(object_store_id, key,
                                                        std::move(value)));

  {
    TRACE_EVENT1("IndexedDB", "Database::PutOperation.UpdateIndexes", "txn.id",
                 id());
    for (const auto& writer : index_writers) {
      writer->WriteIndexKeys(new_record, BackingStoreTransaction(),
                             object_store_id);
    }
  }

  if (object_store.auto_increment &&
      put_mode != blink::mojom::IDBPutMode::CursorUpdate &&
      key.type() == blink::mojom::IDBKeyType::Number) {
    TRACE_EVENT1("IndexedDB", "Database::PutOperation.AutoIncrement", "txn.id",
                 id());
    // Maximum integer uniquely representable as ECMAScript number.
    const double max_generator_value = 9007199254740992.0;
    int64_t new_max = 1 + base::saturated_cast<int64_t>(floor(
                              std::min(key.number(), max_generator_value)));
    IDB_RETURN_IF_ERROR(
        BackingStoreTransaction()->MaybeUpdateKeyGeneratorCurrentNumber(
            object_store_id, new_max, key_was_generated));
  }
  {
    TRACE_EVENT1("IndexedDB", "Database::PutOperation.Callbacks", "txn.id",
                 id());
    std::move(callback).Run(
        blink::mojom::IDBTransactionPutResult::NewKey(std::move(key)));
  }

  bucket_context()->delegate().on_content_changed.Run(
      connection()->database()->name(), object_store.name);
  return Status::OK();
}

void Transaction::SetIndexKeys(int64_t object_store_id,
                               IndexedDBKey primary_key,
                               IndexedDBIndexKeys index_keys) {
  if (!IsAcceptingRequests() || !connection()->IsConnected()) {
    return;
  }

  if (!primary_key.IsValid()) {
    mojo::ReportBadMessage("SetIndexKeys used with invalid key.");
    return;
  }

  if (mode() != blink::mojom::IDBTransactionMode::VersionChange) {
    mojo::ReportBadMessage(
        "SetIndexKeys must be called from a version change transaction.");
    return;
  }

  ScheduleTask(blink::mojom::IDBTaskType::Preemptive,
               base::BindOnce(&Transaction::DoSetIndexKeys,
                              base::Unretained(this), object_store_id,
                              std::move(primary_key), std::move(index_keys)),
               ObjectStoreMustExist(object_store_id));
}

Status Transaction::DoSetIndexKeys(int64_t object_store_id,
                                   IndexedDBKey primary_key,
                                   IndexedDBIndexKeys index_keys,
                                   Transaction* transaction) {
  DCHECK_EQ(this, transaction);
  TRACE_EVENT1("IndexedDB", "Database::SetIndexKeysOperation", "txn.id",
               transaction->id());
  DCHECK_EQ(mode(), blink::mojom::IDBTransactionMode::VersionChange);

  ASSIGN_OR_RETURN(std::optional<BackingStore::RecordIdentifier> found_record,
                   BackingStoreTransaction()->KeyExistsInObjectStore(
                       object_store_id, primary_key));
  if (!found_record) {
    return Abort(
        DatabaseError(blink::mojom::IDBException::kUnknownError,
                      "Internal error setting index keys for object store."));
  }

  std::vector<std::unique_ptr<IndexWriter>> index_writers;
  std::string error_message;
  bool obeys_constraints = false;

  const IndexedDBObjectStoreMetadata& object_store_metadata =
      connection()->database()->GetObjectStoreMetadata(object_store_id);
  std::vector<IndexedDBIndexKeys> keys_vec;
  keys_vec.emplace_back(std::move(index_keys));
  bool backing_store_success = MakeIndexWriters(
      this, object_store_metadata, primary_key, false, std::move(keys_vec),
      &index_writers, &error_message, &obeys_constraints);
  if (!backing_store_success) {
    return Abort(DatabaseError(blink::mojom::IDBException::kUnknownError,
                               "Internal error: backing store error updating "
                               "index keys."));
  }
  if (!obeys_constraints) {
    return Abort(DatabaseError(blink::mojom::IDBException::kConstraintError,
                               error_message));
  }

  for (const auto& writer : index_writers) {
    IDB_RETURN_IF_ERROR(writer->WriteIndexKeys(
        *found_record, BackingStoreTransaction(), object_store_id));
  }
  return Status::OK();
}

void Transaction::SetIndexKeysDone() {
  if (!IsAcceptingRequests() || !connection()->IsConnected()) {
    return;
  }

  if (mode() != blink::mojom::IDBTransactionMode::VersionChange) {
    mojo::ReportBadMessage(
        "SetIndexKeysDone must be called from a version change transaction.");
    return;
  }

  ScheduleTask(blink::mojom::IDBTaskType::Preemptive,
               base::BindOnce([](Transaction* transaction) {
                 transaction->DidCompletePreemptiveEvent();
                 return Status::OK();
               }));
}

void Transaction::Commit(int64_t num_errors_handled) {
  if (!IsAcceptingRequests() || !connection()->IsConnected()) {
    return;
  }

  num_errors_handled_ = num_errors_handled;

  // Always allow empty or delete-only transactions.
  if (preliminary_size_estimate_ <= 0) {
    SetCommitFlag();
    return;
  }

  bucket_context()->CheckCanUseDiskSpace(
      preliminary_size_estimate_, base::BindOnce(&Transaction::OnQuotaCheckDone,
                                                 ptr_factory_.GetWeakPtr()));
}

void Transaction::OnQuotaCheckDone(bool allowed) {
  // May have disconnected while quota check was pending.
  if (!connection()->IsConnected()) {
    return;
  }

  if (allowed) {
    SetCommitFlag();
  } else {
    connection()->AbortTransactionAndTearDownOnError(
        this, DatabaseError(blink::mojom::IDBException::kQuotaError));
  }
}

bool Transaction::CreateExternalObjects(
    blink::mojom::IDBValuePtr& value,
    std::vector<IndexedDBExternalObject>* external_objects,
    uint64_t* total_size) {
  // Should only be called if there are external objects to process.
  CHECK(!value->external_objects.empty());

  base::CheckedNumeric<uint64_t> total_blob_size = 0;
  external_objects->resize(value->external_objects.size());
  for (size_t i = 0; i < value->external_objects.size(); ++i) {
    auto& object = value->external_objects[i];
    switch (object->which()) {
      case blink::mojom::IDBExternalObject::Tag::kBlobOrFile: {
        blink::mojom::IDBBlobInfoPtr& info = object->get_blob_or_file();
        if (info->size < 0) {
          return false;
        }

        total_blob_size += info->size;

        if (info->file) {
          (*external_objects)[i] = IndexedDBExternalObject(
              std::move(info->blob), info->file->name, info->mime_type,
              info->file->last_modified, info->size);
        } else {
          (*external_objects)[i] = IndexedDBExternalObject(
              std::move(info->blob), info->mime_type, info->size);
        }
        break;
      }
      case blink::mojom::IDBExternalObject::Tag::kFileSystemAccessToken:
        (*external_objects)[i] = IndexedDBExternalObject(
            std::move(object->get_file_system_access_token()));
        break;
    }
  }
  *total_size = total_blob_size.ValueOrDie();
  return true;
}

Status Transaction::BlobWriteComplete(
    BlobWriteResult result,
    storage::mojom::WriteBlobToFileResult error) {
  TRACE_EVENT0("IndexedDB", "Transaction::BlobWriteComplete");
  if (state_ == FINISHED) {  // aborted
    return Status::OK();
  }
  DCHECK_EQ(state_, COMMITTING);

  switch (result) {
    case BlobWriteResult::kFailure: {
      Status status = Abort(
          DatabaseError(blink::mojom::IDBException::kDataError,
                        base::ASCIIToUTF16(base::StringPrintf(
                            "Failed to write blobs (%s)",
                            WriteBlobToFileResultToString(error).c_str()))));
      if (!status.ok()) {
        bucket_context_->OnDatabaseError(database_.get(), status, {});
      }
      // The result is ignored.
      return Status::OK();
    }
    case BlobWriteResult::kRunPhaseTwoAsync:
      ScheduleTask(base::BindOnce(&CommitPhaseTwoProxy));
      bucket_context_->QueueRunTasks();
      return Status::OK();
    case BlobWriteResult::kRunPhaseTwoAndReturnResult: {
      return CommitPhaseTwo();
    }
  }
  NOTREACHED();
}

Status Transaction::DoPendingCommit() {
  TRACE_EVENT1("IndexedDB", "Transaction::DoPendingCommit", "txn.id", id());
  CHECK(is_commit_pending_, base::NotFatalUntil::M145);

  ResetTimeoutTimer();

  // In multiprocess ports, front-end may have requested a commit but
  // an abort has already been initiated asynchronously by the
  // back-end.
  if (state_ == FINISHED) {
    return Status::OK();
  }
  DCHECK_NE(state_, COMMITTING);

  // Front-end has requested a commit, but this transaction is blocked by
  // other transactions. The commit will be initiated when the transaction
  // coordinator unblocks this transaction.
  if (state_ != STARTED) {
    return Status::OK();
  }

  // Front-end has requested a commit, but there may be tasks like
  // create_index which are considered synchronous by the front-end
  // but are processed asynchronously.
  if (HasPendingTasks()) {
    return Status::OK();
  }

  // If a transaction is being committed but it has sent more errors to the
  // front end than have been handled at this point, the transaction should be
  // aborted as it is unknown whether or not any errors unaccounted for will be
  // properly handled.
  if (num_errors_sent_ != num_errors_handled_) {
    is_commit_pending_ = false;
    return Abort(DatabaseError(blink::mojom::IDBException::kUnknownError));
  }

  SetState(COMMITTING);

  Status s;
  if (!used_) {
    s = CommitPhaseTwo();
  } else {
    // CommitPhaseOne will call the callback synchronously if there are no blobs
    // to write.
    s = backing_store_transaction_->CommitPhaseOne(
        /*blob_write_callback=*/
        base::BindOnce(
            [](base::WeakPtr<Transaction> transaction, BlobWriteResult result,
               storage::mojom::WriteBlobToFileResult error) {
              if (!transaction) {
                return Status::OK();
              }
              return transaction->BlobWriteComplete(result, error);
            },
            ptr_factory_.GetWeakPtr()),
        // This callback is only used by SQLite. The LevelDB version of this
        // code lives in `BackingStore::Transaction::WriteNewBlobs`.
        /*serialize_fsa_callback=*/
        base::BindRepeating(
            [](base::WeakPtr<Transaction> transaction,
               blink::mojom::FileSystemAccessTransferToken& token_remote,
               base::OnceCallback<void(const std::vector<uint8_t>&)>
                   deliver_serialized_token) {
              if (!transaction) {
                return;
              }

              // TODO(dmurph): Refactor IndexedDBExternalObject to not use a
              // SharedRemote, so this code can just move the remote, instead of
              // cloning.
              mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>
                  token_clone;
              token_remote.Clone(token_clone.InitWithNewPipeAndPassReceiver());
              transaction->bucket_context()
                  ->file_system_access_context()
                  ->SerializeHandle(std::move(token_clone),
                                    std::move(deliver_serialized_token));
            },
            ptr_factory_.GetWeakPtr()));
  }

  return s;
}

Status Transaction::CommitPhaseTwo() {
  // Abort may have been called just as the blob write completed.
  if (state_ == FINISHED) {
    return Status::OK();
  }

  DCHECK_EQ(state_, COMMITTING);

  std::optional scheduling_priority_at_last_state_change =
      scheduling_priority_at_last_state_change_;
  SetState(FINISHED);

  Status s;
  bool committed;
  if (!used_) {
    committed = true;
  } else {
    s = backing_store_transaction_->CommitPhaseTwo();

    // This measurement includes the time it takes to commit to the backing
    // store (i.e. LevelDB), not just the blobs.
    const base::TimeDelta active_time =
        base::Time::Now() - diagnostics_.start_time;

    switch (mode_) {
      case blink::mojom::IDBTransactionMode::ReadOnly:
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.ReadOnly.TimeActive2", active_time);
        if (scheduling_priority_at_last_state_change == 0) {
          base::UmaHistogramMediumTimes(
              "WebCore.IndexedDB.Transaction.ReadOnly.TimeActive2.Foreground",
              active_time);
        }
        break;
      case blink::mojom::IDBTransactionMode::ReadWrite:
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.ReadWrite.TimeActive2", active_time);
        if (scheduling_priority_at_last_state_change == 0) {
          base::UmaHistogramMediumTimes(
              "WebCore.IndexedDB.Transaction.ReadWrite.TimeActive2.Foreground",
              active_time);
        }
        break;
      case blink::mojom::IDBTransactionMode::VersionChange:
        base::UmaHistogramMediumTimes(
            "WebCore.IndexedDB.Transaction.VersionChange.TimeActive2",
            active_time);
        if (scheduling_priority_at_last_state_change == 0) {
          base::UmaHistogramMediumTimes(
              "WebCore.IndexedDB.Transaction.VersionChange.TimeActive2."
              "Foreground",
              active_time);
        }
        break;
      default:
        NOTREACHED();
    }

    committed = s.ok();
  }

  // Backing store resources (held via cursors) must be released
  // before script callbacks are fired, as the script callbacks may
  // release references and allow the backing store itself to be
  // released, and order is critical.
  CloseOpenCursors();
  backing_store_transaction_.reset();

  // Transactions must also be marked as completed before the
  // front-end is notified, as the transaction completion unblocks
  // operations like closing connections.
  locks_receiver_.locks.clear();

  if (committed) {
    {
      TRACE_EVENT1("IndexedDB",
                   "Transaction::CommitPhaseTwo.TransactionCompleteCallbacks",
                   "txn.id", id());
      connection()->callbacks()->OnComplete(*this);
    }

    if (mode() != blink::mojom::IDBTransactionMode::ReadOnly) {
      const bool did_sync =
          mode() == blink::mojom::IDBTransactionMode::VersionChange ||
          durability_ == blink::mojom::IDBTransactionDurability::Strict;
      bucket_context_->delegate().on_files_written.Run(did_sync);
    }
    return s;
  }

  DatabaseError error;
  if (s.IndicatesDiskFull()) {
    error =
        DatabaseError(blink::mojom::IDBException::kQuotaError,
                      "Encountered disk full while committing transaction.");
  } else {
    error = DatabaseError(blink::mojom::IDBException::kUnknownError,
                          "Internal error committing transaction.");
  }
  connection()->callbacks()->OnAbort(*this, error);
  return s;
}

Status Transaction::RunTasks() {
  TRACE_EVENT1("IndexedDB", "Transaction::RunTasks", "txn.id", id());

  // No re-entrancy allowed.
  CHECK(!processing_event_queue_);
  // Should not be called after completion.
  CHECK(!aborted_);
  CHECK_NE(state_, FINISHED);

  if (IsTaskQueueEmpty() && !is_commit_pending_) {
    return Status::OK();
  }

  if (!backing_store_transaction_begun_) {
    IDB_RETURN_IF_ERROR(
        backing_store_transaction_->Begin(std::move(locks_receiver_.locks)));
    backing_store_transaction_begun_ = true;
  }

  base::AutoReset<bool> reset(&processing_event_queue_, true);

  bool run_preemptive_queue =
      !preemptive_task_queue_.empty() || pending_preemptive_events_ != 0;
  TaskQueue* task_queue =
      run_preemptive_queue ? &preemptive_task_queue_ : &task_queue_;
  while (!task_queue->empty() && state_ != FINISHED) {
    CHECK(state_ == STARTED || state_ == COMMITTING) << state_;
    auto [operation, verify] = task_queue->pop();
    Status result = verify ? std::move(verify).Run(*this) : Status::OK();
    if (result.ok()) {
      result = std::move(operation).Run(this);
    }
    if (!run_preemptive_queue) {
      CHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
      ++diagnostics_.tasks_completed;
      NotifyOfIdbInternalsRelevantChange();
    }
    IDB_RETURN_IF_ERROR(result);

    run_preemptive_queue =
        !preemptive_task_queue_.empty() || pending_preemptive_events_ != 0;
    // Event itself may change which queue should be processed next.
    task_queue = run_preemptive_queue ? &preemptive_task_queue_ : &task_queue_;
  }

  if (!HasPendingTasks() && state_ == STARTED) {
    if (is_commit_pending_) {
      // If there are no pending tasks, we haven't already committed/aborted,
      // and the front-end requested a commit, it is now safe to do so.
      IDB_RETURN_IF_ERROR(DoPendingCommit());
    } else if (g_inactivity_timeout_enabled) {
      // Otherwise, start a timer in case the front-end gets wedged and never
      // requests further activity.
      timeout_timer_.Start(FROM_HERE, kInactivityTimeoutPollPeriod,
                           base::BindRepeating(&Transaction::TimeoutFired,
                                               ptr_factory_.GetWeakPtr()));
    }
  }

  return Status::OK();
}

storage::mojom::IdbTransactionMetadataPtr Transaction::GetIdbInternalsMetadata()
    const {
  storage::mojom::IdbTransactionMetadataPtr info =
      storage::mojom::IdbTransactionMetadata::New();
  info->mode = static_cast<storage::mojom::IdbTransactionMode>(mode());
  switch (state()) {
    case Transaction::CREATED:
      info->state = storage::mojom::IdbTransactionState::kBlocked;
      break;
    case Transaction::STARTED:
      info->state = diagnostics().tasks_scheduled > 0
                        ? storage::mojom::IdbTransactionState::kRunning
                        : storage::mojom::IdbTransactionState::kStarted;
      break;
    case Transaction::COMMITTING:
      info->state = storage::mojom::IdbTransactionState::kCommitting;
      break;
    case Transaction::FINISHED:
      info->state = storage::mojom::IdbTransactionState::kFinished;
      break;
  }

  info->tid = id();
  info->connection_id = connection()->id();
  info->client_token = connection()->client_token().ToString();
  info->age =
      (base::Time::Now() - diagnostics().creation_time).InMillisecondsF();
  if (diagnostics().start_time.InMillisecondsSinceUnixEpoch() > 0) {
    info->runtime =
        (base::Time::Now() - diagnostics().start_time).InMillisecondsF();
  }
  info->tasks_scheduled = diagnostics().tasks_scheduled;
  info->tasks_completed = diagnostics().tasks_completed;

  for (int64_t id : scope()) {
    auto stores_it = database_->metadata().object_stores.find(id);
    if (stores_it != database_->metadata().object_stores.end()) {
      info->scope.emplace_back(stores_it->second.name);
    }
  }
  return info;
}

void Transaction::NotifyOfIdbInternalsRelevantChange() {
  // This metadata is included in the databases metadata, so call up the chain.
  if (database_) {
    database_->NotifyOfIdbInternalsRelevantChange();
  }
}

void Transaction::TimeoutFired() {
  // The timeout timer should only be running when these conditions are met:
  CHECK(used_, base::NotFatalUntil::M145);
  CHECK(!diagnostics_.mojo_receiver_disconnected, base::NotFatalUntil::M145);
  CHECK(task_queue_.empty(), base::NotFatalUntil::M145);
  CHECK(preemptive_task_queue_.empty(), base::NotFatalUntil::M145);
  CHECK(connection_.get() != nullptr);

  const size_t num_transactions_across_all_connections =
      database_->GetNumTransactionsAcrossAllConnections();

  // Histograms to diagnose memory leak crbug.com/381086791.
  // TODO(crbug.com/381086791): Remove after the leak is fixed.
  base::UmaHistogramEnumeration("IndexedDB.TransactionTimeout.Mode", mode_);
  base::UmaHistogramBoolean("IndexedDB.TransactionTimeout.CommitPending",
                            is_commit_pending_);
  base::UmaHistogramBoolean("IndexedDB.TransactionTimeout.IsAborted", aborted_);
  base::UmaHistogramBoolean("IndexedDB.TransactionTimeout.TaskRunQueued",
                            bucket_context_->task_run_queued());
  base::UmaHistogramCounts10000(
      "IndexedDB.TransactionTimeout.NumTransactionsInDB",
      num_transactions_across_all_connections);
  base::UmaHistogramBoolean("IndexedDB.TransactionTimeout.IsConnected",
                            connection_->IsConnected());
  base::UmaHistogramCounts10000(
      "IndexedDB.TransactionTimeout.NumTransactionsInConnection",
      connection_->transactions().size());

  // Same histograms as above, but only when there are a lot of transactions in
  // the connection.
  if (connection_->transactions().size() > 10000) {
    base::UmaHistogramEnumeration(
        "IndexedDB.TransactionTimeout.10kTransactions.Mode", mode_);
    base::UmaHistogramBoolean(
        "IndexedDB.TransactionTimeout.10kTransactions.CommitPending",
        is_commit_pending_);
    base::UmaHistogramBoolean(
        "IndexedDB.TransactionTimeout.10kTransactions.IsAborted", aborted_);
    base::UmaHistogramBoolean(
        "IndexedDB.TransactionTimeout.10kTransactions.TaskRunQueued",
        bucket_context_->task_run_queued());
    base::UmaHistogramCounts100000(
        "IndexedDB.TransactionTimeout.10kTransactions.NumTransactionsInDB",
        num_transactions_across_all_connections);
    base::UmaHistogramBoolean(
        "IndexedDB.TransactionTimeout.10kTransactions.IsConnected",
        connection_->IsConnected());
    base::UmaHistogramCounts100000(
        "IndexedDB.TransactionTimeout.10kTransactions."
        "NumTransactionsInConnection",
        connection_->transactions().size());
  }

  if (!IsTransactionBlockingOtherClients(/*consider_priority=*/true)) {
    return;
  }

  if (++timeout_strikes_ >= kMaxTimeoutStrikes) {
    Status result =
        Abort(DatabaseError(blink::mojom::IDBException::kTimeoutError,
                            u"Transaction timed out due to inactivity."));
    if (!result.ok()) {
      bucket_context_->OnDatabaseError(database_.get(), result, {});
    }
    ResetTimeoutTimer();
  }
}

void Transaction::ResetTimeoutTimer() {
  timeout_timer_.Stop();
  timeout_strikes_ = 0;
}

void Transaction::SetState(State state) {
  state_ = state;
  if (connection_) {
    scheduling_priority_at_last_state_change_ =
        connection_->scheduling_priority();
  } else {
    scheduling_priority_at_last_state_change_ = std::nullopt;
  }
  NotifyOfIdbInternalsRelevantChange();
}

void Transaction::CloseOpenCursors() {
  TRACE_EVENT1("IndexedDB", "Transaction::CloseOpenCursors", "txn.id", id());

  // Cursor::Close() indirectly mutates |open_cursors_|, when it calls
  // Transaction::UnregisterOpenCursor().
  std::set<raw_ptr<Cursor, SetExperimental>> open_cursors =
      std::move(open_cursors_);
  open_cursors_.clear();
  for (Cursor* cursor : open_cursors) {
    cursor->Close();
  }
}

void Transaction::OnSchedulingPriorityUpdated(int new_priority) {
  auto* lock_request_data = static_cast<LockRequestData*>(
      locks_receiver_.GetUserData(LockRequestData::kKey));
  DCHECK(lock_request_data);
  lock_request_data->scheduling_priority = new_priority;
}

IndexedDBKey Transaction::GenerateAutoIncrementKey(int64_t object_store_id) {
  ASSIGN_OR_RETURN(
      int64_t current_number,
      BackingStoreTransaction()->GetKeyGeneratorCurrentNumber(object_store_id),
      [](auto) {
        LOG(ERROR) << "Failed to GetKeyGeneratorCurrentNumber";
        return IndexedDBKey();
      });
  // Maximum integer uniquely representable as ECMAScript number.
  const int64_t max_generator_value = 9007199254740992LL;
  if (current_number < 0 || current_number > max_generator_value) {
    return {};
  }

  return IndexedDBKey(current_number, blink::mojom::IDBKeyType::Number);
}

void Transaction::OnMojoReceiverDisconnected() {
  diagnostics_.mojo_receiver_disconnected = true;
}

blink::mojom::IDBValuePtr Transaction::BuildMojoValue(IndexedDBValue value) {
  return backing_store_transaction_->BuildMojoValue(
      std::move(value),
      // Note that this callback is only used by the SQLite store. The LevelDB
      // store reaches directly into the bucket context and its
      // FileSystemAccessContext (a layering violation).
      /*deserialize_handle=*/
      base::BindRepeating(
          &storage::mojom::FileSystemAccessContext::DeserializeHandle,
          base::Unretained(bucket_context_->file_system_access_context()),
          bucket_context_->bucket_info().storage_key));
}

// static
Transaction::VerificationCallback Transaction::ObjectStoreMustExist(
    int64_t object_store_id) {
  return base::BindOnce(
      [](int64_t object_store_id,
         mojo::ReportBadMessageCallback report_bad_message_callback,
         Transaction& transaction) {
        if (!transaction.connection()->database()->IsObjectStoreIdInMetadata(
                object_store_id)) {
          std::move(report_bad_message_callback).Run("Invalid object_store_id");
          return Status::InvalidArgument("Invalid object_store_id.");
        }

        return Status::OK();
      },
      object_store_id, mojo::GetBadMessageCallback());
}

// static
Transaction::VerificationCallback Transaction::ObjectStoreAndIndexMustExist(
    int64_t object_store_id,
    std::optional<int64_t> index_id) {
  return base::BindOnce(
      [](int64_t object_store_id, std::optional<int64_t> index_id,
         mojo::ReportBadMessageCallback report_bad_message_callback,
         Transaction& transaction) {
        if (index_id.has_value() &&
            *index_id == IndexedDBIndexMetadata::kInvalidId) {
          std::move(report_bad_message_callback).Run("index_id must be valid");
          return Status::InvalidArgument("index_id must be valid.");
        }
        if (!transaction.connection()
                 ->database()
                 ->IsObjectStoreIdAndMaybeIndexIdInMetadata(
                     object_store_id,
                     index_id.value_or(IndexedDBIndexMetadata::kInvalidId))) {
          std::move(report_bad_message_callback)
              .Run("Invalid object_store_id or index_id");
          return Status::InvalidArgument(
              "Invalid object_store_id or index_id.");
        }

        return Status::OK();
      },
      object_store_id, index_id, mojo::GetBadMessageCallback());
}

}  // namespace content::indexed_db
