// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_ #define NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_ #include #include #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 "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 { // `SessionStoreImpl` implements a persistent store for sessions data. // It uses the sqlite-proto library to store the data in a string-to-proto // SQLite table. The key is a serialized `SchemefulSite` string that // represents an eTLD+1 site. The value is a protobuf of session objects // associated the site. class NET_EXPORT SessionStoreImpl : public SessionStore { public: enum DBStatus { kSuccess, kFailure, kNotLoaded, }; // Instantiates a store object. // `db_storage_path` is the path to the underlying SQLite DB file. // `key_service` is used to convert a session binding key to/from // its persistable form. 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; // SessionStore implementation: void LoadSessions(LoadSessionsCallback callback) override; void SaveSession(const SchemefulSite& site, const Session& session) override; void DeleteSession(const SchemefulSite& site, const Session::Id& session_id) override; SessionsMap GetAllSessions() const override; void RestoreSessionBindingKey( const SchemefulSite& site, const Session::Id& session_id, RestoreSessionBindingKeyCallback callback) override; DBStatus db_status() const { return db_status_; } // Allows test to wait until DB shutdown tasks are complete. 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); void OnDatabaseLoaded(LoadSessionsCallback callback, DBStatus status); // Helper function called by `OnDatabaseLoaded` to prune out any invalid // entries found in the data loaded from disk. Returns a map of valid // session objects that is returned to the caller of `LoadSessions` via // the provided callback. `keys_to_delete` represents the list of invalid // keys that are deleted from the store. static SessionsMap CreateSessionsFromLoadedData( const std::map& loaded_data, std::vector& keys_to_delete); // Key service used to wrap/unwrap unexportable session keys. const raw_ref key_service_; // Background task runner used to perform DB tasks. scoped_refptr db_task_runner_; // Path to the backing database file. base::FilePath db_storage_path_; // The following objects are use to work with an SQLite database. //`db_`, `proto_table_manager_` are deleted on the db sequence, // while `session_table_` and `session_data_` are deleted on the // main sequence. std::unique_ptr db_; scoped_refptr table_manager_; std::unique_ptr> session_table_; // TODO(crbug.com/371556007) : Keeping the `session_data_` around // facilitates DB operations that would otherwise require read+write // operations. However, it does create some redundancy in the cached // data since we also convert the cached data into `Session` objects. // Look into reducing the cached data storage size. std::unique_ptr> session_data_; DBStatus db_status_ = kNotLoaded; // Used only for tests to notify that shutdown tasks are completed on // the DB sequence. base::OnceClosure shutdown_callback_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_