blob: b58ba5a4b2605da0b95735f8708132f583267979 [file] [log] [blame]
Mikel Astizaadda5912018-04-13 11:14:371// Copyright 2018 The Chromium Authors. All rights reserved.
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 COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_
6#define COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_
7
8#include <map>
9#include <memory>
10#include <string>
11#include <vector>
12
13#include "base/callback_forward.h"
14#include "base/macros.h"
15#include "base/memory/weak_ptr.h"
16#include "base/time/time.h"
Mikel Astizaadda5912018-04-13 11:14:3717#include "components/sync/model/data_batch.h"
18#include "components/sync/model/model_error.h"
19#include "components/sync/model/model_type_store.h"
20#include "components/sync_sessions/synced_session_tracker.h"
Lei Zhang698df03c2021-05-21 04:23:3421#include "third_party/abseil-cpp/absl/types/optional.h"
Mikel Astizaadda5912018-04-13 11:14:3722
Mikel Astizaadda5912018-04-13 11:14:3723namespace sync_sessions {
24
25// Class responsible for maintaining an in-memory representation of sync
26// sessions (by owning a SyncedSessionTracker) with the capability to persist
27// state to disk and restore (data and metadata). The API enforces a valid and
28// consistent state of the model, e.g. by making sure there is at most one sync
29// entity per client tag.
30class SessionStore {
31 public:
32 struct SessionInfo {
33 std::string session_tag;
34 std::string client_name;
35 sync_pb::SyncEnums::DeviceType device_type = sync_pb::SyncEnums::TYPE_UNSET;
36 };
37
Mikel Astiz6265a182019-02-11 15:26:0138 using OpenCallback = base::OnceCallback<void(
Anton Bikineev1156b5f2021-05-15 22:35:3639 const absl::optional<syncer::ModelError>& error,
Mikel Astizaadda5912018-04-13 11:14:3740 std::unique_ptr<SessionStore> store,
41 std::unique_ptr<syncer::MetadataBatch> metadata_batch)>;
Mikel Astizaadda5912018-04-13 11:14:3742
Mikel Astiz6265a182019-02-11 15:26:0143 // Opens a SessionStore instance, which involves IO to load previous state
44 // from disk. |sessions_client| must not be null and must outlive the
45 // SessionStore instance returned via |callback|, or until the callback is
46 // cancelled.
47 static void Open(
Mikel Astiz8680bb32019-04-10 19:55:1348 const std::string& cache_guid,
Mikel Astizaadda5912018-04-13 11:14:3749 SyncSessionsClient* sessions_client,
Mikel Astiz6265a182019-02-11 15:26:0150 OpenCallback callback);
Mikel Astizaadda5912018-04-13 11:14:3751
52 // Verifies whether a proto is malformed (e.g. required fields are missing).
53 static bool AreValidSpecifics(const sync_pb::SessionSpecifics& specifics);
54 // |specifics| must be valid, see AreValidSpecifics().
55 static std::string GetClientTag(const sync_pb::SessionSpecifics& specifics);
56 // |specifics| must be valid, see AreValidSpecifics().
57 static std::string GetStorageKey(const sync_pb::SessionSpecifics& specifics);
Mikel Astizc6a0352f2018-04-20 13:29:1458 static std::string GetHeaderStorageKey(const std::string& session_tag);
59 static std::string GetTabStorageKey(const std::string& session_tag,
60 int tab_node_id);
Mikel Astiz527ec912018-04-18 15:25:2861 // Verifies if |storage_key| corresponds to an entity in the local session,
62 // identified by the session tag.
63 bool StorageKeyMatchesLocalSession(const std::string& storage_key) const;
Mikel Astizaadda5912018-04-13 11:14:3764
Mikel Astiz527ec912018-04-18 15:25:2865 // Various equivalents for testing.
Mikel Astiz527ec912018-04-18 15:25:2866 static std::string GetTabClientTagForTest(const std::string& session_tag,
67 int tab_node_id);
Mikel Astizaadda5912018-04-13 11:14:3768
69 // Similar to ModelTypeStore::WriteBatch but enforces a consistent state. In
70 // the current implementation, some functions do *NOT* update the tracker, so
71 // callers are responsible for doing so.
72 // TODO(crbug.com/681921): Enforce consistency between in-memory and persisted
73 // data by always updating the tracker.
74 class WriteBatch {
75 public:
76 // Callback that mimics the signature of ModelTypeStore::CommitWriteBatch().
77 using CommitCallback = base::OnceCallback<void(
78 std::unique_ptr<syncer::ModelTypeStore::WriteBatch>,
79 syncer::ModelTypeStore::CallbackWithResult)>;
80
81 // Raw pointers must not be nullptr and must outlive this object.
82 WriteBatch(std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch,
83 CommitCallback commit_cb,
84 syncer::OnceModelErrorHandler error_handler,
85 SyncedSessionTracker* session_tracker);
86 ~WriteBatch();
87
Mikel Astiza1074c52018-12-04 09:22:4988 // Most mutations below return storage keys.
Mikel Astizaadda5912018-04-13 11:14:3789 std::string PutAndUpdateTracker(const sync_pb::SessionSpecifics& specifics,
90 base::Time modification_time);
Mikel Astiza1074c52018-12-04 09:22:4991 // Returns all deleted storage keys, which may be more than one if
92 // |storage_key| refers to a header entity.
93 std::vector<std::string> DeleteForeignEntityAndUpdateTracker(
94 const std::string& storage_key);
Mikel Astizaadda5912018-04-13 11:14:3795 // The functions below do not update SyncedSessionTracker and hence it is
96 // the caller's responsibility to do so *before* calling these functions.
97 std::string PutWithoutUpdatingTracker(
98 const sync_pb::SessionSpecifics& specifics);
99 std::string DeleteLocalTabWithoutUpdatingTracker(int tab_node_id);
100
101 syncer::MetadataChangeList* GetMetadataChangeList();
102
103 static void Commit(std::unique_ptr<WriteBatch> batch);
104
105 private:
106 std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch_;
107 CommitCallback commit_cb_;
108 syncer::OnceModelErrorHandler error_handler_;
109 SyncedSessionTracker* const session_tracker_;
110
111 DISALLOW_COPY_AND_ASSIGN(WriteBatch);
112 };
113
Mikel Astizaadda5912018-04-13 11:14:37114 ~SessionStore();
115
116 const SessionInfo& local_session_info() const { return local_session_info_; }
117
Mikel Astizdb744b642018-04-20 10:17:14118 // Converts the in-memory model (SyncedSessionTracker) of sessions to sync
119 // protos.
120 std::unique_ptr<syncer::DataBatch> GetSessionDataForKeys(
Mikel Astizaadda5912018-04-13 11:14:37121 const std::vector<std::string>& storage_keys) const;
122
Mikel Astizdb744b642018-04-20 10:17:14123 // Returns all known session entities, local and foreign, generated from the
124 // in-memory model (SyncedSessionTracker).
125 std::unique_ptr<syncer::DataBatch> GetAllSessionData() const;
Mikel Astizaadda5912018-04-13 11:14:37126
127 // Write API. WriteBatch instances must not outlive this store and must be
128 // committed prior to destruction. Besides, more than one uncommitted
129 // instance must not exist at any time.
130 std::unique_ptr<WriteBatch> CreateWriteBatch(
131 syncer::OnceModelErrorHandler error_handler);
132 void DeleteAllDataAndMetadata();
133
134 // TODO(crbug.com/681921): Avoid exposing a mutable tracker, because that
135 // bypasses the consistency-enforcing API.
136 SyncedSessionTracker* mutable_tracker() { return &session_tracker_; }
137 const SyncedSessionTracker* tracker() const { return &session_tracker_; }
138
139 private:
Mikel Astiz8680bb32019-04-10 19:55:13140 // Helper class used to collect all parameters needed by the constructor.
141 struct Builder;
142
Mikel Astiz6265a182019-02-11 15:26:01143 static void OnStoreCreated(
Mikel Astiz8680bb32019-04-10 19:55:13144 std::unique_ptr<Builder> builder,
Anton Bikineev1156b5f2021-05-15 22:35:36145 const absl::optional<syncer::ModelError>& error,
Mikel Astiz6265a182019-02-11 15:26:01146 std::unique_ptr<syncer::ModelTypeStore> underlying_store);
147 static void OnReadAllMetadata(
Mikel Astiz8680bb32019-04-10 19:55:13148 std::unique_ptr<Builder> builder,
Anton Bikineev1156b5f2021-05-15 22:35:36149 const absl::optional<syncer::ModelError>& error,
Mikel Astiz6265a182019-02-11 15:26:01150 std::unique_ptr<syncer::MetadataBatch> metadata_batch);
Mikel Astiz8680bb32019-04-10 19:55:13151 static void OnReadAllData(std::unique_ptr<Builder> builder,
Anton Bikineev1156b5f2021-05-15 22:35:36152 const absl::optional<syncer::ModelError>& error);
Mikel Astiz6265a182019-02-11 15:26:01153
Mikel Astiz8680bb32019-04-10 19:55:13154 // |sessions_client| must not be null and must outlive this object.
Mikel Astiz6265a182019-02-11 15:26:01155 SessionStore(const SessionInfo& local_session_info,
Mikel Astiz8680bb32019-04-10 19:55:13156 std::unique_ptr<syncer::ModelTypeStore> underlying_store,
157 std::map<std::string, sync_pb::SessionSpecifics> initial_data,
158 const syncer::EntityMetadataMap& initial_metadata,
Mikel Astiz6265a182019-02-11 15:26:01159 SyncSessionsClient* sessions_client);
160
Mikel Astiz6265a182019-02-11 15:26:01161 const SessionInfo local_session_info_;
Mikel Astiz6265a182019-02-11 15:26:01162
Mikel Astizaadda5912018-04-13 11:14:37163 // In charge of actually persisting changes to disk.
Mikel Astiz8680bb32019-04-10 19:55:13164 const std::unique_ptr<syncer::ModelTypeStore> store_;
Mikel Astizaadda5912018-04-13 11:14:37165
Mikel Astiz9a366382020-12-17 17:52:48166 SyncSessionsClient* const sessions_client_;
167
Mikel Astizaadda5912018-04-13 11:14:37168 SyncedSessionTracker session_tracker_;
169
Jeremy Roman5c341f6d2019-07-15 15:56:10170 base::WeakPtrFactory<SessionStore> weak_ptr_factory_{this};
Mikel Astizaadda5912018-04-13 11:14:37171
172 DISALLOW_COPY_AND_ASSIGN(SessionStore);
173};
174
175} // namespace sync_sessions
176
177#endif // COMPONENTS_SYNC_SESSIONS_SESSION_STORE_H_