1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
// 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 <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/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 {
// `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 SessionKey& key) 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,
base::ElapsedTimer timer,
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<std::string, proto::SiteSessions>& loaded_data,
std::vector<std::string>& keys_to_delete);
// Key service used to wrap/unwrap unexportable session keys.
const raw_ref<unexportable_keys::UnexportableKeyService> key_service_;
// Background task runner used to perform DB tasks.
scoped_refptr<base::SequencedTaskRunner> 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<sql::Database> db_;
scoped_refptr<sqlite_proto::ProtoTableManager> table_manager_;
std::unique_ptr<sqlite_proto::KeyValueTable<proto::SiteSessions>>
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<sqlite_proto::KeyValueData<proto::SiteSessions>>
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<SessionStoreImpl> weak_ptr_factory_{this};
};
} // namespace net::device_bound_sessions
#endif // NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
|