#ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
#define NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
#include <optional>
#include <string>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/timer/elapsed_timer.h"
#include "components/sqlite_proto/key_value_data.h"
#include "components/sqlite_proto/key_value_table.h"
#include "components/sqlite_proto/proto_table_manager.h"
#include "components/unexportable_keys/service_error.h"
#include "components/unexportable_keys/unexportable_key_id.h"
#include "net/base/net_export.h"
#include "net/device_bound_sessions/proto/storage.pb.h"
#include "net/device_bound_sessions/session_store.h"
namespace unexportable_keys {
class UnexportableKeyService;
}
namespace net::device_bound_sessions {
class NET_EXPORT SessionStoreImpl : public SessionStore {
public:
enum DBStatus {
kSuccess,
kFailure,
kNotLoaded,
};
SessionStoreImpl(base::FilePath db_storage_path,
unexportable_keys::UnexportableKeyService& key_service);
SessionStoreImpl(const SessionStoreImpl& other) = delete;
SessionStoreImpl& operator=(const SessionStoreImpl& other) = delete;
SessionStoreImpl(SessionStoreImpl&& other) = delete;
SessionStoreImpl& operator=(SessionStoreImpl&& other) = delete;
~SessionStoreImpl() override;
void LoadSessions(LoadSessionsCallback callback) override;
void SaveSession(const SchemefulSite& site, const Session& session) override;
void DeleteSession(const SessionKey& key) override;
SessionsMap GetAllSessions() const override;
void RestoreSessionBindingKey(
const SessionKey& session_key,
RestoreSessionBindingKeyCallback callback) override;
DBStatus db_status() const { return db_status_; }
void SetShutdownCallbackForTesting(base::OnceClosure shutdown_callback);
private:
FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
PruneLoadedEntryWithInvalidSite);
FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
PruneLoadedEntryWithInvalidSession);
FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
PruneLoadedEntryWithSessionMissingWrappedKey);
FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
PruneLoadedEntryWithInvalidRefreshInitiator);
void OnDatabaseLoaded(LoadSessionsCallback callback,
base::ElapsedTimer timer,
DBStatus status);
static SessionsMap CreateSessionsFromLoadedData(
const std::map<std::string, proto::SiteSessions>& loaded_data,
std::vector<std::string>& keys_to_delete);
void OnSessionBindingKeyRestored(
const SessionKey& session_key,
unexportable_keys::ServiceErrorOr<unexportable_keys::UnexportableKeyId>
key_or_error);
const raw_ref<unexportable_keys::UnexportableKeyService> key_service_;
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
base::FilePath db_storage_path_;
std::unique_ptr<sql::Database> db_;
scoped_refptr<sqlite_proto::ProtoTableManager> table_manager_;
std::unique_ptr<sqlite_proto::KeyValueTable<proto::SiteSessions>>
session_table_;
std::unique_ptr<sqlite_proto::KeyValueData<proto::SiteSessions>>
session_data_;
DBStatus db_status_ = kNotLoaded;
base::OnceClosure shutdown_callback_;
std::map<SessionKey, std::vector<RestoreSessionBindingKeyCallback>>
restore_callbacks_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<SessionStoreImpl> weak_ptr_factory_{this};
};
}
#endif