chromium/content/browser/indexed_db/indexed_db_backing_store.cc

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

#include <algorithm>
#include <optional>
#include <string_view>
#include <tuple>
#include <utility>

#include "base/dcheck_is_on.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/important_file_writer.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/trace_event/base_tracing.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
#include "components/services/storage/indexed_db/scopes/leveldb_scope.h"
#include "components/services/storage/indexed_db/scopes/leveldb_scopes.h"
#include "components/services/storage/indexed_db/scopes/varint_coding.h"
#include "components/services/storage/indexed_db/transactional_leveldb/leveldb_write_batch.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_iterator.h"
#include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction.h"
#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
#include "components/services/storage/public/mojom/file_system_access_context.mojom.h"
#include "content/browser/indexed_db/file_path_util.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_bucket_context.h"
#include "content/browser/indexed_db/indexed_db_data_format_version.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_external_object.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_leveldb_operations.h"
#include "content/browser/indexed_db/indexed_db_reporting.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/file_system/file_stream_writer.h"
#include "storage/browser/file_system/file_writer_delegate.h"
#include "storage/browser/file_system/local_file_stream_writer.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/file_system/file_system_mount_option.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/leveldatabase/env_chromium.h"

IndexedDBDatabaseMetadata;
IndexedDBKey;
IndexedDBKeyRange;
Status;

namespace content {
CheckIndexAndMetaDataKey;
CheckObjectStoreAndMetaDataType;
FindGreatestKeyLessThanOrEqual;
GetInt;
GetString;
GetVarInt;
InternalInconsistencyStatus;
InvalidDBKeyStatus;
IOErrorStatus;
PutBool;
PutIDBKeyPath;
PutInt;
PutString;
PutVarInt;
ReportOpenStatus;

// An RAII helper to ensure that "DidCommitTransaction" is called
// during this class's destruction.
class AutoDidCommitTransaction {};

namespace {

std::string ComputeOriginIdentifier(
    const storage::BucketLocator& bucket_locator) {}

leveldb::Status GetDBSizeFromEnv(leveldb::Env* env,
                                 const std::string& path,
                                 int64_t* total_size_out) {}

// TODO(ericu): Error recovery. If we persistently can't read the
// blob journal, the safe thing to do is to clear it and leak the blobs,
// though that may be costly. Still, database/directory deletion should always
// clean things up, and we can write an fsck that will do a full correction if
// need be.

// Read and decode the specified blob journal via the supplied transaction.
// The key must be either the recovery journal key or active journal key.
template <typename TransactionType>
Status GetBlobJournal(std::string_view key,
                      TransactionType* transaction,
                      BlobJournalType* journal) {}

template <typename TransactionType>
Status GetRecoveryBlobJournal(TransactionType* transaction,
                              BlobJournalType* journal) {}

template <typename TransactionType>
Status GetActiveBlobJournal(TransactionType* transaction,
                            BlobJournalType* journal) {}

// Clear the specified blob journal via the supplied transaction.
// The key must be either the recovery journal key or active journal key.
template <typename TransactionType>
void ClearBlobJournal(TransactionType* transaction, const std::string& key) {}

// Overwrite the specified blob journal via the supplied transaction.
// The key must be either the recovery journal key or active journal key.
template <typename TransactionType>
leveldb::Status UpdateBlobJournal(TransactionType* transaction,
                                  const std::string& key,
                                  const BlobJournalType& journal) {}

template <typename TransactionType>
leveldb::Status UpdateRecoveryBlobJournal(TransactionType* transaction,
                                          const BlobJournalType& journal) {}

template <typename TransactionType>
leveldb::Status UpdateActiveBlobJournal(TransactionType* transaction,
                                        const BlobJournalType& journal) {}

// Append blobs to the specified blob journal via the supplied transaction.
// The key must be either the recovery journal key or active journal key.
template <typename TransactionType>
Status AppendBlobsToBlobJournal(TransactionType* transaction,
                                const std::string& key,
                                const BlobJournalType& journal) {}

template <typename TransactionType>
Status AppendBlobsToRecoveryBlobJournal(TransactionType* transaction,
                                        const BlobJournalType& journal) {}

template <typename TransactionType>
Status AppendBlobsToActiveBlobJournal(TransactionType* transaction,
                                      const BlobJournalType& journal) {}

// Append a database to the specified blob journal via the supplied transaction.
// The key must be either the recovery journal key or active journal key.
Status MergeDatabaseIntoBlobJournal(
    TransactionalLevelDBTransaction* transaction,
    const std::string& key,
    int64_t database_id) {}

Status MergeDatabaseIntoRecoveryBlobJournal(
    TransactionalLevelDBTransaction* leveldb_transaction,
    int64_t database_id) {}

Status MergeDatabaseIntoActiveBlobJournal(
    TransactionalLevelDBTransaction* leveldb_transaction,
    int64_t database_id) {}

// Blob Data is encoded as a series of:
//   { object_type [IndexedDBExternalObject::ObjectType as byte],
//     (for Blobs and Files only) blob_number [int64_t as varInt],
//     (for Blobs and Files only) type [string-with-length, may be empty],
//     (for Blobs and Files only) size [int64_t as varInt]
//     (for Files only) fileName [string-with-length]
//     (for Files only) lastModified [int64_t as varInt, in microseconds]
//     (for File System Access Handles only) token [binary-with-length]
//   }
// There is no length field; just read until you run out of data.
std::string EncodeExternalObjects(
    const std::vector<IndexedDBExternalObject>& external_objects) {}

bool DecodeV3ExternalObjects(std::string_view data,
                             std::vector<IndexedDBExternalObject>* output) {}

bool DecodeExternalObjects(const std::string& data,
                           std::vector<IndexedDBExternalObject>* output) {}

Status DeleteBlobsInRange(IndexedDBBackingStore::Transaction* transaction,
                          int64_t database_id,
                          const std::string& start_key,
                          const std::string& end_key,
                          bool upper_open) {}

Status DeleteBlobsInObjectStore(IndexedDBBackingStore::Transaction* transaction,
                                int64_t database_id,
                                int64_t object_store_id) {}

bool ObjectStoreCursorOptions(
    TransactionalLevelDBTransaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    IndexedDBBackingStore::Cursor::CursorOptions* cursor_options,
    Status* status) {}

bool IndexCursorOptions(
    TransactionalLevelDBTransaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    IndexedDBBackingStore::Cursor::CursorOptions* cursor_options,
    Status* status) {}

Status ReadIndexes(TransactionalLevelDBDatabase* db,
                   int64_t database_id,
                   int64_t object_store_id,
                   std::map<int64_t, blink::IndexedDBIndexMetadata>* indexes) {}

Status ReadObjectStores(
    TransactionalLevelDBDatabase* db,
    int64_t database_id,
    std::map<int64_t, blink::IndexedDBObjectStoreMetadata>* object_stores) {}

Status FindDatabaseId(TransactionalLevelDBDatabase* db,
                      const std::string& origin_identifier,
                      const std::u16string& name,
                      int64_t* id,
                      bool* found) {}

}  // namespace

IndexedDBBackingStore::IndexedDBBackingStore(
    Mode backing_store_mode,
    const storage::BucketLocator& bucket_locator,
    const base::FilePath& blob_path,
    TransactionalLevelDBFactory& transactional_leveldb_factory,
    std::unique_ptr<TransactionalLevelDBDatabase> db,
    BlobFilesCleanedCallback blob_files_cleaned,
    ReportOutstandingBlobsCallback report_outstanding_blobs,
    scoped_refptr<base::SequencedTaskRunner> idb_task_runner)
    :{}

IndexedDBBackingStore::~IndexedDBBackingStore() {}

IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
    std::string primary_key,
    int64_t version)
    :{}

IndexedDBBackingStore::RecordIdentifier::RecordIdentifier() = default;

IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}

void IndexedDBBackingStore::RecordIdentifier::Reset(std::string primary_key,
                                                    int64_t version) {}

constexpr const int IndexedDBBackingStore::kMaxJournalCleanRequests;
constexpr const base::TimeDelta
    IndexedDBBackingStore::kMaxJournalCleaningWindowTime;
constexpr const base::TimeDelta
    IndexedDBBackingStore::kInitialJournalCleaningWindowTime;

leveldb::Status IndexedDBBackingStore::Initialize(bool clean_active_journal) {}

void IndexedDBBackingStore::TearDown(
    base::WaitableEvent* signal_on_destruction) {}

Status IndexedDBBackingStore::AnyDatabaseContainsBlobs(bool* blobs_exist) {}

Status IndexedDBBackingStore::UpgradeBlobEntriesToV4(
    LevelDBWriteBatch* write_batch,
    std::vector<base::FilePath>* empty_blobs_to_delete) {}

Status IndexedDBBackingStore::ValidateBlobFiles() {}

std::unique_ptr<IndexedDBBackingStore::Transaction>
IndexedDBBackingStore::CreateTransaction(
    blink::mojom::IDBTransactionDurability durability,
    blink::mojom::IDBTransactionMode mode) {}

// static
bool IndexedDBBackingStore::ShouldSyncOnCommit(
    blink::mojom::IDBTransactionDurability durability) {}

leveldb::Status IndexedDBBackingStore::GetCompleteMetadata(
    std::vector<IndexedDBDatabaseMetadata>* output) {}

// static
bool IndexedDBBackingStore::RecordCorruptionInfo(
    const base::FilePath& path_base,
    const storage::BucketLocator& bucket_locator,
    const std::string& message) {}

Status IndexedDBBackingStore::CreateDatabase(
    blink::IndexedDBDatabaseMetadata& metadata) {}

Status IndexedDBBackingStore::DeleteDatabase(
    const std::u16string& name,
    TransactionalLevelDBTransaction* transaction) {}

leveldb::Status IndexedDBBackingStore::SetDatabaseVersion(
    Transaction* transaction,
    int64_t row_id,
    int64_t version,
    blink::IndexedDBDatabaseMetadata* metadata) {}

leveldb::Status IndexedDBBackingStore::CreateObjectStore(
    Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    std::u16string name,
    blink::IndexedDBKeyPath key_path,
    bool auto_increment,
    blink::IndexedDBObjectStoreMetadata* metadata) {}

Status IndexedDBBackingStore::DeleteObjectStore(
    Transaction* transaction,
    int64_t database_id,
    const blink::IndexedDBObjectStoreMetadata& object_store) {}

Status IndexedDBBackingStore::RenameObjectStore(
    Transaction* transaction,
    int64_t database_id,
    std::u16string new_name,
    std::u16string* old_name,
    blink::IndexedDBObjectStoreMetadata* metadata) {}

Status IndexedDBBackingStore::CreateIndex(
    Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    std::u16string name,
    blink::IndexedDBKeyPath key_path,
    bool is_unique,
    bool is_multi_entry,
    blink::IndexedDBIndexMetadata* metadata) {}

Status IndexedDBBackingStore::DeleteIndex(
    Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const blink::IndexedDBIndexMetadata& metadata) {}

Status IndexedDBBackingStore::RenameIndex(
    Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    std::u16string new_name,
    std::u16string* old_name,
    blink::IndexedDBIndexMetadata* metadata) {}

void IndexedDBBackingStore::Compact() {}

Status IndexedDBBackingStore::GetRecord(Transaction* transaction,
                                        int64_t database_id,
                                        int64_t object_store_id,
                                        const IndexedDBKey& key,
                                        IndexedDBValue* record) {}

int64_t IndexedDBBackingStore::GetInMemorySize() const {}

Status IndexedDBBackingStore::PutRecord(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKey& key,
    IndexedDBValue* value,
    RecordIdentifier* record_identifier) {}

Status IndexedDBBackingStore::ClearObjectStore(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id) {}

Status IndexedDBBackingStore::DeleteRecord(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const RecordIdentifier& record_identifier) {}

Status IndexedDBBackingStore::DeleteRange(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKeyRange& key_range) {}

Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t* key_generator_current_number) {}

Status IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t new_number,
    bool check_current) {}

Status IndexedDBBackingStore::KeyExistsInObjectStore(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKey& key,
    RecordIdentifier* found_record_identifier,
    bool* found) {}

void IndexedDBBackingStore::ReportBlobUnused(int64_t database_id,
                                             int64_t blob_number) {}

// The this reference is a raw pointer that's declared Unretained inside the
// timer code, so this won't confuse IndexedDBFactory's check for
// HasLastBackingStoreReference.  It's safe because if the backing store is
// deleted, the timer will automatically be canceled on destruction.
void IndexedDBBackingStore::StartJournalCleaningTimer() {}

// This assumes a file path of dbId/second-to-LSB-of-counter/counter.
base::FilePath IndexedDBBackingStore::GetBlobFileName(
    int64_t database_id,
    int64_t blob_number) const {}

bool IndexedDBBackingStore::RemoveBlobFile(int64_t database_id,
                                           int64_t blob_number) const {}

bool IndexedDBBackingStore::RemoveBlobDirectory(int64_t database_id) const {}

Status IndexedDBBackingStore::CleanUpBlobJournal(
    const std::string& level_db_key) const {}

Status IndexedDBBackingStore::CleanUpBlobJournalEntries(
    const BlobJournalType& journal) const {}

void IndexedDBBackingStore::WillCommitTransaction() {}

void IndexedDBBackingStore::DidCommitTransaction() {}

Status IndexedDBBackingStore::Transaction::GetExternalObjectsForRecord(
    int64_t database_id,
    const std::string& object_store_data_key,
    IndexedDBValue* value) {}

base::WeakPtr<IndexedDBBackingStore::Transaction>
IndexedDBBackingStore::Transaction::AsWeakPtr() {}

void IndexedDBBackingStore::CleanRecoveryJournalIgnoreReturn() {}

Status IndexedDBBackingStore::ClearIndex(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id) {}

Status IndexedDBBackingStore::PutIndexDataForRecord(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKey& key,
    const RecordIdentifier& record_identifier) {}

Status IndexedDBBackingStore::FindKeyInIndex(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKey& key,
    std::string* found_encoded_primary_key,
    bool* found) {}

Status IndexedDBBackingStore::GetPrimaryKeyViaIndex(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKey& key,
    std::unique_ptr<IndexedDBKey>* primary_key) {}

Status IndexedDBBackingStore::KeyExistsInIndex(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKey& index_key,
    std::unique_ptr<IndexedDBKey>* found_primary_key,
    bool* exists) {}

Status IndexedDBBackingStore::GetDatabaseNames(
    std::vector<std::u16string>* names) {}

Status IndexedDBBackingStore::GetDatabaseNamesAndVersions(
    std::vector<blink::mojom::IDBNameAndVersionPtr>* names_and_versions) {}

leveldb::Status IndexedDBBackingStore::ReadMetadataForDatabaseName(
    const std::u16string& name,
    blink::IndexedDBDatabaseMetadata* metadata,
    bool* found) {}

IndexedDBBackingStore::Cursor::Cursor(
    const IndexedDBBackingStore::Cursor* other,
    std::unique_ptr<TransactionalLevelDBIterator> iterator)
    :{}

IndexedDBBackingStore::Cursor::Cursor(base::WeakPtr<Transaction> transaction,
                                      int64_t database_id,
                                      const CursorOptions& cursor_options)
    :{}

IndexedDBBackingStore::Cursor::~Cursor() {}

// static
std::unique_ptr<TransactionalLevelDBIterator>
IndexedDBBackingStore::Cursor::CloneIterator(
    const IndexedDBBackingStore::Cursor* other) {}

bool IndexedDBBackingStore::Cursor::FirstSeek(Status* s) {}

bool IndexedDBBackingStore::Cursor::Advance(uint32_t count, Status* s) {}

bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
                                             const IndexedDBKey* primary_key,
                                             IteratorState next_state,
                                             Status* s) {}

IndexedDBBackingStore::Cursor::ContinueResult
IndexedDBBackingStore::Cursor::ContinueNext(const IndexedDBKey* key,
                                            const IndexedDBKey* primary_key,
                                            IteratorState next_state,
                                            Status* s) {}

IndexedDBBackingStore::Cursor::ContinueResult
IndexedDBBackingStore::Cursor::ContinuePrevious(const IndexedDBKey* key,
                                                const IndexedDBKey* primary_key,
                                                IteratorState next_state,
                                                Status* s) {}

bool IndexedDBBackingStore::Cursor::HaveEnteredRange() const {}

bool IndexedDBBackingStore::Cursor::IsPastBounds() const {}

const IndexedDBKey& IndexedDBBackingStore::Cursor::primary_key() const {}

class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {};

IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() = default;

IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions(
    const CursorOptions& other) = default;

IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() = default;

const IndexedDBBackingStore::RecordIdentifier&
IndexedDBBackingStore::Cursor::record_identifier() const {}

bool ObjectStoreKeyCursorImpl::LoadCurrentRow(Status* s) {}

class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {};

bool ObjectStoreCursorImpl::LoadCurrentRow(Status* s) {}

class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {};

bool IndexKeyCursorImpl::LoadCurrentRow(Status* s) {}

class IndexCursorImpl : public IndexedDBBackingStore::Cursor {};

bool IndexCursorImpl::LoadCurrentRow(Status* s) {}

std::unique_ptr<IndexedDBBackingStore::Cursor>
IndexedDBBackingStore::OpenObjectStoreCursor(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    Status* s) {}

std::unique_ptr<IndexedDBBackingStore::Cursor>
IndexedDBBackingStore::OpenObjectStoreKeyCursor(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    Status* s) {}

std::unique_ptr<IndexedDBBackingStore::Cursor>
IndexedDBBackingStore::OpenIndexKeyCursor(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    Status* s) {}

std::unique_ptr<IndexedDBBackingStore::Cursor>
IndexedDBBackingStore::OpenIndexCursor(
    IndexedDBBackingStore::Transaction* transaction,
    int64_t database_id,
    int64_t object_store_id,
    int64_t index_id,
    const IndexedDBKeyRange& range,
    blink::mojom::IDBCursorDirection direction,
    Status* s) {}

bool IndexedDBBackingStore::IsBlobCleanupPending() {}

void IndexedDBBackingStore::ForceRunBlobCleanup() {}

IndexedDBBackingStore::Transaction::BlobWriteState::BlobWriteState() = default;

IndexedDBBackingStore::Transaction::BlobWriteState::BlobWriteState(
    int calls_left,
    BlobWriteCallback on_complete)
    :{}

IndexedDBBackingStore::Transaction::BlobWriteState::~BlobWriteState() = default;

// `backing_store` can be null in unittests (see FakeTransaction).
IndexedDBBackingStore::Transaction::Transaction(
    base::WeakPtr<IndexedDBBackingStore> backing_store,
    blink::mojom::IDBTransactionDurability durability,
    blink::mojom::IDBTransactionMode mode)
    :{}

IndexedDBBackingStore::Transaction::~Transaction() {}

void IndexedDBBackingStore::Transaction::Begin(
    std::vector<PartitionedLock> locks) {}

Status IndexedDBBackingStore::MigrateToV4(LevelDBWriteBatch* write_batch) {}

Status IndexedDBBackingStore::MigrateToV5(LevelDBWriteBatch* write_batch) {}

Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction() {}

bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {}

void IndexedDBBackingStore::Transaction::PartitionBlobsToRemove(
    BlobJournalType* inactive_blobs,
    BlobJournalType* active_blobs) const {}

Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
    BlobWriteCallback callback) {}

Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {}

leveldb::Status IndexedDBBackingStore::Transaction::WriteNewBlobs(
    BlobWriteCallback callback) {}

void IndexedDBBackingStore::Transaction::Reset() {}

void IndexedDBBackingStore::Transaction::Rollback() {}

uint64_t IndexedDBBackingStore::Transaction::GetTransactionSize() {}

Status IndexedDBBackingStore::Transaction::PutExternalObjectsIfNeeded(
    int64_t database_id,
    const std::string& object_store_data_key,
    std::vector<IndexedDBExternalObject>* external_objects) {}

// This is storing an info, even if empty, even if the previous key had no blob
// info that we know of.  It duplicates a bunch of information stored in the
// leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
// changes to exists or index keys here.
void IndexedDBBackingStore::Transaction::PutExternalObjects(
    int64_t database_id,
    const std::string& object_store_data_key,
    std::vector<IndexedDBExternalObject>* external_objects) {}

}  // namespace content