#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_CONNECTION_H_
#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_CONNECTION_H_
#include <array>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/types/expected.h"
#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h"
#include "components/services/storage/public/cpp/buckets/bucket_info.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "content/browser/indexed_db/instance/bucket_context_handle.h"
#include "content/browser/indexed_db/instance/database.h"
#include "content/browser/indexed_db/instance/transaction.h"
#include "content/common/content_export.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_set.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h"
#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace blink {
class IndexedDBKeyRange;
}
namespace content::indexed_db {
class DatabaseCallbacks;
class DatabaseError;
class BucketContext;
class CONTENT_EXPORT Connection : public blink::mojom::IDBDatabase {
public:
static mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase>
MakeSelfOwnedReceiverAndBindRemote(std::unique_ptr<Connection> connection);
Connection(BucketContext& bucket_context,
base::WeakPtr<Database> database,
base::RepeatingClosure on_version_change_ignored,
base::OnceCallback<void(Connection&)> on_close,
std::unique_ptr<DatabaseCallbacks> callbacks,
mojo::Remote<storage::mojom::IndexedDBClientStateChecker>
client_state_checker,
base::UnguessableToken client_token,
int scheduling_priority);
Connection(const Connection&) = delete;
Connection& operator=(const Connection&) = delete;
~Connection() override;
base::WeakPtr<Connection> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
base::WeakPtr<Database> database() const { return database_; }
DatabaseCallbacks* callbacks() const { return callbacks_.get(); }
const base::UnguessableToken& client_token() const { return client_token_; }
const std::map<int64_t, std::unique_ptr<Transaction>>& transactions() const {
return transactions_;
}
bool IsConnected() const;
bool is_shutting_down() const { return is_shutting_down_; }
int32_t id() const { return id_; }
Transaction* CreateVersionChangeTransaction(
int64_t id,
const std::set<int64_t>& scope,
std::unique_ptr<BackingStore::Transaction> backing_store_transaction);
void DisallowInactiveClient(
storage::mojom::DisallowInactiveClientReason reason,
base::OnceCallback<void(bool)> callback);
void RemoveTransaction(int64_t id);
void AbortTransactionAndTearDownOnError(Transaction* transaction,
const DatabaseError& error);
void CloseAndReportForceClose(const std::string& message);
int scheduling_priority() const { return scheduling_priority_; }
static bool HasHigherPriorityThan(const PartitionedLockHolder* this_one,
const PartitionedLockHolder& other);
bool IsHoldingLocks(const std::vector<PartitionedLockId>& lock_ids) const;
base::expected<Transaction*, DatabaseError> GetTransactionAndVerifyState(
int64_t transaction_id,
std::optional<blink::mojom::IDBTransactionMode> required_mode = {});
private:
friend class TransactionTestBase;
FRIEND_TEST_ALL_PREFIXES(DatabaseTest, ForcedClose);
FRIEND_TEST_ALL_PREFIXES(DatabaseTest, PendingDelete);
FRIEND_TEST_ALL_PREFIXES(DatabaseOperationTest, GetWithInvalidId);
FRIEND_TEST_ALL_PREFIXES(TransactionTest, PostedStartTaskRunAfterAbort);
void RenameObjectStore(int64_t transaction_id,
int64_t object_store_id,
const std::u16string& new_name) override;
void CreateTransaction(
mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction>
transaction_receiver,
int64_t transaction_id,
const std::vector<int64_t>& object_store_ids,
blink::mojom::IDBTransactionMode mode,
blink::mojom::IDBTransactionDurability durability) override;
void VersionChangeIgnored() override;
void Get(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
blink::IndexedDBKeyRange key_range,
bool key_only,
blink::mojom::IDBDatabase::GetCallback callback) override;
void GetAll(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
blink::IndexedDBKeyRange key_range,
blink::mojom::IDBGetAllResultType result_type,
uint32_t max_count,
blink::mojom::IDBCursorDirection direction,
blink::mojom::IDBDatabase::GetAllCallback callback) override;
void OpenCursor(
int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
blink::IndexedDBKeyRange key_range,
blink::mojom::IDBCursorDirection direction,
bool key_only,
blink::mojom::IDBTaskType task_type,
blink::mojom::IDBDatabase::OpenCursorCallback callback) override;
void Count(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
blink::IndexedDBKeyRange key_range,
CountCallback callback) override;
void DeleteRange(int64_t transaction_id,
int64_t object_store_id,
blink::IndexedDBKeyRange key_range,
DeleteRangeCallback success_callback) override;
void GetKeyGeneratorCurrentNumber(
int64_t transaction_id,
int64_t object_store_id,
GetKeyGeneratorCurrentNumberCallback callback) override;
void Clear(int64_t transaction_id,
int64_t object_store_id,
ClearCallback callback) override;
void CreateIndex(int64_t transaction_id,
int64_t object_store_id,
const blink::IndexedDBIndexMetadata& index) override;
void DeleteIndex(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id) override;
void RenameIndex(int64_t transaction_id,
int64_t object_store_id,
int64_t index_id,
const std::u16string& new_name) override;
void Abort(int64_t transaction_id) override;
void DidBecomeInactive() override;
void UpdatePriority(int new_priority) override;
const storage::BucketInfo& GetBucketInfo();
storage::BucketLocator GetBucketLocator();
Transaction* GetTransaction(int64_t id) const;
enum class CloseErrorHandling {
kReturnOnFirstError,
kAbortAllReturnLastError,
};
std::unique_ptr<DatabaseCallbacks> AbortTransactionsAndClose(
CloseErrorHandling error_handling,
const std::string& message);
Status AbortAllTransactionsAndIgnoreErrors(const DatabaseError& error);
Status AbortAllTransactions(const DatabaseError& error);
BucketContext* bucket_context() {
return bucket_context_handle_.bucket_context();
}
void RecordCreateTransactionHistograms(blink::mojom::IDBTransactionMode mode);
const int32_t id_;
BucketContextHandle bucket_context_handle_;
base::WeakPtr<Database> database_;
base::RepeatingClosure on_version_change_ignored_;
base::OnceCallback<void(Connection&)> on_close_;
std::map<int64_t, std::unique_ptr<Transaction>> transactions_;
std::unique_ptr<DatabaseCallbacks> callbacks_;
mojo::Remote<storage::mojom::IndexedDBClientStateChecker>
client_state_checker_;
static constexpr size_t kNumKeepActiveReasons =
static_cast<size_t>(
storage::mojom::DisallowInactiveClientReason::kMaxValue) +
1;
std::array<mojo::Remote<storage::mojom::IndexedDBClientKeepActive>,
kNumKeepActiveReasons>
client_keep_active_remotes_;
base::UnguessableToken client_token_;
SEQUENCE_CHECKER(sequence_checker_);
int scheduling_priority_;
bool is_shutting_down_ = false;
mojo::SelfOwnedAssociatedReceiverRef<blink::mojom::IDBDatabase> receiver_;
base::WeakPtrFactory<Connection> weak_factory_{this};
};
}
#endif