• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
6 #define NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
7 
8 #include <optional>
9 #include <string>
10 
11 #include "base/files/file_path.h"
12 #include "base/functional/callback.h"
13 #include "base/functional/callback_forward.h"
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "components/sqlite_proto/key_value_data.h"
17 #include "components/sqlite_proto/key_value_table.h"
18 #include "components/sqlite_proto/proto_table_manager.h"
19 #include "components/unexportable_keys/service_error.h"
20 #include "components/unexportable_keys/unexportable_key_id.h"
21 #include "net/base/net_export.h"
22 #include "net/device_bound_sessions/proto/storage.pb.h"
23 #include "net/device_bound_sessions/session_store.h"
24 
25 namespace unexportable_keys {
26 class UnexportableKeyService;
27 }
28 
29 namespace net::device_bound_sessions {
30 
31 // `SessionStoreImpl` implements a persistent store for sessions data.
32 // It uses the sqlite-proto library to store the data in a string-to-proto
33 // SQLite table. The key is a serialized `SchemefulSite` string that
34 // represents an eTLD+1 site. The value is a protobuf of session objects
35 // associated the site.
36 class NET_EXPORT SessionStoreImpl : public SessionStore {
37  public:
38   enum DBStatus {
39     kSuccess,
40     kFailure,
41     kNotLoaded,
42   };
43 
44   // Instantiates a store object.
45   // `db_storage_path` is the path to the underlying SQLite DB file.
46   // `key_service` is used to convert a session binding key to/from
47   // its persistable form.
48   SessionStoreImpl(base::FilePath db_storage_path,
49                    unexportable_keys::UnexportableKeyService& key_service);
50 
51   SessionStoreImpl(const SessionStoreImpl& other) = delete;
52   SessionStoreImpl& operator=(const SessionStoreImpl& other) = delete;
53   SessionStoreImpl(SessionStoreImpl&& other) = delete;
54   SessionStoreImpl& operator=(SessionStoreImpl&& other) = delete;
55 
56   ~SessionStoreImpl() override;
57 
58   // SessionStore implementation:
59   void LoadSessions(LoadSessionsCallback callback) override;
60   void SaveSession(const SchemefulSite& site, const Session& session) override;
61   void DeleteSession(const SchemefulSite& site,
62                      const Session::Id& session_id) override;
63   SessionsMap GetAllSessions() const override;
64   void RestoreSessionBindingKey(
65       const SchemefulSite& site,
66       const Session::Id& session_id,
67       RestoreSessionBindingKeyCallback callback) override;
68 
db_status()69   DBStatus db_status() const { return db_status_; }
70 
71   // Allows test to wait until DB shutdown tasks are complete.
72   void SetShutdownCallbackForTesting(base::OnceClosure shutdown_callback);
73 
74  private:
75   FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
76                            PruneLoadedEntryWithInvalidSite);
77   FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
78                            PruneLoadedEntryWithInvalidSession);
79   FRIEND_TEST_ALL_PREFIXES(SessionStoreImplTest,
80                            PruneLoadedEntryWithSessionMissingWrappedKey);
81 
82   void OnDatabaseLoaded(LoadSessionsCallback callback, DBStatus status);
83 
84   // Helper function called by `OnDatabaseLoaded` to prune out any invalid
85   // entries found in the data loaded from disk. Returns a map of valid
86   // session objects that is returned to the caller of `LoadSessions` via
87   // the provided callback. `keys_to_delete` represents the list of invalid
88   // keys that are deleted from the store.
89   static SessionsMap CreateSessionsFromLoadedData(
90       const std::map<std::string, proto::SiteSessions>& loaded_data,
91       std::vector<std::string>& keys_to_delete);
92 
93   // Key service used to wrap/unwrap unexportable session keys.
94   const raw_ref<unexportable_keys::UnexportableKeyService> key_service_;
95 
96   // Background task runner used to perform DB tasks.
97   scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
98   // Path to the backing database file.
99   base::FilePath db_storage_path_;
100 
101   // The following objects are use to work with an SQLite database.
102   //`db_`, `proto_table_manager_` are deleted on the db sequence,
103   // while `session_table_` and `session_data_` are deleted on the
104   // main sequence.
105   std::unique_ptr<sql::Database> db_;
106   scoped_refptr<sqlite_proto::ProtoTableManager> table_manager_;
107   std::unique_ptr<sqlite_proto::KeyValueTable<proto::SiteSessions>>
108       session_table_;
109   // TODO(crbug.com/371556007) : Keeping the `session_data_` around
110   // facilitates DB operations that would otherwise require read+write
111   // operations. However, it does create some redundancy in the cached
112   // data since we also convert the cached data into `Session` objects.
113   // Look into reducing the cached data storage size.
114   std::unique_ptr<sqlite_proto::KeyValueData<proto::SiteSessions>>
115       session_data_;
116 
117   DBStatus db_status_ = kNotLoaded;
118 
119   // Used only for tests to notify that shutdown tasks are completed on
120   // the DB sequence.
121   base::OnceClosure shutdown_callback_;
122 
123   SEQUENCE_CHECKER(sequence_checker_);
124 
125   base::WeakPtrFactory<SessionStoreImpl> weak_ptr_factory_{this};
126 };
127 
128 }  // namespace net::device_bound_sessions
129 
130 #endif  // NET_DEVICE_BOUND_SESSIONS_SESSION_STORE_IMPL_H_
131