blob: 852e129e03cb9f53bd94922e355f0b7a572ea37f [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2018 The Chromium Authors
Mikel Astizaadda5912018-04-13 11:14:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_
6#define COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_
7
8#include <map>
9#include <memory>
Arthur Sonzognic571efb2024-01-26 20:26:1810#include <optional>
Mikel Astizaadda5912018-04-13 11:14:3711#include <string>
12#include <vector>
13
Avi Drissman12be0312023-01-11 09:16:0914#include "base/functional/callback_forward.h"
Keishi Hattori0e45c022021-11-27 09:25:5215#include "base/memory/raw_ptr.h"
Mikel Astizaadda5912018-04-13 11:14:3716#include "base/memory/weak_ptr.h"
17#include "base/time/time.h"
Mikel Astizaadda5912018-04-13 11:14:3718#include "components/sync/model/data_batch.h"
Mikel Astiz9048b122024-08-05 12:55:4119#include "components/sync/model/data_type_store.h"
Victor Hugo Vianna Silvab06c50972022-02-22 21:35:1020#include "components/sync/model/metadata_batch.h"
Mikel Astizaadda5912018-04-13 11:14:3721#include "components/sync/model/model_error.h"
Jood Hajeer438e5162022-11-21 12:02:1922#include "components/sync_device_info/device_info.h"
Mikel Astizaadda5912018-04-13 11:14:3723#include "components/sync_sessions/synced_session_tracker.h"
24
Mikel Astizaadda5912018-04-13 11:14:3725namespace sync_sessions {
26
27// Class responsible for maintaining an in-memory representation of sync
28// sessions (by owning a SyncedSessionTracker) with the capability to persist
29// state to disk and restore (data and metadata). The API enforces a valid and
30// consistent state of the model, e.g. by making sure there is at most one sync
31// entity per client tag.
32class SessionStore {
33 public:
34 struct SessionInfo {
35 std::string session_tag;
36 std::string client_name;
37 sync_pb::SyncEnums::DeviceType device_type = sync_pb::SyncEnums::TYPE_UNSET;
Jood Hajeer438e5162022-11-21 12:02:1938 syncer::DeviceInfo::FormFactor device_form_factor =
39 syncer::DeviceInfo::FormFactor::kUnknown;
Mikel Astizaadda5912018-04-13 11:14:3740 };
41
Mikel Astiz6265a182019-02-11 15:26:0142 using OpenCallback = base::OnceCallback<void(
Arthur Sonzognic571efb2024-01-26 20:26:1843 const std::optional<syncer::ModelError>& error,
Mikel Astizaadda5912018-04-13 11:14:3744 std::unique_ptr<SessionStore> store,
45 std::unique_ptr<syncer::MetadataBatch> metadata_batch)>;
Mikel Astizaadda5912018-04-13 11:14:3746
Mikel Astiz6265a182019-02-11 15:26:0147 // Opens a SessionStore instance, which involves IO to load previous state
48 // from disk. |sessions_client| must not be null and must outlive the
49 // SessionStore instance returned via |callback|, or until the callback is
50 // cancelled.
Victor Hugo Vianna Silva53785e52021-09-23 13:37:2151 static void Open(const std::string& cache_guid,
52 SyncSessionsClient* sessions_client,
53 OpenCallback callback);
Mikel Astizaadda5912018-04-13 11:14:3754
55 // Verifies whether a proto is malformed (e.g. required fields are missing).
56 static bool AreValidSpecifics(const sync_pb::SessionSpecifics& specifics);
57 // |specifics| must be valid, see AreValidSpecifics().
58 static std::string GetClientTag(const sync_pb::SessionSpecifics& specifics);
59 // |specifics| must be valid, see AreValidSpecifics().
60 static std::string GetStorageKey(const sync_pb::SessionSpecifics& specifics);
Mikel Astizc6a0352f2018-04-20 13:29:1461 static std::string GetHeaderStorageKey(const std::string& session_tag);
62 static std::string GetTabStorageKey(const std::string& session_tag,
63 int tab_node_id);
Mikel Astiz527ec912018-04-18 15:25:2864 // Verifies if |storage_key| corresponds to an entity in the local session,
65 // identified by the session tag.
66 bool StorageKeyMatchesLocalSession(const std::string& storage_key) const;
Mikel Astizaadda5912018-04-13 11:14:3767
Mikel Astiz527ec912018-04-18 15:25:2868 // Various equivalents for testing.
Mikel Astiz527ec912018-04-18 15:25:2869 static std::string GetTabClientTagForTest(const std::string& session_tag,
70 int tab_node_id);
Mikel Astizaadda5912018-04-13 11:14:3771
Mikel Astiz31a57c5e2024-08-05 15:45:5272 // Similar to DataTypeStore::WriteBatch but enforces a consistent state. In
Mikel Astizaadda5912018-04-13 11:14:3773 // the current implementation, some functions do *NOT* update the tracker, so
74 // callers are responsible for doing so.
Alison Gale45c4058f2024-04-26 19:30:0275 // TODO(crbug.com/41295474): Enforce consistency between in-memory and
76 // persisted data by always updating the tracker.
Mikel Astizaadda5912018-04-13 11:14:3777 class WriteBatch {
78 public:
Mikel Astiz31a57c5e2024-08-05 15:45:5279 // Callback that mimics the signature of DataTypeStore::CommitWriteBatch().
Mikel Astizaadda5912018-04-13 11:14:3780 using CommitCallback = base::OnceCallback<void(
Mikel Astiz31a57c5e2024-08-05 15:45:5281 std::unique_ptr<syncer::DataTypeStore::WriteBatch>,
82 syncer::DataTypeStore::CallbackWithResult)>;
Mikel Astizaadda5912018-04-13 11:14:3783
84 // Raw pointers must not be nullptr and must outlive this object.
Mikel Astiz31a57c5e2024-08-05 15:45:5285 WriteBatch(std::unique_ptr<syncer::DataTypeStore::WriteBatch> batch,
Mikel Astizaadda5912018-04-13 11:14:3786 CommitCallback commit_cb,
87 syncer::OnceModelErrorHandler error_handler,
88 SyncedSessionTracker* session_tracker);
Peter Boström09c01822021-09-20 22:43:2789
90 WriteBatch(const WriteBatch&) = delete;
91 WriteBatch& operator=(const WriteBatch&) = delete;
92
Mikel Astizaadda5912018-04-13 11:14:3793 ~WriteBatch();
94
Mikel Astiza1074c52018-12-04 09:22:4995 // Most mutations below return storage keys.
Mikel Astizaadda5912018-04-13 11:14:3796 std::string PutAndUpdateTracker(const sync_pb::SessionSpecifics& specifics,
97 base::Time modification_time);
Mikel Astiza1074c52018-12-04 09:22:4998 // Returns all deleted storage keys, which may be more than one if
99 // |storage_key| refers to a header entity.
100 std::vector<std::string> DeleteForeignEntityAndUpdateTracker(
101 const std::string& storage_key);
Mikel Astizaadda5912018-04-13 11:14:37102 // The functions below do not update SyncedSessionTracker and hence it is
103 // the caller's responsibility to do so *before* calling these functions.
104 std::string PutWithoutUpdatingTracker(
105 const sync_pb::SessionSpecifics& specifics);
106 std::string DeleteLocalTabWithoutUpdatingTracker(int tab_node_id);
107
108 syncer::MetadataChangeList* GetMetadataChangeList();
109
110 static void Commit(std::unique_ptr<WriteBatch> batch);
111
112 private:
Mikel Astiz31a57c5e2024-08-05 15:45:52113 std::unique_ptr<syncer::DataTypeStore::WriteBatch> batch_;
Mikel Astizaadda5912018-04-13 11:14:37114 CommitCallback commit_cb_;
115 syncer::OnceModelErrorHandler error_handler_;
Keishi Hattori0e45c022021-11-27 09:25:52116 const raw_ptr<SyncedSessionTracker> session_tracker_;
Mikel Astizaadda5912018-04-13 11:14:37117 };
118
Peter Boström9f667c382021-10-01 20:09:31119 SessionStore(const SessionStore&) = delete;
120 SessionStore& operator=(const SessionStore&) = delete;
121
Mikel Astizaadda5912018-04-13 11:14:37122 ~SessionStore();
123
124 const SessionInfo& local_session_info() const { return local_session_info_; }
125
Mikel Astizdb744b642018-04-20 10:17:14126 // Converts the in-memory model (SyncedSessionTracker) of sessions to sync
127 // protos.
128 std::unique_ptr<syncer::DataBatch> GetSessionDataForKeys(
Mikel Astizaadda5912018-04-13 11:14:37129 const std::vector<std::string>& storage_keys) const;
130
Mikel Astizdb744b642018-04-20 10:17:14131 // Returns all known session entities, local and foreign, generated from the
132 // in-memory model (SyncedSessionTracker).
133 std::unique_ptr<syncer::DataBatch> GetAllSessionData() const;
Mikel Astizaadda5912018-04-13 11:14:37134
135 // Write API. WriteBatch instances must not outlive this store and must be
136 // committed prior to destruction. Besides, more than one uncommitted
137 // instance must not exist at any time.
138 std::unique_ptr<WriteBatch> CreateWriteBatch(
139 syncer::OnceModelErrorHandler error_handler);
Marc Treib71e67bc72024-09-26 10:33:12140
141 using RecreateEmptyStoreCallback =
142 base::OnceCallback<std::unique_ptr<SessionStore>(
143 const std::string& cache_guid,
144 SyncSessionsClient* sessions_client)>;
145
146 // Deletes all data and metadata from the `session_store` and destroys it.
147 // Returns a callback that allows synchronously re-creating an empty
148 // SessionStore, by reusing the underlying DataTypeStore.
149 static RecreateEmptyStoreCallback DeleteAllDataAndMetadata(
150 std::unique_ptr<SessionStore> session_store);
Mikel Astizaadda5912018-04-13 11:14:37151
Alison Gale45c4058f2024-04-26 19:30:02152 // TODO(crbug.com/41295474): Avoid exposing a mutable tracker, because that
Mikel Astizaadda5912018-04-13 11:14:37153 // bypasses the consistency-enforcing API.
154 SyncedSessionTracker* mutable_tracker() { return &session_tracker_; }
155 const SyncedSessionTracker* tracker() const { return &session_tracker_; }
156
157 private:
Mikel Astiz8680bb32019-04-10 19:55:13158 // Helper class used to collect all parameters needed by the constructor.
159 struct Builder;
160
Mikel Astiz6265a182019-02-11 15:26:01161 static void OnStoreCreated(
Mikel Astiz8680bb32019-04-10 19:55:13162 std::unique_ptr<Builder> builder,
Arthur Sonzognic571efb2024-01-26 20:26:18163 const std::optional<syncer::ModelError>& error,
Mikel Astiz31a57c5e2024-08-05 15:45:52164 std::unique_ptr<syncer::DataTypeStore> underlying_store);
Mikel Astiz6265a182019-02-11 15:26:01165 static void OnReadAllMetadata(
Mikel Astiz8680bb32019-04-10 19:55:13166 std::unique_ptr<Builder> builder,
Arthur Sonzognic571efb2024-01-26 20:26:18167 const std::optional<syncer::ModelError>& error,
Mikel Astiz6265a182019-02-11 15:26:01168 std::unique_ptr<syncer::MetadataBatch> metadata_batch);
Mikel Astiz8680bb32019-04-10 19:55:13169 static void OnReadAllData(std::unique_ptr<Builder> builder,
Arthur Sonzognic571efb2024-01-26 20:26:18170 const std::optional<syncer::ModelError>& error);
Mikel Astiz6265a182019-02-11 15:26:01171
Marc Treib71e67bc72024-09-26 10:33:12172 static std::unique_ptr<SessionStore> RecreateEmptyStore(
173 SessionInfo local_session_info_without_session_tag,
174 std::unique_ptr<syncer::DataTypeStore> underlying_store,
175 const std::string& cache_guid,
176 SyncSessionsClient* sessions_client);
177
Mikel Astiz8680bb32019-04-10 19:55:13178 // |sessions_client| must not be null and must outlive this object.
Mikel Astiz6265a182019-02-11 15:26:01179 SessionStore(const SessionInfo& local_session_info,
Mikel Astiz31a57c5e2024-08-05 15:45:52180 std::unique_ptr<syncer::DataTypeStore> underlying_store,
Mikel Astiz8680bb32019-04-10 19:55:13181 std::map<std::string, sync_pb::SessionSpecifics> initial_data,
182 const syncer::EntityMetadataMap& initial_metadata,
Mikel Astiz6265a182019-02-11 15:26:01183 SyncSessionsClient* sessions_client);
184
Mikel Astiz6265a182019-02-11 15:26:01185 const SessionInfo local_session_info_;
Mikel Astiz6265a182019-02-11 15:26:01186
Mikel Astizaadda5912018-04-13 11:14:37187 // In charge of actually persisting changes to disk.
Marc Treib71e67bc72024-09-26 10:33:12188 std::unique_ptr<syncer::DataTypeStore> store_;
Mikel Astizaadda5912018-04-13 11:14:37189
Keishi Hattori0e45c022021-11-27 09:25:52190 const raw_ptr<SyncSessionsClient> sessions_client_;
Mikel Astiz9a36638e2020-12-17 17:52:48191
Mikel Astizaadda5912018-04-13 11:14:37192 SyncedSessionTracker session_tracker_;
193
Jeremy Roman5c341f6d2019-07-15 15:56:10194 base::WeakPtrFactory<SessionStore> weak_ptr_factory_{this};
Mikel Astizaadda5912018-04-13 11:14:37195};
196
197} // namespace sync_sessions
198
199#endif // COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_