#include "content/browser/indexed_db/indexed_db_bucket_context.h"
#include <inttypes.h>
#include <stddef.h>
#include <algorithm>
#include <atomic>
#include <compare>
#include <list>
#include <ostream>
#include <set>
#include <type_traits>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/containers/contains.h"
#include "base/containers/map_util.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "components/services/storage/indexed_db/leveldb/leveldb_state.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
#include "components/services/storage/indexed_db/scopes/leveldb_scopes.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_transaction.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-forward.h"
#include "components/services/storage/privileged/mojom/indexed_db_internals_types.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 "components/services/storage/public/mojom/blob_storage_context.mojom.h"
#include "content/browser/indexed_db/file_path_util.h"
#include "content/browser/indexed_db/file_stream_reader_to_data_pipe.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_bucket_context_handle.h"
#include "content/browser/indexed_db/indexed_db_compaction_task.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_data_format_version.h"
#include "content/browser/indexed_db/indexed_db_data_loss_info.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_callbacks.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_factory_client.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_pending_connection.h"
#include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h"
#include "content/browser/indexed_db/indexed_db_reporting.h"
#include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/list_set.h"
#include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h"
#include "content/public/common/content_features.h"
#include "env_chromium.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/net_errors.h"
#include "storage/browser/file_system/file_stream_reader.h"
#include "storage/browser/quota/quota_manager_proxy.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/file_system_access/file_system_access_transfer_token.mojom.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-shared.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
namespace content {
namespace {
const int64_t kBackingStoreGracePeriodSeconds = …;
const int64_t kRunningPreCloseTasksMaxRunPeriodSeconds = …;
const int kTombstoneSweeperRoundIterations = …;
const int kTombstoneSweeperMaxIterations = …;
constexpr const base::TimeDelta kMinEarliestBucketSweepFromNow = …;
static_assert …;
constexpr const base::TimeDelta kMinEarliestGlobalSweepFromNow = …;
static_assert …;
base::Time GenerateNextBucketSweepTime(base::Time now) { … }
base::Time GenerateNextGlobalSweepTime(base::Time now) { … }
constexpr const base::TimeDelta kMinEarliestBucketCompactionFromNow = …;
static_assert …;
constexpr const base::TimeDelta kMinEarliestGlobalCompactionFromNow = …;
static_assert …;
base::Time GenerateNextBucketCompactionTime(base::Time now) { … }
base::Time GenerateNextGlobalCompactionTime(base::Time now) { … }
struct GetBucketSpaceRequestWrapper { … };
IndexedDBDatabaseError CreateDefaultError() { … }
leveldb_env::Options GetLevelDBOptions() { … }
std::tuple<scoped_refptr<LevelDBState>,
leveldb::Status,
bool>
CreateLevelDBState(const leveldb_env::Options& base_options,
const base::FilePath& file_name,
bool create_if_missing,
const std::string& in_memory_name) { … }
std::tuple<base::FilePath ,
base::FilePath ,
leveldb::Status>
CreateDatabaseDirectories(const base::FilePath& path_base,
const storage::BucketLocator& bucket_locator) { … }
std::tuple<bool, leveldb::Status> AreSchemasKnown(
TransactionalLevelDBDatabase* db) { … }
}
class IndexedDBDataItemReader : public storage::mojom::BlobDataItemReader { … };
constexpr const base::TimeDelta
IndexedDBBucketContext::kMaxEarliestGlobalSweepFromNow;
constexpr const base::TimeDelta
IndexedDBBucketContext::kMaxEarliestBucketSweepFromNow;
constexpr const base::TimeDelta
IndexedDBBucketContext::kMaxEarliestGlobalCompactionFromNow;
constexpr const base::TimeDelta
IndexedDBBucketContext::kMaxEarliestBucketCompactionFromNow;
IndexedDBBucketContext::Delegate::Delegate()
: … { … }
IndexedDBBucketContext::Delegate::Delegate(Delegate&& other) = default;
IndexedDBBucketContext::Delegate::~Delegate() = default;
IndexedDBBucketContext::IndexedDBBucketContext(
storage::BucketInfo bucket_info,
const base::FilePath& data_path,
Delegate&& delegate,
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
scoped_refptr<base::TaskRunner> io_task_runner,
mojo::PendingRemote<storage::mojom::BlobStorageContext>
blob_storage_context,
mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
file_system_access_context,
InstanceClosure initialize_closure)
: … { … }
IndexedDBBucketContext::~IndexedDBBucketContext() { … }
void IndexedDBBucketContext::ForceClose(bool doom) { … }
void IndexedDBBucketContext::StartMetadataRecording() { … }
std::vector<storage::mojom::IdbBucketMetadataPtr>
IndexedDBBucketContext::StopMetadataRecording() { … }
int64_t IndexedDBBucketContext::GetInMemorySize() { … }
void IndexedDBBucketContext::ReportOutstandingBlobs(bool blobs_outstanding) { … }
void IndexedDBBucketContext::RunInstanceClosure(InstanceClosure method) { … }
void IndexedDBBucketContext::CheckCanUseDiskSpace(
int64_t space_requested,
base::OnceCallback<void(bool)> bucket_space_check_callback) { … }
void IndexedDBBucketContext::OnGotBucketSpaceRemaining(
storage::QuotaErrorOr<int64_t> space_left) { … }
int64_t IndexedDBBucketContext::GetBucketSpaceToAllot() { … }
void IndexedDBBucketContext::CreateAllExternalObjects(
const std::vector<IndexedDBExternalObject>& objects,
std::vector<blink::mojom::IDBExternalObjectPtr>* mojo_objects) { … }
void IndexedDBBucketContext::QueueRunTasks() { … }
void IndexedDBBucketContext::RunTasks() { … }
void IndexedDBBucketContext::AddReceiver(
const storage::BucketClientInfo& client_info,
mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
client_state_checker_remote,
mojo::PendingReceiver<blink::mojom::IDBFactory> pending_receiver) { … }
void IndexedDBBucketContext::GetDatabaseInfo(GetDatabaseInfoCallback callback) { … }
void IndexedDBBucketContext::Open(
mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
factory_client,
mojo::PendingAssociatedRemote<blink::mojom::IDBDatabaseCallbacks>
database_callbacks_remote,
const std::u16string& name,
int64_t version,
mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction>
transaction_receiver,
int64_t transaction_id) { … }
void IndexedDBBucketContext::DeleteDatabase(
mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
factory_client,
const std::u16string& name,
bool force_close) { … }
storage::mojom::IdbBucketMetadataPtr IndexedDBBucketContext::FillInMetadata(
storage::mojom::IdbBucketMetadataPtr info) { … }
void IndexedDBBucketContext::NotifyOfIdbInternalsRelevantChange() { … }
IndexedDBBucketContext* IndexedDBBucketContext::GetReferenceForTesting() { … }
void IndexedDBBucketContext::CompactBackingStoreForTesting() { … }
void IndexedDBBucketContext::WriteToIndexedDBForTesting(
const std::string& key,
const std::string& value) { … }
void IndexedDBBucketContext::BindMockFailureSingletonForTesting(
mojo::PendingReceiver<storage::mojom::MockFailureInjector> receiver) { … }
void IndexedDBBucketContext::SetInternalState(
base::Time earliest_global_sweep_time,
base::Time earliest_global_compaction_time,
IndexedDBBucketContext& context) { … }
IndexedDBDatabase* IndexedDBBucketContext::AddDatabase(
const std::u16string& name,
std::unique_ptr<IndexedDBDatabase> database) { … }
void IndexedDBBucketContext::OnHandleCreated() { … }
void IndexedDBBucketContext::OnHandleDestruction() { … }
bool IndexedDBBucketContext::CanClose() { … }
void IndexedDBBucketContext::MaybeStartClosing() { … }
void IndexedDBBucketContext::StartClosing() { … }
void IndexedDBBucketContext::StartPreCloseTasks() { … }
void IndexedDBBucketContext::CloseNow() { … }
bool IndexedDBBucketContext::ShouldRunTombstoneSweeper() { … }
bool IndexedDBBucketContext::ShouldRunCompaction() { … }
void IndexedDBBucketContext::BindFileReader(
const base::FilePath& path,
base::Time expected_modification_time,
base::OnceClosure release_callback,
mojo::PendingReceiver<storage::mojom::BlobDataItemReader> receiver) { … }
void IndexedDBBucketContext::RemoveBoundReaders(const base::FilePath& path) { … }
void IndexedDBBucketContext::HandleBackingStoreCorruption(
const IndexedDBDatabaseError& error) { … }
void IndexedDBBucketContext::OnDatabaseError(leveldb::Status status,
const std::string& message) { … }
bool IndexedDBBucketContext::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) { … }
std::tuple<std::unique_ptr<IndexedDBBackingStore>,
leveldb::Status,
IndexedDBDataLossInfo,
bool >
IndexedDBBucketContext::OpenAndVerifyIndexedDBBackingStore(
base::FilePath data_directory,
base::FilePath database_path,
base::FilePath blob_path,
PartitionedLockManager* lock_manager,
bool is_first_attempt,
bool create_if_missing) { … }
std::tuple<leveldb::Status, IndexedDBDatabaseError, IndexedDBDataLossInfo>
IndexedDBBucketContext::InitBackingStoreIfNeeded(bool create_if_missing) { … }
void IndexedDBBucketContext::ResetBackingStore() { … }
void IndexedDBBucketContext::OnReceiverDisconnected() { … }
void IndexedDBBucketContext::RecordInternalsSnapshot() { … }
IndexedDBBucketContext::ReceiverContext::ReceiverContext(
const storage::BucketClientInfo& client_info,
mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
client_state_checker_remote)
: … { … }
IndexedDBBucketContext::ReceiverContext::ReceiverContext(
IndexedDBBucketContext::ReceiverContext&&) noexcept = default;
IndexedDBBucketContext::ReceiverContext::~ReceiverContext() = default;
}